gin-tonic-core 0.7.0

core functions for gin-tonic
Documentation
use std::hash::Hash;

use indexmap::IndexMap;

use crate::{
    Decode, Encode, Map, RawMessageView, Scalar, Tag, decoder::Decoder, encoder::SizeHint,
    error::ProtoError, wire_types::WIRE_TYPE_LENGTH_ENCODED,
};

pub struct KeyValuePairView<'p, RustKey, RustValue> {
    pub key: &'p RustKey,
    pub value: &'p RustValue,
}

impl<'p, RustKey, RustValue> KeyValuePairView<'p, RustKey, RustValue> {
    fn size_hint<ProtobufKey, ProtobufValue>(&self) -> usize
    where
        RustKey: Scalar<ProtobufKey>,
        RustValue: Scalar<ProtobufValue>,
    {
        let mut hint = SizeHint::default();
        self.encode(&mut hint);
        hint.size()
    }

    fn encode<ProtobufKey, ProtobufValue>(&self, encoder: &mut impl Encode)
    where
        RustKey: Scalar<ProtobufKey>,
        RustValue: Scalar<ProtobufValue>,
    {
        let tag = Tag::from_parts(1u32, <RustKey as Scalar<ProtobufKey>>::WIRE_TYPE);
        encoder.encode_tag(tag);
        <RustKey as Scalar<ProtobufKey>>::encode(self.key, encoder);

        let tag = Tag::from_parts(2u32, <RustValue as Scalar<ProtobufValue>>::WIRE_TYPE);
        encoder.encode_tag(tag);
        <RustValue as Scalar<ProtobufValue>>::encode(self.value, encoder);
    }
}

pub struct KeyValuePairOwned<RustKey, RustValue> {
    pub key: RustKey,
    pub value: RustValue,
}

impl<RustKey, RustValue> KeyValuePairOwned<RustKey, RustValue> {
    pub fn decode<ProtobufKey, ProtobufValue>(buffer: &[u8]) -> Result<Self, ProtoError>
    where
        RustKey: Scalar<ProtobufKey>,
        RustValue: Scalar<ProtobufValue>,
    {
        let raw_message = RawMessageView::try_from(buffer)?;

        let tag = Tag::from_parts(1u32, <RustKey as Scalar<ProtobufKey>>::WIRE_TYPE);
        let bytes = raw_message
            .tag_data(tag)
            .next_back()
            .ok_or(ProtoError::MissingField(1))?;
        let mut decoder = Decoder::new(bytes);
        let key = <RustKey as Scalar<ProtobufKey>>::decode(&mut decoder)?;

        let tag = Tag::from_parts(2u32, <RustValue as Scalar<ProtobufValue>>::WIRE_TYPE);
        let bytes = raw_message
            .tag_data(tag)
            .next_back()
            .ok_or(ProtoError::MissingField(2))?;
        let mut decoder = Decoder::new(bytes);
        let value = <RustValue as Scalar<ProtobufValue>>::decode(&mut decoder)?;

        Ok(Self { key, value })
    }
}

impl<RustKey, ProtobufKey, RustValue, ProtobufValue> Map<ProtobufKey, ProtobufValue>
    for IndexMap<RustKey, RustValue>
where
    RustKey: Scalar<ProtobufKey> + Hash + Eq,
    RustValue: Scalar<ProtobufValue>,
{
    fn encode(&self, field_number: u32, encoder: &mut impl Encode) {
        for (key, value) in self.iter() {
            encoder.encode_tag(Tag::from_parts(field_number, WIRE_TYPE_LENGTH_ENCODED));

            let pair = KeyValuePairView { key, value };

            encoder.encode_uint64(pair.size_hint() as u64);
            pair.encode(encoder);
        }
    }

    fn decode<'buf>(
        field_number: u32,
        raw_message: &'buf RawMessageView<'buf>,
    ) -> Result<Self, ProtoError>
    where
        Self: Sized,
    {
        let mut map = Self::new();

        for buffer in raw_message.tag_data(Tag::from_parts(field_number, WIRE_TYPE_LENGTH_ENCODED))
        {
            let mut decoder = Decoder::new(buffer);
            let _size = decoder.decode_uint64()?;

            let pair = KeyValuePairOwned::<RustKey, RustValue>::decode::<ProtobufKey, ProtobufValue>(
                decoder.buffer(),
            )?;
            map.insert(pair.key, pair.value);
        }

        Ok(map)
    }
}