winget_types/locale/
installation_notes.rs1use alloc::string::String;
2use core::{fmt, str::FromStr};
3
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 = "String"))]
9#[repr(transparent)]
10pub struct InstallationNotes(String);
11
12#[derive(Debug, Error, Eq, PartialEq)]
13pub enum InstallationNotesError {
14 #[error("Installation notes must not be empty")]
15 Empty,
16 #[error(
17 "Installation notes must not have more than {} characters but has {_0}",
18 InstallationNotes::MAX_CHAR_LENGTH
19 )]
20 TooLong(usize),
21}
22
23impl InstallationNotes {
24 pub const MAX_CHAR_LENGTH: usize = 10_000;
25
26 pub fn new<T: AsRef<str> + Into<String>>(
33 installation_notes: T,
34 ) -> Result<Self, InstallationNotesError> {
35 let notes = installation_notes.as_ref();
36
37 if notes.is_empty() {
38 return Err(InstallationNotesError::Empty);
39 }
40
41 let char_count = notes.chars().count();
42 if char_count > Self::MAX_CHAR_LENGTH {
43 return Err(InstallationNotesError::TooLong(char_count));
44 }
45
46 Ok(Self(installation_notes.into()))
47 }
48
49 #[inline]
56 pub unsafe fn new_unchecked<T: Into<String>>(installation_notes: T) -> Self {
57 Self(installation_notes.into())
58 }
59
60 #[must_use]
62 #[inline]
63 pub const fn as_str(&self) -> &str {
64 self.0.as_str()
65 }
66}
67
68impl AsRef<str> for InstallationNotes {
69 #[inline]
70 fn as_ref(&self) -> &str {
71 self.as_str()
72 }
73}
74
75impl fmt::Display for InstallationNotes {
76 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77 self.0.fmt(f)
78 }
79}
80
81impl FromStr for InstallationNotes {
82 type Err = InstallationNotesError;
83
84 #[inline]
85 fn from_str(s: &str) -> Result<Self, Self::Err> {
86 Self::new(s)
87 }
88}
89
90impl TryFrom<String> for InstallationNotes {
91 type Error = InstallationNotesError;
92
93 #[inline]
94 fn try_from(value: String) -> Result<Self, Self::Error> {
95 Self::new(value)
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use crate::locale::installation_notes::{InstallationNotes, InstallationNotesError};
102
103 #[test]
104 fn valid_installation_notes() {
105 assert!(
106 "Be careful when using this application"
107 .parse::<InstallationNotes>()
108 .is_ok()
109 );
110 }
111
112 #[test]
113 fn installation_notes_max_length() {
114 let installation_notes = "🦀".repeat(InstallationNotes::MAX_CHAR_LENGTH);
115
116 assert!(installation_notes.len() > InstallationNotes::MAX_CHAR_LENGTH);
118 assert!(installation_notes.encode_utf16().count() > InstallationNotes::MAX_CHAR_LENGTH);
119 assert_eq!(
120 installation_notes.chars().count(),
121 InstallationNotes::MAX_CHAR_LENGTH
122 );
123 assert!(InstallationNotes::new(installation_notes).is_ok());
124 }
125
126 #[test]
127 fn installation_notes_too_long() {
128 let installation_notes = "a".repeat(InstallationNotes::MAX_CHAR_LENGTH + 1);
129
130 assert_eq!(
131 installation_notes.parse::<InstallationNotes>(),
132 Err(InstallationNotesError::TooLong(installation_notes.len()))
133 );
134 }
135
136 #[test]
137 fn empty_installation_notes() {
138 assert_eq!(
139 "".parse::<InstallationNotes>(),
140 Err(InstallationNotesError::Empty)
141 );
142 }
143}