mod auto;
pub(crate) mod mmap;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u8)]
#[non_exhaustive]
pub enum Method {
Sync = 0,
Data = 1,
Direct = 2,
Mmap = 3,
Journal = 4,
Auto = 5,
}
impl Method {
#[must_use]
#[inline]
pub(crate) const fn to_u8(self) -> u8 {
self as u8
}
#[must_use]
#[inline]
pub(crate) fn from_u8(v: u8) -> Self {
match v {
0 => Method::Sync,
1 => Method::Data,
2 => Method::Direct,
3 => Method::Mmap,
4 => Method::Journal,
5 => Method::Auto,
_ => Method::Sync,
}
}
#[must_use]
#[inline]
pub const fn is_reserved(self) -> bool {
matches!(self, Method::Journal)
}
#[must_use]
pub fn resolve(self) -> Method {
if self != Method::Auto {
return self;
}
auto::resolve_auto()
}
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Method::Sync => "sync",
Method::Data => "data",
Method::Direct => "direct",
Method::Mmap => "mmap",
Method::Journal => "journal",
Method::Auto => "auto",
}
}
}
impl fmt::Display for Method {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_method_sync_as_str() {
assert_eq!(Method::Sync.as_str(), "sync");
}
#[test]
fn test_method_auto_as_str() {
assert_eq!(Method::Auto.as_str(), "auto");
}
#[test]
fn test_method_display_matches_as_str() {
for m in [
Method::Sync,
Method::Data,
Method::Direct,
Method::Mmap,
Method::Journal,
Method::Auto,
] {
assert_eq!(m.to_string(), m.as_str());
}
}
#[test]
fn test_method_to_u8_and_back() {
for m in [
Method::Sync,
Method::Data,
Method::Direct,
Method::Mmap,
Method::Journal,
Method::Auto,
] {
assert_eq!(Method::from_u8(m.to_u8()), m);
}
}
#[test]
fn test_method_from_u8_invalid_returns_sync() {
assert_eq!(Method::from_u8(200), Method::Sync);
}
#[test]
fn test_method_is_reserved_true_for_journal_only() {
assert!(Method::Journal.is_reserved());
assert!(!Method::Mmap.is_reserved());
}
#[test]
fn test_method_is_reserved_false_for_real_methods() {
for m in [
Method::Sync,
Method::Data,
Method::Direct,
Method::Mmap,
Method::Auto,
] {
assert!(!m.is_reserved(), "{} should not be reserved", m);
}
}
#[test]
fn test_method_resolve_passes_through_non_auto() {
assert_eq!(Method::Sync.resolve(), Method::Sync);
assert_eq!(Method::Data.resolve(), Method::Data);
assert_eq!(Method::Direct.resolve(), Method::Direct);
assert_eq!(Method::Mmap.resolve(), Method::Mmap);
}
#[test]
fn test_method_auto_resolves_to_concrete_variant() {
let resolved = Method::Auto.resolve();
assert_ne!(
resolved,
Method::Auto,
"Auto must resolve to a concrete method"
);
}
#[test]
fn test_method_auto_resolves_to_known_real_variant() {
let resolved = Method::Auto.resolve();
assert!(
matches!(resolved, Method::Sync | Method::Data | Method::Direct),
"Auto must resolve to Sync, Data, or Direct; got {:?}",
resolved
);
}
}