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