Skip to main content

ferogram_tl_types/
deserialize.rs

1// Copyright (c) Ankit Chaubey <ankitchaubey.dev@gmail.com>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3//
4// ferogram: async Telegram MTProto client in Rust
5// https://github.com/ankit-chaubey/ferogram
6//
7// Based on layer: https://github.com/ankit-chaubey/layer
8// Follows official Telegram client behaviour (tdesktop, TDLib).
9//
10// If you use or modify this code, keep this notice at the top of your file
11// and include the LICENSE-MIT or LICENSE-APACHE file from this repository:
12// https://github.com/ankit-chaubey/ferogram
13
14//! The [`Deserializable`] trait, [`Cursor`] buffer, and primitive impls.
15
16use std::fmt;
17
18/// Errors that can occur during deserialization.
19#[derive(Clone, Debug, PartialEq)]
20pub enum Error {
21    /// Ran out of bytes before the type was fully read.
22    UnexpectedEof,
23    /// Decoded a constructor ID that doesn't match any known variant.
24    UnexpectedConstructor { id: u32 },
25}
26
27impl fmt::Display for Error {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        match self {
30            Self::UnexpectedEof => write!(f, "unexpected end of buffer"),
31            Self::UnexpectedConstructor { id } => {
32                write!(f, "unexpected constructor id: {id:#010x}")
33            }
34        }
35    }
36}
37
38impl std::error::Error for Error {}
39
40/// Specialized `Result` for deserialization.
41pub type Result<T> = std::result::Result<T, Error>;
42
43// Cursor
44
45/// A zero-copy cursor over an in-memory byte slice.
46///
47/// Avoids `std::io::Cursor` and its wide error surface; only the two error
48/// cases above can ever occur during TL deserialization.
49pub struct Cursor<'a> {
50    buf: &'a [u8],
51    pos: usize,
52}
53
54impl<'a> Cursor<'a> {
55    /// Create a cursor positioned at the start of `buf`.
56    pub fn from_slice(buf: &'a [u8]) -> Self {
57        Self { buf, pos: 0 }
58    }
59
60    /// Current byte offset.
61    pub fn pos(&self) -> usize {
62        self.pos
63    }
64
65    /// Remaining bytes.
66    pub fn remaining(&self) -> usize {
67        self.buf.len() - self.pos
68    }
69
70    /// Read a single byte.
71    pub fn read_byte(&mut self) -> Result<u8> {
72        match self.buf.get(self.pos).copied() {
73            Some(b) => {
74                self.pos += 1;
75                Ok(b)
76            }
77            None => Err(Error::UnexpectedEof),
78        }
79    }
80
81    /// Read exactly `buf.len()` bytes.
82    pub fn read_exact(&mut self, out: &mut [u8]) -> Result<()> {
83        let end = self.pos + out.len();
84        if end > self.buf.len() {
85            return Err(Error::UnexpectedEof);
86        }
87        out.copy_from_slice(&self.buf[self.pos..end]);
88        self.pos = end;
89        Ok(())
90    }
91
92    /// Consume all remaining bytes into `out`.
93    pub fn read_to_end(&mut self, out: &mut Vec<u8>) -> usize {
94        let slice = &self.buf[self.pos..];
95        out.extend_from_slice(slice);
96        self.pos = self.buf.len();
97        slice.len()
98    }
99}
100
101/// Alias used by generated code: `crate::deserialize::Buffer<'_, '_>`.
102pub type Buffer<'a, 'b> = &'a mut Cursor<'b>;
103
104// Deserializable
105
106/// Deserialize a value from TL binary format.
107pub trait Deserializable: Sized {
108    /// Read `Self` from `buf`, advancing its position.
109    fn deserialize(buf: Buffer) -> Result<Self>;
110
111    /// Convenience: deserialize from a byte slice.
112    fn from_bytes(bytes: &[u8]) -> Result<Self> {
113        let mut cursor = Cursor::from_slice(bytes);
114        Self::deserialize(&mut cursor)
115    }
116}
117
118// Primitives
119
120impl Deserializable for bool {
121    fn deserialize(buf: Buffer) -> Result<Self> {
122        match u32::deserialize(buf)? {
123            0x997275b5 => Ok(true),
124            0xbc799737 => Ok(false),
125            id => Err(Error::UnexpectedConstructor { id }),
126        }
127    }
128}
129
130impl Deserializable for i32 {
131    fn deserialize(buf: Buffer) -> Result<Self> {
132        let mut b = [0u8; 4];
133        buf.read_exact(&mut b)?;
134        Ok(i32::from_le_bytes(b))
135    }
136}
137
138impl Deserializable for u32 {
139    fn deserialize(buf: Buffer) -> Result<Self> {
140        let mut b = [0u8; 4];
141        buf.read_exact(&mut b)?;
142        Ok(u32::from_le_bytes(b))
143    }
144}
145
146impl Deserializable for i64 {
147    fn deserialize(buf: Buffer) -> Result<Self> {
148        let mut b = [0u8; 8];
149        buf.read_exact(&mut b)?;
150        Ok(i64::from_le_bytes(b))
151    }
152}
153
154impl Deserializable for f64 {
155    fn deserialize(buf: Buffer) -> Result<Self> {
156        let mut b = [0u8; 8];
157        buf.read_exact(&mut b)?;
158        Ok(f64::from_le_bytes(b))
159    }
160}
161
162impl Deserializable for [u8; 16] {
163    fn deserialize(buf: Buffer) -> Result<Self> {
164        let mut b = [0u8; 16];
165        buf.read_exact(&mut b)?;
166        Ok(b)
167    }
168}
169
170impl Deserializable for [u8; 32] {
171    fn deserialize(buf: Buffer) -> Result<Self> {
172        let mut b = [0u8; 32];
173        buf.read_exact(&mut b)?;
174        Ok(b)
175    }
176}
177
178// Bytes / String
179
180impl Deserializable for Vec<u8> {
181    fn deserialize(buf: Buffer) -> Result<Self> {
182        let first = buf.read_byte()?;
183        let (len, header_extra) = if first != 0xfe {
184            (first as usize, 0)
185        } else {
186            let a = buf.read_byte()? as usize;
187            let b = buf.read_byte()? as usize;
188            let c = buf.read_byte()? as usize;
189            (a | (b << 8) | (c << 16), 3)
190        };
191
192        let mut data = vec![0u8; len];
193        buf.read_exact(&mut data)?;
194
195        // Skip alignment padding
196        let total = 1 + header_extra + len;
197        let padding = (4 - (total % 4)) % 4;
198        for _ in 0..padding {
199            buf.read_byte()?;
200        }
201
202        Ok(data)
203    }
204}
205
206impl Deserializable for String {
207    fn deserialize(buf: Buffer) -> Result<Self> {
208        let bytes = Vec::<u8>::deserialize(buf)?;
209        String::from_utf8(bytes).map_err(|_| Error::UnexpectedEof)
210    }
211}
212
213// Vectors
214
215impl<T: Deserializable> Deserializable for Vec<T> {
216    fn deserialize(buf: Buffer) -> Result<Self> {
217        let id = u32::deserialize(buf)?;
218        if id != 0x1cb5c415 {
219            return Err(Error::UnexpectedConstructor { id });
220        }
221        let len = i32::deserialize(buf)? as usize;
222        (0..len).map(|_| T::deserialize(buf)).collect()
223    }
224}
225
226impl<T: Deserializable> Deserializable for crate::RawVec<T> {
227    fn deserialize(buf: Buffer) -> Result<Self> {
228        let len = i32::deserialize(buf)? as usize;
229        let inner = (0..len)
230            .map(|_| T::deserialize(buf))
231            .collect::<Result<_>>()?;
232        Ok(crate::RawVec(inner))
233    }
234}