1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Copyright (c) Ankit Chaubey <ankitchaubey.dev@gmail.com>
//
// ferogram: async Telegram MTProto client in Rust
// https://github.com/ankit-chaubey/ferogram
//
// Licensed under either the MIT License or the Apache License 2.0.
// See the LICENSE-MIT or LICENSE-APACHE file in this repository:
// https://github.com/ankit-chaubey/ferogram
//
// Feel free to use, modify, and share this code.
// Please keep this notice when redistributing.
use ferogram_tl_types::Deserializable;
use crate::InvocationError;
/// Strict TL decode helper.
///
/// Deserializes `T` from `body` and returns an error if:
/// - deserialization itself fails (wrong constructor, truncated data, etc.)
/// - any trailing bytes remain after decoding (misaligned schema)
///
/// This prevents:
/// - partial successful decode hiding schema mismatches
/// - trailing unread bytes causing fake random constructor failures later
/// - silent `.ok()` swallowing the real bug
///
/// Never use `tl::deserialize(...).ok()` for core MTProto paths; use this instead.
pub fn decode_checked<T>(name: &str, body: &[u8]) -> Result<T, InvocationError>
where
T: Deserializable,
{
let mut cursor = ferogram_tl_types::Cursor::from_slice(body);
let value = T::deserialize(&mut cursor)
.map_err(|e| InvocationError::Deserialize(format!("{name} deserialize error: {e}")))?;
if cursor.remaining() != 0 {
return Err(InvocationError::Deserialize(format!(
"{name} trailing bytes after decode: {} byte(s) left",
cursor.remaining()
)));
}
Ok(value)
}