orchestra_toolkit/
string255.rs1use ascii::AsciiString;
14use serde::{Deserialize, Serialize};
15use std::fmt::Display;
16use std::ops::Deref;
17use thiserror::Error;
18
19#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
21#[serde(try_from = "String", into = "String", expecting = "a string")]
22pub struct String255(String);
23
24#[derive(Error, Debug)]
25#[error("String is too long. Maximum size is 255 bytes but is {0}.")]
26pub struct String255TooLongError(pub usize);
27
28impl String255 {
29 pub const NULL: Self = Self(String::new());
30
31 pub fn unchecked(from: &str) -> Self {
34 Self::try_from(from.to_string()).expect("ShortString::unchecked failed")
35 }
36
37 pub fn from_str_truncate(s: &str) -> Self {
38 if s.len() <= 255 {
39 Self::unchecked(s)
40 } else {
41 Self::unchecked(&s[..255])
42 }
43 }
44
45 pub fn is_null(&self) -> bool {
47 self.0.is_empty()
48 }
49}
50
51impl TryFrom<String> for String255 {
52 type Error = String255TooLongError;
53
54 fn try_from(value: String) -> Result<Self, Self::Error> {
55 if value.len() > 255 {
56 Err(String255TooLongError(value.len()))
57 } else {
58 Ok(Self(value))
59 }
60 }
61}
62
63impl TryFrom<AsciiString> for String255 {
64 type Error = String255TooLongError;
65
66 fn try_from(value: AsciiString) -> Result<Self, Self::Error> {
67 value.to_string().try_into()
68 }
69}
70
71impl Deref for String255 {
72 type Target = String;
73
74 fn deref(&self) -> &Self::Target {
75 &self.0
76 }
77}
78
79impl From<String255> for String {
81 fn from(val: String255) -> Self {
82 val.0
83 }
84}
85
86impl Display for String255 {
87 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
88 self.0.fmt(f)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_truncate_short_string() {
98 let expected = String255::unchecked("Hello");
99 let actual = String255::from_str_truncate("Hello");
100 assert_eq!(expected, actual);
101 }
102
103 #[test]
104 fn test_truncate_len_254() {
105 let str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
106 assert_eq!(str.len(), 254);
107 let expected = String255::unchecked(str);
108
109 let actual = String255::from_str_truncate(str);
110 assert_eq!(expected, actual);
111 }
112
113 #[test]
114 fn test_truncate_len_255() {
115 let str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
116 assert_eq!(str.len(), 255);
117 let expected = String255::unchecked(str);
118
119 let actual = String255::from_str_truncate(str);
120 assert_eq!(expected, actual);
121 }
122 #[test]
123 fn test_truncate_len_256() {
124 let str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
125 assert_eq!(str.len(), 256);
126 let expected = String255::unchecked("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
127 assert_eq!(expected.len(), 255);
128
129 let actual = String255::from_str_truncate(str);
130 assert_eq!(expected, actual);
131 }
132}