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 
14 use std::io;
15 use std::io::{Read, Write};
16 
17 use crate::io::ReadBuf;
18 
19 pub(crate) struct FileBuf {
20     pub(crate) buf: Vec<u8>,
21     idx: usize,
22 }
23 
24 impl FileBuf {
25     #[inline]
with_capacity(n: usize) -> FileBuf26     pub(crate) fn with_capacity(n: usize) -> FileBuf {
27         FileBuf {
28             buf: Vec::with_capacity(n),
29             idx: 0,
30         }
31     }
32 
remaining(&self) -> usize33     pub(crate) fn remaining(&self) -> usize {
34         self.buf.len() - self.idx
35     }
36 
append_to(&mut self, buf: &mut ReadBuf<'_>) -> usize37     pub(crate) fn append_to(&mut self, buf: &mut ReadBuf<'_>) -> usize {
38         let n = std::cmp::min(self.remaining(), buf.remaining());
39         let r_idx = n + self.idx;
40         buf.append(&self.buf[self.idx..r_idx]);
41 
42         if r_idx == self.buf.len() {
43             self.idx = 0;
44             self.buf.truncate(0);
45         } else {
46             self.idx = r_idx;
47         }
48         n
49     }
50 
51     #[inline]
append(&mut self, other: &[u8], buf_size_limit: usize) -> usize52     pub(crate) fn append(&mut self, other: &[u8], buf_size_limit: usize) -> usize {
53         let n = std::cmp::min(other.len(), buf_size_limit);
54         self.buf.extend_from_slice(&other[..n]);
55         n
56     }
57 
58     #[allow(clippy::uninit_vec)]
59     #[inline]
reserve(&mut self, size: usize, buf_size_limit: usize)60     pub(crate) fn reserve(&mut self, size: usize, buf_size_limit: usize) {
61         let len = std::cmp::min(size, buf_size_limit);
62         self.buf.reserve(len.saturating_sub(self.buf.len()));
63         // need to set length in order to read
64         unsafe { self.buf.set_len(len) }
65     }
66 
read<R: Read>(&mut self, io: &mut R) -> io::Result<usize>67     pub(crate) fn read<R: Read>(&mut self, io: &mut R) -> io::Result<usize> {
68         let ret = loop {
69             match io.read(&mut self.buf) {
70                 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
71                 res => break res,
72             }
73         };
74         match ret {
75             Ok(n) => self.buf.truncate(n),
76             _ => self.buf.truncate(0),
77         }
78         ret
79     }
80 
81     #[inline]
write<W: Write>(&mut self, io: &mut W) -> io::Result<()>82     pub(crate) fn write<W: Write>(&mut self, io: &mut W) -> io::Result<()> {
83         let res = io.write_all(&self.buf);
84         self.buf.clear();
85         res
86     }
87 
88     // Returns the number of bytes that get dropped in the file buf
89     #[inline]
drop_unread(&mut self) -> i6490     pub(crate) fn drop_unread(&mut self) -> i64 {
91         let ret = self.buf.len();
92         self.clear();
93         ret as i64
94     }
95 
96     #[inline]
clear(&mut self)97     pub(crate) fn clear(&mut self) {
98         self.idx = 0;
99         self.buf.clear();
100     }
101 }
102