rsocket / rsocket-py

RSocket implementation in Python
MIT License
76 stars 23 forks source link

CompositeMetadata Metadata Length is one byte less than real length #255

Closed sigusr1 closed 1 week ago

sigusr1 commented 1 week ago

Any one can tell me why encoding_length - 1

https://github.com/rsocket/rsocket-py/blob/ae62f6222206db9394e224bd4a519fbd800ed3aa/rsocket/frame_helpers.py#L49

For example, if input of serialize_128max_value is [0x12, 0x34, 0x56], the returned value is [0x02, 0x12, 0x34, 0x56], does this meet rsocket's requirements


def serialize_128max_value(encoding: bytes) -> bytes:
    encoding_length = len(encoding)
    encoded_encoding_length = encoding_length - 1  # mime length cannot be 0

    if encoded_encoding_length > 0b1111111:
        raise RSocketMimetypeTooLong(encoding)

    serialized = ((0 << 7) | encoded_encoding_length & 0b1111111).to_bytes(1, 'big')
    serialized += encoding
    return serialized
jell-o-fishi commented 1 week ago

If i remember correctly:

The mime length is encoded as 7 bits. the values which can be encoded in 7 bits are 0 to 127. since the mime-type length cannot be 0 (according to spec) , this value range can be shifted to actually be 1 to 128 by mapping the value to the range 0 to 127, and then mapping it back when decoding. this is the -1 and +1 which happens in the code.

hence the 2 variables encoded_encoding_length and encoding_length. there can be a better naming convention for this in order for the code to be more clear.

The reverse of this is at the following method, with the same comment of "mime length cannot be 0".

https://github.com/rsocket/rsocket-py/blob/ae62f6222206db9394e224bd4a519fbd800ed3aa/rsocket/helpers.py#L106

def parse_well_known_encoding(buffer: bytes, encoding_name_provider: Callable[[int], V]) -> Tuple[bytes, int]:
    is_known_mime_id, mime_length_or_type = parse_type(buffer)

    if is_known_mime_id:
        metadata_encoding = encoding_name_provider(mime_length_or_type)
        offset = 1
    else:
        real_mime_type_length = mime_length_or_type + 1  # mime length cannot be 0
        metadata_encoding = bytes(buffer[1:1 + real_mime_type_length])
        offset = 1 + real_mime_type_length

    return metadata_encoding, offset
sigusr1 commented 1 week ago

If i remember correctly:

The mime length is encoded as 7 bits. the values which can be encoded in 7 bits are 0 to 127. since the mime-type length cannot be 0 (according to spec) , this value range can be shifted to actually be 1 to 128 by mapping the value to the range 0 to 127, and then mapping it back when decoding. this is the -1 and +1 which happens in the code.

hence the 2 variables encoded_encoding_length and encoding_length. there can be a better naming convention for this in order for the code to be more clear.

The reverse of this is at the following method, with the same comment of "mime length cannot be 0".

https://github.com/rsocket/rsocket-py/blob/ae62f6222206db9394e224bd4a519fbd800ed3aa/rsocket/helpers.py#L106

def parse_well_known_encoding(buffer: bytes, encoding_name_provider: Callable[[int], V]) -> Tuple[bytes, int]:
    is_known_mime_id, mime_length_or_type = parse_type(buffer)

    if is_known_mime_id:
        metadata_encoding = encoding_name_provider(mime_length_or_type)
        offset = 1
    else:
        real_mime_type_length = mime_length_or_type + 1  # mime length cannot be 0
        metadata_encoding = bytes(buffer[1:1 + real_mime_type_length])
        offset = 1 + real_mime_type_length

    return metadata_encoding, offset

@jell-o-fishi Thanks for your reply, I get it. ^_^