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