1use super::{is_highest_bit_set, uint, value_cmp};
4use crate::{
5 AnyRef, BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
6 Result, Tag, ValueOrd, Writer, ord::OrdIsValueOrd,
7};
8use core::cmp::Ordering;
9
10#[cfg(feature = "alloc")]
11pub use allocating::Int;
12
13macro_rules! impl_encoding_traits {
14 ($($int:ty => $uint:ty),+) => {
15 $(
16 impl<'a> DecodeValue<'a> for $int {
17 type Error = $crate::Error;
18
19 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> $crate::Result<Self> {
20 let mut buf = [0u8; Self::BITS as usize / 8];
21 let max_length = u32::from(header.length()) as usize;
22
23 if max_length == 0 {
24 return Err(reader.error(Tag::Integer.length_error()));
25 }
26
27 if max_length > buf.len() {
28 return Err(reader.error(Self::TAG.non_canonical_error()));
29 }
30
31 let bytes = reader.read_into(&mut buf[..max_length])?;
32
33 #[allow(clippy::cast_possible_wrap)]
35 let result = if is_highest_bit_set(bytes) {
36 <$uint>::from_be_bytes(decode_to_array(bytes)?) as $int
37 } else {
38 Self::from_be_bytes(uint::decode_to_array(bytes)?)
39 };
40
41 if header.length() != result.value_len()? {
43 return Err(reader.error(Self::TAG.non_canonical_error()));
44 }
45
46 Ok(result)
47 }
48 }
49
50 impl EncodeValue for $int {
51 fn value_len(&self) -> Result<Length> {
52 if *self < 0 {
53 #[allow(clippy::cast_sign_loss)]
55 negative_encoded_len(&(*self as $uint).to_be_bytes())
56 } else {
57 uint::encoded_len(&self.to_be_bytes())
58 }
59 }
60
61 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
62 if *self < 0 {
63 #[allow(clippy::cast_sign_loss)]
65 encode_bytes(writer, &(*self as $uint).to_be_bytes())
66 } else {
67 uint::encode_bytes(writer, &self.to_be_bytes())
68 }
69 }
70 }
71
72 impl FixedTag for $int {
73 const TAG: Tag = Tag::Integer;
74 }
75
76 impl ValueOrd for $int {
77 fn value_cmp(&self, other: &Self) -> Result<Ordering> {
78 value_cmp(*self, *other)
79 }
80 }
81
82 impl TryFrom<AnyRef<'_>> for $int {
83 type Error = Error;
84
85 fn try_from(any: AnyRef<'_>) -> Result<Self> {
86 any.decode_as()
87 }
88 }
89 )+
90 };
91}
92
93impl_encoding_traits!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128);
94
95#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
103pub struct IntRef<'a> {
104 inner: &'a BytesRef,
106}
107
108impl<'a> IntRef<'a> {
109 pub fn new(bytes: &'a [u8]) -> Result<Self> {
114 let inner = BytesRef::new(strip_leading_ones(bytes))
115 .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
116
117 Ok(Self { inner })
118 }
119
120 #[must_use]
123 pub fn as_bytes(&self) -> &'a [u8] {
124 self.inner.as_slice()
125 }
126
127 #[must_use]
129 pub fn len(&self) -> Length {
130 self.inner.len()
131 }
132
133 #[must_use]
135 pub fn is_empty(&self) -> bool {
136 self.inner.is_empty()
137 }
138}
139
140impl_any_conversions!(IntRef<'a>, 'a);
141
142impl<'a> DecodeValue<'a> for IntRef<'a> {
143 type Error = Error;
144
145 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
146 let bytes = <&'a BytesRef>::decode_value(reader, header)?;
147 validate_canonical(bytes.as_slice())?;
148
149 let result = Self::new(bytes.as_slice())?;
150
151 if result.value_len()? != header.length() {
153 return Err(reader.error(Self::TAG.non_canonical_error()));
154 }
155
156 Ok(result)
157 }
158}
159
160impl EncodeValue for IntRef<'_> {
161 fn value_len(&self) -> Result<Length> {
162 Ok(self.inner.len())
164 }
165
166 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
167 writer.write(self.as_bytes())
168 }
169}
170
171impl<'a> From<&IntRef<'a>> for IntRef<'a> {
172 fn from(value: &IntRef<'a>) -> IntRef<'a> {
173 *value
174 }
175}
176
177impl FixedTag for IntRef<'_> {
178 const TAG: Tag = Tag::Integer;
179}
180
181impl OrdIsValueOrd for IntRef<'_> {}
182
183#[cfg(feature = "alloc")]
184mod allocating {
185 use super::{IntRef, strip_leading_ones, validate_canonical};
186 use crate::{
187 BytesOwned, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
188 Result, Tag, Writer,
189 asn1::Uint,
190 ord::OrdIsValueOrd,
191 referenced::{OwnedToRef, RefToOwned},
192 };
193 use alloc::{borrow::ToOwned, vec::Vec};
194
195 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
203 pub struct Int {
204 inner: BytesOwned,
206 }
207
208 impl Int {
209 pub fn new(bytes: &[u8]) -> Result<Self> {
214 let inner = BytesOwned::new(strip_leading_ones(bytes))
215 .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
216
217 Ok(Self { inner })
218 }
219
220 #[must_use]
223 pub fn as_bytes(&self) -> &[u8] {
224 self.inner.as_slice()
225 }
226
227 #[must_use]
229 pub fn len(&self) -> Length {
230 self.inner.len()
231 }
232
233 #[must_use]
235 pub fn is_empty(&self) -> bool {
236 self.inner.is_empty()
237 }
238 }
239
240 impl_any_conversions!(Int);
241
242 impl<'a> DecodeValue<'a> for Int {
243 type Error = Error;
244
245 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
246 let bytes = BytesOwned::decode_value_parts(reader, header, Self::TAG)?;
247 validate_canonical(bytes.as_slice())?;
248
249 let result = Self::new(bytes.as_slice())?;
250
251 if result.value_len()? != header.length() {
253 return Err(reader.error(Self::TAG.non_canonical_error()));
254 }
255
256 Ok(result)
257 }
258 }
259
260 impl EncodeValue for Int {
261 fn value_len(&self) -> Result<Length> {
262 Ok(self.inner.len())
264 }
265
266 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
267 writer.write(self.as_bytes())
268 }
269 }
270
271 impl<'a> From<&IntRef<'a>> for Int {
272 fn from(value: &IntRef<'a>) -> Int {
273 let inner = BytesOwned::new(value.as_bytes()).expect("Invalid Int");
274 Int { inner }
275 }
276 }
277
278 impl From<Uint> for Int {
279 fn from(value: Uint) -> Self {
280 let mut inner: Vec<u8> = Vec::new();
281
282 if value.value_len().expect("invalid Uint") > value.len() {
284 inner.push(0x00);
285 }
286
287 inner.extend_from_slice(value.as_bytes());
288 let inner = BytesOwned::new(inner).expect("invalid Uint");
289
290 Int { inner }
291 }
292 }
293
294 impl FixedTag for Int {
295 const TAG: Tag = Tag::Integer;
296 }
297
298 impl OrdIsValueOrd for Int {}
299
300 impl<'a> RefToOwned<'a> for IntRef<'a> {
301 type Owned = Int;
302 fn ref_to_owned(&self) -> Self::Owned {
303 let inner = self.inner.to_owned();
304
305 Int { inner }
306 }
307 }
308
309 impl OwnedToRef for Int {
310 type Borrowed<'a> = IntRef<'a>;
311 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
312 let inner = self.inner.as_ref();
313
314 IntRef { inner }
315 }
316 }
317
318 macro_rules! impl_from_traits {
319 ($($int:ty),+) => {
320 $(
321 impl TryFrom<$int> for Int {
322 type Error = $crate::Error;
323
324 fn try_from(value: $int) -> $crate::Result<Self> {
325 let mut buf = [0u8; 16];
326 let buf = $crate::encode::encode_value_to_slice(&mut buf, &value)?;
327 Int::new(buf)
328 }
329 }
330 )+
331 };
332 }
333
334 impl_from_traits!(i8, i16, i32, i64, i128);
335
336 #[cfg(test)]
337 #[allow(clippy::unwrap_used)]
338 mod tests {
339 use super::Int;
340
341 #[test]
342 fn from_uint() {
343 assert_eq!(Int::try_from(i8::MIN).unwrap().as_bytes(), &[0x80]);
344 assert_eq!(Int::try_from(i8::MAX).unwrap().as_bytes(), &[0x7F]);
345 assert_eq!(Int::try_from(i16::MIN).unwrap().as_bytes(), &[0x80, 0]);
346 assert_eq!(Int::try_from(i16::MAX).unwrap().as_bytes(), &[0x7F, 0xFF]);
347 assert_eq!(
348 Int::try_from(i32::MIN).unwrap().as_bytes(),
349 &[0x80, 0, 0, 0]
350 );
351 assert_eq!(
352 Int::try_from(i32::MAX).unwrap().as_bytes(),
353 &[0x7F, 0xFF, 0xFF, 0xFF]
354 );
355 assert_eq!(
356 Int::try_from(i64::MIN).unwrap().as_bytes(),
357 &[
358 0x80, 0, 0, 0, 0, 0, 0, 0
360 ]
361 );
362 assert_eq!(
363 Int::try_from(i64::MAX).unwrap().as_bytes(),
364 &[
365 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]
368 );
369 assert_eq!(
370 Int::try_from(i128::MIN).unwrap().as_bytes(),
371 &[0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
372 );
373 assert_eq!(
374 Int::try_from(i128::MAX).unwrap().as_bytes(),
375 &[
376 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ]
381 );
382 }
383 }
384}
385
386fn validate_canonical(bytes: &[u8]) -> Result<()> {
388 let non_canonical_error = Tag::Integer.non_canonical_error().into();
389
390 match bytes {
394 [] => Err(non_canonical_error),
395 [0x00, byte, ..] if *byte < 0x80 => Err(non_canonical_error),
396 [0xFF, byte, ..] if *byte >= 0x80 => Err(non_canonical_error),
397 _ => Ok(()),
398 }
399}
400
401fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> {
405 match N.checked_sub(bytes.len()) {
406 Some(offset) => {
407 let mut output = [0xFFu8; N];
408 output[offset..].copy_from_slice(bytes);
409 Ok(output)
410 }
411 None => {
412 let expected_len = Length::try_from(N)?;
413 let actual_len = Length::try_from(bytes.len())?;
414
415 Err(ErrorKind::Incomplete {
416 expected_len,
417 actual_len,
418 }
419 .into())
420 }
421 }
422}
423
424fn encode_bytes<W>(writer: &mut W, bytes: &[u8]) -> Result<()>
426where
427 W: Writer + ?Sized,
428{
429 writer.write(strip_leading_ones(bytes))
430}
431
432#[inline]
434fn negative_encoded_len(bytes: &[u8]) -> Result<Length> {
435 Length::try_from(strip_leading_ones(bytes).len())
436}
437
438pub(crate) fn strip_leading_ones(mut bytes: &[u8]) -> &[u8] {
440 while let Some((byte, rest)) = bytes.split_first() {
441 if *byte == 0xFF && is_highest_bit_set(rest) {
442 bytes = rest;
443 continue;
444 }
445
446 break;
447 }
448
449 bytes
450}
451
452#[cfg(test)]
453#[allow(clippy::unwrap_used)]
454mod tests {
455 use super::{IntRef, validate_canonical};
456 use crate::{Decode, Encode, SliceWriter, asn1::integer::tests::*};
457
458 #[test]
459 fn validate_canonical_ok() {
460 assert_eq!(validate_canonical(&[0x00]), Ok(()));
461 assert_eq!(validate_canonical(&[0x01]), Ok(()));
462 assert_eq!(validate_canonical(&[0x00, 0x80]), Ok(()));
463 assert_eq!(validate_canonical(&[0xFF, 0x00]), Ok(()));
464 }
465
466 #[test]
467 fn validate_canonical_err() {
468 assert!(validate_canonical(&[]).is_err());
470
471 assert!(validate_canonical(&[0x00, 0x00]).is_err());
473
474 assert!(validate_canonical(&[0xFF, 0x80]).is_err());
476 }
477
478 #[test]
479 fn decode_intref() {
480 assert_eq!(&[0], IntRef::from_der(I0_BYTES).unwrap().as_bytes());
483 assert_eq!(&[127], IntRef::from_der(I127_BYTES).unwrap().as_bytes());
484 assert_eq!(&[0, 128], IntRef::from_der(I128_BYTES).unwrap().as_bytes());
485 assert_eq!(&[0, 255], IntRef::from_der(I255_BYTES).unwrap().as_bytes());
486
487 assert_eq!(
488 &[0x01, 0x00],
489 IntRef::from_der(I256_BYTES).unwrap().as_bytes()
490 );
491
492 assert_eq!(
493 &[0x7F, 0xFF],
494 IntRef::from_der(I32767_BYTES).unwrap().as_bytes()
495 );
496
497 assert_eq!(&[128], IntRef::from_der(INEG128_BYTES).unwrap().as_bytes());
499 assert_eq!(
500 &[255, 127],
501 IntRef::from_der(INEG129_BYTES).unwrap().as_bytes()
502 );
503 assert_eq!(
504 &[128, 0],
505 IntRef::from_der(INEG32768_BYTES).unwrap().as_bytes()
506 );
507 }
508
509 #[test]
510 fn encode_intref() {
511 for &example in &[
512 I0_BYTES,
513 I127_BYTES,
514 I128_BYTES,
515 I255_BYTES,
516 I256_BYTES,
517 I32767_BYTES,
518 ] {
519 let uint = IntRef::from_der(example).unwrap();
520
521 let mut buf = [0u8; 128];
522 let mut writer = SliceWriter::new(&mut buf);
523 uint.encode(&mut writer).unwrap();
524
525 let result = writer.finish().unwrap();
526 assert_eq!(example, result);
527 }
528
529 for &example in &[INEG128_BYTES, INEG129_BYTES, INEG32768_BYTES] {
530 let uint = IntRef::from_der(example).unwrap();
531
532 let mut buf = [0u8; 128];
533 let mut writer = SliceWriter::new(&mut buf);
534 uint.encode(&mut writer).unwrap();
535
536 let result = writer.finish().unwrap();
537 assert_eq!(example, result);
538 }
539 }
540}