mina_node_testing/scenario/
id.rs

1use std::str::FromStr;
2
3use serde::{Deserialize, Deserializer, Serialize};
4
5#[derive(Serialize, Debug, Eq, PartialEq, Clone)]
6pub struct ScenarioId(String);
7
8#[derive(thiserror::Error, Debug)]
9pub enum ScenarioIdParseError {
10    #[error("scenario id can't contain upper-case characters")]
11    ContainsUpperCaseCharacters,
12    #[error("scenario id must match pattern /[a-z0-9_-]*/")]
13    AcceptedPatternMismatch,
14}
15
16#[cfg(feature = "scenario-generators")]
17impl From<crate::scenarios::Scenarios> for ScenarioId {
18    fn from(value: crate::scenarios::Scenarios) -> Self {
19        Self(value.to_str().to_owned())
20    }
21}
22
23impl std::fmt::Display for ScenarioId {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        self.0.fmt(f)
26    }
27}
28
29impl FromStr for ScenarioId {
30    type Err = ScenarioIdParseError;
31
32    fn from_str(s: &str) -> Result<Self, Self::Err> {
33        for c in s.chars() {
34            if c.is_ascii_uppercase() {
35                return Err(ScenarioIdParseError::ContainsUpperCaseCharacters);
36            }
37            if c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-' || c == '_' {
38                continue;
39            }
40            return Err(ScenarioIdParseError::AcceptedPatternMismatch);
41        }
42        Ok(Self(s.to_owned()))
43    }
44}
45
46impl<'de> Deserialize<'de> for ScenarioId {
47    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
48    where
49        D: Deserializer<'de>,
50    {
51        let s: &str = Deserialize::deserialize(deserializer)?;
52
53        Self::from_str(s).map_err(serde::de::Error::custom)
54    }
55}