1use super::{Tag, Length, TagClass, TagType};
4use crate::error::Result;
5
6#[derive(Debug, Default)]
8pub struct BerWriter {
9 buffer: Vec<u8>,
10}
11
12impl BerWriter {
13 pub fn new() -> Self {
15 BerWriter { buffer: Vec::new() }
16 }
17
18 pub fn with_capacity(capacity: usize) -> Self {
20 BerWriter { buffer: Vec::with_capacity(capacity) }
21 }
22
23 pub fn as_bytes(&self) -> &[u8] {
25 &self.buffer
26 }
27
28 pub fn into_bytes(self) -> Vec<u8> {
30 self.buffer
31 }
32
33 pub fn len(&self) -> usize {
35 self.buffer.len()
36 }
37
38 pub fn is_empty(&self) -> bool {
40 self.buffer.is_empty()
41 }
42
43 pub fn write_raw(&mut self, bytes: &[u8]) {
45 self.buffer.extend_from_slice(bytes);
46 }
47
48 pub fn write_tag(&mut self, tag: &Tag) {
50 self.buffer.extend(tag.encode());
51 }
52
53 pub fn write_length(&mut self, length: &Length) {
55 self.buffer.extend(length.encode());
56 }
57
58 pub fn write_tlv(&mut self, tag: &Tag, value: &[u8]) {
60 self.write_tag(tag);
61 self.write_length(&Length::Definite(value.len()));
62 self.write_raw(value);
63 }
64
65 pub fn write_boolean(&mut self, value: bool) -> Result<()> {
67 self.write_tlv(&Tag::BOOLEAN, &[if value { 0xFF } else { 0x00 }]);
68 Ok(())
69 }
70
71 pub fn write_integer(&mut self, value: i64) -> Result<()> {
73 let bytes = Self::encode_integer(value);
74 self.write_tlv(&Tag::INTEGER, &bytes);
75 Ok(())
76 }
77
78 pub fn write_context_integer(&mut self, tag_number: u32, value: i64) -> Result<()> {
80 let tag = Tag::new(TagClass::Context, TagType::Primitive, tag_number);
81 let bytes = Self::encode_integer(value);
82 self.write_tlv(&tag, &bytes);
83 Ok(())
84 }
85
86 fn encode_integer(value: i64) -> Vec<u8> {
88 if value == 0 {
89 return vec![0];
90 }
91
92 let mut bytes = Vec::new();
93 let mut remaining = value;
94
95 if value > 0 {
97 while remaining > 0 {
98 bytes.push((remaining & 0xFF) as u8);
99 remaining >>= 8;
100 }
101 if !bytes.is_empty() && (bytes.last().unwrap() & 0x80) != 0 {
103 bytes.push(0);
104 }
105 } else {
106 while remaining != -1 || bytes.is_empty() || (bytes.last().unwrap() & 0x80) == 0 {
108 bytes.push((remaining & 0xFF) as u8);
109 remaining >>= 8;
110 if bytes.len() >= 8 {
111 break;
112 }
113 }
114 }
115
116 bytes.reverse();
117 bytes
118 }
119
120 pub fn write_real(&mut self, value: f64) -> Result<()> {
122 let bytes = Self::encode_real(value);
123 self.write_tlv(&Tag::REAL, &bytes);
124 Ok(())
125 }
126
127 fn encode_real(value: f64) -> Vec<u8> {
129 if value == 0.0 {
130 if value.is_sign_negative() {
131 return vec![0x43]; }
133 return vec![]; }
135
136 if value.is_infinite() {
137 return if value.is_sign_positive() {
138 vec![0x40] } else {
140 vec![0x41] };
142 }
143
144 if value.is_nan() {
145 return vec![0x42]; }
147
148 let bits = value.to_bits();
150 let sign = (bits >> 63) as u8;
151 let exponent = ((bits >> 52) & 0x7FF) as i16 - 1023 - 52;
152 let mantissa = if ((bits >> 52) & 0x7FF) == 0 {
153 bits & 0xFFFFFFFFFFFFF } else {
155 (bits & 0xFFFFFFFFFFFFF) | 0x10000000000000 };
157
158 let mut m = mantissa;
160 let mut exp = exponent;
161 while m != 0 && (m & 1) == 0 {
162 m >>= 1;
163 exp += 1;
164 }
165
166 let mut mantissa_bytes = Vec::new();
168 let mut temp = m;
169 while temp > 0 {
170 mantissa_bytes.push((temp & 0xFF) as u8);
171 temp >>= 8;
172 }
173 mantissa_bytes.reverse();
174
175 let exp_bytes = Self::encode_integer(exp as i64);
177
178 let mut result = Vec::new();
180
181 let mut first_byte: u8 = 0x80; if sign != 0 {
184 first_byte |= 0x40; }
186
187 match exp_bytes.len() {
188 1 => first_byte |= 0x00,
189 2 => first_byte |= 0x01,
190 3 => first_byte |= 0x02,
191 _ => first_byte |= 0x03,
192 }
193
194 result.push(first_byte);
195
196 if exp_bytes.len() > 3 {
197 result.push(exp_bytes.len() as u8);
198 }
199
200 result.extend(&exp_bytes);
201 result.extend(&mantissa_bytes);
202
203 result
204 }
205
206 pub fn write_utf8_string(&mut self, value: &str) -> Result<()> {
208 self.write_tlv(&Tag::UTF8_STRING, value.as_bytes());
209 Ok(())
210 }
211
212 pub fn write_octet_string(&mut self, value: &[u8]) -> Result<()> {
214 self.write_tlv(&Tag::OCTET_STRING, value);
215 Ok(())
216 }
217
218 pub fn write_null(&mut self) -> Result<()> {
220 self.write_tlv(&Tag::NULL, &[]);
221 Ok(())
222 }
223
224 pub fn write_sequence<F>(&mut self, f: F) -> Result<()>
226 where
227 F: FnOnce(&mut BerWriter) -> Result<()>,
228 {
229 let mut inner = BerWriter::new();
230 f(&mut inner)?;
231 self.write_tlv(&Tag::SEQUENCE, inner.as_bytes());
232 Ok(())
233 }
234
235 pub fn write_set<F>(&mut self, f: F) -> Result<()>
237 where
238 F: FnOnce(&mut BerWriter) -> Result<()>,
239 {
240 let mut inner = BerWriter::new();
241 f(&mut inner)?;
242 self.write_tlv(&Tag::SET, inner.as_bytes());
243 Ok(())
244 }
245
246 pub fn write_utf8string(&mut self, value: &str) {
248 self.write_tlv(&Tag::UTF8_STRING, value.as_bytes());
249 }
250
251 pub fn write_context<F>(&mut self, tag_number: u32, f: F) -> Result<()>
253 where
254 F: FnOnce(&mut BerWriter) -> Result<()>,
255 {
256 let tag = Tag::context_constructed(tag_number);
257 let mut inner = BerWriter::new();
258 f(&mut inner)?;
259 self.write_tlv(&tag, inner.as_bytes());
260 Ok(())
261 }
262
263 pub fn write_context_primitive(&mut self, tag_number: u32, value: &[u8]) -> Result<()> {
265 let tag = Tag::context_primitive(tag_number);
266 self.write_tlv(&tag, value);
267 Ok(())
268 }
269
270 pub fn write_application<F>(&mut self, tag_number: u32, f: F) -> Result<()>
272 where
273 F: FnOnce(&mut BerWriter) -> Result<()>,
274 {
275 let tag = Tag::application_constructed(tag_number);
276 let mut inner = BerWriter::new();
277 f(&mut inner)?;
278 self.write_tlv(&tag, inner.as_bytes());
279 Ok(())
280 }
281
282 pub fn write_application_primitive(&mut self, tag_number: u32, value: &[u8]) -> Result<()> {
284 let tag = Tag::application_primitive(tag_number);
285 self.write_tlv(&tag, value);
286 Ok(())
287 }
288
289 pub fn write_relative_oid(&mut self, components: &[u32]) -> Result<()> {
291 let mut bytes = Vec::new();
292
293 for &component in components {
294 let mut temp = Vec::new();
295 let mut value = component;
296
297 temp.push((value & 0x7F) as u8);
298 value >>= 7;
299
300 while value > 0 {
301 temp.push(((value & 0x7F) | 0x80) as u8);
302 value >>= 7;
303 }
304
305 temp.reverse();
306 bytes.extend(temp);
307 }
308
309 self.write_tlv(&Tag::RELATIVE_OID, &bytes);
310 Ok(())
311 }
312}
313
314#[cfg(test)]
315mod tests {
316 use super::*;
317
318 #[test]
319 fn test_integer_encoding() {
320 let cases = [
322 (0i64, vec![0x00]),
323 (1, vec![0x01]),
324 (127, vec![0x7F]),
325 (128, vec![0x00, 0x80]),
326 (256, vec![0x01, 0x00]),
327 (-1, vec![0xFF]),
328 (-128, vec![0x80]),
329 (-129, vec![0xFF, 0x7F]),
330 ];
331
332 for (value, expected) in cases {
333 let encoded = BerWriter::encode_integer(value);
334 assert_eq!(encoded, expected, "failed for value {}", value);
335 }
336 }
337}