protospec_build/prelude/
var.rs

1use crate::{emit_type_ref, PartialType, PartialScalarType};
2
3use super::*;
4
5pub struct VarInt {
6    scalar_type: ScalarType,
7    unsigned: Type,
8}
9
10impl VarInt {
11    pub fn new(scalar_type: ScalarType) -> Self {
12        VarInt {
13            scalar_type,
14            unsigned: Type::Scalar(match scalar_type {
15                x if !x.is_signed() => x,
16                ScalarType::I8 => ScalarType::U8,
17                ScalarType::I16 => ScalarType::U16,
18                ScalarType::I32 => ScalarType::U32,
19                ScalarType::I64 => ScalarType::U64,
20                ScalarType::I128 => ScalarType::U128,
21                _ => unimplemented!(),
22            }),
23        }
24    }
25}
26
27impl ForeignType for VarInt {
28    fn assignable_from(&self, type_: &Type) -> bool {
29        Type::Scalar(self.scalar_type).assignable_from(type_)
30    }
31
32    fn assignable_from_partial(&self, type_: &PartialType) -> bool {
33        match type_ {
34            PartialType::Type(t) => self.assignable_from(t),
35            PartialType::Scalar(PartialScalarType::Some(scalar)) |
36            PartialType::Scalar(PartialScalarType::Defaults(scalar))
37                => self.assignable_from(&Type::Scalar(*scalar)),
38            _ => false,
39        }
40    }
41
42    fn assignable_to_partial(&self, type_: &PartialType) -> bool {
43        match type_ {
44            PartialType::Type(t) => self.assignable_to(t),
45            PartialType::Any => true,
46            PartialType::Scalar(PartialScalarType::Some(scalar)) => self.assignable_from(&Type::Scalar(*scalar)),
47            PartialType::Scalar(_) => true,
48            _ => false,
49        }
50    }
51
52    fn assignable_to(&self, type_: &Type) -> bool {
53        type_.assignable_from(&Type::Scalar(self.scalar_type))
54    }
55
56    fn type_ref(&self) -> TokenStream {
57        emit_type_ref(&Type::Scalar(self.scalar_type))
58    }
59
60    fn decoding_gen(
61        &self,
62        source: TokenStream,
63        output_ref: TokenStream,
64        _arguments: Vec<TokenStream>,
65        is_async: bool,
66    ) -> TokenStream {
67        let inner = self.type_ref();
68        let end = (self.scalar_type.size() as f64 / 7.0).ceil() as usize;
69        let inner_unsigned = emit_type_ref(&self.unsigned);
70        let async_ = map_async(is_async);
71        quote! {
72            let #output_ref = {
73                let mut i = 0usize;
74                let mut buf = [0xffu8; 1];
75                let mut output: #inner = 0;
76                while (buf[0] & 128) == 128 {
77                    #source.read_exact(&mut buf[..])#async_?;
78                    output |= ((buf[0] as #inner_unsigned & 127) << (i * 7)) as #inner;
79                    i += 1;
80                    if i > #end {
81                        break;
82                    }
83                }
84                output
85            };
86        }
87    }
88
89    fn encoding_gen(
90        &self,
91        target: TokenStream,
92        field_ref: TokenStream,
93        _arguments: Vec<TokenStream>,
94        is_async: bool,
95    ) -> TokenStream {
96        let inner_unsigned = emit_type_ref(&self.unsigned);
97        let async_ = map_async(is_async);
98        quote! {
99            {
100                let mut value = #field_ref.clone() as #inner_unsigned;
101                while (value & !0b1111111) != 0 {
102                    #target.write_all(&[(value as u8 & 127) | 128])#async_?;
103                    value >>= 7;
104                }
105                #target.write_all(&[value as u8])#async_?;
106            }
107        }
108    }
109
110    fn arguments(&self) -> Vec<TypeArgument> {
111        vec![]
112    }
113
114    fn can_receive_auto(&self) -> Option<ScalarType> {
115        Some(self.scalar_type)
116    }
117}