1use super::value_cmp;
4use crate::{
5 AnyRef, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
6 Result, Tag, ValueOrd, Writer, asn1::integer::AsUintRef, ord::OrdIsValueOrd,
7};
8use core::cmp::Ordering;
9
10#[cfg(feature = "alloc")]
11pub use allocating::Uint;
12
13macro_rules! impl_encoding_traits {
14 ($($uint:ty),+) => {
15 $(
16 impl<'a> DecodeValue<'a> for $uint {
17 type Error = $crate::Error;
18
19 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
20 const UNSIGNED_HEADROOM: usize = 1;
23
24 let mut buf = [0u8; (Self::BITS as usize / 8) + UNSIGNED_HEADROOM];
25 let max_length = u32::from(header.length()) as usize;
26
27 if max_length == 0 {
28 return Err(reader.error(Tag::Integer.length_error()));
29 }
30
31 if max_length > buf.len() {
32 return Err(reader.error(Self::TAG.non_canonical_error()));
33 }
34
35 let bytes = reader.read_into(&mut buf[..max_length])?;
36 let result = Self::from_be_bytes(
37 decode_to_array(bytes).map_err(|err| reader.error(err.kind()))?
38 );
39
40 if header.length() != result.value_len()? {
42 return Err(reader.error(Self::TAG.non_canonical_error()));
43 }
44
45 Ok(result)
46 }
47 }
48
49 impl EncodeValue for $uint {
50 fn value_len(&self) -> Result<Length> {
51 encoded_len(&self.to_be_bytes())
52 }
53
54 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
55 encode_bytes(writer, &self.to_be_bytes())
56 }
57 }
58
59 impl FixedTag for $uint {
60 const TAG: Tag = Tag::Integer;
61 }
62
63 impl ValueOrd for $uint {
64 fn value_cmp(&self, other: &Self) -> Result<Ordering> {
65 value_cmp(*self, *other)
66 }
67 }
68
69 impl TryFrom<AnyRef<'_>> for $uint {
70 type Error = Error;
71
72 fn try_from(any: AnyRef<'_>) -> Result<Self> {
73 any.decode_as()
74 }
75 }
76 )+
77 };
78}
79
80impl_encoding_traits!(u8, u16, u32, u64, u128);
81
82#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
90pub struct UintRef<'a> {
91 inner: &'a BytesRef,
93}
94
95impl<'a> UintRef<'a> {
96 pub fn new(bytes: &'a [u8]) -> Result<Self> {
101 let inner = BytesRef::new(strip_leading_zeroes(bytes))
102 .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
103
104 Ok(Self { inner })
105 }
106
107 #[must_use]
110 pub fn as_bytes(&self) -> &'a [u8] {
111 self.inner.as_slice()
112 }
113
114 #[must_use]
116 pub fn len(&self) -> Length {
117 self.inner.len()
118 }
119
120 #[must_use]
122 pub fn is_empty(&self) -> bool {
123 self.inner.is_empty()
124 }
125}
126
127impl_any_conversions!(UintRef<'a>, 'a);
128
129impl<'a> DecodeValue<'a> for UintRef<'a> {
130 type Error = Error;
131
132 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
133 let bytes = <&'a BytesRef>::decode_value(reader, header)?.as_slice();
134 let result = Self::new(decode_to_slice(bytes).map_err(|err| reader.error(err.kind()))?)?;
135
136 if result.value_len()? != header.length() {
138 return Err(reader.error(Self::TAG.non_canonical_error()));
139 }
140
141 Ok(result)
142 }
143}
144
145impl EncodeValue for UintRef<'_> {
146 fn value_len(&self) -> Result<Length> {
147 encoded_len(self.inner.as_slice())
148 }
149
150 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
151 if self.value_len()? > self.len() {
153 writer.write_byte(0)?;
154 }
155
156 writer.write(self.as_bytes())
157 }
158}
159
160impl<'a> From<&UintRef<'a>> for UintRef<'a> {
161 fn from(value: &UintRef<'a>) -> UintRef<'a> {
162 *value
163 }
164}
165
166impl FixedTag for UintRef<'_> {
167 const TAG: Tag = Tag::Integer;
168}
169
170impl OrdIsValueOrd for UintRef<'_> {}
171
172impl AsUintRef for UintRef<'_> {
173 fn as_uint_ref<'a>(&'a self) -> UintRef<'a> {
174 *self
175 }
176}
177
178#[cfg(feature = "alloc")]
179mod allocating {
180 use super::{UintRef, decode_to_slice, encoded_len, strip_leading_zeroes};
181 use crate::{
182 BytesOwned, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
183 Result, Tag, Writer,
184 asn1::integer::AsUintRef,
185 ord::OrdIsValueOrd,
186 referenced::{OwnedToRef, RefToOwned},
187 };
188 use alloc::borrow::ToOwned;
189
190 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
198 pub struct Uint {
199 inner: BytesOwned,
201 }
202
203 impl Uint {
204 pub fn new(bytes: &[u8]) -> Result<Self> {
209 let inner = BytesOwned::new(strip_leading_zeroes(bytes))
210 .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
211
212 Ok(Self { inner })
213 }
214
215 #[must_use]
218 pub fn as_bytes(&self) -> &[u8] {
219 self.inner.as_slice()
220 }
221
222 #[must_use]
224 pub fn len(&self) -> Length {
225 self.inner.len()
226 }
227
228 #[must_use]
230 pub fn is_empty(&self) -> bool {
231 self.inner.is_empty()
232 }
233 }
234
235 impl_any_conversions!(Uint);
236
237 impl<'a> DecodeValue<'a> for Uint {
238 type Error = Error;
239
240 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
241 let bytes = BytesOwned::decode_value_parts(reader, header, Self::TAG)?;
242 let result = Self::new(decode_to_slice(bytes.as_slice())?)?;
243
244 if result.value_len()? != header.length() {
246 return Err(reader.error(Self::TAG.non_canonical_error()));
247 }
248
249 Ok(result)
250 }
251 }
252
253 impl EncodeValue for Uint {
254 fn value_len(&self) -> Result<Length> {
255 encoded_len(self.inner.as_slice())
256 }
257
258 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
259 if self.value_len()? > self.len() {
261 writer.write_byte(0)?;
262 }
263
264 writer.write(self.as_bytes())
265 }
266 }
267
268 impl<'a> From<&UintRef<'a>> for Uint {
269 fn from(value: &UintRef<'a>) -> Uint {
270 Uint {
271 inner: value.inner.into(),
272 }
273 }
274 }
275
276 impl FixedTag for Uint {
277 const TAG: Tag = Tag::Integer;
278 }
279
280 impl OrdIsValueOrd for Uint {}
281
282 impl<'a> RefToOwned<'a> for UintRef<'a> {
283 type Owned = Uint;
284 fn ref_to_owned(&self) -> Self::Owned {
285 let inner = self.inner.to_owned();
286
287 Uint { inner }
288 }
289 }
290
291 impl OwnedToRef for Uint {
292 type Borrowed<'a> = UintRef<'a>;
293 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
294 let inner = self.inner.as_ref();
295
296 UintRef { inner }
297 }
298 }
299
300 impl AsUintRef for Uint {
301 fn as_uint_ref<'a>(&'a self) -> UintRef<'a> {
302 let inner = self.inner.as_ref();
303
304 UintRef { inner }
305 }
306 }
307
308 macro_rules! impl_from_traits {
309 ($($uint:ty),+) => {
310 $(
311 impl TryFrom<$uint> for Uint {
312 type Error = $crate::Error;
313
314 fn try_from(value: $uint) -> $crate::Result<Self> {
315 let mut buf = [0u8; 17];
316 let buf = $crate::encode::encode_value_to_slice(&mut buf, &value)?;
317 Uint::new(buf)
318 }
319 }
320 )+
321 };
322 }
323
324 impl_from_traits!(u8, u16, u32, u64, u128);
325
326 #[cfg(test)]
327 #[allow(clippy::unwrap_used)]
328 mod tests {
329 use super::Uint;
330
331 #[test]
332 fn from_uint() {
333 assert_eq!(Uint::try_from(u8::MIN).unwrap().as_bytes(), &[0]);
334 assert_eq!(Uint::try_from(u8::MAX).unwrap().as_bytes(), &[0xFF]);
335 assert_eq!(Uint::try_from(u16::MIN).unwrap().as_bytes(), &[0]);
336 assert_eq!(Uint::try_from(u16::MAX).unwrap().as_bytes(), &[0xFF; 2]);
337 assert_eq!(Uint::try_from(u32::MIN).unwrap().as_bytes(), &[0]);
338 assert_eq!(Uint::try_from(u32::MAX).unwrap().as_bytes(), &[0xFF; 4]);
339 assert_eq!(Uint::try_from(u64::MIN).unwrap().as_bytes(), &[0]);
340 assert_eq!(Uint::try_from(u64::MAX).unwrap().as_bytes(), &[0xFF; 8]);
341 assert_eq!(Uint::try_from(u128::MIN).unwrap().as_bytes(), &[0]);
342 assert_eq!(Uint::try_from(u128::MAX).unwrap().as_bytes(), &[0xFF; 16]);
343 }
344 }
345}
346
347pub(crate) fn decode_to_slice(bytes: &[u8]) -> Result<&[u8]> {
352 match bytes {
359 [] => Err(Tag::Integer.non_canonical_error().into()),
360 [0] => Ok(bytes),
361 [0, byte, ..] if *byte < 0x80 => Err(Tag::Integer.non_canonical_error().into()),
362 [0, rest @ ..] => Ok(rest),
363 [byte, ..] if *byte >= 0x80 => Err(Tag::Integer.value_error().into()),
364 _ => Ok(bytes),
365 }
366}
367
368pub(super) fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> {
371 let input = decode_to_slice(bytes)?;
372
373 let num_zeroes = N
375 .checked_sub(input.len())
376 .ok_or_else(|| Tag::Integer.length_error())?;
377
378 let mut output = [0u8; N];
380 output[num_zeroes..].copy_from_slice(input);
381 Ok(output)
382}
383
384pub(crate) fn encode_bytes<W>(writer: &mut W, bytes: &[u8]) -> Result<()>
386where
387 W: Writer + ?Sized,
388{
389 let bytes = strip_leading_zeroes(bytes);
390
391 if needs_leading_zero(bytes) {
392 writer.write_byte(0)?;
393 }
394
395 writer.write(bytes)
396}
397
398#[inline]
400pub(crate) fn encoded_len(bytes: &[u8]) -> Result<Length> {
401 let bytes = strip_leading_zeroes(bytes);
402 Length::try_from(bytes.len())? + u8::from(needs_leading_zero(bytes))
403}
404
405pub(crate) fn strip_leading_zeroes(mut bytes: &[u8]) -> &[u8] {
407 while let Some((byte, rest)) = bytes.split_first() {
408 if *byte == 0 && !rest.is_empty() {
409 bytes = rest;
410 } else {
411 break;
412 }
413 }
414
415 bytes
416}
417
418fn needs_leading_zero(bytes: &[u8]) -> bool {
420 matches!(bytes.first(), Some(byte) if *byte >= 0x80)
421}
422
423#[cfg(test)]
424#[allow(clippy::unwrap_used)]
425mod tests {
426 use super::{UintRef, decode_to_array};
427 use crate::{AnyRef, Decode, Encode, ErrorKind, SliceWriter, Tag, asn1::integer::tests::*};
428
429 #[test]
430 fn decode_to_array_no_leading_zero() {
431 let arr = decode_to_array::<4>(&[1, 2]).unwrap();
432 assert_eq!(arr, [0, 0, 1, 2]);
433 }
434
435 #[test]
436 fn decode_to_array_leading_zero() {
437 let arr = decode_to_array::<4>(&[0x00, 0xFF, 0xFE]).unwrap();
438 assert_eq!(arr, [0x00, 0x00, 0xFF, 0xFE]);
439 }
440
441 #[test]
442 fn decode_to_array_extra_zero() {
443 let err = decode_to_array::<4>(&[0, 1, 2]).err().unwrap();
444 assert_eq!(err.kind(), ErrorKind::Noncanonical { tag: Tag::Integer });
445 }
446
447 #[test]
448 fn decode_to_array_missing_zero() {
449 let err = decode_to_array::<4>(&[0xFF, 0xFE]).err().unwrap();
451 assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer });
452 }
453
454 #[test]
455 fn decode_to_array_oversized_input() {
456 let err = decode_to_array::<1>(&[1, 2, 3]).err().unwrap();
457 assert_eq!(err.kind(), ErrorKind::Length { tag: Tag::Integer });
458 }
459
460 #[test]
461 fn decode_uintref() {
462 assert_eq!(&[0], UintRef::from_der(I0_BYTES).unwrap().as_bytes());
463 assert_eq!(&[127], UintRef::from_der(I127_BYTES).unwrap().as_bytes());
464 assert_eq!(&[128], UintRef::from_der(I128_BYTES).unwrap().as_bytes());
465 assert_eq!(&[255], UintRef::from_der(I255_BYTES).unwrap().as_bytes());
466
467 assert_eq!(
468 &[0x01, 0x00],
469 UintRef::from_der(I256_BYTES).unwrap().as_bytes()
470 );
471
472 assert_eq!(
473 &[0x7F, 0xFF],
474 UintRef::from_der(I32767_BYTES).unwrap().as_bytes()
475 );
476 }
477
478 #[test]
479 fn encode_uintref() {
480 for &example in &[
481 I0_BYTES,
482 I127_BYTES,
483 I128_BYTES,
484 I255_BYTES,
485 I256_BYTES,
486 I32767_BYTES,
487 ] {
488 let uint = UintRef::from_der(example).unwrap();
489
490 let mut buf = [0u8; 128];
491 let mut writer = SliceWriter::new(&mut buf);
492 uint.encode(&mut writer).unwrap();
493
494 let result = writer.finish().unwrap();
495 assert_eq!(example, result);
496 }
497 }
498
499 #[test]
500 fn reject_oversize_without_extra_zero() {
501 let err = UintRef::try_from(AnyRef::new(Tag::Integer, &[0x81]).unwrap())
502 .err()
503 .unwrap();
504
505 assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer });
506 }
507}