Skip to main content

dope_core/driver/settings/
receive.rs

1use 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        Ok(Self::from_parts(entries.buffers(), len))
53    }
54
55    pub const fn buffers(self) -> Buffers {
56        self.entries
57    }
58    pub(crate) const fn entries(self) -> u16 {
59        self.entries.get()
60    }
61    pub(crate) const fn count(self) -> num::NonZero<u16> {
62        self.entries.0
63    }
64    /// Keeps one receive slot available while other buffers remain accounted.
65    pub(crate) const fn accounts(self) -> u32 {
66        self.entries.get() as u32 - 1
67    }
68    /// Returns the positive slot length proven representable by every backend.
69    pub const fn buffer_len(self) -> transfer::NonZero {
70        self.len
71    }
72}