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 14mod io_reader; 15pub(crate) use io_reader::IoReader; 16 17mod slice_reader; 18pub(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. 23pub(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. 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. 32 fn peek(&mut self) -> Result<Option<u8>, Self::Error>; 33 34 /// Discard the next character and move the cursor to the next place. 35 fn discard(&mut self); 36 37 /// Get the current cursor position and return it as usize. 38 fn index(&self) -> usize; 39 40 /// Get the current cursor position and return it as `Position`. 41 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. 46pub(crate) trait Cacheable: BytesReader { 47 /// Start the cache operation. This interface needs to be used with 48 /// `end_caching` or `take_cached_data`. 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. 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. 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. 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`. 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`. 72 fn take_cached_data(&mut self) -> Option<Vec<u8>>; 73} 74 75/// `RemainderCountable` provides the interface related to the remainder. 76pub(crate) trait RemainderCountable: BytesReader { 77 /// Get the length of the remainder. 78 fn remainder_len(&self) -> usize; 79 80 /// Get a slice of the remainder. 81 fn remainder_slice(&self) -> &[u8]; 82 83 /// Get a `Vec<u8>` of the remainder. 84 fn remainder_data(&self) -> Vec<u8>; 85} 86 87/// `NBytesReadable` provides interfaces to read 'n' bytes at one time. 88pub(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. 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. 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. 100 fn discard_n(&mut self, n: usize); 101} 102 103/// Position information which expressed in row and column. 104#[derive(Clone)] 105pub(crate) struct Position { 106 line: usize, 107 column: usize, 108} 109 110impl Position { 111 /// Create a `Position` from the given line and column. 112 #[inline] 113 pub(crate) fn new(line: usize, column: usize) -> Self { 114 Self { line, column } 115 } 116 117 /// Get line. 118 #[inline] 119 pub(crate) fn line(&self) -> usize { 120 self.line 121 } 122 123 /// Get column. 124 #[inline] 125 pub(crate) fn column(&self) -> usize { 126 self.column 127 } 128} 129 130#[cfg(test)] 131mod 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] 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] 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] 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] 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