tl_proto/
primitive.rs

1use crate::traits::*;
2
3impl TlRead<'_> for () {
4    type Repr = Bare;
5
6    fn read_from(_packet: &mut &'_ [u8]) -> TlResult<Self> {
7        Ok(())
8    }
9}
10
11impl TlWrite for () {
12    type Repr = Bare;
13
14    #[inline]
15    fn max_size_hint(&self) -> usize {
16        0
17    }
18
19    #[inline]
20    fn write_to<P>(&self, _packet: &mut P)
21    where
22        P: TlPacket,
23    {
24    }
25}
26
27impl TlRead<'_> for bool {
28    type Repr = Boxed;
29
30    fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
31        match u32::read_from(packet) {
32            Ok(BOOL_TRUE) => Ok(true),
33            Ok(BOOL_FALSE) => Ok(false),
34            Ok(_) => Err(TlError::UnknownConstructor),
35            Err(e) => Err(e),
36        }
37    }
38}
39
40impl TlWrite for bool {
41    type Repr = Boxed;
42
43    #[inline(always)]
44    fn max_size_hint(&self) -> usize {
45        std::mem::size_of::<u32>()
46    }
47
48    #[inline(always)]
49    fn write_to<T>(&self, packet: &mut T)
50    where
51        T: TlPacket,
52    {
53        packet.write_u32(if *self { BOOL_TRUE } else { BOOL_FALSE })
54    }
55}
56
57macro_rules! impl_read_from_packet(
58    ($ty:ty) => {
59        impl TlRead<'_> for $ty {
60            type Repr = Bare;
61
62            #[inline(always)]
63            fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
64                match packet.split_first_chunk() {
65                    Some((first, tail)) => {
66                        let value = <$ty>::from_le_bytes(*first);
67                        *packet = tail;
68                        Ok(value)
69                    }
70                    None => Err(TlError::UnexpectedEof),
71                }
72            }
73        }
74    }
75);
76
77impl_read_from_packet!(u32);
78
79impl TlWrite for u32 {
80    type Repr = Bare;
81
82    #[inline(always)]
83    fn max_size_hint(&self) -> usize {
84        std::mem::size_of::<Self>()
85    }
86
87    #[inline(always)]
88    fn write_to<T>(&self, packet: &mut T)
89    where
90        T: TlPacket,
91    {
92        packet.write_u32(*self)
93    }
94}
95
96impl_read_from_packet!(i32);
97
98impl TlWrite for i32 {
99    type Repr = Bare;
100
101    #[inline(always)]
102    fn max_size_hint(&self) -> usize {
103        std::mem::size_of::<Self>()
104    }
105
106    #[inline(always)]
107    fn write_to<T>(&self, packet: &mut T)
108    where
109        T: TlPacket,
110    {
111        packet.write_i32(*self)
112    }
113}
114
115impl_read_from_packet!(u64);
116
117impl TlWrite for u64 {
118    type Repr = Bare;
119
120    #[inline(always)]
121    fn max_size_hint(&self) -> usize {
122        std::mem::size_of::<Self>()
123    }
124
125    #[inline(always)]
126    fn write_to<T>(&self, packet: &mut T)
127    where
128        T: TlPacket,
129    {
130        packet.write_u64(*self)
131    }
132}
133
134impl_read_from_packet!(i64);
135
136impl TlWrite for i64 {
137    type Repr = Bare;
138
139    #[inline(always)]
140    fn max_size_hint(&self) -> usize {
141        std::mem::size_of::<Self>()
142    }
143
144    #[inline(always)]
145    fn write_to<T>(&self, packet: &mut T)
146    where
147        T: TlPacket,
148    {
149        packet.write_i64(*self)
150    }
151}
152
153impl_read_from_packet!(f64);
154
155impl TlWrite for f64 {
156    type Repr = Bare;
157
158    #[inline(always)]
159    fn max_size_hint(&self) -> usize {
160        std::mem::size_of::<Self>()
161    }
162
163    #[inline(always)]
164    fn write_to<T>(&self, packet: &mut T)
165    where
166        T: TlPacket,
167    {
168        packet.write_u64(convert_f64(self))
169    }
170}
171
172#[inline(always)]
173fn convert_f64(f: &f64) -> u64 {
174    const SIGN_MASK: u64 = 0x8000000000000000u64;
175    const EXP_MASK: u64 = 0x7ff0000000000000u64;
176    const MAN_MASK: u64 = 0x000fffffffffffffu64;
177
178    const CANONICAL_NAN_BITS: u64 = 0x7ff8000000000000u64;
179    const CANONICAL_ZERO_BITS: u64 = 0x0u64;
180
181    if f.is_nan() {
182        return CANONICAL_NAN_BITS;
183    }
184
185    let bits = f.to_bits();
186
187    let sign = if bits >> 63 == 0 { 1i8 } else { -1 };
188    let mut exp = ((bits >> 52) & 0x7ff) as i16;
189    let man = if exp == 0 {
190        (bits & 0xfffffffffffff) << 1
191    } else {
192        (bits & 0xfffffffffffff) | 0x10000000000000
193    };
194
195    if man == 0 {
196        return CANONICAL_ZERO_BITS;
197    }
198
199    // Exponent bias + mantissa shift
200    exp -= 1023 + 52;
201
202    let exp_u64 = exp as u64;
203    let sign_u64 = u64::from(sign > 0);
204    (man & MAN_MASK) | ((exp_u64 << 52) & EXP_MASK) | ((sign_u64 << 63) & SIGN_MASK)
205}
206
207const BOOL_FALSE: u32 = 0xbc799737;
208const BOOL_TRUE: u32 = 0x997275b5;
209
210macro_rules! impl_non_zero {
211    ($($ty:ty => ($write_method:ident, $read_ty:ty)),*$(,)?) => {
212        $(
213        impl TlWrite for $ty {
214            type Repr = Bare;
215
216            #[inline(always)]
217            fn max_size_hint(&self) -> usize {
218                std::mem::size_of::<Self>()
219            }
220
221            #[inline(always)]
222            fn write_to<T>(&self, packet: &mut T)
223            where
224                T: TlPacket,
225            {
226                packet.$write_method(self.get())
227            }
228        }
229
230        impl TlRead<'_> for $ty {
231            type Repr = Bare;
232
233            #[inline(always)]
234            fn read_from(packet: &mut &'_ [u8]) -> TlResult<Self> {
235                match <$ty>::new(<$read_ty>::read_from(packet)?) {
236                    Some(value) => Ok(value),
237                    None => Err(TlError::InvalidData),
238                }
239            }
240        }
241
242        )*
243    };
244}
245
246impl_non_zero! {
247    std::num::NonZeroU32 => (write_u32, u32),
248    std::num::NonZeroI32 => (write_i32, i32),
249    std::num::NonZeroU64 => (write_u64, u64),
250    std::num::NonZeroI64 => (write_i64, i64),
251}
252
253#[cfg(test)]
254mod test {
255    use super::*;
256
257    #[test]
258    fn write_non_zero() {
259        macro_rules! decl_writes {
260            ($($ty:ty => [$($lit:expr),*$(,)?]),*$(,)?) => {
261                $($(assert_eq!(crate::serialize(<$ty>::new($lit).unwrap()), $lit.to_le_bytes());)*)*
262            };
263        }
264
265        decl_writes! {
266            std::num::NonZeroU32 => [1u32, 123u32, u32::MAX],
267            std::num::NonZeroI32 => [-123i32, 123i32, i32::MIN, i32::MAX],
268            std::num::NonZeroU64 => [1u64, 123u64, u64::MAX],
269            std::num::NonZeroI64 => [-123i64, 123i64, i64::MIN, i64::MAX]
270        }
271    }
272
273    #[test]
274    fn read_non_zero() {
275        // u32
276        assert!(matches!(
277            std::num::NonZeroU32::read_from(&mut [0, 0].as_ref()).unwrap_err(),
278            TlError::UnexpectedEof
279        ));
280        assert!(matches!(
281            std::num::NonZeroU32::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
282            TlError::InvalidData
283        ));
284        let mut packet: &[u8] = &[123, 0, 0, 0];
285        assert_eq!(
286            std::num::NonZeroU32::read_from(&mut packet).unwrap(),
287            std::num::NonZeroU32::new(123).unwrap(),
288        );
289        assert!(packet.is_empty());
290
291        // i32
292        assert!(matches!(
293            std::num::NonZeroI32::read_from(&mut [0, 0].as_ref()).unwrap_err(),
294            TlError::UnexpectedEof
295        ));
296        assert!(matches!(
297            std::num::NonZeroI32::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
298            TlError::InvalidData
299        ));
300        let mut packet: &[u8] = &[0xfe, 0xff, 0xff, 0xff];
301        assert_eq!(
302            std::num::NonZeroI32::read_from(&mut packet).unwrap(),
303            std::num::NonZeroI32::new(-2).unwrap(),
304        );
305        assert!(packet.is_empty());
306
307        // u64
308        assert!(matches!(
309            std::num::NonZeroU64::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
310            TlError::UnexpectedEof
311        ));
312        assert!(matches!(
313            std::num::NonZeroU64::read_from(&mut [0, 0, 0, 0, 0, 0, 0, 0].as_ref()).unwrap_err(),
314            TlError::InvalidData
315        ));
316        let mut packet: &[u8] = &[123, 0, 0, 0, 0, 0, 0, 0];
317        assert_eq!(
318            std::num::NonZeroU64::read_from(&mut packet).unwrap(),
319            std::num::NonZeroU64::new(123).unwrap(),
320        );
321        assert!(packet.is_empty());
322
323        // i64
324        assert!(matches!(
325            std::num::NonZeroI64::read_from(&mut [0, 0, 0, 0].as_ref()).unwrap_err(),
326            TlError::UnexpectedEof
327        ));
328
329        assert!(matches!(
330            std::num::NonZeroI64::read_from(&mut [0, 0, 0, 0, 0, 0, 0, 0].as_ref()).unwrap_err(),
331            TlError::InvalidData
332        ));
333        let mut packet: &[u8] = &[0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
334        assert_eq!(
335            std::num::NonZeroI64::read_from(&mut packet,).unwrap(),
336            std::num::NonZeroI64::new(-2).unwrap(),
337        );
338        assert!(packet.is_empty());
339    }
340}