winget_types/locale/
publisher.rs

1use core::{fmt, str::FromStr};
2
3use compact_str::CompactString;
4use thiserror::Error;
5
6#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[cfg_attr(feature = "serde", serde(try_from = "CompactString"))]
9#[repr(transparent)]
10pub struct Publisher(CompactString);
11
12#[derive(Debug, Error, Eq, PartialEq)]
13pub enum PublisherError {
14    #[error(
15        "Publisher must have at least {} characters but has {_0}",
16        Publisher::MIN_CHAR_LENGTH
17    )]
18    TooShort(usize),
19    #[error(
20        "Publisher must not have more than {} characters but has {_0}",
21        Publisher::MAX_CHAR_LENGTH
22    )]
23    TooLong(usize),
24}
25
26impl Publisher {
27    pub const MIN_CHAR_LENGTH: usize = 2;
28
29    pub const MAX_CHAR_LENGTH: usize = 256;
30
31    /// Creates a new `Publisher` from any type that implements `AsRef<str>` and
32    /// `Into<CompactString>`.
33    ///
34    /// # Errors
35    ///
36    /// Returns an `Err` if the publisher is less than 2 characters long or more than 256 characters
37    /// long.
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use winget_types::locale::Publisher;
43    /// # use winget_types::locale::PublisherError;
44    ///
45    /// # fn main() -> Result<(), PublisherError>  {
46    /// let publisher = Publisher::new("Microsoft")?;
47    ///
48    /// assert_eq!(publisher.as_str(), "Microsoft");
49    /// # Ok(())
50    /// # }
51    /// ```
52    pub fn new<T: AsRef<str> + Into<CompactString>>(publisher: T) -> Result<Self, PublisherError> {
53        match publisher.as_ref().chars().count() {
54            count if count < Self::MIN_CHAR_LENGTH => Err(PublisherError::TooShort(count)),
55            count if count > Self::MAX_CHAR_LENGTH => Err(PublisherError::TooLong(count)),
56            _ => Ok(Self(publisher.into())),
57        }
58    }
59
60    /// Creates a new `Publisher` from any type that implements `Into<CompactString>` without
61    /// checking its validity.
62    ///
63    /// # Safety
64    ///
65    /// The publisher must not be less than 2 characters long or more than 256 characters long.
66    #[must_use]
67    #[inline]
68    pub unsafe fn new_unchecked<T: Into<CompactString>>(publisher: T) -> Self {
69        Self(publisher.into())
70    }
71
72    /// Extracts a string slice containing the entire `Publisher`.
73    #[must_use]
74    #[inline]
75    pub fn as_str(&self) -> &str {
76        self.0.as_str()
77    }
78}
79
80impl AsRef<str> for Publisher {
81    #[inline]
82    fn as_ref(&self) -> &str {
83        self.as_str()
84    }
85}
86
87impl Default for Publisher {
88    fn default() -> Self {
89        // SAFETY: `Publisher` is longer than 2 characters
90        unsafe { Self::new_unchecked("Publisher") }
91    }
92}
93
94impl fmt::Display for Publisher {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96        self.0.fmt(f)
97    }
98}
99
100impl FromStr for Publisher {
101    type Err = PublisherError;
102
103    #[inline]
104    fn from_str(s: &str) -> Result<Self, Self::Err> {
105        Self::new(s)
106    }
107}
108
109impl TryFrom<CompactString> for Publisher {
110    type Error = PublisherError;
111
112    #[inline]
113    fn try_from(value: CompactString) -> Result<Self, Self::Error> {
114        Self::new(value)
115    }
116}