real-logic / simple-binary-encoding

Simple Binary Encoding (SBE) - High Performance Message Codec
Apache License 2.0
3.12k stars 524 forks source link

[Rust] cumulate offset of header and message_header_codec::ENCODED_LENGTH in generated Decoder::header method #987

Closed wbprime closed 4 weeks ago

wbprime commented 7 months ago

Code generator for rust would generate a header method for Decoder (see following)

impl<'a> DonotUsePlaceHolderDecoder<'a> {
        pub fn wrap(
            mut self,
            buf: ReadBuf<'a>,
            offset: usize,
            acting_block_length: u16,
            acting_version: u16,
        ) -> Self {
            let limit = offset + acting_block_length as usize;
            self.buf = buf;
            self.initial_offset = offset;
            self.offset = offset;
            self.limit = limit;
            self.acting_block_length = acting_block_length;
            self.acting_version = acting_version;
            self
        }

        #[inline]
        pub fn encoded_length(&self) -> usize {
            self.limit - self.offset
        }

        pub fn header(self, mut header: MessageHeaderDecoder<ReadBuf<'a>>) -> Self {
            debug_assert_eq!(SBE_TEMPLATE_ID, header.template_id());
            let acting_block_length = header.block_length();
            let acting_version = header.version();

            self.wrap(
                header.parent().unwrap(),
                message_header_codec::ENCODED_LENGTH,
                acting_block_length,
                acting_version,
            )
        }
}

The header method take a header decoder and call wrap method, passing message_header_codec::ENCODED_LENGTH as offset.

Considering a header decoder may be wraped with a none-zero offset header_off, header method should wrap with header_off + message_header_codec::ENCODED_LENGTH. To support this functionality, a MessageHeaderDecoder should expose its offset via, say get_limit() or something else.

mward commented 7 months ago

@wbprime just to clarify, you are suggesting that the MessageHeaderDecoder is generated with additional function:

pub fn get_limit(&self) -> usize {
  self.limit + message_header_code::ENCODED_LENGTH
} 

and then the generated header functions be updated to:

pub fn header(self, mut header: MessageHeaderDecoder<ReadBuf<'a>>) -> Self {
  debug_assert_eq!(SBE_TEMPLATE_ID, header.template_id());
  let acting_block_length = header.block_length();
  let acting_version = header.version();
  let limit = header.get_limit();

  self.wrap(
    header.parent().unwrap(),
    limit,
    acting_block_length,
    acting_version,
  )
}
wbprime commented 7 months ago

Yes, decoder wrap offset should be set to header offset + message_header_codec::ENCODED_LENGTH when wrapping using a header I suppose.

The generated header functions should be something like:

pub fn header(self, mut header: MessageHeaderDecoder<ReadBuf<'a>>) -> Self {
  debug_assert_eq!(SBE_TEMPLATE_ID, header.template_id());
  let acting_block_length = header.block_length();
  let acting_version = header.version();
  let limit = header.get_limit();

  self.wrap(
    header.parent().unwrap(),
    // limit, 
    limit + message_header_codec::ENCODED_LENGTH,
    acting_block_length,
    acting_version,
  )
}
wbprime commented 7 months ago

Yes, decoder wrap offset should be set to header offset + message_header_codec::ENCODED_LENGTH when wrapping using a header I suppose.

The generated header functions should be something like:

pub fn header(self, mut header: MessageHeaderDecoder<ReadBuf<'a>>) -> Self {
  debug_assert_eq!(SBE_TEMPLATE_ID, header.template_id());
  let acting_block_length = header.block_length();
  let acting_version = header.version();
  let limit = header.get_limit();

  self.wrap(
    header.parent().unwrap(),
    // limit, 
    limit + message_header_codec::ENCODED_LENGTH,
    acting_block_length,
    acting_version,
  )
}