dope_core/driver/settings/
receive.rs1use std::num;
2
3use crate::{
4 driver::settings::{Buffers, Ring, demands, errors},
5 io::{datagram::payload, transfer},
6};
7
8#[derive(Clone, Copy, PartialEq, Eq)]
9pub struct Receive {
10 pub(in crate::driver::settings) entries: Buffers,
11 pub(in crate::driver::settings) len: transfer::NonZero,
12}
13
14impl Receive {
15 pub const DEFAULT: Self = Self::fixed::<4096, 4096>();
16 pub const MIN_DATAGRAM_SLOT: transfer::NonZero =
17 transfer::NonZero::from_payload(payload::Len::fixed::<1>());
18
19 pub const fn fixed<const ENTRIES: u16, const LEN: u32>() -> Self {
20 const {
21 assert!(ENTRIES >= 2);
22 assert!(ENTRIES.is_power_of_two());
23 assert!(LEN != 0);
24 assert!(LEN <= transfer::MAX_BYTES as u32);
25 assert!((ENTRIES as usize) <= (isize::MAX as usize) / (LEN as usize));
26 Self {
27 entries: Buffers(num::NonZero::<u16>::MIN.saturating_add(ENTRIES - 1)),
28 len: transfer::NonZero::fixed::<LEN>(),
29 }
30 }
31 }
32
33 pub(super) const fn from_parts(entries: Buffers, len: transfer::NonZero) -> Self {
34 Self { entries, len }
35 }
36
37 pub fn resolve(self, need: demands::Receive) -> Result<Self, errors::Claim> {
38 let base = demands::Receive::from(self);
39 let entries = if base.entries().get() >= need.entries().get() {
40 base.entries()
41 } else {
42 need.entries()
43 };
44 let len = base.buffer_len().max(need.buffer_len());
45 Self::exact(demands::Receive::new(entries, len))
46 }
47
48 pub fn exact(need: demands::Receive) -> Result<Self, errors::Claim> {
49 let entries = Ring::try_round(need.entries().get())?;
50 let len = transfer::NonZero::try_from(need.buffer_len())
51 .map_err(errors::Config::ReceiveBuffer)?;
52 Self::assemble(entries, len).map_err(Into::into)
53 }
54
55 pub(super) const fn assemble(
56 entries: Ring,
57 len: transfer::NonZero,
58 ) -> Result<Self, errors::Config> {
59 let entries = entries.buffers();
60 let raw = len.into_nonzero().get();
61 let bytes = entries.get() as u64 * raw as u64;
62 if bytes > isize::MAX as u64 {
63 return Err(errors::Config::ReceiveAllocationTooLarge {
64 entries: entries.get(),
65 buffer_len: raw,
66 actual: bytes,
67 maximum: isize::MAX as u64,
68 });
69 }
70 Ok(Self { entries, len })
71 }
72
73 pub const fn buffers(self) -> Buffers {
74 self.entries
75 }
76 pub(crate) const fn entries(self) -> u16 {
77 self.entries.get()
78 }
79 pub(crate) const fn count(self) -> num::NonZero<u16> {
80 self.entries.0
81 }
82 pub(crate) const fn accounts(self) -> u32 {
84 self.entries.get() as u32 - 1
85 }
86 pub const fn buffer_len(self) -> transfer::NonZero {
88 self.len
89 }
90}