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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/*
* Copyright (c) 2026 Ankit Chaubey <ankitchaubey.dev@gmail.com>
* https://github.com/ankit-chaubey
*
* Project: ferogram
* Website: https://ferogram.dev
*
* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
* https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
* <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
* This file may not be copied, modified, or distributed except according
* to those terms.
*/
use Deserializable;
use crateInvocationError;
/// 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.
/// E.164 caps a phone number at 15 digits - a hard, universal ceiling, not
/// a guess. Anything longer cannot be a valid phone number under any
/// numbering plan, so it's rejected here rather than spending a real
/// `contacts.importContacts` call (which has a side effect - see
/// [`PeerRef::Phone`]) on input that structurally cannot succeed.
///
/// [`PeerRef::Phone`]: crate::PeerRef::Phone
const MAX_PHONE_DIGITS: usize = 15;
/// Floor below which a `+`-prefixed string isn't worth trying as a phone
/// number. 5 covers real short numbers too, e.g. Telegram's own service
/// notification account, `+42777`.
const MIN_PHONE_DIGITS: usize = 5;
/// Normalize a phone number to canonical `+<digits>` form.
///
/// Accepts input with or without a leading `+`, and tolerates spaces,
/// hyphens, dots, and parentheses as separators (what people actually paste
/// when copying a number from another app). Returns `None` if any other
/// character is present, or if the digit count falls outside
/// `MIN_PHONE_DIGITS..=MAX_PHONE_DIGITS`.
///
/// This is the single source of truth for phone normalization: classifying
/// a `PeerRef::Phone` from user input, indexing `PeerCache::phone_to_user`
/// from Telegram's own `User.phone` field (digits only, no `+`), and the
/// `contacts.importContacts` RPC call all key off the same string, so they
/// must all normalize through this function to stay consistent.
pub