///|
/// Protocol errors are fatal for a decoder/connection.
pub suberror ProtocolError {
Invalid(String)
} derive(Debug)
///|
/// Ordered headers preserve repetition/history. `header` returns the first.
pub struct Frame {
command : String
headers : Array[(String, String)]
body : Bytes
} derive(Debug, Eq)
///|
pub fn Frame::new(
command : String,
headers : Array[(String, String)],
body~ : Bytes = b"",
) -> Frame {
{ command, headers: headers.copy(), body, }
}
///|
pub fn Frame::header(self : Frame, key : String) -> String? {
for pair in self.headers {
if pair.0 == key {
return Some(pair.1)
}
}
None
}
///|
pub fn valid_command(command : String) -> Bool {
match command {
"CONNECT"
| "STOMP"
| "CONNECTED"
| "SEND"
| "SUBSCRIBE"
| "UNSUBSCRIBE"
| "ACK"
| "NACK"
| "BEGIN"
| "COMMIT"
| "ABORT"
| "DISCONNECT"
| "MESSAGE"
| "RECEIPT"
| "ERROR" => true
_ => false
}
}
///|
fn body_allowed(command : String) -> Bool {
command == "SEND" || command == "MESSAGE" || command == "ERROR"
}
///|
fn unescaped(command : String) -> Bool {
command == "CONNECT" || command == "CONNECTED"
}
///|
/// Decimal only, bounded before multiplying; no sign, whitespace or overflow.
fn decimal(s : String, limit : Int32) -> Int32 raise ProtocolError {
if s.length() == 0 {
raise Invalid("empty decimal")
}
let mut n = 0
for c in s {
if c < '0' || c > '9' {
raise Invalid("non-decimal length")
}
let digit = c.to_int() - 48
if n > limit / 10 || (n == limit / 10 && digit > limit % 10) {
raise Invalid("decimal exceeds limit")
}
n = n * 10 + digit
}
n
}
///|
pub extend ProtocolError with @debug.Debug::{to_repr}
///|
pub extend Frame with @debug.Debug::{to_repr}
///|
pub extend Frame with Eq::{equal, not_equal}