1#![allow(clippy::upper_case_acronyms)]
5
6use super::limits::*;
7use crate::serialize::writer::*;
8use crate::serialize::writer_unchecked::*;
9
10const V_MULTIBYTE: u8 = 63;
11const S_8BYTE: u8 = 3 << 6;
12const S_4BYTE: u8 = 2 << 6;
13const S_2BYTE: u8 = 1 << 6;
14const S_1BYTE: u8 = 0 << 6;
15const S_HEADER: u8 = 0 << 6;
16
17pub(crate) trait Put {
20 fn put_byte(&mut self, b: u8) -> WriteResult<()>;
22 fn put_bytes(&mut self, bytes: &[u8]) -> WriteResult<()>;
23}
24
25pub struct CXS;
26
27impl<P> Writer<CXS> for P
28where
29 P: Put,
30{
31 #[inline]
32 fn write_opaque_fixed(&mut self, bytes: &[u8]) -> WriteResult<()> {
33 debug_assert!(bytes.len() <= u32::MAX as usize);
34 self.put_bytes(bytes)
35 }
36
37 #[inline]
38 fn write_opaque_unpadded(&mut self, bytes: &[u8]) -> WriteResult<()> {
39 self.put_bytes(bytes)
40 }
41
42 #[inline]
44 fn write_opaque_padding(&mut self, _len: usize) -> WriteResult<()> {
45 Ok(())
46 }
47
48 fn write_opaque_variable(&mut self, bytes: &[u8]) -> WriteResult<()> {
50 if bytes.len() > u32::MAX as usize {
51 return Err(WriteError::InvalidArrayLength);
52 }
53
54 self.write_u32(bytes.len() as u32)?;
55 self.put_bytes(bytes)
56 }
57
58 #[inline]
59 fn write_bool(&mut self, v: bool) -> WriteResult<()> {
60 self.write_i32(if v { 1 } else { 0 })
61 }
62
63 #[inline]
64 fn write_i64(&mut self, n: i64) -> WriteResult<()> {
65 if n > i32::MAX as i64 || n < i32::MIN as i64 {
66 let h = V_MULTIBYTE | S_8BYTE;
68 let b = n.to_le_bytes();
69 let combined = [h, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]];
70 self.put_bytes(&combined)
71 } else {
72 self.write_i32(n as i32)
73 }
74 }
75
76 #[inline]
77 fn write_i32(&mut self, n: i32) -> WriteResult<()> {
78 if n > i16::MAX as i32 || n < i16::MIN as i32 {
79 let h = V_MULTIBYTE | S_4BYTE;
81 let b = n.to_le_bytes();
82 let combined = [h, b[0], b[1], b[2], b[3]];
83 self.put_bytes(&combined)
84 } else {
85 self.write_i16(n as i16)
86 }
87 }
88
89 #[inline]
90 fn write_i16(&mut self, n: i16) -> WriteResult<()> {
91 if n > i8::MAX as i16 || n < i8::MIN as i16 {
92 let h = V_MULTIBYTE | S_2BYTE;
94 let b = n.to_le_bytes();
95 let combined = [h, b[0], b[1]];
96 self.put_bytes(&combined)
97 } else {
98 write_i8(self, n as i8)
99 }
100 }
101
102 #[inline]
103 fn write_u64(&mut self, n: u64) -> WriteResult<()> {
104 if n > u32::MAX as u64 {
105 let h = V_MULTIBYTE | S_8BYTE;
107 let b = n.to_le_bytes();
108 let combined = [h, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]];
109 self.put_bytes(&combined)
110 } else {
111 self.write_u32(n as u32)
112 }
113 }
114
115 #[inline]
116 fn write_u32(&mut self, n: u32) -> WriteResult<()> {
117 if n > u16::MAX as u32 {
118 let h = V_MULTIBYTE | S_4BYTE;
120 let b = n.to_le_bytes();
121 let combined = [h, b[0], b[1], b[2], b[3]];
122 self.put_bytes(&combined)
123 } else {
124 self.write_u16(n as u16)
125 }
126 }
127
128 #[inline]
129 fn write_u16(&mut self, n: u16) -> WriteResult<()> {
130 if n > u8::MAX as u16 {
131 let h = V_MULTIBYTE | S_2BYTE;
133 let b = n.to_le_bytes();
134 let combined = [h, b[0], b[1]];
135 self.put_bytes(&combined)
136 } else {
137 write_u8(self, n as u8)
138 }
139 }
140
141 #[inline]
147 fn write_f32(&mut self, n: f32) -> WriteResult<()> {
148 let bytes: [u8; 4] = n.to_le_bytes();
149 self.put_bytes(&bytes)
150 }
151
152 #[inline]
158 fn write_f64(&mut self, n: f64) -> WriteResult<()> {
159 let bytes: [u8; 8] = n.to_le_bytes();
160 self.put_bytes(&bytes)
161 }
162}
163
164#[inline]
165fn write_u8<P>(p: &mut P, n: u8) -> WriteResult<()>
166where
167 P: Put,
168{
169 if n > UH_MAX {
170 let h = V_MULTIBYTE | S_1BYTE;
172 let combined = [h, n];
173 p.put_bytes(&combined)
174 } else {
175 p.put_byte(n)
177 }
178}
179
180#[inline]
181fn write_i8<P>(p: &mut P, n: i8) -> WriteResult<()>
182where
183 P: Put,
184{
185 if !(IH_MIN..=IH_MAX).contains(&n) {
186 let h = V_MULTIBYTE | S_1BYTE;
188 let combined = [h, n as u8];
189 p.put_bytes(&combined)
190 } else {
191 let nu: u8 = n.unsigned_abs();
194 let v = if n >= 0 {
195 nu
196 } else {
197 (!nu & 0b01_1111) | 0b0010_0000
199 };
200
201 let s = S_HEADER;
202 let h = v | s;
203 p.put_byte(h)
204 }
205}
206
207pub(crate) trait PutUnchecked {
210 unsafe fn put_byte(&mut self, b: u8);
213
214 unsafe fn put_bytes(&mut self, bytes: &[u8]);
217}
218
219impl<P> WriterUnchecked<CXS> for P
220where
221 P: PutUnchecked,
222{
223 #[inline]
224 unsafe fn write_opaque_fixed(&mut self, bytes: &[u8]) {
225 debug_assert!(bytes.len() <= u32::MAX as usize);
226 unsafe { self.put_bytes(bytes) }
228 }
229
230 #[inline]
231 unsafe fn write_opaque_unpadded(&mut self, bytes: &[u8]) {
232 unsafe { self.put_bytes(bytes) }
234 }
235
236 #[inline]
238 unsafe fn write_opaque_padding(&mut self, _len: usize) {}
239
240 unsafe fn write_opaque_variable(&mut self, bytes: &[u8]) {
241 debug_assert!(bytes.len() <= u32::MAX as usize);
242 unsafe {
244 self.write_u32(bytes.len() as u32);
245 self.put_bytes(bytes);
246 }
247 }
248
249 #[inline]
250 unsafe fn write_bool(&mut self, v: bool) {
251 unsafe { self.write_i32(if v { 1 } else { 0 }) }
253 }
254
255 #[inline]
256 unsafe fn write_i64(&mut self, n: i64) {
257 if n > i32::MAX as i64 || n < i32::MIN as i64 {
258 let h = V_MULTIBYTE | S_8BYTE;
260 let b = n.to_le_bytes();
261 let combined = [h, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]];
262 unsafe { self.put_bytes(&combined) }
264 } else {
265 unsafe { self.write_i32(n as i32) }
267 }
268 }
269
270 #[inline]
271 unsafe fn write_i32(&mut self, n: i32) {
272 if n > i16::MAX as i32 || n < i16::MIN as i32 {
273 let h = V_MULTIBYTE | S_4BYTE;
275 let b = n.to_le_bytes();
276 let combined = [h, b[0], b[1], b[2], b[3]];
277 unsafe { self.put_bytes(&combined) }
279 } else {
280 unsafe { self.write_i16(n as i16) }
282 }
283 }
284
285 #[inline]
286 unsafe fn write_i16(&mut self, n: i16) {
287 if n > i8::MAX as i16 || n < i8::MIN as i16 {
288 let h = V_MULTIBYTE | S_2BYTE;
290 let b = n.to_le_bytes();
291 let combined = [h, b[0], b[1]];
292 unsafe { self.put_bytes(&combined) }
294 } else {
295 unsafe { write_i8_unchecked(self, n as i8) }
297 }
298 }
299
300 #[inline]
301 unsafe fn write_u64(&mut self, n: u64) {
302 if n > u32::MAX as u64 {
303 let h = V_MULTIBYTE | S_8BYTE;
305 let b = n.to_le_bytes();
306 let combined = [h, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]];
307 unsafe { self.put_bytes(&combined) }
309 } else {
310 unsafe { self.write_u32(n as u32) }
312 }
313 }
314
315 #[inline]
316 unsafe fn write_u32(&mut self, n: u32) {
317 if n > u16::MAX as u32 {
318 let h = V_MULTIBYTE | S_4BYTE;
320 let b = n.to_le_bytes();
321 let combined = [h, b[0], b[1], b[2], b[3]];
322 unsafe { self.put_bytes(&combined) }
324 } else {
325 unsafe { self.write_u16(n as u16) }
327 }
328 }
329
330 #[inline]
331 unsafe fn write_u16(&mut self, n: u16) {
332 if n > u8::MAX as u16 {
333 let h = V_MULTIBYTE | S_2BYTE;
335 let b = n.to_le_bytes();
336 let combined = [h, b[0], b[1]];
337 unsafe { self.put_bytes(&combined) }
339 } else {
340 unsafe { write_u8_unchecked(self, n as u8) }
342 }
343 }
344
345 #[inline]
348 unsafe fn write_f32(&mut self, n: f32) {
349 let bytes: [u8; 4] = n.to_le_bytes();
350 unsafe { self.put_bytes(&bytes) }
352 }
353
354 #[inline]
357 unsafe fn write_f64(&mut self, n: f64) {
358 let bytes: [u8; 8] = n.to_le_bytes();
359 unsafe { self.put_bytes(&bytes) }
361 }
362}
363
364#[inline]
367unsafe fn write_u8_unchecked<P>(p: &mut P, n: u8)
368where
369 P: PutUnchecked,
370{
371 if n > UH_MAX {
372 let h = V_MULTIBYTE | S_1BYTE;
374 let combined = [h, n];
375 unsafe { p.put_bytes(&combined) }
377 } else {
378 unsafe { p.put_byte(n) }
381 }
382}
383
384#[inline]
387unsafe fn write_i8_unchecked<P>(p: &mut P, n: i8)
388where
389 P: PutUnchecked,
390{
391 if !(IH_MIN..=IH_MAX).contains(&n) {
392 let h = V_MULTIBYTE | S_1BYTE;
394 let combined = [h, n as u8];
395 unsafe { p.put_bytes(&combined) }
397 } else {
398 let nu: u8 = n.unsigned_abs();
401 let v = if n >= 0 {
402 nu
403 } else {
404 (!nu & 0b01_1111) | 0b0010_0000
406 };
407
408 let s = S_HEADER;
409 let h = v | s;
410 unsafe { p.put_byte(h) }
412 }
413}