mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-25 08:22:43 +01:00
116 lines
2.7 KiB
Rust
116 lines
2.7 KiB
Rust
|
use std::mem;
|
||
|
use std::cell::RefCell;
|
||
|
use std::rc::Rc;
|
||
|
use std::collections::VecDeque;
|
||
|
use bytes::BytesMut;
|
||
|
|
||
|
use body::Binary;
|
||
|
|
||
|
|
||
|
/// Internal use only! unsafe
|
||
|
#[derive(Debug)]
|
||
|
pub(crate) struct SharedBytesPool(RefCell<VecDeque<Rc<BytesMut>>>);
|
||
|
|
||
|
impl SharedBytesPool {
|
||
|
pub fn new() -> SharedBytesPool {
|
||
|
SharedBytesPool(RefCell::new(VecDeque::with_capacity(128)))
|
||
|
}
|
||
|
|
||
|
pub fn get_bytes(&self) -> Rc<BytesMut> {
|
||
|
if let Some(bytes) = self.0.borrow_mut().pop_front() {
|
||
|
bytes
|
||
|
} else {
|
||
|
Rc::new(BytesMut::new())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn release_bytes(&self, mut bytes: Rc<BytesMut>) {
|
||
|
let v = &mut self.0.borrow_mut();
|
||
|
if v.len() < 128 {
|
||
|
Rc::get_mut(&mut bytes).unwrap().take();
|
||
|
v.push_front(bytes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub(crate) struct SharedBytes(
|
||
|
Option<Rc<BytesMut>>, Option<Rc<SharedBytesPool>>);
|
||
|
|
||
|
impl Drop for SharedBytes {
|
||
|
fn drop(&mut self) {
|
||
|
if let Some(ref pool) = self.1 {
|
||
|
if let Some(bytes) = self.0.take() {
|
||
|
if Rc::strong_count(&bytes) == 1 {
|
||
|
pool.release_bytes(bytes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl SharedBytes {
|
||
|
|
||
|
pub fn empty() -> Self {
|
||
|
SharedBytes(None, None)
|
||
|
}
|
||
|
|
||
|
pub fn new(bytes: Rc<BytesMut>, pool: Rc<SharedBytesPool>) -> SharedBytes {
|
||
|
SharedBytes(Some(bytes), Some(pool))
|
||
|
}
|
||
|
|
||
|
#[inline(always)]
|
||
|
#[allow(mutable_transmutes)]
|
||
|
#[cfg_attr(feature = "cargo-clippy", allow(mut_from_ref, inline_always))]
|
||
|
pub fn get_mut(&self) -> &mut BytesMut {
|
||
|
let r: &BytesMut = self.0.as_ref().unwrap().as_ref();
|
||
|
unsafe{mem::transmute(r)}
|
||
|
}
|
||
|
|
||
|
#[inline]
|
||
|
pub fn len(&self) -> usize {
|
||
|
self.0.as_ref().unwrap().len()
|
||
|
}
|
||
|
|
||
|
#[inline]
|
||
|
pub fn is_empty(&self) -> bool {
|
||
|
self.0.as_ref().unwrap().is_empty()
|
||
|
}
|
||
|
|
||
|
#[inline]
|
||
|
pub fn as_ref(&self) -> &[u8] {
|
||
|
self.0.as_ref().unwrap().as_ref()
|
||
|
}
|
||
|
|
||
|
pub fn split_to(&self, n: usize) -> BytesMut {
|
||
|
self.get_mut().split_to(n)
|
||
|
}
|
||
|
|
||
|
pub fn take(&self) -> BytesMut {
|
||
|
self.get_mut().take()
|
||
|
}
|
||
|
|
||
|
#[inline]
|
||
|
#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
|
||
|
pub fn extend(&self, data: Binary) {
|
||
|
self.get_mut().extend_from_slice(data.as_ref());
|
||
|
}
|
||
|
|
||
|
#[inline]
|
||
|
pub fn extend_from_slice(&self, data: &[u8]) {
|
||
|
self.get_mut().extend_from_slice(data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Default for SharedBytes {
|
||
|
fn default() -> Self {
|
||
|
SharedBytes(Some(Rc::new(BytesMut::new())), None)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Clone for SharedBytes {
|
||
|
fn clone(&self) -> SharedBytes {
|
||
|
SharedBytes(self.0.clone(), self.1.clone())
|
||
|
}
|
||
|
}
|