1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use super::Error;
use super::ToBuffer;
use core::fmt::Debug;
use concurrent_arena::Arena;
use openssh_sftp_protocol::response::ResponseInner;
use derive_destructure2::destructure;
#[derive(Debug)]
pub(crate) enum Response<Buffer: ToBuffer> {
Header(ResponseInner),
Buffer(Buffer),
AllocatedBox(Box<[u8]>),
}
pub(crate) type Awaitable<Buffer> = awaitable::Awaitable<Buffer, Response<Buffer>>;
const BITARRAY_LEN: usize = 1;
const LEN: usize = 64;
pub(crate) type ArenaArc<Buffer> = concurrent_arena::ArenaArc<Awaitable<Buffer>, BITARRAY_LEN, LEN>;
#[derive(Debug)]
pub(crate) struct AwaitableResponses<Buffer: ToBuffer + 'static>(
Arena<Awaitable<Buffer>, BITARRAY_LEN, LEN>,
);
impl<Buffer: Debug + ToBuffer + Send + Sync> AwaitableResponses<Buffer> {
pub(crate) fn new() -> Self {
Self(Arena::with_capacity(3))
}
pub(crate) fn insert(&self) -> Id<Buffer> {
Id::new(self.0.insert(Awaitable::new()))
}
pub(crate) fn try_reserve(&self, new_id_cnt: u32) -> bool {
self.0.try_reserve(new_id_cnt / (LEN as u32))
}
pub(crate) fn reserve(&self, new_id_cnt: u32) {
self.0.reserve(new_id_cnt / (LEN as u32));
}
pub(crate) fn get(&self, slot: u32) -> Result<ArenaArc<Buffer>, Error> {
self.0
.get(slot)
.ok_or(Error::InvalidResponseId { response_id: slot })
}
}
#[derive(Debug, destructure)]
struct IdInner<Buffer: ToBuffer + Send + Sync>(ArenaArc<Buffer>);
impl<Buffer: ToBuffer + Send + Sync> Drop for IdInner<Buffer> {
fn drop(&mut self) {
ArenaArc::remove(&self.0);
}
}
#[derive(Debug)]
pub struct Id<Buffer: ToBuffer + Send + Sync>(IdInner<Buffer>);
impl<Buffer: ToBuffer + Debug + Send + Sync> Id<Buffer> {
pub(crate) fn new(arc: ArenaArc<Buffer>) -> Self {
Id(IdInner(arc))
}
pub(crate) fn into_inner(self) -> ArenaArc<Buffer> {
self.0.destructure().0
}
}