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            (4, vec![
82                0xfe,
83                (len & 0xff) as u8,
84                ((len >> 8) & 0xff) as u8,
85                ((len >> 16) & 0xff) as u8,
86            ])
87        };
88
89        let total = header_len + len;
90        let padding = (4 - (total % 4)) % 4;
91
92        buf.extend(header);
93        buf.extend(self.iter().copied());
94        buf.extend(std::iter::repeat(0u8).take(padding));
95    }
96}
97
98impl Serializable for Vec<u8> {
99    fn serialize(&self, buf: &mut impl Extend<u8>) {
100        self.as_slice().serialize(buf);
101    }
102}
103
104impl Serializable for String {
105    fn serialize(&self, buf: &mut impl Extend<u8>) {
106        self.as_bytes().serialize(buf);
107    }
108}
109
110// ─── vectors ─────────────────────────────────────────────────────────────────
111
112/// Boxed `Vector<T>` — prefixed with constructor ID `0x1cb5c415`.
113impl<T: Serializable> Serializable for Vec<T> {
114    fn serialize(&self, buf: &mut impl Extend<u8>) {
115        0x1cb5c415u32.serialize(buf);
116        (self.len() as i32).serialize(buf);
117        for item in self { item.serialize(buf); }
118    }
119}
120
121/// Bare `vector<T>` — just a count followed by items, no constructor ID.
122impl<T: Serializable> Serializable for crate::RawVec<T> {
123    fn serialize(&self, buf: &mut impl Extend<u8>) {
124        (self.0.len() as i32).serialize(buf);
125        for item in &self.0 { item.serialize(buf); }
126    }
127}
128
129// ─── Option ──────────────────────────────────────────────────────────────────
130
131/// Optional parameters are handled by flags; when `Some`, serialize the value.
132/// When `None`, nothing is written (the flags word already encodes absence).
133impl<T: Serializable> Serializable for Option<T> {
134    fn serialize(&self, buf: &mut impl Extend<u8>) {
135        if let Some(v) = self { v.serialize(buf); }
136    }
137}