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, asn1::integer::AsIntRef, 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
183impl AsIntRef for IntRef<'_> {
184 fn as_int_ref<'a>(&'a self) -> IntRef<'a> {
185 *self
186 }
187}
188
189#[cfg(feature = "alloc")]
190mod allocating {
191 use super::{IntRef, strip_leading_ones, validate_canonical};
192 use crate::{
193 BytesOwned, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader,
194 Result, Tag, Writer,
195 asn1::{Uint, integer::AsIntRef},
196 ord::OrdIsValueOrd,
197 referenced::{OwnedToRef, RefToOwned},
198 };
199 use alloc::{borrow::ToOwned, vec::Vec};
200
201 #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
209 pub struct Int {
210 inner: BytesOwned,
212 }
213
214 impl Int {
215 pub fn new(bytes: &[u8]) -> Result<Self> {
220 let inner = BytesOwned::new(strip_leading_ones(bytes))
221 .map_err(|_| ErrorKind::Length { tag: Self::TAG })?;
222
223 Ok(Self { inner })
224 }
225
226 #[must_use]
229 pub fn as_bytes(&self) -> &[u8] {
230 self.inner.as_slice()
231 }
232
233 #[must_use]
235 pub fn len(&self) -> Length {
236 self.inner.len()
237 }
238
239 #[must_use]
241 pub fn is_empty(&self) -> bool {
242 self.inner.is_empty()
243 }
244 }
245
246 impl AsIntRef for Int {
247 fn as_int_ref<'a>(&'a self) -> IntRef<'a> {
248 let inner = self.inner.as_ref();
249
250 IntRef { inner }
251 }
252 }
253
254 impl_any_conversions!(Int);
255
256 impl<'a> DecodeValue<'a> for Int {
257 type Error = Error;
258
259 fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
260 let bytes = BytesOwned::decode_value_parts(reader, header, Self::TAG)?;
261 validate_canonical(bytes.as_slice())?;
262
263 let result = Self::new(bytes.as_slice())?;
264
265 if result.value_len()? != header.length() {
267 return Err(reader.error(Self::TAG.non_canonical_error()));
268 }
269
270 Ok(result)
271 }
272 }
273
274 impl EncodeValue for Int {
275 fn value_len(&self) -> Result<Length> {
276 Ok(self.inner.len())
278 }
279
280 fn encode_value(&self, writer: &mut impl Writer) -> Result<()> {
281 writer.write(self.as_bytes())
282 }
283 }
284
285 impl<'a> From<&IntRef<'a>> for Int {
286 fn from(value: &IntRef<'a>) -> Int {
287 let inner = BytesOwned::new(value.as_bytes()).expect("Invalid Int");
288 Int { inner }
289 }
290 }
291
292 impl From<Uint> for Int {
293 fn from(value: Uint) -> Self {
294 let mut inner: Vec<u8> = Vec::new();
295
296 if value.value_len().expect("invalid Uint") > value.len() {
298 inner.push(0x00);
299 }
300
301 inner.extend_from_slice(value.as_bytes());
302 let inner = BytesOwned::new(inner).expect("invalid Uint");
303
304 Int { inner }
305 }
306 }
307
308 impl FixedTag for Int {
309 const TAG: Tag = Tag::Integer;
310 }
311
312 impl OrdIsValueOrd for Int {}
313
314 impl<'a> RefToOwned<'a> for IntRef<'a> {
315 type Owned = Int;
316 fn ref_to_owned(&self) -> Self::Owned {
317 let inner = self.inner.to_owned();
318
319 Int { inner }
320 }
321 }
322
323 impl OwnedToRef for Int {
324 type Borrowed<'a> = IntRef<'a>;
325 fn owned_to_ref(&self) -> Self::Borrowed<'_> {
326 let inner = self.inner.as_ref();
327
328 IntRef { inner }
329 }
330 }
331
332 macro_rules! impl_from_traits {
333 ($($int:ty),+) => {
334 $(
335 impl TryFrom<$int> for Int {
336 type Error = $crate::Error;
337
338 fn try_from(value: $int) -> $crate::Result<Self> {
339 let mut buf = [0u8; 16];
340 let buf = $crate::encode::encode_value_to_slice(&mut buf, &value)?;
341 Int::new(buf)
342 }
343 }
344 )+
345 };
346 }
347
348 impl_from_traits!(i8, i16, i32, i64, i128);
349
350 #[cfg(test)]
351 #[allow(clippy::unwrap_used)]
352 mod tests {
353 use super::Int;
354
355 #[test]
356 fn from_uint() {
357 assert_eq!(Int::try_from(i8::MIN).unwrap().as_bytes(), &[0x80]);
358 assert_eq!(Int::try_from(i8::MAX).unwrap().as_bytes(), &[0x7F]);
359 assert_eq!(Int::try_from(i16::MIN).unwrap().as_bytes(), &[0x80, 0]);
360 assert_eq!(Int::try_from(i16::MAX).unwrap().as_bytes(), &[0x7F, 0xFF]);
361 assert_eq!(
362 Int::try_from(i32::MIN).unwrap().as_bytes(),
363 &[0x80, 0, 0, 0]
364 );
365 assert_eq!(
366 Int::try_from(i32::MAX).unwrap().as_bytes(),
367 &[0x7F, 0xFF, 0xFF, 0xFF]
368 );
369 assert_eq!(
370 Int::try_from(i64::MIN).unwrap().as_bytes(),
371 &[
372 0x80, 0, 0, 0, 0, 0, 0, 0
374 ]
375 );
376 assert_eq!(
377 Int::try_from(i64::MAX).unwrap().as_bytes(),
378 &[
379 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ]
382 );
383 assert_eq!(
384 Int::try_from(i128::MIN).unwrap().as_bytes(),
385 &[0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
386 );
387 assert_eq!(
388 Int::try_from(i128::MAX).unwrap().as_bytes(),
389 &[
390 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ]
395 );
396 }
397 }
398}
399
400fn validate_canonical(bytes: &[u8]) -> Result<()> {
402 let non_canonical_error = Tag::Integer.non_canonical_error().into();
403
404 match bytes {
408 [] => Err(non_canonical_error),
409 [0x00, byte, ..] if *byte < 0x80 => Err(non_canonical_error),
410 [0xFF, byte, ..] if *byte >= 0x80 => Err(non_canonical_error),
411 _ => Ok(()),
412 }
413}
414
415fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> {
419 match N.checked_sub(bytes.len()) {
420 Some(offset) => {
421 let mut output = [0xFFu8; N];
422 output[offset..].copy_from_slice(bytes);
423 Ok(output)
424 }
425 None => {
426 let expected_len = Length::try_from(N)?;
427 let actual_len = Length::try_from(bytes.len())?;
428
429 Err(ErrorKind::Incomplete {
430 expected_len,
431 actual_len,
432 }
433 .into())
434 }
435 }
436}
437
438fn encode_bytes<W>(writer: &mut W, bytes: &[u8]) -> Result<()>
440where
441 W: Writer + ?Sized,
442{
443 writer.write(strip_leading_ones(bytes))
444}
445
446#[inline]
448fn negative_encoded_len(bytes: &[u8]) -> Result<Length> {
449 Length::try_from(strip_leading_ones(bytes).len())
450}
451
452pub(crate) fn strip_leading_ones(mut bytes: &[u8]) -> &[u8] {
454 while let Some((byte, rest)) = bytes.split_first() {
455 if *byte == 0xFF && is_highest_bit_set(rest) {
456 bytes = rest;
457 continue;
458 }
459
460 break;
461 }
462
463 bytes
464}
465
466#[cfg(test)]
467#[allow(clippy::unwrap_used)]
468mod tests {
469 use super::{IntRef, validate_canonical};
470 use crate::{Decode, Encode, SliceWriter, asn1::integer::tests::*};
471
472 #[test]
473 fn validate_canonical_ok() {
474 assert_eq!(validate_canonical(&[0x00]), Ok(()));
475 assert_eq!(validate_canonical(&[0x01]), Ok(()));
476 assert_eq!(validate_canonical(&[0x00, 0x80]), Ok(()));
477 assert_eq!(validate_canonical(&[0xFF, 0x00]), Ok(()));
478 }
479
480 #[test]
481 fn validate_canonical_err() {
482 assert!(validate_canonical(&[]).is_err());
484
485 assert!(validate_canonical(&[0x00, 0x00]).is_err());
487
488 assert!(validate_canonical(&[0xFF, 0x80]).is_err());
490 }
491
492 #[test]
493 fn decode_intref() {
494 assert_eq!(&[0], IntRef::from_der(I0_BYTES).unwrap().as_bytes());
497 assert_eq!(&[127], IntRef::from_der(I127_BYTES).unwrap().as_bytes());
498 assert_eq!(&[0, 128], IntRef::from_der(I128_BYTES).unwrap().as_bytes());
499 assert_eq!(&[0, 255], IntRef::from_der(I255_BYTES).unwrap().as_bytes());
500
501 assert_eq!(
502 &[0x01, 0x00],
503 IntRef::from_der(I256_BYTES).unwrap().as_bytes()
504 );
505
506 assert_eq!(
507 &[0x7F, 0xFF],
508 IntRef::from_der(I32767_BYTES).unwrap().as_bytes()
509 );
510
511 assert_eq!(&[128], IntRef::from_der(INEG128_BYTES).unwrap().as_bytes());
513 assert_eq!(
514 &[255, 127],
515 IntRef::from_der(INEG129_BYTES).unwrap().as_bytes()
516 );
517 assert_eq!(
518 &[128, 0],
519 IntRef::from_der(INEG32768_BYTES).unwrap().as_bytes()
520 );
521 }
522
523 #[test]
524 fn encode_intref() {
525 for &example in &[
526 I0_BYTES,
527 I127_BYTES,
528 I128_BYTES,
529 I255_BYTES,
530 I256_BYTES,
531 I32767_BYTES,
532 ] {
533 let uint = IntRef::from_der(example).unwrap();
534
535 let mut buf = [0u8; 128];
536 let mut writer = SliceWriter::new(&mut buf);
537 uint.encode(&mut writer).unwrap();
538
539 let result = writer.finish().unwrap();
540 assert_eq!(example, result);
541 }
542
543 for &example in &[INEG128_BYTES, INEG129_BYTES, INEG32768_BYTES] {
544 let uint = IntRef::from_der(example).unwrap();
545
546 let mut buf = [0u8; 128];
547 let mut writer = SliceWriter::new(&mut buf);
548 uint.encode(&mut writer).unwrap();
549
550 let result = writer.finish().unwrap();
551 assert_eq!(example, result);
552 }
553 }
554}