openssh_sftp_client_lowlevel/
awaitable_responses.rs#![forbid(unsafe_code)]
use super::Error;
use concurrent_arena::Arena;
use derive_destructure2::destructure;
use openssh_sftp_protocol::response::ResponseInner;
#[derive(Debug)]
pub(crate) enum Response<Buffer> {
Header(ResponseInner),
Buffer(Buffer),
AllocatedBox(Box<[u8]>),
ExtendedReply(Box<[u8]>),
}
pub(crate) type Awaitable<Buffer> = awaitable::Awaitable<Buffer, Response<Buffer>>;
const BITARRAY_LEN: usize = 2;
const LEN: usize = 128;
pub(crate) type ArenaArc<Buffer> = concurrent_arena::ArenaArc<Awaitable<Buffer>, BITARRAY_LEN, LEN>;
#[derive(Debug)]
#[repr(transparent)]
pub(crate) struct AwaitableResponses<Buffer>(Arena<Awaitable<Buffer>, BITARRAY_LEN, LEN>);
impl<Buffer: Send + Sync> AwaitableResponses<Buffer> {
#[inline(always)]
pub(crate) fn new() -> Self {
Self(Arena::with_capacity(3))
}
pub(crate) fn insert(&self) -> Id<Buffer> {
Id::new(self.0.insert(Awaitable::new()))
}
#[inline]
pub(crate) fn try_reserve(&self, new_id_cnt: u32) -> bool {
self.0.try_reserve(new_id_cnt / (LEN as u32))
}
#[inline]
pub(crate) fn reserve(&self, new_id_cnt: u32) {
self.0.reserve(new_id_cnt / (LEN as u32));
}
#[inline]
pub(crate) fn get(&self, slot: u32) -> Result<ArenaArc<Buffer>, Error> {
self.0
.get(slot)
.ok_or(Error::InvalidResponseId { response_id: slot })
}
}
#[repr(transparent)]
#[derive(Debug, destructure)]
pub struct Id<Buffer: Send + Sync>(pub(crate) ArenaArc<Buffer>);
impl<Buffer: Send + Sync> Id<Buffer> {
#[inline(always)]
pub(crate) fn new(arc: ArenaArc<Buffer>) -> Self {
Id(arc)
}
#[inline(always)]
pub(crate) fn into_inner(self) -> ArenaArc<Buffer> {
self.destructure().0
}
}
impl<Buffer: Send + Sync> Drop for Id<Buffer> {
#[inline(always)]
fn drop(&mut self) {
ArenaArc::remove(&self.0);
}
}