1#![allow(clippy::upper_case_acronyms)]
5
6use crate::serialize::writer::*;
7use crate::serialize::writer_unchecked::*;
8
9pub(crate) trait Put {
12 fn put_bytes(&mut self, bytes: &[u8]) -> WriteResult<()>;
14
15 fn put_opaque_variable(&mut self, bytes: &[u8]) -> WriteResult<()>;
20
21 fn put_opaque_fixed(&mut self, bytes: &[u8]) -> WriteResult<()>;
23}
24
25pub struct TXS;
26
27#[inline]
30fn padding_len(len: usize) -> usize {
31 (4 - len % 4) % 4
32}
33
34static PADDING: [u8; 3] = [0; 3];
35
36macro_rules! write_int {
37 [ $($write:ident($nbytes:expr): $ty:ty),* $(,)? ] => {
38
39 $(
40 #[inline]
41 fn $write(&mut self, n: $ty) -> WriteResult<()> {
42 let bytes: [u8; $nbytes] = n.to_be_bytes();
43 self.put_bytes(&bytes)
44 }
45 )*
46
47 };
48}
49
50impl<P> Writer<TXS> for P
51where
52 P: Put,
53{
54 #[inline]
55 fn write_opaque_fixed(&mut self, bytes: &[u8]) -> WriteResult<()> {
56 debug_assert!(bytes.len() <= u32::MAX as usize);
57 self.put_opaque_fixed(bytes)
58 }
59
60 #[inline]
61 fn write_opaque_unpadded(&mut self, bytes: &[u8]) -> WriteResult<()> {
62 self.put_bytes(bytes)
63 }
64
65 #[inline]
66 fn write_opaque_padding(&mut self, len: usize) -> WriteResult<()> {
67 self.put_bytes(&PADDING[..padding_len(len)])
68 }
69
70 #[inline]
71 fn write_opaque_variable(&mut self, bytes: &[u8]) -> WriteResult<()> {
72 if bytes.len() > u32::MAX as usize {
73 return Err(WriteError::InvalidArrayLength);
74 }
75
76 self.put_opaque_variable(bytes)
77 }
78
79 #[inline]
80 fn write_bool(&mut self, v: bool) -> WriteResult<()> {
81 self.write_i32(if v { 1 } else { 0 })
82 }
83
84 #[inline]
85 fn write_i16(&mut self, n: i16) -> WriteResult<()> {
86 self.write_i32(n as i32)
87 }
88
89 #[inline]
90 fn write_u16(&mut self, n: u16) -> WriteResult<()> {
91 self.write_u32(n as u32)
92 }
93
94 write_int! [
95 write_i64(8): i64,
96 write_i32(4): i32,
97
98 write_u64(8): u64,
99 write_u32(4): u32,
100 ];
101
102 #[inline]
103 fn write_f32(&mut self, n: f32) -> WriteResult<()> {
104 let bytes: [u8; 4] = n.to_be_bytes();
105 self.put_bytes(&bytes)
106 }
107
108 #[inline]
109 fn write_f64(&mut self, n: f64) -> WriteResult<()> {
110 let bytes: [u8; 8] = n.to_be_bytes();
111 self.put_bytes(&bytes)
112 }
113}
114
115pub(crate) trait PutUnchecked {
118 unsafe fn put_bytes(&mut self, bytes: &[u8]);
121
122 unsafe fn put_opaque_variable(&mut self, bytes: &[u8]);
127
128 unsafe fn put_opaque_fixed(&mut self, bytes: &[u8]);
132}
133
134macro_rules! write_int_unchecked {
135 [ $($write:ident($nbytes:expr): $ty:ty),* $(,)? ] => {
136
137 $(
138 #[inline]
139 unsafe fn $write(&mut self, n: $ty) {
140 let bytes: [u8; $nbytes] = n.to_be_bytes();
141 unsafe { self.put_bytes(&bytes) }
143 }
144 )*
145
146 };
147}
148
149impl<P> WriterUnchecked<TXS> for P
150where
151 P: PutUnchecked,
152{
153 #[inline]
154 unsafe fn write_opaque_fixed(&mut self, bytes: &[u8]) {
155 debug_assert!(bytes.len() <= u32::MAX as usize);
156 unsafe { self.put_opaque_fixed(bytes) }
158 }
159
160 #[inline]
161 unsafe fn write_opaque_unpadded(&mut self, bytes: &[u8]) {
162 unsafe { self.put_bytes(bytes) }
164 }
165
166 #[inline]
167 unsafe fn write_opaque_padding(&mut self, len: usize) {
168 unsafe { self.put_bytes(&PADDING[..padding_len(len)]) }
170 }
171
172 #[inline]
173 unsafe fn write_opaque_variable(&mut self, bytes: &[u8]) {
174 debug_assert!(bytes.len() <= u32::MAX as usize);
175 unsafe { self.put_opaque_variable(bytes) }
177 }
178
179 #[inline]
180 unsafe fn write_bool(&mut self, v: bool) {
181 unsafe { self.write_i32(if v { 1 } else { 0 }) }
183 }
184
185 #[inline]
186 unsafe fn write_i16(&mut self, n: i16) {
187 unsafe { self.write_i32(n as i32) }
189 }
190
191 #[inline]
192 unsafe fn write_u16(&mut self, n: u16) {
193 unsafe { self.write_u32(n as u32) }
195 }
196
197 write_int_unchecked![
198 write_i64(8): i64,
199 write_i32(4): i32,
200
201 write_u64(8): u64,
202 write_u32(4): u32,
203 ];
204
205 #[inline]
206 unsafe fn write_f32(&mut self, n: f32) {
207 let bytes: [u8; 4] = n.to_be_bytes();
208 unsafe { self.put_bytes(&bytes) }
210 }
211
212 #[inline]
213 unsafe fn write_f64(&mut self, n: f64) {
214 let bytes: [u8; 8] = n.to_be_bytes();
215 unsafe { self.put_bytes(&bytes) }
217 }
218}