1use crate::{Length, Result, Tag, Writer};
4
5pub(crate) fn decode_to_slice(bytes: &[u8]) -> Result<&[u8]> {
10 match bytes {
17 [] => Err(Tag::Integer.non_canonical_error()),
18 [0] => Ok(bytes),
19 [0, byte, ..] if *byte < 0x80 => Err(Tag::Integer.non_canonical_error()),
20 [0, rest @ ..] => Ok(rest),
21 [byte, ..] if *byte >= 0x80 => Err(Tag::Integer.value_error()),
22 _ => Ok(bytes),
23 }
24}
25
26pub(super) fn decode_to_array<const N: usize>(bytes: &[u8]) -> Result<[u8; N]> {
29 let input = decode_to_slice(bytes)?;
30
31 let num_zeroes = N
33 .checked_sub(input.len())
34 .ok_or_else(|| Tag::Integer.length_error())?;
35
36 let mut output = [0u8; N];
38 output[num_zeroes..].copy_from_slice(input);
39 Ok(output)
40}
41
42pub(crate) fn encode_bytes<W>(encoder: &mut W, bytes: &[u8]) -> Result<()>
44where
45 W: Writer + ?Sized,
46{
47 let bytes = strip_leading_zeroes(bytes);
48
49 if needs_leading_zero(bytes) {
50 encoder.write_byte(0)?;
51 }
52
53 encoder.write(bytes)
54}
55
56#[inline]
58pub(crate) fn encoded_len(bytes: &[u8]) -> Result<Length> {
59 let bytes = strip_leading_zeroes(bytes);
60 Length::try_from(bytes.len())? + u8::from(needs_leading_zero(bytes))
61}
62
63pub(crate) fn strip_leading_zeroes(mut bytes: &[u8]) -> &[u8] {
65 while let Some((byte, rest)) = bytes.split_first() {
66 if *byte == 0 && !rest.is_empty() {
67 bytes = rest;
68 } else {
69 break;
70 }
71 }
72
73 bytes
74}
75
76fn needs_leading_zero(bytes: &[u8]) -> bool {
78 matches!(bytes.get(0), Some(byte) if *byte >= 0x80)
79}
80
81#[cfg(test)]
82mod tests {
83 use super::decode_to_array;
84 use crate::{ErrorKind, Tag};
85
86 #[test]
87 fn decode_to_array_no_leading_zero() {
88 let arr = decode_to_array::<4>(&[1, 2]).unwrap();
89 assert_eq!(arr, [0, 0, 1, 2]);
90 }
91
92 #[test]
93 fn decode_to_array_leading_zero() {
94 let arr = decode_to_array::<4>(&[0x00, 0xFF, 0xFE]).unwrap();
95 assert_eq!(arr, [0x00, 0x00, 0xFF, 0xFE]);
96 }
97
98 #[test]
99 fn decode_to_array_extra_zero() {
100 let err = decode_to_array::<4>(&[0, 1, 2]).err().unwrap();
101 assert_eq!(err.kind(), ErrorKind::Noncanonical { tag: Tag::Integer });
102 }
103
104 #[test]
105 fn decode_to_array_missing_zero() {
106 let err = decode_to_array::<4>(&[0xFF, 0xFE]).err().unwrap();
108 assert_eq!(err.kind(), ErrorKind::Value { tag: Tag::Integer });
109 }
110
111 #[test]
112 fn decode_to_array_oversized_input() {
113 let err = decode_to_array::<1>(&[1, 2, 3]).err().unwrap();
114 assert_eq!(err.kind(), ErrorKind::Length { tag: Tag::Integer });
115 }
116}