Skip to main content

saml_rs/model/
identifiers.rs

1use crate::error::SamlError;
2
3/// SAML protocol message `ID`.
4#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5pub struct MessageId(String);
6
7impl MessageId {
8    /// Validate and wrap a SAML protocol message ID.
9    ///
10    /// # Errors
11    ///
12    /// Returns [`SamlError::Invalid`] when the message ID is empty.
13    pub fn try_new(value: impl Into<String>) -> Result<Self, SamlError> {
14        let value = value.into();
15        if value.trim().is_empty() {
16            return Err(SamlError::Invalid(
17                "SAML message ID must not be empty".into(),
18            ));
19        }
20        Ok(Self(value))
21    }
22
23    /// Borrow the message ID string.
24    pub fn as_str(&self) -> &str {
25        &self.0
26    }
27}
28
29/// Assertion ID extracted from a SAML assertion.
30#[derive(Debug, Clone, PartialEq, Eq, Hash)]
31pub struct AssertionId(String);
32
33impl AssertionId {
34    /// Validate and wrap an assertion ID.
35    ///
36    /// # Errors
37    ///
38    /// Returns [`SamlError::Invalid`] when the assertion ID is empty.
39    pub fn try_new(value: impl Into<String>) -> Result<Self, SamlError> {
40        let value = value.into();
41        if value.trim().is_empty() {
42            return Err(SamlError::Invalid("assertion ID must not be empty".into()));
43        }
44        Ok(Self(value))
45    }
46
47    /// Borrow the assertion ID string.
48    pub fn as_str(&self) -> &str {
49        &self.0
50    }
51}
52
53/// SAML instant text carried in pending snapshots and parsed results.
54#[derive(Debug, Clone, PartialEq, Eq, Hash)]
55pub struct SamlInstant(String);
56
57impl SamlInstant {
58    /// Validate and wrap a SAML instant string.
59    ///
60    /// # Errors
61    ///
62    /// Returns [`SamlError::Invalid`] when the instant is empty. Full temporal
63    /// enforcement is left to the validation policy that consumes the value.
64    pub fn try_new(value: impl Into<String>) -> Result<Self, SamlError> {
65        let value = value.into();
66        if value.trim().is_empty() {
67            return Err(SamlError::Invalid("SAML instant must not be empty".into()));
68        }
69        Ok(Self(value))
70    }
71
72    /// Borrow the instant string.
73    pub fn as_str(&self) -> &str {
74        &self.0
75    }
76}
77
78/// SessionIndex from an AuthnStatement or LogoutRequest.
79#[derive(Debug, Clone, PartialEq, Eq, Hash)]
80pub struct SessionIndex(String);
81
82impl SessionIndex {
83    /// Validate and wrap a SessionIndex.
84    ///
85    /// # Errors
86    ///
87    /// Returns [`SamlError::Invalid`] when the SessionIndex is empty.
88    pub fn try_new(value: impl Into<String>) -> Result<Self, SamlError> {
89        let value = value.into();
90        if value.trim().is_empty() {
91            return Err(SamlError::Invalid("SessionIndex must not be empty".into()));
92        }
93        Ok(Self(value))
94    }
95
96    /// Borrow the SessionIndex string.
97    pub fn as_str(&self) -> &str {
98        &self.0
99    }
100}