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