dope_core/driver/settings/
config.rs1use 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 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 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};