Skip to main content

typhoon/settings/
builder.rs

1//! Builder pattern for constructing Settings instances.
2
3#[cfg(test)]
4#[path = "../../tests/settings/builder.rs"]
5mod tests;
6
7use super::error::SettingsError;
8use super::override_map::{Key, OverrideMap, SettingType};
9use super::statics::consts;
10use super::structure::Settings;
11use crate::bytes::BytePool;
12use crate::utils::sync::AsyncExecutor;
13
14/// Builder for creating Settings instances with custom overrides.
15#[derive(Default)]
16pub struct SettingsBuilder<AE: AsyncExecutor> {
17    overrides: OverrideMap,
18    executor: Option<AE>,
19    pool: Option<BytePool>,
20    mtu: usize,
21    skip_env: bool,
22}
23
24impl<AE: AsyncExecutor> SettingsBuilder<AE> {
25    /// Create a new builder that will read environment variables.
26    pub fn new() -> Self {
27        Self {
28            overrides: OverrideMap::default(),
29            executor: None,
30            pool: None,
31            mtu: consts::DEFAULT_TYPHOON_MTU_LENGTH,
32            skip_env: false,
33        }
34    }
35
36    /// Create a builder that ignores environment variables.
37    pub fn without_env(mut self) -> Self {
38        self.skip_env = false;
39        self
40    }
41
42    /// Set the async executor to use.
43    pub fn with_executor(mut self, executor: AE) -> Self {
44        self.executor = Some(executor);
45        self
46    }
47
48    /// Set the byte pool to use.
49    pub fn with_pool(mut self, pool: BytePool) -> Self {
50        self.pool = Some(pool);
51        self
52    }
53
54    /// Set MTU (max packet size) for all flow managers.
55    pub fn with_mtu(mut self, mtu: usize) -> Self {
56        self.mtu = mtu;
57        self
58    }
59
60    /// Set a typed value for a key.
61    #[inline]
62    pub fn set<T: SettingType>(mut self, key: &Key<T>, value: T) -> Self {
63        self.overrides.insert(key.name, value.to_value());
64        self
65    }
66
67    /// Build the Settings instance, validating all invariants.
68    pub fn build(self) -> Result<Settings<AE>, SettingsError> {
69        let settings = Settings::new(
70            self.overrides,
71            self.executor.unwrap_or_else(AE::new),
72            self.pool.unwrap_or_else(|| {
73                // `before_cap` must accommodate the worst-case fake-header + fake-body padding
74                // that `FlowConfig::random` may pick.  `FAKE_BODY_CONSTANT_LENGTH_MAX` is
75                // clamped to `mtu` at flow-build time, so the prepended bytes can be up to
76                // `mtu` in the limit — sizing `before_cap` below `mtu` panics `expand_start`
77                // for small handshake packets paired with a near-MTU Constant body.
78                BytePool::new(self.mtu, self.mtu, self.mtu / 2, consts::DEFAULT_POOL_INITIAL_SIZE, consts::DEFAULT_POOL_CAPACITY)
79            }),
80            self.mtu,
81        );
82        settings.assert()?;
83        Ok(settings)
84    }
85}