///|
/// Message serialization boundary. Framing, sequence correlation and socket
/// lifetimes stay in the runtime, independently of the selected wire codec.
pub struct MessageCodec {
encoder : (Message) -> Bytes raise CodecError
decoder : (Bytes) -> Message raise CodecError
}
///|
pub fn MessageCodec::new(
encode~ : (Message) -> Bytes raise CodecError,
decode~ : (Bytes) -> Message raise CodecError,
) -> MessageCodec {
{ encoder: encode, decoder: decode, }
}
///|
pub fn MessageCodec::builtin(
protocol : Protocol,
strict_read? : Bool = true,
strict_write? : Bool = true,
) -> MessageCodec {
MessageCodec::new(
encode=message => encode_message(message, protocol, strict_write~),
decode=data => decode_message(data, protocol, strict_read~),
)
}
///|
fn check_envelope(message : Message) -> Unit raise CodecError {
if message.message_type < 1 ||
message.message_type > 4 ||
message.body.kind() != StructKind {
raise Invalid("invalid RPC envelope")
}
if @utf8.encode(message.name).length() > 1024 {
raise Invalid("RPC method name exceeds 1024 bytes")
}
}
///|
pub fn MessageCodec::encode(
self : MessageCodec,
message : Message,
) -> Bytes raise CodecError {
check_envelope(message)
let data = (self.encoder)(message)
if data.length() > 1048576 {
raise Invalid("RPC message exceeds one MiB")
}
data
}
///|
pub fn MessageCodec::decode(
self : MessageCodec,
data : Bytes,
) -> Message raise CodecError {
if data.length() > 1048576 {
raise Invalid("RPC message exceeds one MiB")
}
let message = (self.decoder)(data)
check_envelope(message)
message
}