use crate::models::DefaultConsistencyLevel;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ReadConsistencyStrategy {
Default,
Eventual,
Session,
GlobalStrong,
}
impl ReadConsistencyStrategy {
fn parse(s: &str) -> Option<Self> {
match s {
"Default" => Some(Self::Default),
"Eventual" => Some(Self::Eventual),
"Session" => Some(Self::Session),
"GlobalStrong" => Some(Self::GlobalStrong),
_ => {
if s.eq_ignore_ascii_case("Default") {
Some(Self::Default)
} else if s.eq_ignore_ascii_case("Eventual") {
Some(Self::Eventual)
} else if s.eq_ignore_ascii_case("Session") {
Some(Self::Session)
} else if s.eq_ignore_ascii_case("GlobalStrong") {
Some(Self::GlobalStrong)
} else {
None
}
}
}
}
pub fn as_str(&self) -> &'static str {
match self {
Self::Default => "Default",
Self::Eventual => "Eventual",
Self::Session => "Session",
Self::GlobalStrong => "GlobalStrong",
}
}
pub(crate) fn is_session_effective(&self, account_default: DefaultConsistencyLevel) -> bool {
match self {
Self::Session => true,
Self::Default => account_default.is_session(),
_ => false,
}
}
}
impl std::fmt::Display for ReadConsistencyStrategy {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl std::str::FromStr for ReadConsistencyStrategy {
type Err = azure_core::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::parse(s).ok_or_else(|| {
azure_core::Error::with_message(
azure_core::error::ErrorKind::DataConversion,
format!("Unknown read consistency strategy: {}", s),
)
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_all_strategies() {
assert_eq!(
"Default".parse::<ReadConsistencyStrategy>().ok(),
Some(ReadConsistencyStrategy::Default)
);
assert_eq!(
"Eventual".parse::<ReadConsistencyStrategy>().ok(),
Some(ReadConsistencyStrategy::Eventual)
);
assert_eq!(
"Session".parse::<ReadConsistencyStrategy>().ok(),
Some(ReadConsistencyStrategy::Session)
);
assert_eq!(
"GlobalStrong".parse::<ReadConsistencyStrategy>().ok(),
Some(ReadConsistencyStrategy::GlobalStrong)
);
}
#[test]
fn parse_unknown_returns_none() {
assert!("Unknown".parse::<ReadConsistencyStrategy>().is_err());
}
#[test]
fn parse_case_insensitive_fallback() {
assert_eq!(
"eventual".parse::<ReadConsistencyStrategy>().ok(),
Some(ReadConsistencyStrategy::Eventual)
);
}
#[test]
fn to_string_roundtrip() {
for strategy in &[
ReadConsistencyStrategy::Default,
ReadConsistencyStrategy::Eventual,
ReadConsistencyStrategy::Session,
ReadConsistencyStrategy::GlobalStrong,
] {
let s = strategy.to_string();
assert_eq!(s.parse::<ReadConsistencyStrategy>().ok(), Some(*strategy));
}
}
#[test]
fn session_effective_when_strategy_is_session() {
assert!(
ReadConsistencyStrategy::Session.is_session_effective(DefaultConsistencyLevel::Strong)
);
assert!(ReadConsistencyStrategy::Session
.is_session_effective(DefaultConsistencyLevel::Eventual));
}
#[test]
fn session_effective_when_default_and_account_is_session() {
assert!(
ReadConsistencyStrategy::Default.is_session_effective(DefaultConsistencyLevel::Session)
);
}
#[test]
fn not_session_effective_when_default_and_account_is_not_session() {
assert!(
!ReadConsistencyStrategy::Default.is_session_effective(DefaultConsistencyLevel::Strong)
);
assert!(!ReadConsistencyStrategy::Default
.is_session_effective(DefaultConsistencyLevel::BoundedStaleness));
assert!(!ReadConsistencyStrategy::Default
.is_session_effective(DefaultConsistencyLevel::ConsistentPrefix));
assert!(!ReadConsistencyStrategy::Default
.is_session_effective(DefaultConsistencyLevel::Eventual));
}
#[test]
fn not_session_effective_for_eventual_or_global_strong() {
assert!(!ReadConsistencyStrategy::Eventual
.is_session_effective(DefaultConsistencyLevel::Session));
assert!(!ReadConsistencyStrategy::GlobalStrong
.is_session_effective(DefaultConsistencyLevel::Session));
}
}