1use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct ByteRange {
13 ranges: Vec<(u64, u64)>,
15}
16
17impl ByteRange {
18 pub fn new(ranges: Vec<(u64, u64)>) -> Self {
20 Self { ranges }
21 }
22
23 pub fn from_array(values: &[i64]) -> Result<Self, String> {
25 if values.len() % 2 != 0 {
26 return Err("ByteRange array must have even number of elements".to_string());
27 }
28 if values.len() < 4 {
29 return Err("ByteRange array must have at least 4 elements".to_string());
30 }
31
32 let mut ranges = Vec::with_capacity(values.len() / 2);
33 for chunk in values.chunks(2) {
34 let offset = chunk[0];
35 let length = chunk[1];
36
37 if offset < 0 {
38 return Err(format!("ByteRange offset cannot be negative: {}", offset));
39 }
40 if length < 0 {
41 return Err(format!("ByteRange length cannot be negative: {}", length));
42 }
43
44 ranges.push((offset as u64, length as u64));
45 }
46
47 Ok(Self { ranges })
48 }
49
50 pub fn ranges(&self) -> &[(u64, u64)] {
52 &self.ranges
53 }
54
55 pub fn len(&self) -> usize {
57 self.ranges.len()
58 }
59
60 pub fn is_empty(&self) -> bool {
62 self.ranges.is_empty()
63 }
64
65 pub fn total_bytes(&self) -> u64 {
67 self.ranges.iter().map(|(_, len)| len).sum()
68 }
69
70 pub fn validate(&self) -> Result<(), String> {
77 if self.ranges.len() != 2 {
78 return Err(format!(
79 "Expected 2 ranges for signature, got {}",
80 self.ranges.len()
81 ));
82 }
83
84 let (offset1, _len1) = self.ranges[0];
85 if offset1 != 0 {
86 return Err(format!(
87 "First range should start at offset 0, got {}",
88 offset1
89 ));
90 }
91
92 let (offset1, len1) = self.ranges[0];
94 let (offset2, _len2) = self.ranges[1];
95 if offset2 < offset1 + len1 {
96 return Err("ByteRange ranges overlap".to_string());
97 }
98
99 Ok(())
100 }
101}
102
103impl fmt::Display for ByteRange {
104 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105 write!(f, "[")?;
106 for (i, (offset, length)) in self.ranges.iter().enumerate() {
107 if i > 0 {
108 write!(f, " ")?;
109 }
110 write!(f, "{} {}", offset, length)?;
111 }
112 write!(f, "]")
113 }
114}
115
116#[derive(Debug, Clone)]
118pub struct SignatureField {
119 pub name: Option<String>,
121
122 pub byte_range: ByteRange,
124
125 pub contents: Vec<u8>,
127
128 pub filter: String,
130
131 pub sub_filter: Option<String>,
133
134 pub reason: Option<String>,
136
137 pub location: Option<String>,
139
140 pub contact_info: Option<String>,
142
143 pub signing_time: Option<String>,
145}
146
147impl SignatureField {
148 pub fn new(filter: String, byte_range: ByteRange, contents: Vec<u8>) -> Self {
150 Self {
151 name: None,
152 byte_range,
153 contents,
154 filter,
155 sub_filter: None,
156 reason: None,
157 location: None,
158 contact_info: None,
159 signing_time: None,
160 }
161 }
162
163 pub fn is_pades(&self) -> bool {
165 self.sub_filter
166 .as_ref()
167 .map(|sf| sf.contains("CAdES") || sf.contains("cades"))
168 .unwrap_or(false)
169 }
170
171 pub fn is_pkcs7_detached(&self) -> bool {
173 self.sub_filter
174 .as_ref()
175 .map(|sf| sf.contains("pkcs7.detached"))
176 .unwrap_or(false)
177 }
178
179 pub fn contents_size(&self) -> usize {
181 self.contents.len()
182 }
183}
184
185impl fmt::Display for SignatureField {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 write!(
188 f,
189 "SignatureField {{ name: {:?}, filter: {}, sub_filter: {:?}, contents: {} bytes }}",
190 self.name,
191 self.filter,
192 self.sub_filter,
193 self.contents.len()
194 )
195 }
196}
197
198#[cfg(test)]
199mod tests {
200 use super::*;
201
202 #[test]
205 fn test_byterange_from_array_valid() {
206 let values = vec![0, 1000, 2000, 500];
207 let br = ByteRange::from_array(&values).unwrap();
208 assert_eq!(br.len(), 2);
209 assert_eq!(br.ranges()[0], (0, 1000));
210 assert_eq!(br.ranges()[1], (2000, 500));
211 }
212
213 #[test]
214 fn test_byterange_from_array_odd_elements() {
215 let values = vec![0, 1000, 2000];
216 let result = ByteRange::from_array(&values);
217 assert!(result.is_err());
218 assert!(result.unwrap_err().contains("even"));
219 }
220
221 #[test]
222 fn test_byterange_from_array_too_few_elements() {
223 let values = vec![0, 1000];
224 let result = ByteRange::from_array(&values);
225 assert!(result.is_err());
226 assert!(result.unwrap_err().contains("at least 4"));
227 }
228
229 #[test]
230 fn test_byterange_from_array_negative_offset() {
231 let values = vec![-1, 1000, 2000, 500];
232 let result = ByteRange::from_array(&values);
233 assert!(result.is_err());
234 assert!(result.unwrap_err().contains("negative"));
235 }
236
237 #[test]
238 fn test_byterange_from_array_negative_length() {
239 let values = vec![0, -100, 2000, 500];
240 let result = ByteRange::from_array(&values);
241 assert!(result.is_err());
242 assert!(result.unwrap_err().contains("negative"));
243 }
244
245 #[test]
246 fn test_byterange_total_bytes() {
247 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
248 assert_eq!(br.total_bytes(), 1500);
249 }
250
251 #[test]
252 fn test_byterange_validate_valid() {
253 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
254 assert!(br.validate().is_ok());
255 }
256
257 #[test]
258 fn test_byterange_validate_wrong_range_count() {
259 let br = ByteRange::new(vec![(0, 1000)]);
260 let result = br.validate();
261 assert!(result.is_err());
262 assert!(result.unwrap_err().contains("2 ranges"));
263 }
264
265 #[test]
266 fn test_byterange_validate_first_not_zero() {
267 let br = ByteRange::new(vec![(100, 1000), (2000, 500)]);
268 let result = br.validate();
269 assert!(result.is_err());
270 assert!(result.unwrap_err().contains("offset 0"));
271 }
272
273 #[test]
274 fn test_byterange_validate_overlapping() {
275 let br = ByteRange::new(vec![(0, 1000), (500, 500)]);
276 let result = br.validate();
277 assert!(result.is_err());
278 assert!(result.unwrap_err().contains("overlap"));
279 }
280
281 #[test]
282 fn test_byterange_display() {
283 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
284 assert_eq!(br.to_string(), "[0 1000 2000 500]");
285 }
286
287 #[test]
288 fn test_byterange_is_empty() {
289 let empty = ByteRange::new(vec![]);
290 assert!(empty.is_empty());
291
292 let non_empty = ByteRange::new(vec![(0, 100)]);
293 assert!(!non_empty.is_empty());
294 }
295
296 #[test]
299 fn test_signature_field_new() {
300 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
301 let contents = vec![0x30, 0x82]; let sig = SignatureField::new("Adobe.PPKLite".to_string(), br, contents);
303
304 assert_eq!(sig.filter, "Adobe.PPKLite");
305 assert!(sig.name.is_none());
306 assert!(sig.sub_filter.is_none());
307 }
308
309 #[test]
310 fn test_signature_field_is_pades() {
311 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
312 let mut sig = SignatureField::new("Adobe.PPKLite".to_string(), br, vec![]);
313
314 assert!(!sig.is_pades());
315
316 sig.sub_filter = Some("ETSI.CAdES.detached".to_string());
317 assert!(sig.is_pades());
318 }
319
320 #[test]
321 fn test_signature_field_is_pkcs7_detached() {
322 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
323 let mut sig = SignatureField::new("Adobe.PPKLite".to_string(), br, vec![]);
324
325 assert!(!sig.is_pkcs7_detached());
326
327 sig.sub_filter = Some("adbe.pkcs7.detached".to_string());
328 assert!(sig.is_pkcs7_detached());
329 }
330
331 #[test]
332 fn test_signature_field_contents_size() {
333 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
334 let contents = vec![0u8; 4096];
335 let sig = SignatureField::new("Adobe.PPKLite".to_string(), br, contents);
336
337 assert_eq!(sig.contents_size(), 4096);
338 }
339
340 #[test]
341 fn test_signature_field_display() {
342 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
343 let mut sig = SignatureField::new("Adobe.PPKLite".to_string(), br, vec![0u8; 100]);
344 sig.name = Some("Signature1".to_string());
345 sig.sub_filter = Some("adbe.pkcs7.detached".to_string());
346
347 let display = sig.to_string();
348 assert!(display.contains("Signature1"));
349 assert!(display.contains("Adobe.PPKLite"));
350 assert!(display.contains("100 bytes"));
351 }
352
353 #[test]
354 fn test_signature_field_clone() {
355 let br = ByteRange::new(vec![(0, 1000), (2000, 500)]);
356 let sig = SignatureField::new("Adobe.PPKLite".to_string(), br, vec![1, 2, 3]);
357 let cloned = sig.clone();
358
359 assert_eq!(sig.filter, cloned.filter);
360 assert_eq!(sig.contents, cloned.contents);
361 }
362}