1use bytes::{BufMut, BytesMut};
2
3use crate::{
4 config::{Config, ContainerLengthStrategy, EndiannessStrategy},
5 error::{Error, Result},
6};
7
8#[derive(Debug, Default)]
9pub struct BinarySerializer {
10 output: BytesMut,
12 config: Config,
14}
15
16impl BinarySerializer {
17 pub fn new(config: Config) -> Self {
19 Self {
20 output: BytesMut::new(),
21 config,
22 }
23 }
24
25 pub fn output(self) -> BytesMut {
27 self.output
28 }
29
30 pub fn config(&self) -> &crate::config::Config {
32 &self.config
33 }
34
35 pub fn size(&self) -> usize {
37 self.output.len()
38 }
39
40 fn check_limit(&self) -> Result<()> {
43 if let Some(limit) = self.config.limit {
44 if self.output.len() > limit {
45 return Err(Error::LimitExceeded {
46 limit,
47 size: self.output.len(),
48 });
49 }
50 }
51 Ok(())
52 }
53
54 pub fn container_length(&mut self, length: usize) {
57 match (
58 self.config.endianness_strategy,
59 self.config.container_length_strategy,
60 ) {
61 (_, ContainerLengthStrategy::OneByte) => {
62 self.output.put_u8(length as u8);
63 }
64 (EndiannessStrategy::Big, ContainerLengthStrategy::TwoBytes) => {
65 self.output.put_u16(length as u16);
66 }
67 (EndiannessStrategy::Little, ContainerLengthStrategy::TwoBytes) => {
68 self.output.put_u16_le(length as u16);
69 }
70 (EndiannessStrategy::Big, ContainerLengthStrategy::FourBytes) => {
71 self.output.put_u32(length as u32);
72 }
73 (EndiannessStrategy::Little, ContainerLengthStrategy::FourBytes) => {
74 self.output.put_u32_le(length as u32);
75 }
76 (EndiannessStrategy::Big, ContainerLengthStrategy::EightBytes) => {
77 self.output.put_u64(length as u64);
78 }
79 (EndiannessStrategy::Little, ContainerLengthStrategy::EightBytes) => {
80 self.output.put_u64_le(length as u64);
81 }
82 (EndiannessStrategy::Big, ContainerLengthStrategy::SixteenBytes) => {
83 self.output.put_u128(length as u128);
84 }
85 (EndiannessStrategy::Little, ContainerLengthStrategy::SixteenBytes) => {
86 self.output.put_u128_le(length as u128);
87 }
88 }
89 }
90
91 pub fn bool(&mut self, v: bool) -> Result<()> {
92 self.output.put_u8(if v { 1 } else { 0 });
93 self.check_limit()
94 }
95
96 pub fn i8(&mut self, v: i8) -> Result<()> {
97 self.output.put_i8(v);
98 self.check_limit()
99 }
100
101 pub fn i16(&mut self, v: i16) -> Result<()> {
102 match self.config.endianness_strategy {
103 EndiannessStrategy::Big => self.output.put_i16(v),
104 EndiannessStrategy::Little => self.output.put_i16_le(v),
105 }
106 self.check_limit()
107 }
108
109 pub fn i32(&mut self, v: i32) -> Result<()> {
110 match self.config.endianness_strategy {
111 EndiannessStrategy::Big => self.output.put_i32(v),
112 EndiannessStrategy::Little => self.output.put_i32_le(v),
113 }
114 self.check_limit()
115 }
116
117 pub fn i64(&mut self, v: i64) -> Result<()> {
118 match self.config.endianness_strategy {
119 EndiannessStrategy::Big => self.output.put_i64(v),
120 EndiannessStrategy::Little => self.output.put_i64_le(v),
121 }
122 self.check_limit()
123 }
124
125 pub fn i128(&mut self, v: i128) -> Result<()> {
126 match self.config.endianness_strategy {
127 EndiannessStrategy::Big => self.output.put_i128(v),
128 EndiannessStrategy::Little => self.output.put_i128_le(v),
129 }
130 self.check_limit()
131 }
132
133 pub fn u8(&mut self, v: u8) -> Result<()> {
134 self.output.put_u8(v);
135 self.check_limit()
136 }
137
138 pub fn u16(&mut self, v: u16) -> Result<()> {
139 match self.config.endianness_strategy {
140 EndiannessStrategy::Big => self.output.put_u16(v),
141 EndiannessStrategy::Little => self.output.put_u16_le(v),
142 }
143 self.check_limit()
144 }
145
146 pub fn u32(&mut self, v: u32) -> Result<()> {
147 match self.config.endianness_strategy {
148 EndiannessStrategy::Big => self.output.put_u32(v),
149 EndiannessStrategy::Little => self.output.put_u32_le(v),
150 }
151 self.check_limit()
152 }
153
154 pub fn u64(&mut self, v: u64) -> Result<()> {
155 match self.config.endianness_strategy {
156 EndiannessStrategy::Big => self.output.put_u64(v),
157 EndiannessStrategy::Little => self.output.put_u64_le(v),
158 }
159 self.check_limit()
160 }
161
162 pub fn u128(&mut self, v: u128) -> Result<()> {
163 match self.config.endianness_strategy {
164 EndiannessStrategy::Big => self.output.put_u128(v),
165 EndiannessStrategy::Little => self.output.put_u128_le(v),
166 }
167 self.check_limit()
168 }
169
170 pub fn f32(&mut self, v: f32) -> Result<()> {
171 match self.config.endianness_strategy {
172 EndiannessStrategy::Big => self.output.put_f32(v),
173 EndiannessStrategy::Little => self.output.put_f32_le(v),
174 }
175 self.check_limit()
176 }
177
178 pub fn f64(&mut self, v: f64) -> Result<()> {
179 match self.config.endianness_strategy {
180 EndiannessStrategy::Big => self.output.put_f64(v),
181 EndiannessStrategy::Little => self.output.put_f64_le(v),
182 }
183 self.check_limit()
184 }
185
186 pub fn char(&mut self, v: char) -> Result<()> {
187 self.output.put_slice(v.to_string().as_bytes());
188 self.check_limit()
189 }
190
191 pub fn str(&mut self, v: &str) -> Result<()> {
192 self.container_length(v.len());
193 self.output.put_slice(v.as_bytes());
194 self.check_limit()
195 }
196
197 pub fn bytes(&mut self, v: &[u8]) -> Result<()> {
198 self.output.put_slice(v);
199 self.check_limit()
200 }
201}