1use std::io;
7use bytes::Bytes;
8use crate::length::Length;
9use crate::mode::Mode;
10use crate::tag::Tag;
11use super::values::Values;
12
13
14pub trait PrimitiveContent: Sized {
32 const TAG: Tag;
34
35 fn encoded_len(&self, mode: Mode) -> usize;
37
38 fn write_encoded<W: io::Write>(
40 &self,
41 mode: Mode,
42 target: &mut W
43 ) -> Result<(), io::Error>;
44
45 fn to_encoded_bytes(&self, mode: Mode) -> Bytes {
47 let l = self.encoded_len(mode);
48 let mut w = Vec::with_capacity(l);
49 self.write_encoded(mode, &mut w).unwrap();
50 w.into()
51 }
52
53 fn encode(self) -> Primitive<Self> {
57 self.encode_as(Self::TAG)
58 }
59
60 fn encode_as(self, tag: Tag) -> Primitive<Self> {
66 Primitive { tag, prim: self }
67 }
68
69 fn encode_ref(&self) -> Primitive<&Self> {
71 self.encode_ref_as(Self::TAG)
72 }
73
74 fn encode_ref_as(&self, tag: Tag) -> Primitive<&Self> {
76 Primitive { tag, prim: self }
77 }
78}
79
80impl<T: PrimitiveContent> PrimitiveContent for &'_ T {
83 const TAG: Tag = T::TAG;
84
85 fn encoded_len(&self, mode: Mode) -> usize {
86 (*self).encoded_len(mode)
87 }
88
89 fn write_encoded<W: io::Write>(
90 &self,
91 mode: Mode,
92 target: &mut W
93 ) -> Result<(), io::Error> {
94 (*self).write_encoded(mode, target)
95 }
96}
97
98
99impl PrimitiveContent for u8 {
102 const TAG: Tag = Tag::INTEGER;
103
104 fn encoded_len(&self, _: Mode) -> usize {
105 if *self > 0x7F { 2 }
106 else { 1 }
107 }
108
109 fn write_encoded<W: io::Write>(
110 &self,
111 _: Mode,
112 target: &mut W
113 ) -> Result<(), io::Error> {
114 if *self > 0x7F {
115 target.write_all(&[0])?;
116 }
117 target.write_all(&[*self])?;
118 Ok(())
119 }
120}
121
122macro_rules! unsigned_content {
123 ( $type:ident, $len:expr) => {
124 impl PrimitiveContent for $type {
125 const TAG: Tag = Tag::INTEGER;
126
127 fn encoded_len(&self, _: Mode) -> usize {
128 if *self == 0 {
129 1
130 }
131 else {
132 let zeros = self.leading_zeros() as usize;
133 if zeros % 8 == 0 {
134 $len - (zeros >> 3) + 1
135 }
136 else {
137 $len - (zeros >> 3)
138 }
139 }
140 }
141
142 fn write_encoded<W: io::Write>(
143 &self,
144 _: Mode,
145 target: &mut W
146 ) -> Result<(), io::Error> {
147 if *self == 0 {
148 target.write_all(&[0x00])?;
149 }
150 else {
151 let mut val = self.swap_bytes();
152 let mut i = 0;
153 while i < $len {
154 if val as u8 != 0 {
155 break
156 }
157 val >>= 8;
158 i += 1
159 }
160 if val & 0x80 != 0 {
161 target.write_all(&[0x00])?;
162 }
163 while i < $len {
164 target.write_all(&[val as u8])?;
165 val >>= 8;
166 i += 1
167 }
168 }
169 Ok(())
170 }
171 }
172 }
173}
174
175unsigned_content!(u16, 2);
176unsigned_content!(u32, 4);
177unsigned_content!(u64, 8);
178unsigned_content!(u128, 16);
179
180
181impl PrimitiveContent for i8 {
182 const TAG: Tag = Tag::INTEGER;
183
184 fn encoded_len(&self, _: Mode) -> usize {
185 1
186 }
187
188 fn write_encoded<W: io::Write>(
189 &self,
190 _: Mode,
191 target: &mut W
192 ) -> Result<(), io::Error> {
193 target.write_all(&[*self as u8])?;
194 Ok(())
195 }
196}
197
198macro_rules! signed_content {
199 ($type:ident, $len:expr) => {
200 impl PrimitiveContent for $type {
201 const TAG: Tag = Tag::INTEGER;
202
203 #[allow(clippy::verbose_bit_mask)]
204 fn encoded_len(&self, _: Mode) -> usize {
205 if *self == 0 || *self == -1 {
206 return 1
207 }
208 let zeros = if *self < 0 {
209 (!*self).leading_zeros() as usize
210 }
211 else {
212 self.leading_zeros() as usize
213 };
214 if zeros & 0x07 == 0 { $len + 1 - (zeros >> 3)
216 }
217 else {
218 $len - (zeros >> 3)
219 }
220 }
221
222 fn write_encoded<W: io::Write>(
223 &self,
224 _: Mode,
225 target: &mut W
226 ) -> Result<(), io::Error> {
227 if *self == 0 {
228 target.write_all(&[0x00])?;
229 }
230 else if *self == -1 {
231 target.write_all(&[0xFF])?;
232 }
233 else if *self < 0 {
234 let mut val = self.swap_bytes();
235 let mut i = 0;
236 while i < $len {
238 if val as u8 != 0xFF {
239 break
240 }
241 val >>= 8;
242 i += 1;
243 }
244 if val & 0x80 != 0x80 {
247 target.write_all(&[0xFF])?;
248 }
249 while i < $len {
250 target.write_all(&[val as u8])?;
251 val >>= 8;
252 i += 1
253 }
254 }
255 else {
256 let mut val = self.swap_bytes();
257 let mut i = 0;
258 while i < $len {
260 if val as u8 != 0x00 {
261 break
262 }
263 val >>= 8;
264 i += 1;
265 }
266 if val & 0x80 == 0x80 {
269 target.write_all(&[0x00])?;
270 }
271 while i < $len {
272 target.write_all(&[val as u8])?;
273 val >>= 8;
274 i += 1
275 }
276 }
277 Ok(())
278 }
279 }
280 }
281}
282
283signed_content!(i16, 2);
284signed_content!(i32, 4);
285signed_content!(i64, 8);
286signed_content!(i128, 16);
287
288
289impl PrimitiveContent for () {
290 const TAG: Tag = Tag::NULL;
291
292 fn encoded_len(&self, _: Mode) -> usize {
293 0
294 }
295
296 fn write_encoded<W: io::Write>(
297 &self,
298 _: Mode,
299 _: &mut W
300 ) -> Result<(), io::Error> {
301 Ok(())
302 }
303}
304
305impl PrimitiveContent for bool {
306 const TAG: Tag = Tag::BOOLEAN;
307
308 fn encoded_len(&self, _: Mode) -> usize {
309 1
310 }
311
312 fn write_encoded<W: io::Write>(
313 &self,
314 _: Mode,
315 target: &mut W
316 ) -> Result<(), io::Error> {
317 if *self {
318 target.write_all(&[0xff])
319 }
320 else {
321 target.write_all(&[0])
322 }
323 }
324}
325
326impl PrimitiveContent for &'_ [u8] {
327 const TAG: Tag = Tag::OCTET_STRING;
328
329 fn encoded_len(&self, _: Mode) -> usize {
330 self.len()
331 }
332
333 fn write_encoded<W: io::Write>(
334 &self,
335 _: Mode,
336 target: &mut W
337 ) -> Result<(), io::Error> {
338 target.write_all(self)
339 }
340}
341
342
343pub struct Primitive<P> {
353 tag: Tag,
355
356 prim: P
358}
359
360impl<P: PrimitiveContent> Values for Primitive<P> {
361 fn encoded_len(&self, mode: Mode) -> usize {
362 let len = self.prim.encoded_len(mode);
363 self.tag.encoded_len()
364 + Length::Definite(len).encoded_len()
365 + len
366 }
367
368 fn write_encoded<W: io::Write>(
369 &self,
370 mode: Mode,
371 target: &mut W
372 ) -> Result<(), io::Error> {
373 self.tag.write_encoded(false, target)?;
374 Length::Definite(self.prim.encoded_len(mode)).write_encoded(target)?;
375 self.prim.write_encoded(mode, target)
376 }
377}
378
379
380#[cfg(test)]
383mod test {
384 use super::*;
385
386 fn test_der<T: PrimitiveContent>(value: T, expected: &[u8]) {
387 assert_eq!(value.encoded_len(Mode::Der), expected.len());
388 let mut target = Vec::new();
389 value.write_encoded(Mode::Der, &mut target).unwrap();
390 assert_eq!(target, expected);
391 }
392
393 #[test]
394 fn encode_u32() {
395 test_der(0u32, b"\0");
396 test_der(0x12u32, b"\x12");
397 test_der(0xf2u32, b"\0\xf2");
398 test_der(0x1234u32, b"\x12\x34");
399 test_der(0xf234u32, b"\0\xf2\x34");
400 test_der(0x123400u32, b"\x12\x34\x00");
401 test_der(0xf23400u32, b"\0\xf2\x34\x00");
402 test_der(0x12345678u32, b"\x12\x34\x56\x78");
403 test_der(0xA2345678u32, b"\x00\xA2\x34\x56\x78");
404 }
405
406 #[test]
407 fn encode_i32() {
408 test_der(0i32, b"\0");
409 test_der(0x12i32, b"\x12");
410 test_der(0xf2i32, b"\0\xf2");
411 test_der(0x1234i32, b"\x12\x34");
412 test_der(0xf234i32, b"\0\xf2\x34");
413 test_der(0x123400i32, b"\x12\x34\x00");
414 test_der(0xf23400i32, b"\0\xf2\x34\x00");
415 test_der(0x12345678i32, b"\x12\x34\x56\x78");
416 test_der(-1i32, b"\xFF");
417 test_der(-0xF0i32, b"\xFF\x10");
418 test_der(-0xF000i32, b"\xFF\x10\x00");
419 test_der(-12000i32, b"\xD1\x20");
420 test_der(-1200000i32, b"\xED\xB0\x80");
421 }
422}