s2_common/record/
fencing.rs

1use std::{ops::Deref, str::FromStr};
2
3use compact_str::{CompactString, ToCompactString};
4
5use crate::deep_size::DeepSize;
6
7pub const MAX_FENCING_TOKEN_LENGTH: usize = 36;
8
9#[derive(Debug, PartialEq, Eq, thiserror::Error)]
10#[error("fencing token must not exceed {MAX_FENCING_TOKEN_LENGTH} bytes in length")]
11pub struct FencingTokenTooLongError(pub usize);
12
13#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
14pub struct FencingToken(CompactString);
15
16#[cfg(feature = "utoipa")]
17impl utoipa::PartialSchema for FencingToken {
18    fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::schema::Schema> {
19        utoipa::openapi::Object::builder()
20            .schema_type(utoipa::openapi::Type::String)
21            .max_length(Some(MAX_FENCING_TOKEN_LENGTH))
22            .into()
23    }
24}
25
26#[cfg(feature = "utoipa")]
27impl utoipa::ToSchema for FencingToken {}
28
29impl serde::Serialize for FencingToken {
30    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
31    where
32        S: serde::Serializer,
33    {
34        serializer.serialize_str(&self.0)
35    }
36}
37
38impl<'de> serde::Deserialize<'de> for FencingToken {
39    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
40    where
41        D: serde::Deserializer<'de>,
42    {
43        let s = CompactString::deserialize(deserializer)?;
44        FencingToken::try_from(s).map_err(serde::de::Error::custom)
45    }
46}
47
48impl std::fmt::Display for FencingToken {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "{}", self.0)
51    }
52}
53
54impl TryFrom<CompactString> for FencingToken {
55    type Error = FencingTokenTooLongError;
56
57    fn try_from(input: CompactString) -> Result<Self, Self::Error> {
58        if input.len() > MAX_FENCING_TOKEN_LENGTH {
59            return Err(FencingTokenTooLongError(input.len()));
60        }
61        Ok(FencingToken(input))
62    }
63}
64
65impl FromStr for FencingToken {
66    type Err = FencingTokenTooLongError;
67
68    fn from_str(s: &str) -> Result<Self, Self::Err> {
69        s.to_compact_string().try_into()
70    }
71}
72
73impl From<FencingToken> for CompactString {
74    fn from(token: FencingToken) -> Self {
75        token.0
76    }
77}
78
79impl AsRef<str> for FencingToken {
80    fn as_ref(&self) -> &str {
81        &self.0
82    }
83}
84
85impl Deref for FencingToken {
86    type Target = str;
87
88    fn deref(&self) -> &Self::Target {
89        &self.0
90    }
91}
92
93impl DeepSize for FencingToken {
94    fn deep_size(&self) -> usize {
95        self.0.len()
96    }
97}