changelog shortlog graph tags branches changeset files file revisions raw help

Mercurial > core / annotate rust/lib/sxp/src/read.rs

changeset 698: 96958d3eb5b0
parent: 3d78bed56188
author: Richard Westhaver <ellis@rwest.io>
date: Fri, 04 Oct 2024 22:04:59 -0400
permissions: -rw-r--r--
description: fixes
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
1
 //! read.rs --- sxp reader
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
2
 use crate::{err::ErrorCode, Error, Result};
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
3
 use alloc::vec::Vec;
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
4
 use core::{char, cmp, ops::Deref, str};
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
5
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
6
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
7
 use crate::io;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
8
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
9
 use crate::iter::LineColIterator;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
10
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
11
 /// Trait used by the deserializer for iterating over input. This is manually
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
12
 /// "specialized" for iterating over &[u8]. Once feature(specialization) is
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
13
 /// stable we can use actual specialization.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
14
 //  TODO 2023-07-14: should we use specialization anyways? we are on
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
15
 //  nightly 99% of the time for better or worse
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
16
 pub trait Read<'de> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
17
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
18
   fn next(&mut self) -> Result<Option<u8>>;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
19
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
20
   fn peek(&mut self) -> Result<Option<u8>>;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
21
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
22
   /// Only valid after a call to peek(). Discards the peeked byte.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
23
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
24
   fn discard(&mut self);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
25
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
26
   /// Position of the most recent call to next().
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
27
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
28
   /// The most recent call was probably next() and not peek(), but this method
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
29
   /// should try to return a sensible result if the most recent call was
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
30
   /// actually peek() because we don't always know.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
31
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
32
   /// Only called in case of an error, so performance is not important.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
33
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
34
   fn position(&self) -> Position;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
35
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
36
   /// Position of the most recent call to peek().
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
37
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
38
   /// The most recent call was probably peek() and not next(), but this method
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
39
   /// should try to return a sensible result if the most recent call was
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
40
   /// actually next() because we don't always know.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
41
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
42
   /// Only called in case of an error, so performance is not important.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
43
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
44
   fn peek_position(&self) -> Position;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
45
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
46
   /// Offset from the beginning of the input to the next byte that would be
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
47
   /// returned by next() or peek().
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
48
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
49
   fn byte_offset(&self) -> usize;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
50
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
51
   /// Assumes the previous byte was a quotation mark. Parses an escaped
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
52
   /// string until the next quotation mark using the given scratch space if
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
53
   /// necessary. The scratch space is initially empty.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
54
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
55
   fn parse_str<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
56
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
57
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
58
   ) -> Result<Reference<'de, 's, str>>;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
59
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
60
   /// Assumes the previous byte was a quotation mark. Parses an escaped
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
61
   /// string until the next quotation mark using the given scratch space if
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
62
   /// necessary. The scratch space is initially empty.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
63
   ///
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
64
   /// This function returns the raw bytes in the string with escape sequences
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
65
   /// expanded but without performing unicode validation.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
66
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
67
   fn parse_str_raw<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
68
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
69
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
70
   ) -> Result<Reference<'de, 's, [u8]>>;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
71
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
72
   /// Assumes the previous byte was a quotation mark. Parses a
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
73
   /// string until the next quotation mark but discards the data.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
74
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
75
   fn ignore_str(&mut self) -> Result<()>;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
76
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
77
   /// Assumes the previous byte was a hex escape sequnce ('\u') in a string.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
78
   /// Parses next hexadecimal sequence.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
79
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
80
   fn decode_hex_escape(&mut self) -> Result<u16>;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
81
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
82
   /// Whether StreamDeserializer::next needs to check the failed flag. True
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
83
   /// for IoRead, false for StrRead and SliceRead which can track failure by
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
84
   /// truncating their input slice to avoid the extra check on every next
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
85
   /// call.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
86
   #[doc(hidden)]
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
87
   const SHOULD_EARLY_RETURN_IF_FAILED: bool;
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
88
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
89
   /// Mark a persistent failure of StreamDeserializer, either by setting the
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
90
   /// flag or by truncating the input data.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
91
   #[doc(hidden)]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
92
   fn set_failed(&mut self, failed: &mut bool);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
93
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
94
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
95
 pub struct Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
