use serde::Deserialize;
use std::{collections::BTreeSet, env, fmt, str::FromStr};
#[derive(Clone, Copy, Debug, Default, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct ExperimentalConfig {
#[serde(default)]
pub record: bool,
}
impl ExperimentalConfig {
pub fn to_set(self) -> BTreeSet<UserConfigExperimental> {
let Self { record } = self;
let mut set = BTreeSet::new();
if record {
set.insert(UserConfigExperimental::Record);
}
set
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[non_exhaustive]
pub enum UserConfigExperimental {
Record,
}
impl UserConfigExperimental {
pub fn env_var(&self) -> &'static str {
match self {
Self::Record => "NEXTEST_EXPERIMENTAL_RECORD",
}
}
pub fn name(&self) -> &'static str {
match self {
Self::Record => "record",
}
}
pub fn all() -> &'static [Self] {
&[Self::Record]
}
pub fn from_env() -> BTreeSet<Self> {
Self::all()
.iter()
.filter(|feature| env::var(feature.env_var()).is_ok_and(|v| v == "1"))
.copied()
.collect()
}
}
impl fmt::Display for UserConfigExperimental {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.name())
}
}
impl FromStr for UserConfigExperimental {
type Err = UnknownUserExperimentalError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"record" => Ok(Self::Record),
_ => Err(UnknownUserExperimentalError {
feature: s.to_owned(),
}),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UnknownUserExperimentalError {
pub feature: String,
}
impl fmt::Display for UnknownUserExperimentalError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"unknown experimental feature `{}`; known features: {}",
self.feature,
UserConfigExperimental::all()
.iter()
.map(|f| f.name())
.collect::<Vec<_>>()
.join(", ")
)
}
}
impl std::error::Error for UnknownUserExperimentalError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from_str() {
assert_eq!(
"record".parse::<UserConfigExperimental>().unwrap(),
UserConfigExperimental::Record
);
assert!("unknown".parse::<UserConfigExperimental>().is_err());
}
#[test]
fn test_display() {
assert_eq!(UserConfigExperimental::Record.to_string(), "record");
}
#[test]
fn test_env_var() {
assert_eq!(
UserConfigExperimental::Record.env_var(),
"NEXTEST_EXPERIMENTAL_RECORD"
);
}
}