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_ciuse super::{BytesReader, Cacheable, Position}; 15a1d56debSopenharmony_ciuse std::io::{Error, ErrorKind, Read, Result}; 16a1d56debSopenharmony_ci 17a1d56debSopenharmony_ci/// Reader for reading I\O. This reader implements `BytesReader` trait and 18a1d56debSopenharmony_ci/// `Cacheable` trait. 19a1d56debSopenharmony_ci/// 20a1d56debSopenharmony_ci/// # Examples 21a1d56debSopenharmony_ci/// ```not run 22a1d56debSopenharmony_ci/// use std::fs::File; 23a1d56debSopenharmony_ci/// use ylong_bytes_reader::{IoReader, BytesReader}; 24a1d56debSopenharmony_ci/// 25a1d56debSopenharmony_ci/// let file = File::open("./test.txt").unwrap(); 26a1d56debSopenharmony_ci/// let mut io_reader = IoReader::new(file); 27a1d56debSopenharmony_ci/// let char = io_reader.next(); 28a1d56debSopenharmony_ci/// let char = io_reader.peek(); 29a1d56debSopenharmony_ci/// ``` 30a1d56debSopenharmony_cipub(crate) struct IoReader<R: Read> { 31a1d56debSopenharmony_ci io: R, 32a1d56debSopenharmony_ci buf: Vec<u8>, // Buffer for storing read bytes. 33a1d56debSopenharmony_ci cur: usize, // The position of the cursor in the current buf. 34a1d56debSopenharmony_ci idx: usize, // A counter of all bytes that have been read. 35a1d56debSopenharmony_ci pos: Position, 36a1d56debSopenharmony_ci cache: Option<Cache>, 37a1d56debSopenharmony_ci} 38a1d56debSopenharmony_ci 39a1d56debSopenharmony_ci// A simple cache implementation for `IoReader`. 40a1d56debSopenharmony_cistruct Cache { 41a1d56debSopenharmony_ci cache: Vec<u8>, 42a1d56debSopenharmony_ci pre: usize, // Last cached location. 43a1d56debSopenharmony_ci} 44a1d56debSopenharmony_ci 45a1d56debSopenharmony_ciimpl Cache { 46a1d56debSopenharmony_ci /// Create a new `Cache`. 47a1d56debSopenharmony_ci fn new() -> Self { 48a1d56debSopenharmony_ci Self { 49a1d56debSopenharmony_ci cache: Vec::new(), 50a1d56debSopenharmony_ci pre: 0, 51a1d56debSopenharmony_ci } 52a1d56debSopenharmony_ci } 53a1d56debSopenharmony_ci} 54a1d56debSopenharmony_ci 55a1d56debSopenharmony_ciimpl<R: Read> IoReader<R> { 56a1d56debSopenharmony_ci /// Create a new `IoReader` from the given I\O. 57a1d56debSopenharmony_ci pub(crate) fn new(io: R) -> Self { 58a1d56debSopenharmony_ci Self { 59a1d56debSopenharmony_ci io, 60a1d56debSopenharmony_ci buf: Vec::with_capacity(1024), // Default size is 1024. 61a1d56debSopenharmony_ci cur: 0, 62a1d56debSopenharmony_ci idx: 0, 63a1d56debSopenharmony_ci pos: Position::new(1, 1), 64a1d56debSopenharmony_ci cache: None, 65a1d56debSopenharmony_ci } 66a1d56debSopenharmony_ci } 67a1d56debSopenharmony_ci 68a1d56debSopenharmony_ci // Try to read some bytes from io to fill buf. 69a1d56debSopenharmony_ci fn read_bytes(&mut self) -> Result<bool> { 70a1d56debSopenharmony_ci unsafe { 71a1d56debSopenharmony_ci self.buf.set_len(1024); 72a1d56debSopenharmony_ci } 73a1d56debSopenharmony_ci loop { 74a1d56debSopenharmony_ci return match self.io.read(self.buf.as_mut_slice()) { 75a1d56debSopenharmony_ci Ok(0) => unsafe { 76a1d56debSopenharmony_ci self.buf.set_len(0); 77a1d56debSopenharmony_ci Ok(false) 78a1d56debSopenharmony_ci }, 79a1d56debSopenharmony_ci Ok(n) => unsafe { 80a1d56debSopenharmony_ci self.buf.set_len(n); 81a1d56debSopenharmony_ci Ok(true) 82a1d56debSopenharmony_ci }, 83a1d56debSopenharmony_ci Err(ref e) if e.kind() == ErrorKind::WouldBlock => continue, 84a1d56debSopenharmony_ci Err(e) => Err(e), 85a1d56debSopenharmony_ci }; 86a1d56debSopenharmony_ci } 87a1d56debSopenharmony_ci } 88a1d56debSopenharmony_ci 89a1d56debSopenharmony_ci // If there is not enough bytes in buf, try to read some bytes from io and 90a1d56debSopenharmony_ci // reset some parameters inside. 91a1d56debSopenharmony_ci fn load(&mut self) -> Result<bool> { 92a1d56debSopenharmony_ci if let Some(ref mut cacher) = self.cache { 93a1d56debSopenharmony_ci cacher.cache.extend_from_slice(&self.buf[cacher.pre..]); 94a1d56debSopenharmony_ci cacher.pre = 0; 95a1d56debSopenharmony_ci } 96a1d56debSopenharmony_ci let result = self.read_bytes(); 97a1d56debSopenharmony_ci if let Ok(true) = result { 98a1d56debSopenharmony_ci self.cur = 0; 99a1d56debSopenharmony_ci } 100a1d56debSopenharmony_ci result 101a1d56debSopenharmony_ci } 102a1d56debSopenharmony_ci 103a1d56debSopenharmony_ci // Every time a user calls a cache-related interface, the cache content 104a1d56debSopenharmony_ci // needs to be updated in time. 105a1d56debSopenharmony_ci fn update_cache(&mut self) { 106a1d56debSopenharmony_ci if let Some(ref mut cacher) = self.cache { 107a1d56debSopenharmony_ci if self.cur > cacher.pre { 108a1d56debSopenharmony_ci cacher 109a1d56debSopenharmony_ci .cache 110a1d56debSopenharmony_ci .extend_from_slice(&self.buf[cacher.pre..self.cur]); 111a1d56debSopenharmony_ci } 112a1d56debSopenharmony_ci cacher.pre = self.cur; 113a1d56debSopenharmony_ci } 114a1d56debSopenharmony_ci } 115a1d56debSopenharmony_ci} 116a1d56debSopenharmony_ci 117a1d56debSopenharmony_ciimpl<R: Read> BytesReader for IoReader<R> { 118a1d56debSopenharmony_ci type Error = Error; 119a1d56debSopenharmony_ci 120a1d56debSopenharmony_ci fn next(&mut self) -> Result<Option<u8>> { 121a1d56debSopenharmony_ci if self.cur == self.buf.len() { 122a1d56debSopenharmony_ci match self.load() { 123a1d56debSopenharmony_ci Ok(true) => {} 124a1d56debSopenharmony_ci Ok(false) => return Ok(None), 125a1d56debSopenharmony_ci Err(e) => return Err(e), 126a1d56debSopenharmony_ci } 127a1d56debSopenharmony_ci } 128a1d56debSopenharmony_ci 129a1d56debSopenharmony_ci let ch = self.buf[self.cur]; 130a1d56debSopenharmony_ci self.cur += 1; 131a1d56debSopenharmony_ci self.idx += 1; 132a1d56debSopenharmony_ci 133a1d56debSopenharmony_ci if ch == b'\n' { 134a1d56debSopenharmony_ci self.pos.line += 1; 135a1d56debSopenharmony_ci self.pos.column = 1; 136a1d56debSopenharmony_ci } else { 137a1d56debSopenharmony_ci self.pos.column += 1; 138a1d56debSopenharmony_ci } 139a1d56debSopenharmony_ci 140a1d56debSopenharmony_ci Ok(Some(ch)) 141a1d56debSopenharmony_ci } 142a1d56debSopenharmony_ci 143a1d56debSopenharmony_ci fn peek(&mut self) -> Result<Option<u8>> { 144a1d56debSopenharmony_ci if self.cur == self.buf.len() { 145a1d56debSopenharmony_ci match self.load() { 146a1d56debSopenharmony_ci Ok(true) => {} 147a1d56debSopenharmony_ci Ok(false) => return Ok(None), 148a1d56debSopenharmony_ci Err(e) => return Err(e), 149a1d56debSopenharmony_ci } 150a1d56debSopenharmony_ci } 151a1d56debSopenharmony_ci 152a1d56debSopenharmony_ci Ok(Some(self.buf[self.cur])) 153a1d56debSopenharmony_ci } 154a1d56debSopenharmony_ci 155a1d56debSopenharmony_ci fn discard(&mut self) { 156a1d56debSopenharmony_ci if self.cur == self.buf.len() { 157a1d56debSopenharmony_ci match self.load() { 158a1d56debSopenharmony_ci Ok(true) => {} 159a1d56debSopenharmony_ci Ok(false) => return, 160a1d56debSopenharmony_ci Err(_) => return, 161a1d56debSopenharmony_ci } 162a1d56debSopenharmony_ci } 163a1d56debSopenharmony_ci 164a1d56debSopenharmony_ci let ch = self.buf[self.cur]; 165a1d56debSopenharmony_ci self.cur += 1; 166a1d56debSopenharmony_ci self.idx += 1; 167a1d56debSopenharmony_ci 168a1d56debSopenharmony_ci if ch == b'\n' { 169a1d56debSopenharmony_ci self.pos.line += 1; 170a1d56debSopenharmony_ci self.pos.column = 1; 171a1d56debSopenharmony_ci } else { 172a1d56debSopenharmony_ci self.pos.column += 1; 173a1d56debSopenharmony_ci } 174a1d56debSopenharmony_ci } 175a1d56debSopenharmony_ci 176a1d56debSopenharmony_ci #[inline] 177a1d56debSopenharmony_ci fn index(&self) -> usize { 178a1d56debSopenharmony_ci self.idx 179a1d56debSopenharmony_ci } 180a1d56debSopenharmony_ci 181a1d56debSopenharmony_ci #[inline] 182a1d56debSopenharmony_ci fn position(&self) -> Position { 183a1d56debSopenharmony_ci self.pos.clone() 184a1d56debSopenharmony_ci } 185a1d56debSopenharmony_ci} 186a1d56debSopenharmony_ci 187a1d56debSopenharmony_ciimpl<R: Read> Cacheable for IoReader<R> { 188a1d56debSopenharmony_ci fn start_caching(&mut self) { 189a1d56debSopenharmony_ci if let Some(ref mut cacher) = self.cache { 190a1d56debSopenharmony_ci cacher.cache.clear(); 191a1d56debSopenharmony_ci cacher.pre = self.cur; 192a1d56debSopenharmony_ci } else { 193a1d56debSopenharmony_ci let mut cache = Cache::new(); 194a1d56debSopenharmony_ci cache.pre = self.cur; 195a1d56debSopenharmony_ci self.cache = Some(cache); 196a1d56debSopenharmony_ci } 197a1d56debSopenharmony_ci } 198a1d56debSopenharmony_ci 199a1d56debSopenharmony_ci fn cached_len(&mut self) -> Option<usize> { 200a1d56debSopenharmony_ci self.update_cache(); 201a1d56debSopenharmony_ci self.cache.as_ref().map(|c| c.cache.len()) 202a1d56debSopenharmony_ci } 203a1d56debSopenharmony_ci 204a1d56debSopenharmony_ci fn cached_slice(&mut self) -> Option<&[u8]> { 205a1d56debSopenharmony_ci self.update_cache(); 206a1d56debSopenharmony_ci self.cache.as_ref().map(|c| c.cache.as_slice()) 207a1d56debSopenharmony_ci } 208a1d56debSopenharmony_ci 209a1d56debSopenharmony_ci fn cached_data(&mut self) -> Option<Vec<u8>> { 210a1d56debSopenharmony_ci self.update_cache(); 211a1d56debSopenharmony_ci self.cache.as_ref().map(|c| c.cache.clone()) 212a1d56debSopenharmony_ci } 213a1d56debSopenharmony_ci 214a1d56debSopenharmony_ci fn end_caching(&mut self) { 215a1d56debSopenharmony_ci self.cache = None; 216a1d56debSopenharmony_ci } 217a1d56debSopenharmony_ci 218a1d56debSopenharmony_ci fn take_cached_data(&mut self) -> Option<Vec<u8>> { 219a1d56debSopenharmony_ci self.update_cache(); 220a1d56debSopenharmony_ci self.cache.take().map(|c| c.cache) 221a1d56debSopenharmony_ci } 222a1d56debSopenharmony_ci} 223a1d56debSopenharmony_ci 224a1d56debSopenharmony_ci#[cfg(test)] 225a1d56debSopenharmony_cimod ut_io_reader { 226a1d56debSopenharmony_ci use super::{BytesReader, Cacheable, IoReader}; 227a1d56debSopenharmony_ci use std::cmp; 228a1d56debSopenharmony_ci use std::io::{ErrorKind, Read}; 229a1d56debSopenharmony_ci 230a1d56debSopenharmony_ci struct TestIo { 231a1d56debSopenharmony_ci vec: Vec<u8>, 232a1d56debSopenharmony_ci idx: usize, 233a1d56debSopenharmony_ci } 234a1d56debSopenharmony_ci 235a1d56debSopenharmony_ci impl TestIo { 236a1d56debSopenharmony_ci fn new(vec: Vec<u8>) -> Self { 237a1d56debSopenharmony_ci Self { vec, idx: 0 } 238a1d56debSopenharmony_ci } 239a1d56debSopenharmony_ci } 240a1d56debSopenharmony_ci 241a1d56debSopenharmony_ci impl Read for TestIo { 242a1d56debSopenharmony_ci fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { 243a1d56debSopenharmony_ci if self.idx == self.vec.len() { 244a1d56debSopenharmony_ci return Ok(0); 245a1d56debSopenharmony_ci } 246a1d56debSopenharmony_ci let last = cmp::min(self.idx + buf.len(), self.vec.len()); 247a1d56debSopenharmony_ci let len = last - self.idx; 248a1d56debSopenharmony_ci buf[..len].copy_from_slice(&self.vec[self.idx..last]); 249a1d56debSopenharmony_ci self.idx = last; 250a1d56debSopenharmony_ci Ok(len) 251a1d56debSopenharmony_ci } 252a1d56debSopenharmony_ci } 253a1d56debSopenharmony_ci 254a1d56debSopenharmony_ci struct TestWouldBlockIo { 255a1d56debSopenharmony_ci cnt: usize, 256a1d56debSopenharmony_ci } 257a1d56debSopenharmony_ci 258a1d56debSopenharmony_ci impl TestWouldBlockIo { 259a1d56debSopenharmony_ci fn new() -> Self { 260a1d56debSopenharmony_ci Self { cnt: 0 } 261a1d56debSopenharmony_ci } 262a1d56debSopenharmony_ci 263a1d56debSopenharmony_ci fn is_finished(&self) -> bool { 264a1d56debSopenharmony_ci self.cnt == 10 265a1d56debSopenharmony_ci } 266a1d56debSopenharmony_ci } 267a1d56debSopenharmony_ci 268a1d56debSopenharmony_ci impl Read for TestWouldBlockIo { 269a1d56debSopenharmony_ci fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> { 270a1d56debSopenharmony_ci if self.cnt < 10 { 271a1d56debSopenharmony_ci self.cnt += 1; 272a1d56debSopenharmony_ci return Err(ErrorKind::WouldBlock.into()); 273a1d56debSopenharmony_ci } 274a1d56debSopenharmony_ci Ok(0) 275a1d56debSopenharmony_ci } 276a1d56debSopenharmony_ci } 277a1d56debSopenharmony_ci 278a1d56debSopenharmony_ci struct TestErrIo; 279a1d56debSopenharmony_ci 280a1d56debSopenharmony_ci impl TestErrIo { 281a1d56debSopenharmony_ci fn new() -> Self { 282a1d56debSopenharmony_ci Self 283a1d56debSopenharmony_ci } 284a1d56debSopenharmony_ci } 285a1d56debSopenharmony_ci 286a1d56debSopenharmony_ci impl Read for TestErrIo { 287a1d56debSopenharmony_ci fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> { 288a1d56debSopenharmony_ci Err(ErrorKind::AddrInUse.into()) 289a1d56debSopenharmony_ci } 290a1d56debSopenharmony_ci } 291a1d56debSopenharmony_ci 292a1d56debSopenharmony_ci /// UT test case for `IoReader::new`. 293a1d56debSopenharmony_ci /// 294a1d56debSopenharmony_ci /// # Title 295a1d56debSopenharmony_ci /// ut_io_reader_new 296a1d56debSopenharmony_ci /// 297a1d56debSopenharmony_ci /// # Brief 298a1d56debSopenharmony_ci /// 1. Call `IoReader::new`. 299a1d56debSopenharmony_ci /// 2. Check that parts of the return value are default values. 300a1d56debSopenharmony_ci #[test] 301a1d56debSopenharmony_ci fn ut_io_reader_new() { 302a1d56debSopenharmony_ci let io = TestIo::new(Vec::new()); 303a1d56debSopenharmony_ci let io_reader = IoReader::new(io); 304a1d56debSopenharmony_ci 305a1d56debSopenharmony_ci assert_eq!(io_reader.cur, 0); 306a1d56debSopenharmony_ci assert_eq!(io_reader.idx, 0); 307a1d56debSopenharmony_ci assert_eq!(io_reader.pos.line, 1); 308a1d56debSopenharmony_ci assert_eq!(io_reader.pos.column, 1); 309a1d56debSopenharmony_ci assert_eq!(io_reader.buf.capacity(), 1024); 310a1d56debSopenharmony_ci assert!(io_reader.buf.is_empty()); 311a1d56debSopenharmony_ci assert!(io_reader.cache.is_none()); 312a1d56debSopenharmony_ci } 313a1d56debSopenharmony_ci 314a1d56debSopenharmony_ci /// UT test case for `IoReader::next`. 315a1d56debSopenharmony_ci /// 316a1d56debSopenharmony_ci /// # Title 317a1d56debSopenharmony_ci /// ut_test_case_io_reader_next 318a1d56debSopenharmony_ci /// 319a1d56debSopenharmony_ci /// # Brief 320a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 321a1d56debSopenharmony_ci /// 2. Call `IoReader::next`. 322a1d56debSopenharmony_ci /// 3. Check the return value against the following conditions: 323a1d56debSopenharmony_ci /// - If the end is not read, it returns `Ok(Some(..))`, and the index 324a1d56debSopenharmony_ci /// is moved backward; if the end is read, it returns `Ok(None)`, and 325a1d56debSopenharmony_ci /// the index is not moved. 326a1d56debSopenharmony_ci #[test] 327a1d56debSopenharmony_ci fn ut_io_reader_next() { 328a1d56debSopenharmony_ci // Use TestIo. 329a1d56debSopenharmony_ci let io = TestIo::new(vec![1u8; 1025]); 330a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 331a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(1)); 332a1d56debSopenharmony_ci for _ in 0..1023 { 333a1d56debSopenharmony_ci let _ = io_reader.next().unwrap(); 334a1d56debSopenharmony_ci } 335a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(1)); 336a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), None); 337a1d56debSopenharmony_ci 338a1d56debSopenharmony_ci // Use TestWouldBlockIo. 339a1d56debSopenharmony_ci let io = TestWouldBlockIo::new(); 340a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 341a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), None); 342a1d56debSopenharmony_ci assert!(io_reader.io.is_finished()); 343a1d56debSopenharmony_ci 344a1d56debSopenharmony_ci // Use TestErrIo 345a1d56debSopenharmony_ci let io = TestErrIo::new(); 346a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 347a1d56debSopenharmony_ci assert!(io_reader.next().is_err()); 348a1d56debSopenharmony_ci } 349a1d56debSopenharmony_ci 350a1d56debSopenharmony_ci /// UT test case for `IoReader::peek`. 351a1d56debSopenharmony_ci /// 352a1d56debSopenharmony_ci /// # Title 353a1d56debSopenharmony_ci /// ut_io_reader_peek 354a1d56debSopenharmony_ci /// 355a1d56debSopenharmony_ci /// # Brief 356a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 357a1d56debSopenharmony_ci /// 2. Call `IoReader::peek`. 358a1d56debSopenharmony_ci /// 3. Check the return value against the following conditions: 359a1d56debSopenharmony_ci /// - If the end is not read, it returns `Ok(Some(..))`; if the end is 360a1d56debSopenharmony_ci /// read, it returns `Ok(None)`. 361a1d56debSopenharmony_ci #[test] 362a1d56debSopenharmony_ci fn ut_io_reader_peek() { 363a1d56debSopenharmony_ci // Use TestIo. 364a1d56debSopenharmony_ci let io = TestIo::new(vec![1u8; 1]); 365a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 366a1d56debSopenharmony_ci assert_eq!(io_reader.peek().unwrap(), Some(1)); 367a1d56debSopenharmony_ci assert_eq!(io_reader.peek().unwrap(), Some(1)); 368a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(1)); 369a1d56debSopenharmony_ci assert_eq!(io_reader.peek().unwrap(), None); 370a1d56debSopenharmony_ci 371a1d56debSopenharmony_ci // Use TestWouldBlockIo. 372a1d56debSopenharmony_ci let io = TestWouldBlockIo::new(); 373a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 374a1d56debSopenharmony_ci assert_eq!(io_reader.peek().unwrap(), None); 375a1d56debSopenharmony_ci assert!(io_reader.io.is_finished()); 376a1d56debSopenharmony_ci 377a1d56debSopenharmony_ci // Use TestErrorIo. 378a1d56debSopenharmony_ci let io = TestErrIo::new(); 379a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 380a1d56debSopenharmony_ci assert!(io_reader.peek().is_err()); 381a1d56debSopenharmony_ci } 382a1d56debSopenharmony_ci 383a1d56debSopenharmony_ci /// UT test case for `IoReader::discard`. 384a1d56debSopenharmony_ci /// 385a1d56debSopenharmony_ci /// # Title 386a1d56debSopenharmony_ci /// ut_io_reader_discard 387a1d56debSopenharmony_ci /// 388a1d56debSopenharmony_ci /// # Brief 389a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 390a1d56debSopenharmony_ci /// 2. Call `IoReader::discard`. 391a1d56debSopenharmony_ci /// 3. Check `index` against the following conditions: 392a1d56debSopenharmony_ci /// - If the end is not read, the index is moved backward; if the end is 393a1d56debSopenharmony_ci /// read, the index is not moved. 394a1d56debSopenharmony_ci #[test] 395a1d56debSopenharmony_ci fn ut_io_reader_discard() { 396a1d56debSopenharmony_ci let io = TestIo::new(vec![1u8; 1]); 397a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 398a1d56debSopenharmony_ci assert_eq!(io_reader.index(), 0); 399a1d56debSopenharmony_ci io_reader.discard(); 400a1d56debSopenharmony_ci assert_eq!(io_reader.index(), 1); 401a1d56debSopenharmony_ci io_reader.discard(); 402a1d56debSopenharmony_ci assert_eq!(io_reader.index(), 1); 403a1d56debSopenharmony_ci } 404a1d56debSopenharmony_ci 405a1d56debSopenharmony_ci /// UT test case for `IoReader::index`. 406a1d56debSopenharmony_ci /// 407a1d56debSopenharmony_ci /// # Title 408a1d56debSopenharmony_ci /// ut_io_reader_index 409a1d56debSopenharmony_ci /// 410a1d56debSopenharmony_ci /// # Brief 411a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 412a1d56debSopenharmony_ci /// 2. Call `IoReader::index`. 413a1d56debSopenharmony_ci /// 3. Check if the `index` is correct. 414a1d56debSopenharmony_ci #[test] 415a1d56debSopenharmony_ci fn ut_io_reader_index() { 416a1d56debSopenharmony_ci let io = TestIo::new(vec![1u8; 1]); 417a1d56debSopenharmony_ci let io_reader = IoReader::new(io); 418a1d56debSopenharmony_ci assert_eq!(io_reader.index(), 0); 419a1d56debSopenharmony_ci } 420a1d56debSopenharmony_ci 421a1d56debSopenharmony_ci /// UT test case for `IoReader::position`. 422a1d56debSopenharmony_ci /// 423a1d56debSopenharmony_ci /// # Title 424a1d56debSopenharmony_ci /// ut_io_reader_position 425a1d56debSopenharmony_ci /// 426a1d56debSopenharmony_ci /// # Brief 427a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 428a1d56debSopenharmony_ci /// 2. Call `IoReader::position`. 429a1d56debSopenharmony_ci /// 3. Check the return value against the following conditions: 430a1d56debSopenharmony_ci /// - If `'\n'` is read, the line number will increase and the column 431a1d56debSopenharmony_ci /// number will return to 1; if other characters are read, the line 432a1d56debSopenharmony_ci /// number will remain unchanged and the column number will increase. 433a1d56debSopenharmony_ci #[test] 434a1d56debSopenharmony_ci fn ut_io_reader_position() { 435a1d56debSopenharmony_ci let io = TestIo::new(vec![1u8, b'\n', 2, b'\n', 3]); 436a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 437a1d56debSopenharmony_ci let position = io_reader.position(); 438a1d56debSopenharmony_ci assert_eq!(position.line(), 1); 439a1d56debSopenharmony_ci assert_eq!(position.column(), 1); 440a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(1)); 441a1d56debSopenharmony_ci 442a1d56debSopenharmony_ci // Use `next()`. 443a1d56debSopenharmony_ci let position = io_reader.position(); 444a1d56debSopenharmony_ci assert_eq!(position.line(), 1); 445a1d56debSopenharmony_ci assert_eq!(position.column(), 2); 446a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(b'\n')); 447a1d56debSopenharmony_ci 448a1d56debSopenharmony_ci let position = io_reader.position(); 449a1d56debSopenharmony_ci assert_eq!(position.line(), 2); 450a1d56debSopenharmony_ci assert_eq!(position.column(), 1); 451a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(2)); 452a1d56debSopenharmony_ci 453a1d56debSopenharmony_ci // Use `peek()` and `discard()`. 454a1d56debSopenharmony_ci let position = io_reader.position(); 455a1d56debSopenharmony_ci assert_eq!(position.line(), 2); 456a1d56debSopenharmony_ci assert_eq!(position.column(), 2); 457a1d56debSopenharmony_ci assert_eq!(io_reader.peek().unwrap(), Some(b'\n')); 458a1d56debSopenharmony_ci io_reader.discard(); 459a1d56debSopenharmony_ci 460a1d56debSopenharmony_ci let position = io_reader.position(); 461a1d56debSopenharmony_ci assert_eq!(position.line(), 3); 462a1d56debSopenharmony_ci assert_eq!(position.column(), 1); 463a1d56debSopenharmony_ci assert_eq!(io_reader.peek().unwrap(), Some(3)); 464a1d56debSopenharmony_ci io_reader.discard(); 465a1d56debSopenharmony_ci 466a1d56debSopenharmony_ci let position = io_reader.position(); 467a1d56debSopenharmony_ci assert_eq!(position.line(), 3); 468a1d56debSopenharmony_ci assert_eq!(position.column(), 2); 469a1d56debSopenharmony_ci assert_eq!(io_reader.peek().unwrap(), None); 470a1d56debSopenharmony_ci } 471a1d56debSopenharmony_ci 472a1d56debSopenharmony_ci /// UT test case for `IoReader::start_caching`. 473a1d56debSopenharmony_ci /// 474a1d56debSopenharmony_ci /// # Title 475a1d56debSopenharmony_ci /// ut_io_reader_start_caching 476a1d56debSopenharmony_ci /// 477a1d56debSopenharmony_ci /// # Brief 478a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 479a1d56debSopenharmony_ci /// 2. Call `IoReader::start_caching`. 480a1d56debSopenharmony_ci /// 3. Check if `cache` is correct. 481a1d56debSopenharmony_ci #[test] 482a1d56debSopenharmony_ci fn ut_io_reader_start_caching() { 483a1d56debSopenharmony_ci let io = TestIo::new(vec![1]); 484a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 485a1d56debSopenharmony_ci assert!(io_reader.cache.is_none()); 486a1d56debSopenharmony_ci io_reader.start_caching(); 487a1d56debSopenharmony_ci assert!(io_reader.cache.is_some()); 488a1d56debSopenharmony_ci assert_eq!(io_reader.cached_len(), Some(0)); 489a1d56debSopenharmony_ci 490a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(1)); 491a1d56debSopenharmony_ci assert_eq!(io_reader.cached_len(), Some(1)); 492a1d56debSopenharmony_ci io_reader.start_caching(); 493a1d56debSopenharmony_ci assert_eq!(io_reader.cached_len(), Some(0)); 494a1d56debSopenharmony_ci } 495a1d56debSopenharmony_ci 496a1d56debSopenharmony_ci /// UT test case for `IoReader::cached_len`. 497a1d56debSopenharmony_ci /// 498a1d56debSopenharmony_ci /// # Title 499a1d56debSopenharmony_ci /// ut_io_reader_cached_len 500a1d56debSopenharmony_ci /// 501a1d56debSopenharmony_ci /// # Brief 502a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 503a1d56debSopenharmony_ci /// 2. Call `IoReader::cached_len`. 504a1d56debSopenharmony_ci /// 3. Check the return value against the following conditions: 505a1d56debSopenharmony_ci /// - Returns `None` if caching is not enabled, otherwise returns 506a1d56debSopenharmony_ci /// `Some(..)`. 507a1d56debSopenharmony_ci #[test] 508a1d56debSopenharmony_ci fn ut_io_reader_cached_len() { 509a1d56debSopenharmony_ci let io = TestIo::new(Vec::new()); 510a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 511a1d56debSopenharmony_ci assert_eq!(io_reader.cached_len(), None); 512a1d56debSopenharmony_ci io_reader.start_caching(); 513a1d56debSopenharmony_ci assert_eq!(io_reader.cached_len(), Some(0)); 514a1d56debSopenharmony_ci } 515a1d56debSopenharmony_ci 516a1d56debSopenharmony_ci /// UT test case for `IoReader::cached_slice`. 517a1d56debSopenharmony_ci /// 518a1d56debSopenharmony_ci /// # Title 519a1d56debSopenharmony_ci /// ut_io_reader_cached_slice 520a1d56debSopenharmony_ci /// 521a1d56debSopenharmony_ci /// # Brief 522a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 523a1d56debSopenharmony_ci /// 2. Call `IoReader::cached_slice`. 524a1d56debSopenharmony_ci /// 3. Check the return value against the following conditions: 525a1d56debSopenharmony_ci /// - Returns `None` if caching is not enabled, otherwise returns 526a1d56debSopenharmony_ci /// `Some(..)`. 527a1d56debSopenharmony_ci #[test] 528a1d56debSopenharmony_ci fn ut_io_reader_cached_slice() { 529a1d56debSopenharmony_ci let io = TestIo::new(Vec::new()); 530a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 531a1d56debSopenharmony_ci assert_eq!(io_reader.cached_slice(), None); 532a1d56debSopenharmony_ci io_reader.start_caching(); 533a1d56debSopenharmony_ci assert_eq!(io_reader.cached_slice(), Some([].as_slice())); 534a1d56debSopenharmony_ci 535a1d56debSopenharmony_ci // Test 1025 bytes. 536a1d56debSopenharmony_ci let mut input = vec![0; 1024]; 537a1d56debSopenharmony_ci input.push(1); 538a1d56debSopenharmony_ci let io = TestIo::new(input); 539a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 540a1d56debSopenharmony_ci for _ in 0..1023 { 541a1d56debSopenharmony_ci let _ = io_reader.next(); 542a1d56debSopenharmony_ci } 543a1d56debSopenharmony_ci io_reader.start_caching(); 544a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(0)); 545a1d56debSopenharmony_ci assert_eq!(io_reader.next().unwrap(), Some(1)); 546a1d56debSopenharmony_ci assert_eq!(io_reader.cached_len(), Some(2)); 547a1d56debSopenharmony_ci } 548a1d56debSopenharmony_ci 549a1d56debSopenharmony_ci /// UT test case for `IoReader::cached_data`. 550a1d56debSopenharmony_ci /// 551a1d56debSopenharmony_ci /// # Title 552a1d56debSopenharmony_ci /// ut_io_reader_cached_slice 553a1d56debSopenharmony_ci /// 554a1d56debSopenharmony_ci /// # Brief 555a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 556a1d56debSopenharmony_ci /// 2. Call `IoReader::cached_data`. 557a1d56debSopenharmony_ci /// 3. Check the return value against the following conditions: 558a1d56debSopenharmony_ci /// - Returns `None` if caching is not enabled, otherwise returns 559a1d56debSopenharmony_ci /// `Some(..)`. 560a1d56debSopenharmony_ci #[test] 561a1d56debSopenharmony_ci fn ut_io_reader_cached_data() { 562a1d56debSopenharmony_ci let io = TestIo::new(Vec::new()); 563a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 564a1d56debSopenharmony_ci assert_eq!(io_reader.cached_data(), None); 565a1d56debSopenharmony_ci io_reader.start_caching(); 566a1d56debSopenharmony_ci assert_eq!(io_reader.cached_data(), Some(Vec::new())); 567a1d56debSopenharmony_ci } 568a1d56debSopenharmony_ci 569a1d56debSopenharmony_ci /// UT test case for `IoReader::end_caching`. 570a1d56debSopenharmony_ci /// 571a1d56debSopenharmony_ci /// # Title 572a1d56debSopenharmony_ci /// ut_io_reader_end_caching 573a1d56debSopenharmony_ci /// 574a1d56debSopenharmony_ci /// # Brief 575a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 576a1d56debSopenharmony_ci /// 2. Call `IoReader::end_caching`. 577a1d56debSopenharmony_ci /// 3. Check if `cache` is correct. 578a1d56debSopenharmony_ci #[test] 579a1d56debSopenharmony_ci fn ut_io_reader_end_caching() { 580a1d56debSopenharmony_ci let io = TestIo::new(Vec::new()); 581a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 582a1d56debSopenharmony_ci io_reader.start_caching(); 583a1d56debSopenharmony_ci assert!(io_reader.cache.is_some()); 584a1d56debSopenharmony_ci io_reader.end_caching(); 585a1d56debSopenharmony_ci assert!(io_reader.cache.is_none()); 586a1d56debSopenharmony_ci } 587a1d56debSopenharmony_ci 588a1d56debSopenharmony_ci /// UT test case for `IoReader::take_cached_data`. 589a1d56debSopenharmony_ci /// 590a1d56debSopenharmony_ci /// # Title 591a1d56debSopenharmony_ci /// ut_io_reader_take_cached_data 592a1d56debSopenharmony_ci /// 593a1d56debSopenharmony_ci /// # Brief 594a1d56debSopenharmony_ci /// 1. Create a `IoReader`. 595a1d56debSopenharmony_ci /// 2. Call `IoReader::take_cached_data`. 596a1d56debSopenharmony_ci /// 3. Check if the return value is correct. 597a1d56debSopenharmony_ci #[test] 598a1d56debSopenharmony_ci fn ut_io_reader_take_cached_data() { 599a1d56debSopenharmony_ci let io = TestIo::new(Vec::new()); 600a1d56debSopenharmony_ci let mut io_reader = IoReader::new(io); 601a1d56debSopenharmony_ci io_reader.start_caching(); 602a1d56debSopenharmony_ci assert!(io_reader.cache.is_some()); 603a1d56debSopenharmony_ci assert_eq!(io_reader.take_cached_data(), Some(Vec::new())); 604a1d56debSopenharmony_ci assert!(io_reader.cache.is_none()); 605a1d56debSopenharmony_ci } 606a1d56debSopenharmony_ci} 607