Слияние кода завершено, страница обновится автоматически
// Copyright (c) 2022 Huawei Technologies Co.,Ltd. All rights reserved.
//
// StratoVirt is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan
// PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
// http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY
// KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
use std::collections::LinkedList;
use std::io::Read;
/// Linked the bytes buffer by linklist, to avoid the
/// extra copies when appending a new bytes buffer.
pub struct BuffPool {
/// Cache received data.
buf_list: LinkedList<Vec<u8>>,
/// Limit size of the buffpool.
limit: Option<usize>,
/// Total length of Buffer.
len: usize,
}
impl Default for BuffPool {
fn default() -> Self {
Self::new()
}
}
impl BuffPool {
pub fn new() -> Self {
Self {
buf_list: LinkedList::new(),
limit: None,
len: 0,
}
}
/// Update the length of bufflist.
fn update_len(&mut self) {
let mut len: usize = 0;
for bytes in &self.buf_list {
len += bytes.len();
}
self.len = len;
}
/// Return the len of the pool.
pub fn len(&self) -> usize {
self.len
}
/// If it is empty.
pub fn is_empty(&self) -> bool {
self.buf_list.is_empty()
}
/// For a given length of buffer data, whether there is
/// enough space left to store.
pub fn is_enough(&self, require: usize) -> bool {
if let Some(limit) = self.limit {
if self.len() + require > limit {
return false;
}
}
true
}
/// Set the limitation for bufferpool.
///
/// # Example
/// ```rust
/// use ui::utils::BuffPool;
///
/// let mut buffpool = BuffPool::new();
/// buffpool.set_limit(Some(1));
/// assert!(!buffpool.is_enough(2));
/// ```
pub fn set_limit(&mut self, limit: Option<usize>) {
self.limit = limit;
}
/// Add data to the bufferpool. If the remaining
/// free space is not enough, it will not work. So it is
/// recommended to call is_enough() before this function.
///
/// # Example
/// ```rust
/// use ui::utils::BuffPool;
///
/// let mut buffpool = BuffPool::new();
/// buffpool.append_limit((0_u8).to_be_bytes().to_vec());
/// ```
pub fn append_limit(&mut self, buf: Vec<u8>) {
let len = buf.len();
if len == 0 {
return;
}
if self.is_enough(len) {
self.buf_list.push_back(buf);
}
self.update_len();
}
/// Read the first n bytes.
///
/// # Example
/// ```rust
/// use ui::utils::BuffPool;
///
/// let mut buffpool = BuffPool::new();
/// buffpool.append_limit((0x12345678 as u32).to_be_bytes().to_vec());
/// let mut buf: Vec<u8> = vec![0_u8; 4];
/// buffpool.read_front(&mut buf, 4);
/// assert_eq!(buf, vec![18, 52, 86, 120]);
/// ```
pub fn read_front(&mut self, buf: &mut [u8], len: usize) -> usize {
if buf.len() < len {
return 0_usize;
}
let mut offset: usize = 0;
for bytes in &self.buf_list {
if let Ok(n) = bytes.as_slice().read(&mut buf[offset..]) {
offset += n;
} else {
return 0_usize;
}
if offset >= len {
break;
}
}
offset
}
/// Remove the first n bytes.
///
/// # Example
/// ```rust
/// use ui::utils::BuffPool;
///
/// let mut buffpool = BuffPool::new();
/// buffpool.append_limit((0x12345678 as u32).to_be_bytes().to_vec());
/// buffpool.remove_front(1);
/// let mut buf: Vec<u8> = vec![0_u8; 3];
/// buffpool.read_front(&mut buf, 3);
/// assert_eq!(buf, vec![52, 86, 120]);
/// ```
pub fn remove_front(&mut self, mut len: usize) {
while let Some(mut bytes) = self.buf_list.pop_front() {
if len < bytes.len() {
self.buf_list.push_front(bytes.split_off(len));
break;
} else {
len -= bytes.len();
}
}
self.update_len();
}
/// Read first chunk of vec in linklist.
pub fn read_front_chunk(&mut self) -> Option<&Vec<u8>> {
self.buf_list.front()
}
/// Remove first front chunk of vec in linklist.
pub fn remove_front_chunk(&mut self) {
if !self.is_empty() {
self.buf_list.pop_front();
}
self.update_len();
}
}
#[cfg(test)]
mod tests {
use crate::utils::BuffPool;
#[test]
fn test_buffpool_base() {
let mut buffpool = BuffPool::new();
buffpool.set_limit(Some(7));
buffpool.append_limit((0x12345678 as u32).to_be_bytes().to_vec());
buffpool.append_limit((0x12 as u8).to_be_bytes().to_vec());
buffpool.append_limit((0x1234 as u16).to_be_bytes().to_vec());
assert!(buffpool.len() == 7 as usize);
buffpool.remove_front(1);
assert!(buffpool.len() == 6 as usize);
let mut buf: Vec<u8> = vec![0_u8; 4];
buffpool.read_front(&mut buf, 4);
assert!(buf == vec![52, 86, 120, 18]);
let ans: Vec<Vec<u8>> = vec![vec![52, 86, 120], vec![18], vec![18, 52]];
let mut idx: usize = 0;
while let Some(buf) = buffpool.read_front_chunk() {
assert_eq!(ans[idx], buf.to_vec());
idx += 1;
buffpool.remove_front_chunk();
}
}
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарий ( 0 )