Skip to main content

dope_core/driver/settings/
config.rs

1use std::io;
2
3use crate::driver::settings;
4
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub struct Config {
7    queues: settings::QueueLayout,
8    scheduler: settings::SchedulerLayout,
9    file_slots: settings::FileSlots,
10    recv: settings::Receive,
11    completion_progress: settings::CompletionProgress,
12}
13
14impl Default for Config {
15    fn default() -> Self {
16        Self {
17            queues: settings::QueueLayout::fixed::<1024, 2048>(),
18            scheduler: settings::SchedulerLayout::fixed::<65_536, 65_536>(),
19            file_slots: settings::FileSlots::fixed::<0, 256>(),
20            recv: settings::Receive::fixed::<128, 4096>(),
21            completion_progress: settings::CompletionProgress::Prompt,
22        }
23    }
24}
25
26impl Config {
27    fn invalid(message: &'static str) -> io::Error {
28        io::Error::new(io::ErrorKind::InvalidInput, message)
29    }
30
31    #[must_use]
32    pub const fn file_slots(&self) -> settings::FileSlots {
33        self.file_slots
34    }
35
36    #[must_use]
37    pub const fn queue_layout(&self) -> settings::QueueLayout {
38        self.queues
39    }
40
41    #[must_use]
42    pub const fn scheduler(&self) -> settings::SchedulerLayout {
43        self.scheduler
44    }
45
46    #[must_use]
47    pub const fn completion_progress(&self) -> settings::CompletionProgress {
48        self.completion_progress
49    }
50
51    #[must_use]
52    pub const fn with_completion_progress(
53        mut self,
54        completion_progress: settings::CompletionProgress,
55    ) -> Self {
56        self.completion_progress = completion_progress;
57        self
58    }
59
60    #[must_use]
61    pub const fn with_file_slots(mut self, file_slots: settings::FileSlots) -> Self {
62        self.file_slots = file_slots;
63        self
64    }
65
66    #[must_use]
67    pub const fn receive(&self) -> settings::Receive {
68        self.recv
69    }
70
71    #[must_use]
72    pub const fn with_queue_layout(mut self, queues: settings::QueueLayout) -> Self {
73        self.queues = queues;
74        self
75    }
76
77    #[must_use]
78    pub const fn with_scheduler(mut self, scheduler: settings::SchedulerLayout) -> Self {
79        self.scheduler = scheduler;
80        self
81    }
82
83    pub fn for_profile<P: settings::Profile>() -> io::Result<Self> {
84        let file_slots = settings::FileSlots::new(0, P::OUTBOUND_SLOTS)
85            .ok_or_else(|| Self::invalid("dope: profile fixed-file layout is invalid"))?;
86        Ok(Self {
87            queues: P::QUEUES,
88            scheduler: P::SCHEDULER,
89            file_slots,
90            recv: P::RECEIVE,
91            completion_progress: P::COMPLETION_PROGRESS,
92        })
93    }
94
95    pub fn for_tcp_profile<P: settings::Profile>(max_connections: usize) -> io::Result<Self> {
96        let accept_slots = u32::try_from(max_connections.min(P::MAX_ACCEPT_SLOTS as usize))
97            .map_err(|_| Self::invalid("dope: connection count exceeds u32"))?;
98        let file_slots = settings::FileSlots::new(accept_slots, P::OUTBOUND_SLOTS)
99            .ok_or_else(|| Self::invalid("dope: profile fixed-file layout is invalid"))?;
100        Ok(Self {
101            queues: P::QUEUES,
102            scheduler: P::SCHEDULER,
103            file_slots,
104            recv: P::RECEIVE,
105            completion_progress: P::COMPLETION_PROGRESS,
106        })
107    }
108
109    /// Creates a UDP layout from usable payload bytes, excluding backend framing.
110    pub fn for_quic_udp(recv_buf_entries: u32, recv_payload_len: u32) -> io::Result<Self> {
111        let entries = u16::try_from(recv_buf_entries)
112            .map_err(|_| Self::invalid("dope: receive buffer entries exceed u16"))?;
113        let recv = settings::Receive::for_datagram_payload(entries, recv_payload_len)
114            .ok_or_else(|| Self::invalid("dope: invalid receive buffer layout"))?;
115        Ok(Self {
116            queues: settings::QueueLayout::fixed::<256, 1024>(),
117            scheduler: settings::SchedulerLayout::DEFAULT,
118            file_slots: settings::FileSlots::fixed::<0, 16>(),
119            recv,
120            completion_progress: settings::CompletionProgress::Prompt,
121        })
122    }
123
124    #[must_use]
125    pub fn with_receive(mut self, receive: settings::Receive) -> Self {
126        self.recv = receive;
127        self
128    }
129
130    /// Validates representation relationships required before driver allocation.
131    pub(crate) fn validate_structure(&self) -> io::Result<()> {
132        let file_slots = self.file_slots;
133        let ready_capacity = (file_slots.capacity() as usize)
134            .checked_add(self.scheduler.ready().get())
135            .ok_or_else(|| Self::invalid("dope: total ready capacity overflow"))?;
136        if ready_capacity > u32::MAX as usize {
137            return Err(Self::invalid("dope: total ready capacity exceeds u32"));
138        }
139        Ok(())
140    }
141}
142
143const _: () = {
144    assert!(std::mem::size_of::<Config>() == std::mem::size_of::<[u32; 9]>());
145    assert!(std::mem::align_of::<Config>() == std::mem::align_of::<u32>());
146};