hayro_postscript/
array.rs1use crate::error::{Error, Result};
2use crate::object;
3use crate::reader::Reader;
4use crate::string;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct Array<'a> {
9 data: &'a [u8],
10}
11
12impl<'a> Array<'a> {
13 pub(crate) fn new(data: &'a [u8]) -> Self {
14 Self { data }
15 }
16
17 pub fn objects(&self) -> crate::Scanner<'a> {
20 crate::Scanner::new(self.data)
21 }
22}
23
24pub(crate) fn parse<'a>(r: &mut Reader<'a>) -> Result<&'a [u8]> {
25 r.forward_tag(b"[").ok_or(Error::SyntaxError)?;
26
27 let start = r.offset();
28 skip_array(r)?;
29 let end = r.offset() - 1;
30
31 r.range(start..end).ok_or(Error::SyntaxError)
32}
33
34fn skip_array(r: &mut Reader<'_>) -> Result<()> {
35 let mut depth = 1_u32;
36
37 while depth > 0 {
38 match r.peek_byte().ok_or(Error::SyntaxError)? {
39 b'[' => {
40 r.forward();
41 depth += 1;
42 }
43 b']' => {
44 r.forward();
45 depth -= 1;
46 }
47 b'(' => {
48 let _ = string::parse_literal(r).ok_or(Error::SyntaxError)?;
49 }
50 b'<' => {
51 if r.peek_bytes(2) == Some(b"<~") {
52 let _ = string::parse_ascii85(r).ok_or(Error::SyntaxError)?;
53 } else if r.peek_bytes(2) == Some(b"<<") {
54 r.forward();
55 r.forward();
56 } else {
57 let _ = string::parse_hex(r).ok_or(Error::SyntaxError)?;
58 }
59 }
60 b'%' => object::skip_whitespace_and_comments(r),
61 _ => {
62 r.forward();
63 }
64 }
65 }
66
67 Ok(())
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 fn parse_array(input: &[u8]) -> Result<&[u8]> {
75 let mut r = Reader::new(input);
76 parse(&mut r)
77 }
78
79 #[test]
80 fn empty() {
81 assert_eq!(parse_array(b"[]").unwrap(), b"");
82 }
83
84 #[test]
85 fn simple() {
86 assert_eq!(parse_array(b"[1 2 3]").unwrap(), b"1 2 3");
87 }
88
89 #[test]
90 fn nested() {
91 assert_eq!(parse_array(b"[1 [2 3] 4]").unwrap(), b"1 [2 3] 4");
92 }
93
94 #[test]
95 fn with_string() {
96 assert_eq!(parse_array(b"[1 (str]) 2]").unwrap(), b"1 (str]) 2");
98 }
99
100 #[test]
101 fn with_hex_string() {
102 assert_eq!(parse_array(b"[<48> /name]").unwrap(), b"<48> /name");
103 }
104
105 #[test]
106 fn with_ascii85_string() {
107 assert_eq!(parse_array(b"[<~87cURDZ~> 1]").unwrap(), b"<~87cURDZ~> 1");
108 }
109
110 #[test]
111 fn with_comment() {
112 assert_eq!(
113 parse_array(b"[1 % comment with ]\n2]").unwrap(),
114 b"1 % comment with ]\n2"
115 );
116 }
117
118 #[test]
119 fn unterminated() {
120 assert_eq!(parse_array(b"[1 2"), Err(Error::SyntaxError));
121 }
122
123 #[test]
124 fn not_an_array() {
125 assert_eq!(parse_array(b"1 2]"), Err(Error::SyntaxError));
126 }
127}