1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 mod io_reader;
15 pub(crate) use io_reader::IoReader;
16 
17 mod slice_reader;
18 pub(crate) use slice_reader::SliceReader;
19 
20 /// `BytesReader` provides the basic byte read interface, such as `next`,
21 /// `peek`, `index`. Users can obtain the next byte or the current read
22 /// position according to these interfaces.
23 pub(crate) trait BytesReader {
24     /// Errors that may occur during reading, usually in the I\O process.
25     type Error: Into<Box<dyn std::error::Error>>;
26 
27     /// Get the next character and move the cursor to the next place.
next(&mut self) -> Result<Option<u8>, Self::Error>28     fn next(&mut self) -> Result<Option<u8>, Self::Error>;
29 
30     /// Get the next character, but don't move the cursor. So the next read
31     /// will get the same character.
peek(&mut self) -> Result<Option<u8>, Self::Error>32     fn peek(&mut self) -> Result<Option<u8>, Self::Error>;
33 
34     /// Discard the next character and move the cursor to the next place.
discard(&mut self)35     fn discard(&mut self);
36 
37     /// Get the current cursor position and return it as usize.
index(&self) -> usize38     fn index(&self) -> usize;
39 
40     /// Get the current cursor position and return it as `Position`.
position(&self) -> Position41     fn position(&self) -> Position;
42 }
43 
44 /// `Cacheable` provides some byte cache interfaces for caching a portion of
45 /// contiguous bytes in a byte stream.
46 pub(crate) trait Cacheable: BytesReader {
47     /// Start the cache operation. This interface needs to be used with
48     /// `end_caching` or `take_cached_data`.
start_caching(&mut self)49     fn start_caching(&mut self);
50 
51     /// Get the length of the cached bytes. Since the logic of caching
52     /// operations is implementation-dependent, we provide an interface that
53     /// uses mutable references here.
cached_len(&mut self) -> Option<usize>54     fn cached_len(&mut self) -> Option<usize>;
55 
56     /// Get a slice of the cached bytes. Since the logic of caching operations
57     /// is implementation-dependent, we provide an interface that uses mutable
58     /// references here.
cached_slice(&mut self) -> Option<&[u8]>59     fn cached_slice(&mut self) -> Option<&[u8]>;
60 
61     /// Get a `Vec` of the cached bytes. Since the logic of caching operations
62     /// is implementation-dependent, we provide an interface that uses mutable
63     /// references here.
cached_data(&mut self) -> Option<Vec<u8>>64     fn cached_data(&mut self) -> Option<Vec<u8>>;
65 
66     /// End the cache operation. This interface needs to be used with
67     /// `start_caching`.
end_caching(&mut self)68     fn end_caching(&mut self);
69 
70     /// End the cache operation and return the cached bytes. This interface
71     /// needs to be used with `start_caching`.
take_cached_data(&mut self) -> Option<Vec<u8>>72     fn take_cached_data(&mut self) -> Option<Vec<u8>>;
73 }
74 
75 /// `RemainderCountable` provides the interface related to the remainder.
76 pub(crate) trait RemainderCountable: BytesReader {
77     /// Get the length of the remainder.
remainder_len(&self) -> usize78     fn remainder_len(&self) -> usize;
79 
80     /// Get a slice of the remainder.
remainder_slice(&self) -> &[u8]81     fn remainder_slice(&self) -> &[u8];
82 
83     /// Get a `Vec<u8>` of the remainder.
remainder_data(&self) -> Vec<u8>84     fn remainder_data(&self) -> Vec<u8>;
85 }
86 
87 /// `NBytesReadable` provides interfaces to read 'n' bytes at one time.
88 pub(crate) trait NBytesReadable: BytesReader {
89     /// Read the next 'n' bytes and move the cursor to the next nth position.
90     /// If there are not enough bytes remaining to satisfy 'n', return `None`
91     /// and do nothing.
next_n(&mut self, n: usize) -> Result<Option<&[u8]>, Self::Error>92     fn next_n(&mut self, n: usize) -> Result<Option<&[u8]>, Self::Error>;
93 
94     /// Get the next 'n' bytes and do not move the cursor. If there are not
95     /// enough bytes remaining to satisfy 'n', return `None` and do nothing.
peek_n(&mut self, n: usize) -> Result<Option<&[u8]>, Self::Error>96     fn peek_n(&mut self, n: usize) -> Result<Option<&[u8]>, Self::Error>;
97 
98     /// Discard the next 'n' bytes and move the cursor to the next nth position.
99     /// If there are not enough bytes remaining to satisfy 'n', do nothing.
discard_n(&mut self, n: usize)100     fn discard_n(&mut self, n: usize);
101 }
102 
103 /// Position information which expressed in row and column.
104 #[derive(Clone)]
105 pub(crate) struct Position {
106     line: usize,
107     column: usize,
108 }
109 
110 impl Position {
111     /// Create a `Position` from the given line and column.
112     #[inline]
new(line: usize, column: usize) -> Self113     pub(crate) fn new(line: usize, column: usize) -> Self {
114         Self { line, column }
115     }
116 
117     /// Get line.
118     #[inline]
line(&self) -> usize119     pub(crate) fn line(&self) -> usize {
120         self.line
121     }
122 
123     /// Get column.
124     #[inline]
column(&self) -> usize125     pub(crate) fn column(&self) -> usize {
126         self.column
127     }
128 }
129 
130 #[cfg(test)]
131 mod ut_position {
132     use super::Position;
133 
134     /// UT test for `Position::new`.
135     ///
136     /// # Title
137     /// ut_position_new
138     ///
139     /// # Brief
140     /// 1. Call `Position::new` to create a `Position`.
141     /// 2. Check if the results are correct.
142     #[test]
ut_position_new()143     fn ut_position_new() {
144         let position = Position::new(1, 1);
145         assert_eq!(position.line, 1);
146         assert_eq!(position.column, 1);
147     }
148 
149     /// UT test for `Position::line`.
150     ///
151     /// # Title
152     /// ut_position_line
153     ///
154     /// # Brief
155     /// 1. Create a `Position`.
156     /// 2. Call `Position::line` to get the line number of `Position`.
157     /// 3. Check if the results are correct.
158     #[test]
ut_position_line()159     fn ut_position_line() {
160         let position = Position::new(1, 1);
161         assert_eq!(position.line(), 1);
162     }
163 
164     /// UT test for `Position::column`.
165     ///
166     /// # Title
167     /// ut_position_column
168     ///
169     /// # Brief
170     /// 1. Create a `Position`.
171     /// 2. Call `Position::column` to get the column number of `Position`.
172     /// 3. Check if the results are correct.
173     #[test]
ut_position_column()174     fn ut_position_column() {
175         let position = Position::new(1, 1);
176         assert_eq!(position.column(), 1);
177     }
178 
179     /// UT test case for `Position::clone`.
180     ///
181     /// # Title
182     /// ut_position_clone
183     ///
184     /// # Brief
185     /// 1. Create a `Position`.
186     /// 2. Call `Position::clone` to get a copy of `Position`.
187     /// 3. Check if the results are correct.
188     #[allow(clippy::redundant_clone)]
189     #[test]
ut_position_clone()190     fn ut_position_clone() {
191         let position = Position::new(1, 1);
192         let position = position.clone();
193         assert_eq!(position.line, 1);
194         assert_eq!(position.column, 1);
195     }
196 }
197