diff --git a/build.rs b/build.rs
index 42af504..eb448b9 100644
--- a/build.rs
+++ b/build.rs
@@ -1,6 +1,7 @@
extern crate capnpc;
use std::path::Path;
+use std::process::Command;
fn main() {
capnpc::CompilerCommand::new()
@@ -14,6 +15,18 @@ fn main() {
inputs: &[Path::new("marketdata.fbs")],
out_dir: Path::new("src/"),
..Default::default()
- })
- .expect("Unable to compile flatc");
+ }).expect("Unable to compile flatc");
+
+ // There's no Rust-style builder crate for SBE,
+ // so we need to run the command by hand.
+ // TODO: Automatically download the SBE JAR?
+ let _output = Command::new("java")
+ .arg("-Dsbe.output.dir=src")
+ .arg("-Dsbe.xinclude.aware=true")
+ .arg("-Dsbe.target.language=uk.co.real_logic.sbe.generation.rust.Rust")
+ .arg("-Dsbe.target.namespace=marketdata_sbe")
+ .arg("-jar").arg("sbe-all-1.13.2-all.jar")
+ .arg("marketdata.xml")
+ .output()
+ .expect("Unable to execute SBE compiler");
}
diff --git a/marketdata.xml b/marketdata.xml
new file mode 100644
index 0000000..038e9d8
--- /dev/null
+++ b/marketdata.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 1
+
+
+ 0
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sbe-all-1.13.2-all.jar b/sbe-all-1.13.2-all.jar
new file mode 100644
index 0000000..00ad10a
Binary files /dev/null and b/sbe-all-1.13.2-all.jar differ
diff --git a/sbe.xsd b/sbe.xsd
new file mode 100644
index 0000000..cce09d0
--- /dev/null
+++ b/sbe.xsd
@@ -0,0 +1,390 @@
+
+
+
+
+ Message schema for FIX Simple Binary Encoding
+ Version: 1.0 Draft Standard
+ © Copyright 2014-2016 FIX Protocol Limited
+ License: Creative Commons Attribution-NoDerivatives 4.0 International Public License
+
+
+
+
+
+ Root of XML document, holds all message templates
+ and their elements
+
+
+
+
+
+
+
+ More than one set of types may be provided.
+ Names must be unique across all encoding
+ types.
+ Encoding types may appear in any order.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Unique ID of a message schema
+
+
+
+
+
+ The version of a message schema. Initial version
+ is 0.
+
+
+
+
+
+ Application layer specification version, such as
+ FIX version 'FIX.5.0SP2'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Name of the encoding type of the message header,
+ which is the same for all messages in a schema. The name has a
+ default, but an encoding of that name must be present under a
+ 'types' element.
+
+
+
+
+
+
+
+
+ A message type, also known as a message template
+
+
+
+
+
+ Base type of message and repeating group entry
+
+
+
+
+
+ Fixed-length fields
+
+
+
+
+
+ Variable-length fields
+
+
+
+
+
+
+ Unique ID of a message template
+
+
+
+
+
+ Space reserved for root level of message, not
+ include groups or variable-length
+ data elements.
+
+
+
+
+
+
+
+
+
+ A repeating group contains an array of entries
+
+
+
+
+
+
+
+
+
+
+
+ Simple wire encoding consisting of a primitive type
+ or array of primitives
+
+
+
+
+
+
+
+ Override of default null indicator for the data
+ type in SBE specification,
+ as a string.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A wire encoding composed of multiple parts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ An enumeration of valid values
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Valid value as a string
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A reference to any existing encoding type (simple type, enum or set)
+ to reuse as a member of a composite type
+
+
+
+
+
+
+
+
+
+
+ A multi value choice (encoded as a bitset)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A choice within a multi value set. Value is the
+ position within a bitset (zero-based index).
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A field of a message of a specified dataType
+
+
+
+
+
+
+ Must match the name of an encoding contained by
+ 'types' element
+
+
+
+
+
+
+ Deprecated - only for back compatibility with RC2
+
+
+
+
+
+
+
+
+
+
+
+
+ Application layer class. Maps a field or encoding
+ to a FIX data type.
+
+
+
+
+
+
+
+
+ Schema versioning supports message extension
+
+
+
+
+
+ The schema version in which an element was added
+
+
+
+
+
+
+ The version of the schema in which an element was
+ deprecated. It is retained for back compatibility but should no
+ longer be used by updated applications.
+
+
+
+
+
+
+
+ Offset from start of a composite type or block
+ as a zero-based index.
+
+
+
+
+
+
+
+
+
+
+ The value must always be populated
+
+
+
+
+
+ Value may be set to nullValue for its data type
+
+
+
+
+
+ Value does not vary so it need not be
+ serialized on the wire
+
+
+
+
+
+
+
+
+ A constant value as valid value of an enum
+ in the form enum-name.valid-value-name
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/marketdata_sbe.rs b/src/marketdata_sbe.rs
new file mode 100644
index 0000000..4d2ea13
--- /dev/null
+++ b/src/marketdata_sbe.rs
@@ -0,0 +1,583 @@
+/// Generated code for SBE package marketdata_sbe
+
+
+/// Imports core rather than std to broaden usable environments.
+extern crate core;
+
+/// Result types for error handling
+
+/// Errors that may occur during the course of encoding or decoding.
+#[derive(Debug)]
+pub enum CodecErr {
+ /// Too few bytes in the byte-slice to read or write the data structure relevant
+ /// to the current state of the codec
+ NotEnoughBytes,
+
+ /// Groups and vardata are constrained by the numeric type chosen to represent their
+ /// length as well as optional maxima imposed by the schema
+ SliceIsLongerThanAllowedBySchema,
+}
+
+pub type CodecResult = core::result::Result;
+
+/// Scratch Decoder Data Wrapper - codec internal use only
+#[derive(Debug)]
+pub struct ScratchDecoderData<'d> {
+ data: &'d [u8],
+ pos: usize,
+}
+
+impl<'d> ScratchDecoderData<'d> {
+ /// Create a struct reference overlaid atop the data buffer
+ /// such that the struct's contents directly reflect the buffer.
+ /// Advances the `pos` index by the size of the struct in bytes.
+ #[inline]
+ fn read_type(&mut self, num_bytes: usize) -> CodecResult<&'d T> {
+ let end = self.pos + num_bytes;
+ if end <= self.data.len() {
+ let s = self.data[self.pos..end].as_ptr() as *mut T;
+ let v: &'d T = unsafe { &*s };
+ self.pos = end;
+ Ok(v)
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+
+ /// Advances the `pos` index by a set number of bytes.
+ #[inline]
+ fn skip_bytes(&mut self, num_bytes: usize) -> CodecResult<()> {
+ let end = self.pos + num_bytes;
+ if end <= self.data.len() {
+ self.pos = end;
+ Ok(())
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+
+ /// Create a slice reference overlaid atop the data buffer
+ /// such that the slice's members' contents directly reflect the buffer.
+ /// Advances the `pos` index by the size of the slice contents in bytes.
+ #[inline]
+ fn read_slice(&mut self, count: usize, bytes_per_item: usize) -> CodecResult<&'d [T]> {
+ let num_bytes = bytes_per_item * count;
+ let end = self.pos + num_bytes;
+ if end <= self.data.len() {
+ let v: &'d [T] = unsafe {
+ core::slice::from_raw_parts(self.data[self.pos..end].as_ptr() as *const T, count)
+ };
+ self.pos = end;
+ Ok(v)
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+}
+
+/// Scratch Encoder Data Wrapper - codec internal use only
+#[derive(Debug)]
+pub struct ScratchEncoderData<'d> {
+ data: &'d mut [u8],
+ pos: usize,
+}
+
+impl<'d> ScratchEncoderData<'d> {
+ /// Copy the bytes of a value into the data buffer
+ /// Advances the `pos` index to after the newly-written bytes.
+ #[inline]
+ fn write_type(&mut self, t: &T, num_bytes: usize) -> CodecResult<()> {
+ let end = self.pos + num_bytes;
+ if end <= self.data.len() {
+ let source_bytes: &[u8] = unsafe {
+ core::slice::from_raw_parts(t as *const T as *const u8, num_bytes)
+ };
+ (&mut self.data[self.pos..end]).copy_from_slice(source_bytes);
+ self.pos = end;
+ Ok(())
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+
+ /// Advances the `pos` index by a set number of bytes.
+ #[inline]
+ fn skip_bytes(&mut self, num_bytes: usize) -> CodecResult<()> {
+ let end = self.pos + num_bytes;
+ if end <= self.data.len() {
+ self.pos = end;
+ Ok(())
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+
+ /// Create a struct reference overlaid atop the data buffer
+ /// such that changes to the struct directly edit the buffer.
+ /// Note that the initial content of the struct's fields may be garbage.
+ /// Advances the `pos` index to after the newly-written bytes.
+ #[inline]
+ fn writable_overlay(&mut self, num_bytes: usize) -> CodecResult<&'d mut T> {
+ let end = self.pos + num_bytes;
+ if end <= self.data.len() {
+ let v: &'d mut T = unsafe {
+ let s = self.data.as_ptr().offset(self.pos as isize) as *mut T;
+ &mut *s
+ };
+ self.pos = end;
+ Ok(v)
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+
+ /// Copy the bytes of a value into the data buffer at a specific position
+ /// Does **not** alter the `pos` index.
+ #[inline]
+ fn write_at_position(&mut self, position: usize, t: &T, num_bytes: usize) -> CodecResult<()> {
+ let end = position + num_bytes;
+ if end <= self.data.len() {
+ let source_bytes: &[u8] = unsafe {
+ core::slice::from_raw_parts(t as *const T as *const u8, num_bytes)
+ };
+ (&mut self.data[position..end]).copy_from_slice(source_bytes);
+ Ok(())
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+ /// Create a mutable slice overlaid atop the data buffer directly
+ /// such that changes to the slice contents directly edit the buffer
+ /// Note that the initial content of the slice's members' fields may be garbage.
+ /// Advances the `pos` index to after the region representing the slice.
+ #[inline]
+ fn writable_slice(&mut self, count: usize, bytes_per_item: usize) -> CodecResult<&'d mut [T]> {
+ let end = self.pos + (count * bytes_per_item);
+ if end <= self.data.len() {
+ let v: &'d mut [T] = unsafe {
+ core::slice::from_raw_parts_mut(self.data[self.pos..end].as_mut_ptr() as *mut T, count)
+ };
+ self.pos = end;
+ Ok(v)
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+
+ /// Copy the raw bytes of a slice's contents into the data buffer
+ /// Does **not** encode the length of the slice explicitly into the buffer.
+ /// Advances the `pos` index to after the newly-written slice bytes.
+ #[inline]
+ fn write_slice_without_count(&mut self, t: &[T], bytes_per_item: usize) -> CodecResult<()> {
+ let content_bytes_size = bytes_per_item * t.len();
+ let end = self.pos + content_bytes_size;
+ if end <= self.data.len() {
+ let source_bytes: &[u8] = unsafe {
+ core::slice::from_raw_parts(t.as_ptr() as *const u8, content_bytes_size)
+ };
+ (&mut self.data[self.pos..end]).copy_from_slice(source_bytes);
+ self.pos = end;
+ Ok(())
+ } else {
+ Err(CodecErr::NotEnoughBytes)
+ }
+ }
+}
+
+/// Convenience Either enum
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+pub enum Either {
+ Left(L),
+ Right(R),
+}
+
+/// Enum Side
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(u8)]
+pub enum Side {
+ Buy = 0u8,
+ Sell = 1u8,
+ NullVal = 255u8,
+}
+
+impl Default for Side {
+ fn default() -> Self { Side::NullVal }
+}
+
+/// Enum MsgType
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(u8)]
+pub enum MsgType {
+ Trade = 0u8,
+ Quote = 1u8,
+ NullVal = 255u8,
+}
+
+impl Default for MsgType {
+ fn default() -> Self { MsgType::NullVal }
+}
+
+/// Quote
+#[repr(C, packed)]
+#[derive(Default)]
+pub struct Quote {
+ pub price: u64,
+ pub size: u32,
+ pub flags: u8,
+ pub side: Side,
+}
+
+impl Quote {}
+
+/// Trade
+#[repr(C, packed)]
+#[derive(Default)]
+pub struct Trade {
+ pub price: u64,
+ pub size: u32,
+}
+
+impl Trade {}
+
+/// MessageHeader
+#[repr(C, packed)]
+#[derive(Default)]
+pub struct MessageHeader {
+ pub block_length: u16,
+ pub template_id: u16,
+ pub schema_id: u16,
+ pub version: u16,
+}
+
+impl MessageHeader {}
+
+/// GroupSizeEncoding
+#[repr(C, packed)]
+#[derive(Default)]
+pub struct GroupSizeEncoding {
+ pub block_length: u16,
+ pub num_in_group: u16,
+}
+
+impl GroupSizeEncoding {}
+
+/// VarAsciiEncoding
+#[repr(C, packed)]
+#[derive(Default)]
+pub struct VarAsciiEncoding {
+ pub length: u32,
+ pub var_data: u8,
+}
+
+impl VarAsciiEncoding {}
+
+/// MessageHeader Decoder entry point
+pub fn start_decoding_message_header<'d>(data: &'d [u8]) -> CodecResult<(&'d MessageHeader, ScratchDecoderData<'d>)> {
+ let mut scratch = ScratchDecoderData { data: data, pos: 0 };
+ let v = scratch.read_type::(8)?;
+ Ok((v, scratch))
+}
+
+/// MultiMessage Fixed-size Fields (8 bytes)
+#[repr(C, packed)]
+#[derive(Default)]
+pub struct MultiMessageFields {
+ pub sequence_number: u64,
+}
+
+
+impl MultiMessageFields {}
+
+/// MultiMessage specific Message Header
+#[repr(C, packed)]
+pub struct MultiMessageMessageHeader {
+ pub message_header: MessageHeader
+}
+
+impl MultiMessageMessageHeader {
+ pub const BLOCK_LENGTH: u16 = 8;
+ pub const TEMPLATE_ID: u16 = 1;
+ pub const SCHEMA_ID: u16 = 1;
+ pub const VERSION: u16 = 0;
+}
+
+impl Default for MultiMessageMessageHeader {
+ fn default() -> MultiMessageMessageHeader {
+ MultiMessageMessageHeader {
+ message_header: MessageHeader {
+ block_length: 8u16,
+ template_id: 1u16,
+ schema_id: 1u16,
+ version: 0u16,
+ }
+ }
+ }
+}
+
+/// Group fixed-field member representations
+#[repr(C, packed)]
+#[derive(Default)]
+pub struct MultiMessageMessagesMember {
+ pub timestamp: i64,
+ pub msg_type: MsgType,
+ pub trade: Trade,
+ pub quote: Quote,
+}
+
+impl MultiMessageMessagesMember {}
+
+/// MultiMessageDecoderDone
+pub struct MultiMessageDecoderDone<'d> {
+ scratch: ScratchDecoderData<'d>,
+}
+
+impl<'d> MultiMessageDecoderDone<'d> {
+ /// Returns the number of bytes decoded
+ pub fn unwrap(self) -> usize {
+ self.scratch.pos
+ }
+
+ pub fn wrap(scratch: ScratchDecoderData<'d>) -> MultiMessageDecoderDone<'d> {
+ MultiMessageDecoderDone { scratch: scratch }
+ }
+}
+
+/// symbol variable-length data
+pub struct MultiMessageMessagesSymbolDecoder<'d> {
+ parent: MultiMessageMessagesMemberDecoder<'d>,
+}
+
+impl<'d> MultiMessageMessagesSymbolDecoder<'d> {
+ fn wrap(parent: MultiMessageMessagesMemberDecoder<'d>) -> Self {
+ MultiMessageMessagesSymbolDecoder { parent: parent }
+ }
+ pub fn symbol(mut self) -> CodecResult<(&'d [u8], Either, MultiMessageDecoderDone<'d>>)> {
+ let count = *self.parent.scratch.read_type::(4)?;
+ Ok((self.parent.scratch.read_slice::(count as usize, 1)?, self.parent.after_member()))
+ }
+}
+
+/// MultiMessageMessages Decoder for fields and header
+pub struct MultiMessageMessagesMemberDecoder<'d> {
+ scratch: ScratchDecoderData<'d>,
+ max_index: u16,
+ index: u16,
+}
+
+impl<'d> MultiMessageMessagesMemberDecoder<'d> {
+ fn new(scratch: ScratchDecoderData<'d>, count: u16) -> Self {
+ assert!(count > 0u16);
+ MultiMessageMessagesMemberDecoder {
+ scratch: scratch,
+ max_index: count - 1,
+ index: 0,
+ }
+ }
+
+ pub fn next_messages_member(mut self) -> CodecResult<(&'d MultiMessageMessagesMember, MultiMessageMessagesSymbolDecoder<'d>)> {
+ let v = self.scratch.read_type::(35)?;
+ self.index += 1;
+ Ok((v, MultiMessageMessagesSymbolDecoder::wrap(self)))
+ }
+ #[inline]
+ fn after_member(self) -> Either, MultiMessageDecoderDone<'d>> {
+ if self.index <= self.max_index {
+ Either::Left(self)
+ } else {
+ Either::Right(MultiMessageDecoderDone::wrap(self.scratch))
+ }
+ }
+}
+
+pub struct MultiMessageMessagesHeaderDecoder<'d> {
+ scratch: ScratchDecoderData<'d>,
+}
+
+impl<'d> MultiMessageMessagesHeaderDecoder<'d> {
+ fn wrap(scratch: ScratchDecoderData<'d>) -> Self {
+ MultiMessageMessagesHeaderDecoder { scratch: scratch }
+ }
+ pub fn messages_individually(mut self) -> CodecResult, MultiMessageDecoderDone<'d>>> {
+ let dim = self.scratch.read_type::(4)?;
+ if dim.num_in_group > 0 {
+ Ok(Either::Left(MultiMessageMessagesMemberDecoder::new(self.scratch, dim.num_in_group)))
+ } else {
+ Ok(Either::Right(MultiMessageDecoderDone::wrap(self.scratch)))
+ }
+ }
+}
+
+/// MultiMessage Fixed fields Decoder
+pub struct MultiMessageFieldsDecoder<'d> {
+ scratch: ScratchDecoderData<'d>,
+}
+
+impl<'d> MultiMessageFieldsDecoder<'d> {
+ pub fn wrap(scratch: ScratchDecoderData<'d>) -> MultiMessageFieldsDecoder<'d> {
+ MultiMessageFieldsDecoder { scratch: scratch }
+ }
+ pub fn multi_message_fields(mut self) -> CodecResult<(&'d MultiMessageFields, MultiMessageMessagesHeaderDecoder<'d>)> {
+ let v = self.scratch.read_type::(8)?;
+ Ok((v, MultiMessageMessagesHeaderDecoder::wrap(self.scratch)))
+ }
+}
+
+/// MultiMessageMessageHeaderDecoder
+pub struct MultiMessageMessageHeaderDecoder<'d> {
+ scratch: ScratchDecoderData<'d>,
+}
+
+impl<'d> MultiMessageMessageHeaderDecoder<'d> {
+ pub fn wrap(scratch: ScratchDecoderData<'d>) -> MultiMessageMessageHeaderDecoder<'d> {
+ MultiMessageMessageHeaderDecoder { scratch: scratch }
+ }
+ pub fn header(mut self) -> CodecResult<(&'d MessageHeader, MultiMessageFieldsDecoder<'d>)> {
+ let v = self.scratch.read_type::(8)?;
+ Ok((v, MultiMessageFieldsDecoder::wrap(self.scratch)))
+ }
+}
+
+/// MultiMessage Decoder entry point
+pub fn start_decoding_multi_message<'d>(data: &'d [u8]) -> MultiMessageMessageHeaderDecoder<'d> {
+ MultiMessageMessageHeaderDecoder::wrap(ScratchDecoderData { data: data, pos: 0 })
+}
+
+/// MultiMessageEncoderDone
+pub struct MultiMessageEncoderDone<'d> {
+ scratch: ScratchEncoderData<'d>,
+}
+
+impl<'d> MultiMessageEncoderDone<'d> {
+ /// Returns the number of bytes encoded
+ pub fn unwrap(self) -> usize {
+ self.scratch.pos
+ }
+
+ pub fn wrap(scratch: ScratchEncoderData<'d>) -> MultiMessageEncoderDone<'d> {
+ MultiMessageEncoderDone { scratch: scratch }
+ }
+}
+
+/// symbol variable-length data
+pub struct MultiMessageMessagesSymbolEncoder<'d> {
+ parent: MultiMessageMessagesMemberEncoder<'d>,
+}
+
+impl<'d> MultiMessageMessagesSymbolEncoder<'d> {
+ fn wrap(parent: MultiMessageMessagesMemberEncoder<'d>) -> Self {
+ MultiMessageMessagesSymbolEncoder { parent: parent }
+ }
+ pub fn symbol(mut self, s: &'d [u8]) -> CodecResult {
+ let l = s.len();
+ if l > 4294967294 {
+ return Err(CodecErr::SliceIsLongerThanAllowedBySchema);
+ }
+ // Write data length
+ self.parent.scratch.write_type::(&(l as u32), 4)?; // group length
+ self.parent.scratch.write_slice_without_count::(s, 1)?;
+ Ok(self.parent)
+ }
+}
+
+/// MultiMessageMessages Encoder for fields and header
+pub struct MultiMessageMessagesMemberEncoder<'d> {
+ scratch: ScratchEncoderData<'d>,
+ count_write_pos: usize,
+ count: u16,
+}
+
+impl<'d> MultiMessageMessagesMemberEncoder<'d> {
+ #[inline]
+ fn new(scratch: ScratchEncoderData<'d>, count_write_pos: usize) -> Self {
+ MultiMessageMessagesMemberEncoder {
+ scratch: scratch,
+ count_write_pos: count_write_pos,
+ count: 0,
+ }
+ }
+
+ #[inline]
+ pub fn next_messages_member(mut self, fields: &MultiMessageMessagesMember) -> CodecResult> {
+ self.scratch.write_type::(fields, 35)?; // block length
+ self.count += 1;
+ Ok(MultiMessageMessagesSymbolEncoder::wrap(self))
+ }
+ #[inline]
+ pub fn done_with_messages(mut self) -> CodecResult> {
+ self.scratch.write_at_position::(self.count_write_pos, &self.count, 2)?;
+ Ok(MultiMessageEncoderDone::wrap(self.scratch))
+ }
+}
+
+pub struct MultiMessageMessagesHeaderEncoder<'d> {
+ scratch: ScratchEncoderData<'d>,
+}
+
+impl<'d> MultiMessageMessagesHeaderEncoder<'d> {
+ #[inline]
+ fn wrap(scratch: ScratchEncoderData<'d>) -> Self {
+ MultiMessageMessagesHeaderEncoder { scratch: scratch }
+ }
+ #[inline]
+ pub fn messages_individually(mut self) -> CodecResult> {
+ self.scratch.write_type::(&35u16, 2)?; // block length
+ let count_pos = self.scratch.pos;
+ self.scratch.write_type::(&0, 2)?; // preliminary group member count
+ Ok(MultiMessageMessagesMemberEncoder::new(self.scratch, count_pos))
+ }
+}
+
+/// MultiMessage Fixed fields Encoder
+pub struct MultiMessageFieldsEncoder<'d> {
+ scratch: ScratchEncoderData<'d>,
+}
+
+impl<'d> MultiMessageFieldsEncoder<'d> {
+ pub fn wrap(scratch: ScratchEncoderData<'d>) -> MultiMessageFieldsEncoder<'d> {
+ MultiMessageFieldsEncoder { scratch: scratch }
+ }
+
+ /// Create a mutable struct reference overlaid atop the data buffer
+ /// such that changes to the struct directly edit the buffer.
+ /// Note that the initial content of the struct's fields may be garbage.
+ pub fn multi_message_fields(mut self) -> CodecResult<(&'d mut MultiMessageFields, MultiMessageMessagesHeaderEncoder<'d>)> {
+ let v = self.scratch.writable_overlay::(8 + 0)?;
+ Ok((v, MultiMessageMessagesHeaderEncoder::wrap(self.scratch)))
+ }
+
+ /// Copy the bytes of a value into the data buffer
+ pub fn multi_message_fields_copy(mut self, t: &MultiMessageFields) -> CodecResult> {
+ self.scratch.write_type::(t, 8)?;
+ Ok(MultiMessageMessagesHeaderEncoder::wrap(self.scratch))
+ }
+}
+
+/// MultiMessageMessageHeaderEncoder
+pub struct MultiMessageMessageHeaderEncoder<'d> {
+ scratch: ScratchEncoderData<'d>,
+}
+
+impl<'d> MultiMessageMessageHeaderEncoder<'d> {
+ pub fn wrap(scratch: ScratchEncoderData<'d>) -> MultiMessageMessageHeaderEncoder<'d> {
+ MultiMessageMessageHeaderEncoder { scratch: scratch }
+ }
+
+ /// Create a mutable struct reference overlaid atop the data buffer
+ /// such that changes to the struct directly edit the buffer.
+ /// Note that the initial content of the struct's fields may be garbage.
+ pub fn header(mut self) -> CodecResult<(&'d mut MessageHeader, MultiMessageFieldsEncoder<'d>)> {
+ let v = self.scratch.writable_overlay::(8 + 0)?;
+ Ok((v, MultiMessageFieldsEncoder::wrap(self.scratch)))
+ }
+
+ /// Copy the bytes of a value into the data buffer
+ pub fn header_copy(mut self, t: &MessageHeader) -> CodecResult> {
+ self.scratch.write_type::(t, 8)?;
+ Ok(MultiMessageFieldsEncoder::wrap(self.scratch))
+ }
+}
+
+/// MultiMessage Encoder entry point
+pub fn start_encoding_multi_message<'d>(data: &'d mut [u8]) -> MultiMessageMessageHeaderEncoder<'d> {
+ MultiMessageMessageHeaderEncoder::wrap(ScratchEncoderData { data: data, pos: 0 })
+}