structured_pades/
bytes.rs1use crate::byte_machine::{Decoder, Step};
4use crate::error::{Error, ErrorKind, Result, Syntax};
5use crate::source::Location;
6use core::cmp::Ordering;
7use structured_asn1::memory::{OwnedVec, Work};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Form {
12 Name,
14 Literal,
16 Hexadecimal,
18}
19
20#[derive(Debug, Clone, Copy)]
23pub struct Bytes<'a> {
24 raw: &'a [u8],
25 form: Form,
26 location: Location,
27}
28
29impl<'a> Bytes<'a> {
30 pub fn new(raw: &'a [u8], form: Form, location: Location) -> Result<Self> {
33 if location.span().length != raw.len() as u64 {
34 return Err(Error {
35 kind: ErrorKind::Foreign,
36 location,
37 });
38 }
39 Ok(Self {
40 raw,
41 form,
42 location,
43 })
44 }
45
46 #[must_use]
48 pub fn as_bytes(self) -> &'a [u8] {
49 self.raw
50 }
51
52 #[must_use]
54 pub fn location(self) -> Location {
55 self.location
56 }
57
58 pub fn decode_in<W: Work>(self, work: &W) -> Result<OwnedVec<u8, W>> {
61 let mut cursor = Cursor::new(self);
62 let mut out = work.vector();
63 while let Some(byte) = cursor.next(work)? {
64 out.try_push(byte).map_err(|cause| Error {
65 kind: ErrorKind::Resource(cause),
66 location: cursor.point(),
67 })?;
68 }
69 Ok(out)
70 }
71
72 pub fn matches_in(self, other: Self, work: &impl Work) -> Result<bool> {
75 Ok(self.compare_in(other, work)? == Ordering::Equal)
76 }
77
78 pub fn compare_in(self, other: Self, work: &impl Work) -> Result<Ordering> {
81 let mut left = Cursor::new(self);
82 let mut right = Cursor::new(other);
83 loop {
84 match (left.next(work)?, right.next(work)?) {
85 (None, None) => return Ok(Ordering::Equal),
86 (Some(a), Some(b)) if a == b => {}
87 (None, Some(_)) => return Ok(Ordering::Less),
88 (Some(_), None) => return Ok(Ordering::Greater),
89 (Some(a), Some(b)) => return Ok(a.cmp(&b)),
90 }
91 }
92 }
93
94 pub fn equals_in(self, expected: &[u8], work: &impl Work) -> Result<bool> {
97 let mut cursor = Cursor::new(self);
98 let mut index = 0;
99 while let Some(byte) = cursor.next(work)? {
100 work.charge_work(1).map_err(|cause| Error {
101 kind: ErrorKind::Resource(cause),
102 location: cursor.point(),
103 })?;
104 if expected.get(index) != Some(&byte) {
105 return Ok(false);
106 }
107 index += 1;
108 }
109 Ok(index == expected.len())
110 }
111}
112
113struct Cursor<'a> {
114 value: Bytes<'a>,
115 index: usize,
116 decoder: Decoder,
117}
118
119impl<'a> Cursor<'a> {
120 fn new(value: Bytes<'a>) -> Self {
121 Self {
122 value,
123 index: 0,
124 decoder: Decoder::new(value.form),
125 }
126 }
127
128 fn point(&self) -> Location {
129 Location::new(
131 self.value.location.source(),
132 self.value.location.span().start + self.index as u64,
133 0,
134 )
135 .expect("a point inside the checked original body")
136 }
137
138 fn malformed(&self) -> Error {
139 Error {
140 kind: ErrorKind::Syntax(match self.value.form {
141 Form::Name => Syntax::Name,
142 Form::Literal | Form::Hexadecimal => Syntax::String,
143 }),
144 location: self.point(),
145 }
146 }
147
148 fn next(&mut self, work: &impl Work) -> Result<Option<u8>> {
149 loop {
150 let input = if self.index < self.value.raw.len() {
151 work.charge_work(1).map_err(|cause| Error {
152 kind: ErrorKind::Resource(cause),
153 location: self.point(),
154 })?;
155 Some(self.value.raw[self.index])
156 } else {
157 None
158 };
159 match self.decoder.step(input) {
160 Step::More => {
161 debug_assert!(input.is_some());
162 self.index += 1;
163 }
164 Step::Byte { value, consumed } => {
165 if consumed {
166 self.index += 1;
167 }
168 return Ok(Some(value));
169 }
170 Step::End => return Ok(None),
171 Step::Malformed => {
172 if input.is_some() {
173 self.index += 1;
174 }
175 return Err(self.malformed());
176 }
177 }
178 }
179 }
180}
181
182pub(crate) const fn is_space(byte: u8) -> bool {
183 matches!(byte, 0 | 9 | 10 | 12 | 13 | 32)
184}