1 use core::fmt; 2 use core::ops::Deref; 3 4 use arrayvec::ArrayString; 5 6 const MAX_DEC_LEN: usize = 8; 7 pub(crate) const MAX_ERR_LEN: usize = 256; 8 const MAX_INF_LEN: usize = 128; 9 pub(crate) const MAX_MIN_LEN: usize = 8; 10 const MAX_NAN_LEN: usize = 64; 11 const MAX_PLUS_LEN: usize = 8; 12 pub(crate) const MAX_SEP_LEN: usize = 8; 13 14 #[cfg(feature = "with-serde")] 15 use serde::{de, ser}; 16 17 use crate::error::Error; 18 19 /// Simple wrapper type for a `&str` to make sure its length is less than the maximum for 20 /// a decimal (8 bytes). 21 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 22 pub struct DecimalStr<'a>(&'a str); 23 24 impl<'a> DecimalStr<'a> { 25 /// Constructs an [`DecimalStr`], ensuring that the length is less than the maximum for 26 /// a decimal (8 bytes). 27 /// 28 /// # Errors 29 /// 30 /// Returns an error if the provided `&str`'s length is more than 8 bytes. 31 /// 32 /// [`DecimalStr`]: struct.DecimalStr.html new(s: &'a str) -> Result<DecimalStr<'a>, Error>33 pub fn new(s: &'a str) -> Result<DecimalStr<'a>, Error> { 34 Self::_new(s) 35 } 36 } 37 38 /// Simple wrapper type for a `&str` to make sure its length is less than the maximum for 39 /// an infinity symbol (128 bytes). 40 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 41 pub struct InfinityStr<'a>(&'a str); 42 43 impl<'a> InfinityStr<'a> { 44 /// Constructs an [`InfinityStr`], ensuring that the length is less than the maximum for 45 /// an infinity symbol (128 bytes). 46 /// 47 /// # Errors 48 /// 49 /// Returns an error if the provided `&str`'s length is more than 128 bytes. 50 /// 51 /// [`InfinityStr`]: struct.InfinityStr.html new(s: &'a str) -> Result<InfinityStr<'a>, Error>52 pub fn new(s: &'a str) -> Result<InfinityStr<'a>, Error> { 53 Self::_new(s) 54 } 55 } 56 57 /// Simple wrapper type for a `&str` to make sure its length is less than the maximum for 58 /// a minus sign (8 bytes). 59 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 60 pub struct MinusSignStr<'a>(&'a str); 61 62 impl<'a> MinusSignStr<'a> { 63 /// Constructs a [`MinusSignStr`], ensuring that the length is less than the maximum for 64 /// a minus sign (8 bytes). 65 /// 66 /// # Errors 67 /// 68 /// Returns an error if the provided `&str`'s length is more than 7 bytes. 69 /// 70 /// [`MinusSignStr`]: struct.MinusSignStr.html new(s: &'a str) -> Result<MinusSignStr<'a>, Error>71 pub fn new(s: &'a str) -> Result<MinusSignStr<'a>, Error> { 72 Self::_new(s) 73 } 74 } 75 76 /// Simple wrapper type for a `&str` to make sure its length is less than the maximum for 77 /// a nan symbol (64 bytes). 78 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 79 pub struct NanStr<'a>(&'a str); 80 81 impl<'a> NanStr<'a> { 82 /// Constructs an [`NanStr`], ensuring that the length is less than the maximum for 83 /// a nan symbol (64 bytes). 84 /// 85 /// # Errors 86 /// 87 /// Returns an error if the provided `&str`'s length is more than 64 bytes. 88 /// 89 /// [`NanStr`]: struct.NanStr.html new(s: &'a str) -> Result<NanStr<'a>, Error>90 pub fn new(s: &'a str) -> Result<NanStr<'a>, Error> { 91 Self::_new(s) 92 } 93 } 94 95 /// Simple wrapper type for a `&str` to make sure its length is less than the maximum for 96 /// a plus sign (8 bytes). 97 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 98 pub struct PlusSignStr<'a>(&'a str); 99 100 impl<'a> PlusSignStr<'a> { 101 /// Constructs an [`PlusSignStr`], ensuring that the length is less than the maximum for 102 /// a plus sign (8 bytes). 103 /// 104 /// # Errors 105 /// 106 /// Returns an error if the provided `&str`'s length is more than 8 bytes. 107 /// 108 /// [`PlusSignStr`]: struct.PlusSignStr.html new(s: &'a str) -> Result<PlusSignStr<'a>, Error>109 pub fn new(s: &'a str) -> Result<PlusSignStr<'a>, Error> { 110 Self::_new(s) 111 } 112 } 113 114 /// Simple wrapper type for a `&str` to make sure its length is less than the maximum for 115 /// a separator (8 bytes). 116 #[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 117 pub struct SeparatorStr<'a>(&'a str); 118 119 impl<'a> SeparatorStr<'a> { 120 /// Constructs an [`SeparatorStr`], ensuring that the length is less than the maximum for 121 /// a separator (8 bytes). 122 /// 123 /// # Errors 124 /// 125 /// Returns an error if the provided `&str`'s length is more than 8 bytes. 126 /// 127 /// [`SeparatorStr`]: struct.SeparatorStr.html new(s: &'a str) -> Result<SeparatorStr<'a>, Error>128 pub fn new(s: &'a str) -> Result<SeparatorStr<'a>, Error> { 129 Self::_new(s) 130 } 131 } 132 133 macro_rules! create_impls { 134 ( $name:ident, $max_len:expr ) => { 135 impl<'a> $name<'a> { 136 #[inline(always)] 137 /// Allows recovery of the initial / wrapped `&str`. 138 pub fn into_str(self) -> &'a str { 139 self.0 140 } 141 142 #[inline(always)] 143 fn _new(s: &'a str) -> Result<$name<'a>, Error> { 144 let len = s.len(); 145 if len > $max_len { 146 return Err(Error::capacity(len, $max_len)); 147 } 148 Ok($name(s)) 149 } 150 } 151 152 impl<'a> AsRef<str> for $name<'a> { 153 #[inline(always)] 154 fn as_ref(&self) -> &str { 155 self.0 156 } 157 } 158 159 impl<'a> fmt::Debug for $name<'a> { 160 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 161 write!(f, "{:?}", self.0) 162 } 163 } 164 165 impl<'a> fmt::Display for $name<'a> { 166 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 167 write!(f, "{}", self.0) 168 } 169 } 170 }; 171 } 172 173 create_impls!(DecimalStr, MAX_DEC_LEN); 174 create_impls!(InfinityStr, MAX_INF_LEN); 175 create_impls!(MinusSignStr, MAX_MIN_LEN); 176 create_impls!(NanStr, MAX_NAN_LEN); 177 create_impls!(PlusSignStr, MAX_PLUS_LEN); 178 create_impls!(SeparatorStr, MAX_SEP_LEN); 179 180 macro_rules! create_string { 181 ( $name:ident, $visitor:ident, $max_len:expr ) => { 182 #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] 183 pub(crate) struct $name(ArrayString<[u8; $max_len]>); 184 185 impl $name { 186 #[allow(dead_code)] 187 pub(crate) fn new<S>(s: S) -> Result<Self, Error> 188 where 189 S: AsRef<str>, 190 { 191 let s = s.as_ref(); 192 let a = ArrayString::from(s).map_err(|_| Error::capacity(s.len(), $max_len))?; 193 Ok($name(a)) 194 } 195 196 #[allow(dead_code)] 197 pub(crate) fn truncated<S>(s: S) -> Self 198 where 199 S: AsRef<str>, 200 { 201 let s = s.as_ref(); 202 let s = if s.len() > $max_len { 203 &s[0..$max_len] 204 } else { 205 s 206 }; 207 $name(ArrayString::from(s).unwrap()) 208 } 209 210 #[allow(dead_code)] 211 #[inline(always)] 212 pub(crate) fn capacity() -> usize { 213 $max_len 214 } 215 } 216 217 impl Deref for $name { 218 type Target = str; 219 220 #[inline(always)] 221 fn deref(&self) -> &str { 222 self.0.deref() 223 } 224 } 225 226 impl fmt::Display for $name { 227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 228 write!(f, "{}", self.0) 229 } 230 } 231 232 impl From<$name> for ArrayString<[u8; $max_len]> { 233 fn from(s: $name) -> Self { 234 s.0 235 } 236 } 237 238 #[cfg(feature = "with-serde")] 239 impl ser::Serialize for $name { 240 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 241 where 242 S: ser::Serializer, 243 { 244 serializer.serialize_str(self.0.as_str()) 245 } 246 } 247 248 #[cfg(feature = "with-serde")] 249 struct $visitor; 250 251 #[cfg(feature = "with-serde")] 252 impl<'de> de::Visitor<'de> for $visitor { 253 type Value = $name; 254 255 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 256 write!(formatter, "a string containing at most {} bytes", $max_len) 257 } 258 259 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> 260 where 261 E: de::Error, 262 { 263 $name::new(s).map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self)) 264 } 265 } 266 267 #[cfg(feature = "with-serde")] 268 impl<'de> de::Deserialize<'de> for $name { 269 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 270 where 271 D: de::Deserializer<'de>, 272 { 273 deserializer.deserialize_str($visitor) 274 } 275 } 276 }; 277 } 278 279 create_string!(DecString, DecVisitor, MAX_DEC_LEN); 280 create_string!(ErrString, ErrVisitor, MAX_ERR_LEN); 281 create_string!(InfString, InfVisitor, MAX_INF_LEN); 282 create_string!(MinString, MinVisitor, MAX_MIN_LEN); 283 create_string!(NanString, NanVisitor, MAX_NAN_LEN); 284 create_string!(PlusString, PlusVisitor, MAX_PLUS_LEN); 285 create_string!(SepString, SepVisitor, MAX_SEP_LEN); 286