96
   pub line: usize,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
97
   pub column: usize,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
98
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
99
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
100
 pub enum Reference<'b, 'c, T>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
101
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
102
   T: ?Sized + 'static,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
103
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
104
   Borrowed(&'b T),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
105
   Copied(&'c T),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
106
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
107
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
108
 impl<'b, 'c, T> Deref for Reference<'b, 'c, T>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
109
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
110
   T: ?Sized + 'static,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
111
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
112
   type Target = T;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
113
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
114
   fn deref(&self) -> &Self::Target {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
115
     match *self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
116
       Reference::Borrowed(b) => b,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
117
       Reference::Copied(c) => c,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
118
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
119
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
120
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
121
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
122
 /// SXP input source that reads from a std::io input stream.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
123
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
124
 #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
125
 pub struct IoRead<R>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
126
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
127
   R: io::Read,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
128
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
129
   iter: LineColIterator<io::Bytes<R>>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
130
   /// Temporary storage of peeked byte.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
131
   ch: Option<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
132
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
133
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
134
 /// SXP input source that reads from a slice of bytes.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
135
 //
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
136
 // This is more efficient than other iterators because peek() can be read-only
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
137
 // and we can compute line/col position only if an error happens.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
138
 pub struct SliceRead<'a> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
139
   slice: &'a [u8],
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
140
   /// Index of the *next* byte that will be returned by next() or peek().
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
141
   index: usize,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
142
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
143
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
144
 /// SXP input source that reads from a UTF-8 string.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
145
 //
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
146
 // Able to elide UTF-8 checks by assuming that the input is valid UTF-8.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
147
 pub struct StrRead<'a> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
148
   delegate: SliceRead<'a>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
149
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
150
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
151
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
152
 impl<R> IoRead<R>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
153
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
154
   R: io::Read,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
155
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
156
   /// Create a SXP input source to read from a std::io input stream.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
157
   pub fn new(reader: R) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
158
     IoRead {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
159
       iter: LineColIterator::new(reader.bytes()),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
160
       ch: None,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
161
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
162
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
163
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
164
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
165
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
166
 impl<R> IoRead<R>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
167
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
168
   R: io::Read,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
169
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
170
   fn parse_str_bytes<'s, T, F>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
171
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
172
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
173
     validate: bool,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
174
     result: F,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
175
   ) -> Result<T>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
176
   where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
177
     T: 's,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
178
     F: FnOnce(&'s Self, &'s [u8]) -> Result<T>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
179
   {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
180
     loop {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
181
       let ch = e!(next_or_eof(self));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
182
       if !ESCAPE[ch as usize] {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
183
         scratch.push(ch);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
184
         continue;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
185
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
186
       match ch {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
187
         b'"' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
188
           return result(self, scratch);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
189
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
190
         b'\\' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
191
           e!(parse_escape(self, validate, scratch));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
192
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
193
         _ => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
194
           if validate {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
195
             return error(self, ErrorCode::ControlCharacterWhileParsingString);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
196
           }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
197
           scratch.push(ch);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
198
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
199
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
200
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
201
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
202
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
203
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
204
 #[cfg(feature = "std")]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
205
 impl<'de, R> Read<'de> for IoRead<R>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
206
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
207
   R: io::Read,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
208
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
209
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
210
   fn next(&mut self) -> Result<Option<u8>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
211
     match self.ch.take() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
212
       Some(ch) => Ok(Some(ch)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
213
       None => match self.iter.next() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
214
         Some(Err(err)) => Err(Error::io(err)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
215
         Some(Ok(ch)) => Ok(Some(ch)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
216
         None => Ok(None),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
217
       },
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
218
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
219
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
220
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
221
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
222
   fn peek(&mut self) -> Result<Option<u8>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
223
     match self.ch {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
224
       Some(ch) => Ok(Some(ch)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
225
       None => match self.iter.next() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
226
         Some(Err(err)) => Err(Error::io(err)),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
227
         Some(Ok(ch)) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
228
           self.ch = Some(ch);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
229
           Ok(self.ch)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
230
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
231
         None => Ok(None),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
232
       },
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
233
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
234
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
235
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
236
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
237
   fn discard(&mut self) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
238
     self.ch = None;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
239
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
240
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
241
   fn position(&self) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
242
     Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
243
       line: self.iter.line(),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
244
       column: self.iter.col(),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
245
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
246
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
247
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
248
   fn peek_position(&self) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
249
     // The LineColIterator updates its position during peek() so it has the
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
250
     // right one here.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
251
     self.position()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
252
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
253
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
254
   fn byte_offset(&self) -> usize {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
255
     match self.ch {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
256
       Some(_) => self.iter.byte_offset() - 1,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
257
       None => self.iter.byte_offset(),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
258
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
259
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
260
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
261
   fn parse_str<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
262
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
263
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
264
   ) -> Result<Reference<'de, 's, str>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
265
     self
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
266
       .parse_str_bytes(scratch, true, as_str)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
267
       .map(Reference::Copied)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
268
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
269
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
270
   fn parse_str_raw<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
271
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
272
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
273
   ) -> Result<Reference<'de, 's, [u8]>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
274
     self
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
275
       .parse_str_bytes(scratch, false, |_, bytes| Ok(bytes))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
276
       .map(Reference::Copied)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
277
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
278
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
279
   fn ignore_str(&mut self) -> Result<()> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
280
     loop {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
281
       let ch = e!(next_or_eof(self));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
282
       if !ESCAPE[ch as usize] {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
283
         continue;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
284
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
285
       match ch {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
286
         b'"' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
287
           return Ok(());
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
288
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
289
         b'\\' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
290
           e!(ignore_escape(self));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
291
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
292
         _ => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
293
           return error(self, ErrorCode::ControlCharacterWhileParsingString);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
294
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
295
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
296
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
297
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
298
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
299
   fn decode_hex_escape(&mut self) -> Result<u16> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
300
     let mut n = 0;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
301
     for _ in 0..4 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
302
       match decode_hex_val(e!(next_or_eof(self))) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
303
         None => return error(self, ErrorCode::InvalidEscape),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
304
         Some(val) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
305
           n = (n << 4) + val;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
306
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
307
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
308
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
309
     Ok(n)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
310
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
311
 
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
312
   const SHOULD_EARLY_RETURN_IF_FAILED: bool = true;
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
313
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
314
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
315
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
316
   fn set_failed(&mut self, failed: &mut bool) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
317
     *failed = true;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
318
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
319
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
320
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
321
 //////////////////////////////////////////////////////////////////////////////
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
322
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
323
 impl<'a> SliceRead<'a> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
324
   /// Create a SXP input source to read from a slice of bytes.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
325
   pub fn new(slice: &'a [u8]) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
326
     SliceRead { slice, index: 0 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
327
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
328
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
329
   fn position_of_index(&self, i: usize) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
330
     let mut position = Position { line: 1, column: 0 };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
331
     for ch in &self.slice[..i] {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
332
       match *ch {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
333
         b'\n' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
334
           position.line += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
335
           position.column = 0;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
336
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
337
         _ => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
338
           position.column += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
339
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
340
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
341
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
342
     position
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
343
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
344
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
345
   /// The big optimization here over IoRead is that if the string contains no
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
346
   /// backslash escape sequences, the returned &str is a slice of the raw SXP
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
347
   /// data so we avoid copying into the scratch space.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
348
   fn parse_str_bytes<'s, T, F>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
349
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
350
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
351
     validate: bool,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
352
     result: F,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
353
   ) -> Result<Reference<'a, 's, T>>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
354
   where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
355
     T: ?Sized + 's,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
356
     F: for<'f> FnOnce(&'s Self, &'f [u8]) -> Result<&'f T>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
357
   {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
358
     // Index of the first byte not yet copied into the scratch space.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
359
     let mut start = self.index;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
360
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
361
     loop {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
362
       while self.index < self.slice.len()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
363
         && !ESCAPE[self.slice[self.index] as usize]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
364
       {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
365
         self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
366
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
367
       if self.index == self.slice.len() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
368
         return error(self, ErrorCode::EofWhileParsingString);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
369
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
370
       match self.slice[self.index] {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
371
         b'"' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
372
           if scratch.is_empty() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
373
             // Fast path: return a slice of the raw SXP without any
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
374
             // copying.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
375
             let borrowed = &self.slice[start..self.index];
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
376
             self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
377
             return result(self, borrowed).map(Reference::Borrowed);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
378
           } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
379
             scratch.extend_from_slice(&self.slice[start..self.index]);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
380
             self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
381
             return result(self, scratch).map(Reference::Copied);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
382
           }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
383
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
384
         b'\\' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
385
           scratch.extend_from_slice(&self.slice[start..self.index]);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
386
           self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
387
           e!(parse_escape(self, validate, scratch));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
388
           start = self.index;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
389
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
390
         _ => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
391
           self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
392
           if validate {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
393
             return error(self, ErrorCode::ControlCharacterWhileParsingString);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
394
           }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
395
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
396
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
397
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
398
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
399
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
400
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
401
 impl<'a> Read<'a> for SliceRead<'a> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
402
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
403
   fn next(&mut self) -> Result<Option<u8>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
404
     // `Ok(self.slice.get(self.index).map(|ch| { self.index += 1; *ch }))`
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
405
     // is about 10% slower.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
406
     Ok(if self.index < self.slice.len() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
407
       let ch = self.slice[self.index];
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
408
       self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
409
       Some(ch)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
410
     } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
411
       None
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
412
     })
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
413
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
414
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
415
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
416
   fn peek(&mut self) -> Result<Option<u8>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
417
     // `Ok(self.slice.get(self.index).map(|ch| *ch))` is about 10% slower
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
418
     // for some reason.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
419
     Ok(if self.index < self.slice.len() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
420
       Some(self.slice[self.index])
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
421
     } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
422
       None
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
423
     })
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
424
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
425
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
426
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
427
   fn discard(&mut self) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
428
     self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
429
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
430
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
431
   fn position(&self) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
432
     self.position_of_index(self.index)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
433
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
434
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
435
   fn peek_position(&self) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
436
     // Cap it at slice.len() just in case the most recent call was next()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
437
     // and it returned the last byte.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
438
     self.position_of_index(cmp::min(self.slice.len(), self.index + 1))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
439
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
440
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
441
   fn byte_offset(&self) -> usize {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
442
     self.index
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
443
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
444
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
445
   fn parse_str<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
446
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
447
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
448
   ) -> Result<Reference<'a, 's, str>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
449
     self.parse_str_bytes(scratch, true, as_str)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
450
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
451
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
452
   fn parse_str_raw<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
453
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
454
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
455
   ) -> Result<Reference<'a, 's, [u8]>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
456
     self.parse_str_bytes(scratch, false, |_, bytes| Ok(bytes))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
457
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
458
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
459
   fn ignore_str(&mut self) -> Result<()> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
460
     loop {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
461
       while self.index < self.slice.len()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
462
         && !ESCAPE[self.slice[self.index] as usize]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
463
       {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
464
         self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
465
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
466
       if self.index == self.slice.len() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
467
         return error(self, ErrorCode::EofWhileParsingString);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
468
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
469
       match self.slice[self.index] {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
470
         b'"' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
471
           self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
472
           return Ok(());
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
473
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
474
         b'\\' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
475
           self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
476
           e!(ignore_escape(self));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
477
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
478
         _ => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
479
           return error(self, ErrorCode::ControlCharacterWhileParsingString);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
480
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
481
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
482
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
483
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
484
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
485
   fn decode_hex_escape(&mut self) -> Result<u16> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
486
     if self.index + 4 > self.slice.len() {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
487
       self.index = self.slice.len();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
488
       return error(self, ErrorCode::EofWhileParsingString);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
489
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
490
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
491
     let mut n = 0;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
492
     for _ in 0..4 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
493
       let ch = decode_hex_val(self.slice[self.index]);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
494
       self.index += 1;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
495
       match ch {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
496
         None => return error(self, ErrorCode::InvalidEscape),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
497
         Some(val) => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
498
           n = (n << 4) + val;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
499
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
500
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
501
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
502
     Ok(n)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
503
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
504
 
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
505
   const SHOULD_EARLY_RETURN_IF_FAILED: bool = false;
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
506
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
507
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
508
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
509
   fn set_failed(&mut self, _failed: &mut bool) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
510
     self.slice = &self.slice[..self.index];
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
511
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
512
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
513
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
514
 //////////////////////////////////////////////////////////////////////////////
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
515
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
516
 impl<'a> StrRead<'a> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
517
   /// Create a SXP input source to read from a UTF-8 string.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
518
   pub fn new(s: &'a str) -> Self {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
519
     StrRead {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
520
       delegate: SliceRead::new(s.as_bytes()),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
521
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
522
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
523
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
524
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
525
 impl<'a> Read<'a> for StrRead<'a> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
526
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
527
   fn next(&mut self) -> Result<Option<u8>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
528
     self.delegate.next()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
529
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
530
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
531
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
532
   fn peek(&mut self) -> Result<Option<u8>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
533
     self.delegate.peek()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
534
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
535
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
536
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
537
   fn discard(&mut self) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
538
     self.delegate.discard();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
539
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
540
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
541
   fn position(&self) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
542
     self.delegate.position()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
543
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
544
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
545
   fn peek_position(&self) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
546
     self.delegate.peek_position()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
547
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
548
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
549
   fn byte_offset(&self) -> usize {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
550
     self.delegate.byte_offset()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
551
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
552
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
553
   fn parse_str<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
554
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
555
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
556
   ) -> Result<Reference<'a, 's, str>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
557
     self.delegate.parse_str_bytes(scratch, true, |_, bytes| {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
558
       // The deserialization input came in as &str with a UTF-8 guarantee,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
559
       // and the \u-escapes are checked along the way, so don't need to
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
560
       // check here.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
561
       Ok(unsafe { str::from_utf8_unchecked(bytes) })
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
562
     })
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
563
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
564
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
565
   fn parse_str_raw<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
566
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
567
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
568
   ) -> Result<Reference<'a, 's, [u8]>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
569
     self.delegate.parse_str_raw(scratch)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
570
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
571
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
572
   fn ignore_str(&mut self) -> Result<()> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
573
     self.delegate.ignore_str()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
574
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
575
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
576
   fn decode_hex_escape(&mut self) -> Result<u16> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
577
     self.delegate.decode_hex_escape()
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
578
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
579
 
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
580
   const SHOULD_EARLY_RETURN_IF_FAILED: bool = false;
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
581
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
582
   #[inline]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
583
   #[cold]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
584
   fn set_failed(&mut self, failed: &mut bool) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
585
     self.delegate.set_failed(failed);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
586
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
587
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
588
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
589
 //////////////////////////////////////////////////////////////////////////////
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
590
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
591
 impl<'a, 'de, R> Read<'de> for &'a mut R
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
592
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
593
   R: Read<'de>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
594
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
595
   fn next(&mut self) -> Result<Option<u8>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
596
     R::next(self)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
597
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
598
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
599
   fn peek(&mut self) -> Result<Option<u8>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
600
     R::peek(self)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
601
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
602
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
603
   fn discard(&mut self) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
604
     R::discard(self);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
605
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
606
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
607
   fn position(&self) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
608
     R::position(self)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
609
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
610
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
611
   fn peek_position(&self) -> Position {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
612
     R::peek_position(self)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
613
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
614
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
615
   fn byte_offset(&self) -> usize {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
616
     R::byte_offset(self)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
617
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
618
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
619
   fn parse_str<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
620
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
621
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
622
   ) -> Result<Reference<'de, 's, str>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
623
     R::parse_str(self, scratch)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
624
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
625
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
626
   fn parse_str_raw<'s>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
627
     &'s mut self,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
628
     scratch: &'s mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
629
   ) -> Result<Reference<'de, 's, [u8]>> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
630
     R::parse_str_raw(self, scratch)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
631
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
632
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
633
   fn ignore_str(&mut self) -> Result<()> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
634
     R::ignore_str(self)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
635
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
636
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
637
   fn decode_hex_escape(&mut self) -> Result<u16> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
638
     R::decode_hex_escape(self)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
639
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
640
 
67
0ccbbd142694 rust cleanup, added rocksdb bindings
ellis <ellis@rwest.io>
parents: 8
diff changeset
641
   const SHOULD_EARLY_RETURN_IF_FAILED: bool = R::SHOULD_EARLY_RETURN_IF_FAILED;
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
642
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
643
   fn set_failed(&mut self, failed: &mut bool) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
644
     R::set_failed(self, failed);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
645
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
646
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
647
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
648
 /// Marker for whether StreamDeserializer can implement FusedIterator.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
649
 pub trait Fused {}
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
650
 impl<'a> Fused for SliceRead<'a> {}
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
651
 impl<'a> Fused for StrRead<'a> {}
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
652
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
653
 // Lookup table of bytes that must be escaped. A value of true at index i means
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
654
 // that byte i requires an escape sequence in the input.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
655
 static ESCAPE: [bool; 256] = {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
656
   const CT: bool = true; // control character \x00..=\x1F
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
657
   const QU: bool = true; // quote \x22
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
658
   const BS: bool = true; // backslash \x5C
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
659
   const __: bool = false; // allow unescaped
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
660
   [
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
661
     //   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
662
     CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 0
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
663
     CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 1
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
664
     __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
665
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
666
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
667
     __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
668
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
669
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
670
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
671
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
672
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
673
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
674
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
675
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
676
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
677
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
678
   ]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
679
 };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
680
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
681
 fn next_or_eof<'de, R>(read: &mut R) -> Result<u8>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
682
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
683
   R: ?Sized + Read<'de>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
684
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
685
   match e!(read.next()) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
686
     Some(b) => Ok(b),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
687
     None => error(read, ErrorCode::EofWhileParsingString),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
688
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
689
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
690
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
691
 fn peek_or_eof<'de, R>(read: &mut R) -> Result<u8>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
692
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
693
   R: ?Sized + Read<'de>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
694
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
695
   match e!(read.peek()) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
696
     Some(b) => Ok(b),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
697
     None => error(read, ErrorCode::EofWhileParsingString),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
698
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
699
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
700
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
701
 fn error<'de, R, T>(read: &R, reason: ErrorCode) -> Result<T>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
702
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
703
   R: ?Sized + Read<'de>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
704
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
705
   let position = read.position();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
706
   Err(Error::syntax(reason, position.line, position.column))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
707
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
708
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
709
 fn as_str<'de, 's, R: Read<'de>>(read: &R, slice: &'s [u8]) -> Result<&'s str> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
710
   str::from_utf8(slice)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
711
     .or_else(|_| error(read, ErrorCode::InvalidUnicodeCodePoint))
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
712
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
713
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
714
 /// Parses a SXP escape sequence and appends it into the scratch space. Assumes
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
715
 /// the previous byte read was a backslash.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
716
 fn parse_escape<'de, R: Read<'de>>(
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
717
   read: &mut R,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
718
   validate: bool,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
719
   scratch: &mut Vec<u8>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
720
 ) -> Result<()> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
721
   let ch = e!(next_or_eof(read));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
722
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
723
   match ch {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
724
     b'"' => scratch.push(b'"'),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
725
     b'\\' => scratch.push(b'\\'),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
726
     b'/' => scratch.push(b'/'),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
727
     b'b' => scratch.push(b'\x08'),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
728
     b'f' => scratch.push(b'\x0c'),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
729
     b'n' => scratch.push(b'\n'),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
730
     b'r' => scratch.push(b'\r'),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
731
     b't' => scratch.push(b'\t'),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
732
     b'u' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
733
       fn encode_surrogate(scratch: &mut Vec<u8>, n: u16) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
734
         scratch.extend_from_slice(&[
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
735
           (n >> 12 & 0b0000_1111) as u8 | 0b1110_0000,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
736
           (n >> 6 & 0b0011_1111) as u8 | 0b1000_0000,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
737
           (n & 0b0011_1111) as u8 | 0b1000_0000,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
738
         ]);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
739
       }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
740
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
741
       let c = match e!(read.decode_hex_escape()) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
742
         n @ 0xDC00..=0xDFFF => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
743
           return if validate {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
744
             error(read, ErrorCode::LoneLeadingSurrogateInHexEscape)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
745
           } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
746
             encode_surrogate(scratch, n);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
747
             Ok(())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
748
           };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
749
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
750
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
751
         // Non-BMP characters are encoded as a sequence of two hex
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
752
         // escapes, representing UTF-16 surrogates. If deserializing a
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
753
         // utf-8 string the surrogates are required to be paired,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
754
         // whereas deserializing a byte string accepts lone surrogates.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
755
         n1 @ 0xD800..=0xDBFF => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
756
           if e!(peek_or_eof(read)) == b'\\' {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
757
             read.discard();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
758
           } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
759
             return if validate {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
760
               read.discard();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
761
               error(read, ErrorCode::UnexpectedEndOfHexEscape)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
762
             } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
763
               encode_surrogate(scratch, n1);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
764
               Ok(())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
765
             };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
766
           }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
767
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
768
           if e!(peek_or_eof(read)) == b'u' {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
769
             read.discard();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
770
           } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
771
             return if validate {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
772
               read.discard();
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
773
               error(read, ErrorCode::UnexpectedEndOfHexEscape)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
774
             } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
775
               encode_surrogate(scratch, n1);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
776
               // The \ prior to this byte started an escape sequence,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
777
               // so we need to parse that now. This recursive call
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
778
               // does not blow the stack on malicious input because
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
779
               // the escape is not \u, so it will be handled by one
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
780
               // of the easy nonrecursive cases.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
781
               parse_escape(read, validate, scratch)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
782
             };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
783
           }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
784
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
785
           let n2 = e!(read.decode_hex_escape());
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
786
 
189
3d78bed56188 apply clippy fixes
Richard Westhaver <ellis@rwest.io>
parents: 67
diff changeset
787
           if !(0xDC00..=0xDFFF).contains(&n2) {
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
788
             return error(read, ErrorCode::LoneLeadingSurrogateInHexEscape);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
789
           }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
790
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
791
           let n =
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
792
             (((n1 - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
793
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
794
           match char::from_u32(n) {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
795
             Some(c) => c,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
796
             None => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
797
               return error(read, ErrorCode::InvalidUnicodeCodePoint);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
798
             }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
799
           }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
800
         }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
801
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
802
         // Every u16 outside of the surrogate ranges above is guaranteed
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
803
         // to be a legal char.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
804
         n => char::from_u32(n as u32).unwrap(),
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
805
       };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
806
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
807
       scratch.extend_from_slice(c.encode_utf8(&mut [0_u8; 4]).as_bytes());
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
808
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
809
     _ => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
810
       return error(read, ErrorCode::InvalidEscape);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
811
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
812
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
813
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
814
   Ok(())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
815
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
816
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
817
 /// Parses a SXP escape sequence and discards the value. Assumes the previous
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
818
 /// byte read was a backslash.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
819
 fn ignore_escape<'de, R>(read: &mut R) -> Result<()>
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
820
 where
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
821
   R: ?Sized + Read<'de>,
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
822
 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
823
   let ch = e!(next_or_eof(read));
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
824
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
825
   match ch {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
826
     b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => {}
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
827
     b'u' => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
828
       // At this point we don't care if the codepoint is valid. We just
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
829
       // want to consume it. We don't actually know what is valid or not
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
830
       // at this point, because that depends on if this string will
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
831
       // ultimately be parsed into a string or a byte buffer in the "real"
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
832
       // parse.
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
833
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
834
       e!(read.decode_hex_escape());
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
835
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
836
     _ => {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
837
       return error(read, ErrorCode::InvalidEscape);
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
838
     }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
839
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
840
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
841
   Ok(())
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
842
 }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
843
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
844
 static HEX: [u8; 256] = {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
845
   const __: u8 = 255; // not a hex digit
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
846
   [
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
847
     //   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
848
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
849
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 1
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
850
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2
189
3d78bed56188 apply clippy fixes
Richard Westhaver <ellis@rwest.io>
parents: 67
diff changeset
851
     0, 1, 2, 3, 4, 5, 6, 7, 8, 9, __, __, __, __, __, __, // 3
8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
852
     __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __, // 4
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
853
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 5
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
854
     __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __, // 6
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
855
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
856
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
857
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
858
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
859
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
860
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
861
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
862
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
863
     __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
864
   ]
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
865
 };
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
866
 
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
867
 fn decode_hex_val(val: u8) -> Option<u16> {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
868
   let n = HEX[val as usize] as u16;
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
869
   if n == 255 {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
870
     None
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
871
   } else {
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
872
     Some(n)
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
873
   }
1227f932b628 rust import
ellis <ellis@rwest.io>
parents:
diff changeset
874
 }