1use std::sync::Arc;
2
3pub trait Repr: private::Sealed {}
8
9pub enum Boxed {}
12impl private::Sealed for Boxed {}
13impl Repr for Boxed {}
14
15pub enum Bare {}
18impl private::Sealed for Bare {}
19impl Repr for Bare {}
20
21pub trait TlRead<'a>: Sized {
23 type Repr: Repr;
25
26 fn read_from(packet: &mut &'a [u8]) -> TlResult<Self>;
28}
29
30impl<'a, T> TlRead<'a> for Arc<T>
31where
32 T: TlRead<'a>,
33{
34 type Repr = T::Repr;
35
36 #[inline(always)]
37 fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
38 match T::read_from(packet) {
39 Ok(data) => Ok(Arc::new(data)),
40 Err(e) => Err(e),
41 }
42 }
43}
44
45impl<'a, T> TlRead<'a> for Box<T>
46where
47 T: TlRead<'a>,
48{
49 type Repr = T::Repr;
50
51 #[inline(always)]
52 fn read_from(packet: &mut &'a [u8]) -> TlResult<Self> {
53 match T::read_from(packet) {
54 Ok(data) => Ok(Box::new(data)),
55 Err(e) => Err(e),
56 }
57 }
58}
59
60pub trait TlWrite {
62 type Repr: Repr;
64
65 fn max_size_hint(&self) -> usize;
67
68 fn write_to<P>(&self, packet: &mut P)
70 where
71 P: TlPacket;
72}
73
74impl<T> TlWrite for &T
75where
76 T: TlWrite,
77{
78 type Repr = T::Repr;
79
80 fn max_size_hint(&self) -> usize {
81 TlWrite::max_size_hint(*self)
82 }
83
84 #[inline(always)]
85 fn write_to<P>(&self, packet: &mut P)
86 where
87 P: TlPacket,
88 {
89 TlWrite::write_to(*self, packet)
90 }
91}
92
93impl<T> TlWrite for Box<T>
94where
95 T: TlWrite,
96{
97 type Repr = T::Repr;
98
99 #[inline(always)]
100 fn max_size_hint(&self) -> usize {
101 TlWrite::max_size_hint(&**self)
102 }
103
104 #[inline(always)]
105 fn write_to<P>(&self, packet: &mut P)
106 where
107 P: TlPacket,
108 {
109 TlWrite::write_to(&**self, packet)
110 }
111}
112
113impl<T> TlWrite for Arc<T>
114where
115 T: TlWrite,
116{
117 type Repr = T::Repr;
118
119 #[inline(always)]
120 fn max_size_hint(&self) -> usize {
121 TlWrite::max_size_hint(&**self)
122 }
123
124 #[inline(always)]
125 fn write_to<P>(&self, packet: &mut P)
126 where
127 P: TlPacket,
128 {
129 TlWrite::write_to(&**self, packet)
130 }
131}
132
133pub trait TlPacket {
135 fn ignore_signature(&self) -> bool;
137
138 fn write_u32(&mut self, data: u32);
140 fn write_i32(&mut self, data: i32);
142 fn write_u64(&mut self, data: u64);
144 fn write_i64(&mut self, data: i64);
146 fn write_raw_slice(&mut self, data: &[u8]);
148}
149
150impl TlPacket for Vec<u8> {
151 #[inline(always)]
152 fn ignore_signature(&self) -> bool {
153 false
154 }
155
156 #[inline(always)]
157 fn write_u32(&mut self, data: u32) {
158 self.extend_from_slice(&data.to_le_bytes());
159 }
160
161 #[inline(always)]
162 fn write_i32(&mut self, data: i32) {
163 self.extend_from_slice(&data.to_le_bytes());
164 }
165
166 #[inline(always)]
167 fn write_u64(&mut self, data: u64) {
168 self.extend_from_slice(&data.to_le_bytes());
169 }
170
171 #[inline(always)]
172 fn write_i64(&mut self, data: i64) {
173 self.extend_from_slice(&data.to_le_bytes());
174 }
175
176 #[inline(always)]
177 fn write_raw_slice(&mut self, data: &[u8]) {
178 self.extend_from_slice(data);
179 }
180}
181
182#[cfg(feature = "bytes")]
183impl TlPacket for bytes::BytesMut {
184 #[inline(always)]
185 fn ignore_signature(&self) -> bool {
186 false
187 }
188
189 #[inline(always)]
190 fn write_u32(&mut self, data: u32) {
191 self.extend_from_slice(&data.to_le_bytes());
192 }
193
194 #[inline(always)]
195 fn write_i32(&mut self, data: i32) {
196 self.extend_from_slice(&data.to_le_bytes());
197 }
198
199 #[inline(always)]
200 fn write_u64(&mut self, data: u64) {
201 self.extend_from_slice(&data.to_le_bytes());
202 }
203
204 #[inline(always)]
205 fn write_i64(&mut self, data: i64) {
206 self.extend_from_slice(&data.to_le_bytes());
207 }
208
209 #[inline(always)]
210 fn write_raw_slice(&mut self, data: &[u8]) {
211 self.extend_from_slice(data);
212 }
213}
214
215pub struct IoWriter<W> {
220 writer: W,
221 status: std::io::Result<()>,
222}
223
224impl<W> IoWriter<W> {
225 pub const fn new(writer: W) -> Self {
227 Self {
228 writer,
229 status: Ok(()),
230 }
231 }
232
233 pub fn get_mut(&mut self) -> &mut W {
235 &mut self.writer
236 }
237
238 pub fn get_ref(&self) -> &W {
240 &self.writer
241 }
242
243 pub fn into_parts(self) -> (W, std::io::Result<()>) {
245 (self.writer, self.status)
246 }
247}
248
249impl<W: std::io::Write> TlPacket for IoWriter<W> {
250 #[inline(always)]
251 fn ignore_signature(&self) -> bool {
252 false
253 }
254
255 #[inline(always)]
256 fn write_u32(&mut self, data: u32) {
257 if self.status.is_ok() {
258 self.status = self.writer.write_all(&data.to_le_bytes());
259 }
260 }
261
262 fn write_i32(&mut self, data: i32) {
263 if self.status.is_ok() {
264 self.status = self.writer.write_all(&data.to_le_bytes());
265 }
266 }
267
268 fn write_u64(&mut self, data: u64) {
269 if self.status.is_ok() {
270 self.status = self.writer.write_all(&data.to_le_bytes());
271 }
272 }
273
274 fn write_i64(&mut self, data: i64) {
275 if self.status.is_ok() {
276 self.status = self.writer.write_all(&data.to_le_bytes());
277 }
278 }
279
280 fn write_raw_slice(&mut self, data: &[u8]) {
281 if self.status.is_ok() {
282 self.status = self.writer.write_all(data);
283 }
284 }
285}
286
287pub type TlResult<T> = Result<T, TlError>;
289
290#[derive(thiserror::Error, Debug)]
292pub enum TlError {
293 #[error("Unexpected packet EOF")]
295 UnexpectedEof,
296 #[error("Unknown constructor")]
298 UnknownConstructor,
299 #[error("Invalid data")]
301 InvalidData,
302}
303
304mod private {
305 pub trait Sealed {}
306}