Skip to main content

shell_sanitize/
sanitized.rs

1use std::fmt;
2use std::marker::PhantomData;
3
4use crate::marker::MarkerType;
5
6/// A value that has passed all sanitization rules for marker type `T`.
7///
8/// This type cannot be constructed directly — it is only produced by
9/// [`Sanitizer::sanitize`](crate::Sanitizer::sanitize). This guarantees
10/// at the type level that the inner string has been validated.
11///
12/// # Example
13///
14/// ```
15/// use shell_sanitize::{Sanitizer, Sanitized, ShellArg};
16///
17/// fn run_command(arg: &Sanitized<ShellArg>) {
18///     // Safe to use in command construction
19///     let _ = arg.as_str();
20/// }
21/// ```
22#[derive(Clone, PartialEq, Eq, Hash)]
23pub struct Sanitized<T: MarkerType> {
24    value: String,
25    _marker: PhantomData<T>,
26}
27
28impl<T: MarkerType> Sanitized<T> {
29    /// Create a new `Sanitized` value.
30    ///
31    /// This is `pub(crate)` to ensure only `Sanitizer` can construct it.
32    pub(crate) fn new(value: String) -> Self {
33        Self {
34            value,
35            _marker: PhantomData,
36        }
37    }
38
39    /// Access the sanitized string.
40    #[must_use]
41    pub fn as_str(&self) -> &str {
42        &self.value
43    }
44
45    /// Consume and return the inner string.
46    #[must_use]
47    pub fn into_inner(self) -> String {
48        self.value
49    }
50}
51
52impl<T: MarkerType> AsRef<str> for Sanitized<T> {
53    fn as_ref(&self) -> &str {
54        &self.value
55    }
56}
57
58impl<T: MarkerType> fmt::Debug for Sanitized<T> {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        write!(f, "Sanitized<{}>({:?})", T::label(), self.value)
61    }
62}
63
64impl<T: MarkerType> fmt::Display for Sanitized<T> {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        write!(f, "{}", self.value)
67    }
68}