#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(clippy::struct_excessive_bools)] pub struct MlockConfig {
current: bool,
future: bool,
required: bool,
onfault: bool,
}
impl MlockConfig {
#[must_use]
pub const fn builder() -> MlockConfigBuilder {
MlockConfigBuilder::new()
}
#[must_use]
pub const fn current(&self) -> bool {
self.current
}
#[must_use]
pub const fn future(&self) -> bool {
self.future
}
#[must_use]
pub const fn required(&self) -> bool {
self.required
}
#[must_use]
pub const fn onfault(&self) -> bool {
self.onfault
}
#[cfg(unix)]
pub(crate) const fn as_flags(self) -> libc::c_int {
let mut flags = 0;
if self.current {
flags |= libc::MCL_CURRENT;
}
if self.future {
flags |= libc::MCL_FUTURE;
}
#[cfg(target_os = "linux")]
if self.onfault {
const MCL_ONFAULT: libc::c_int = 4;
flags |= MCL_ONFAULT;
}
flags
}
}
impl Default for MlockConfig {
fn default() -> Self {
Self {
current: true,
future: true,
required: true,
onfault: false,
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct MlockConfigBuilder {
config: MlockConfig,
}
impl MlockConfigBuilder {
#[must_use]
pub const fn new() -> Self {
Self {
config: MlockConfig {
current: true,
future: true,
required: true,
onfault: false,
},
}
}
#[must_use]
pub const fn current(mut self, value: bool) -> Self {
self.config.current = value;
self
}
#[must_use]
pub const fn future(mut self, value: bool) -> Self {
self.config.future = value;
self
}
#[must_use]
pub const fn required(mut self, value: bool) -> Self {
self.config.required = value;
self
}
#[must_use]
pub const fn onfault(mut self, value: bool) -> Self {
self.config.onfault = value;
self
}
#[must_use]
pub const fn build(self) -> MlockConfig {
self.config
}
}
impl Default for MlockConfigBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_values() {
let config = MlockConfig::default();
assert!(config.current());
assert!(config.future());
assert!(config.required());
assert!(!config.onfault());
}
#[test]
fn test_builder_all_false() {
let config = MlockConfig::builder()
.current(false)
.future(false)
.required(false)
.onfault(false)
.build();
assert!(!config.current());
assert!(!config.future());
assert!(!config.required());
assert!(!config.onfault());
}
#[test]
fn test_builder_all_true() {
let config = MlockConfig::builder()
.current(true)
.future(true)
.required(true)
.onfault(true)
.build();
assert!(config.current());
assert!(config.future());
assert!(config.required());
assert!(config.onfault());
}
#[cfg(unix)]
#[test]
fn test_as_flags_default() {
let config = MlockConfig::default();
let flags = config.as_flags();
assert_eq!(flags, libc::MCL_CURRENT | libc::MCL_FUTURE);
}
#[cfg(unix)]
#[test]
fn test_as_flags_current_only() {
let config = MlockConfig::builder()
.current(true)
.future(false)
.build();
let flags = config.as_flags();
assert_eq!(flags, libc::MCL_CURRENT);
}
#[cfg(unix)]
#[test]
fn test_as_flags_none() {
let config = MlockConfig::builder()
.current(false)
.future(false)
.build();
let flags = config.as_flags();
assert_eq!(flags, 0);
}
}