Skip to main content

layer_tl_types/
serialize.rs

1//! The [`Serializable`] trait and its implementations for primitive TL types.
2//!
3//! Encoding follows the [MTProto Binary Serialization] spec.
4//!
5//! [MTProto Binary Serialization]: https://core.telegram.org/mtproto/serialize
6
7/// Serialize `self` into TL binary format.
8pub trait Serializable {
9    /// Appends the serialized form of `self` to `buf`.
10    fn serialize(&self, buf: &mut impl Extend<u8>);
11
12    /// Convenience: allocate a fresh `Vec<u8>` and serialize into it.
13    fn to_bytes(&self) -> Vec<u8> {
14        let mut v = Vec::new();
15        self.serialize(&mut v);
16        v
17    }
18}
19
20// bool
21
22/// `true`  → `boolTrue#997275b5`
23/// `false` → `boolFalse#bc799737`
24impl Serializable for bool {
25    fn serialize(&self, buf: &mut impl Extend<u8>) {
26        let id: u32 = if *self { 0x997275b5 } else { 0xbc799737 };
27        id.serialize(buf);
28    }
29}
30
31// integers
32
33impl Serializable for i32 {
34    fn serialize(&self, buf: &mut impl Extend<u8>) {
35        buf.extend(self.to_le_bytes());
36    }
37}
38
39impl Serializable for u32 {
40    fn serialize(&self, buf: &mut impl Extend<u8>) {
41        buf.extend(self.to_le_bytes());
42    }
43}
44
45impl Serializable for i64 {
46    fn serialize(&self, buf: &mut impl Extend<u8>) {
47        buf.extend(self.to_le_bytes());
48    }
49}
50
51impl Serializable for f64 {
52    fn serialize(&self, buf: &mut impl Extend<u8>) {
53        buf.extend(self.to_le_bytes());
54    }
55}
56
57impl Serializable for [u8; 16] {
58    fn serialize(&self, buf: &mut impl Extend<u8>) {
59        buf.extend(self.iter().copied());
60    }
61}
62
63impl Serializable for [u8; 32] {
64    fn serialize(&self, buf: &mut impl Extend<u8>) {
65        buf.extend(self.iter().copied());
66    }
67}
68
69// strings / bytes
70
71/// TL string encoding: a length-prefixed, 4-byte aligned byte string.
72///
73/// * If `len ≤ 253`: `[len as u8][data][0-padding to align to 4 bytes]`
74/// * If `len ≥ 254`: `[0xfe][len as 3 LE bytes][data][0-padding]`
75impl Serializable for &[u8] {
76    fn serialize(&self, buf: &mut impl Extend<u8>) {
77        let len = self.len();
78        let (header_len, header): (usize, Vec<u8>) = if len <= 253 {
79            (1, vec![len as u8])
80        } else {
81            (
82                4,
83                vec![
84                    0xfe,
85                    (len & 0xff) as u8,
86                    ((len >> 8) & 0xff) as u8,
87                    ((len >> 16) & 0xff) as u8,
88                ],
89            )
90        };
91
92        let total = header_len + len;
93        let padding = (4 - (total % 4)) % 4;
94
95        buf.extend(header);
96        buf.extend(self.iter().copied());
97        buf.extend(std::iter::repeat_n(0u8, padding));
98    }
99}
100
101impl Serializable for Vec<u8> {
102    fn serialize(&self, buf: &mut impl Extend<u8>) {
103        self.as_slice().serialize(buf);
104    }
105}
106
107impl Serializable for String {
108    fn serialize(&self, buf: &mut impl Extend<u8>) {
109        self.as_bytes().serialize(buf);
110    }
111}
112
113// vectors
114
115/// Boxed `Vector<T>`: prefixed with constructor ID `0x1cb5c415`.
116impl<T: Serializable> Serializable for Vec<T> {
117    fn serialize(&self, buf: &mut impl Extend<u8>) {
118        0x1cb5c415u32.serialize(buf);
119        (self.len() as i32).serialize(buf);
120        for item in self {
121            item.serialize(buf);
122        }
123    }
124}
125
126/// Bare `vector<T>`: just a count followed by items, no constructor ID.
127impl<T: Serializable> Serializable for crate::RawVec<T> {
128    fn serialize(&self, buf: &mut impl Extend<u8>) {
129        (self.0.len() as i32).serialize(buf);
130        for item in &self.0 {
131            item.serialize(buf);
132        }
133    }
134}
135
136// Option
137
138/// Optional parameters are handled by flags; when `Some`, serialize the value.
139/// When `None`, nothing is written (the flags word already encodes absence).
140impl<T: Serializable> Serializable for Option<T> {
141    fn serialize(&self, buf: &mut impl Extend<u8>) {
142        if let Some(v) = self {
143            v.serialize(buf);
144        }
145    }
146}