datetime_string/common/secfrac_digits/
owned.rs1#![cfg(feature = "alloc")]
3
4use core::{convert::TryFrom, fmt, ops, str};
5
6use alloc::{string::String, vec::Vec};
7
8use crate::{ConversionError, Error};
9
10use super::{validate_bytes, SecfracDigitsStr};
11
12#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
40#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
41#[repr(transparent)]
42#[allow(clippy::derive_hash_xor_eq)]
49#[allow(unknown_lints, clippy::derive_ord_xor_partial_ord)]
50pub struct SecfracDigitsString(Vec<u8>);
51
52impl SecfracDigitsString {
53 #[inline]
61 #[must_use]
62 unsafe fn from_bytes_maybe_unchecked(s: Vec<u8>) -> Self {
63 debug_assert_ok!(validate_bytes(&s));
64 Self(s)
65 }
66
67 #[inline]
83 #[must_use]
84 pub fn as_deref(&self) -> &SecfracDigitsStr {
85 unsafe {
86 debug_assert_safe_version_ok!(SecfracDigitsStr::from_bytes(&self.0));
88 SecfracDigitsStr::from_bytes_maybe_unchecked(&self.0)
89 }
90 }
91
92 #[inline]
108 #[must_use]
109 pub fn as_deref_mut(&mut self) -> &mut SecfracDigitsStr {
110 unsafe {
111 debug_assert_ok!(SecfracDigitsStr::from_bytes(&self.0));
113 SecfracDigitsStr::from_bytes_maybe_unchecked_mut(&mut self.0)
114 }
115 }
116}
117
118impl core::borrow::Borrow<SecfracDigitsStr> for SecfracDigitsString {
119 #[inline]
120 fn borrow(&self) -> &SecfracDigitsStr {
121 self.as_deref()
122 }
123}
124
125impl core::borrow::BorrowMut<SecfracDigitsStr> for SecfracDigitsString {
126 #[inline]
127 fn borrow_mut(&mut self) -> &mut SecfracDigitsStr {
128 self.as_deref_mut()
129 }
130}
131
132impl alloc::borrow::ToOwned for SecfracDigitsStr {
133 type Owned = SecfracDigitsString;
134
135 #[inline]
136 fn to_owned(&self) -> Self::Owned {
137 self.into()
138 }
139}
140
141impl AsRef<[u8]> for SecfracDigitsString {
142 #[inline]
143 fn as_ref(&self) -> &[u8] {
144 &self.0
145 }
146}
147
148impl AsRef<str> for SecfracDigitsString {
149 #[inline]
150 fn as_ref(&self) -> &str {
151 self.as_str()
152 }
153}
154
155impl AsRef<SecfracDigitsStr> for SecfracDigitsString {
156 #[inline]
157 fn as_ref(&self) -> &SecfracDigitsStr {
158 self
159 }
160}
161
162impl AsMut<SecfracDigitsStr> for SecfracDigitsString {
163 #[inline]
164 fn as_mut(&mut self) -> &mut SecfracDigitsStr {
165 self
166 }
167}
168
169impl From<SecfracDigitsString> for Vec<u8> {
170 #[inline]
171 fn from(v: SecfracDigitsString) -> Vec<u8> {
172 v.0
173 }
174}
175
176impl From<SecfracDigitsString> for String {
177 #[inline]
178 fn from(v: SecfracDigitsString) -> String {
179 unsafe {
180 debug_assert_ok!(str::from_utf8(&v.0));
182 String::from_utf8_unchecked(v.0)
183 }
184 }
185}
186
187impl From<&SecfracDigitsStr> for SecfracDigitsString {
188 fn from(v: &SecfracDigitsStr) -> Self {
189 unsafe {
190 debug_assert_ok!(validate_bytes(&v.0));
192 Self::from_bytes_maybe_unchecked(v.0.into())
193 }
194 }
195}
196
197impl TryFrom<&[u8]> for SecfracDigitsString {
198 type Error = Error;
199
200 #[inline]
201 fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
202 SecfracDigitsStr::from_bytes(v).map(Into::into)
203 }
204}
205
206impl TryFrom<&str> for SecfracDigitsString {
207 type Error = Error;
208
209 #[inline]
210 fn try_from(v: &str) -> Result<Self, Self::Error> {
211 SecfracDigitsStr::from_str(v).map(Into::into)
212 }
213}
214
215impl TryFrom<Vec<u8>> for SecfracDigitsString {
216 type Error = ConversionError<Vec<u8>>;
217
218 #[inline]
219 fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
220 match validate_bytes(&v) {
221 Ok(_) => Ok(unsafe {
222 Self::from_bytes_maybe_unchecked(v)
224 }),
225 Err(e) => Err(ConversionError::new(v, e)),
226 }
227 }
228}
229
230impl TryFrom<String> for SecfracDigitsString {
231 type Error = ConversionError<String>;
232
233 #[inline]
234 fn try_from(v: String) -> Result<Self, Self::Error> {
235 match validate_bytes(v.as_bytes()) {
236 Ok(_) => Ok(unsafe {
237 Self::from_bytes_maybe_unchecked(v.into_bytes())
239 }),
240 Err(e) => Err(ConversionError::new(v, e)),
241 }
242 }
243}
244
245impl fmt::Display for SecfracDigitsString {
246 #[inline]
247 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
248 self.as_deref().fmt(f)
249 }
250}
251
252impl ops::Deref for SecfracDigitsString {
253 type Target = SecfracDigitsStr;
254
255 #[inline]
256 fn deref(&self) -> &Self::Target {
257 self.as_deref()
258 }
259}
260
261impl ops::DerefMut for SecfracDigitsString {
262 #[inline]
263 fn deref_mut(&mut self) -> &mut Self::Target {
264 self.as_deref_mut()
265 }
266}
267
268impl str::FromStr for SecfracDigitsString {
269 type Err = Error;
270
271 #[inline]
272 fn from_str(s: &str) -> Result<Self, Self::Err> {
273 Self::try_from(s)
274 }
275}
276
277impl_cmp_symmetric!(SecfracDigitsStr, SecfracDigitsString, &SecfracDigitsString);
278impl_cmp_symmetric!(SecfracDigitsStr, SecfracDigitsString, SecfracDigitsStr);
279impl_cmp_symmetric!(SecfracDigitsStr, SecfracDigitsString, &SecfracDigitsStr);
280impl_cmp_symmetric!(str, SecfracDigitsString, str);
281impl_cmp_symmetric!(str, SecfracDigitsString, &str);
282impl_cmp_symmetric!(str, &SecfracDigitsString, str);
283impl_cmp_symmetric!([u8], SecfracDigitsString, [u8]);
284impl_cmp_symmetric!([u8], SecfracDigitsString, &[u8]);
285impl_cmp_symmetric!([u8], &SecfracDigitsString, [u8]);
286
287#[cfg(feature = "serde")]
288#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
289impl serde::Serialize for SecfracDigitsString {
290 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
291 where
292 S: serde::Serializer,
293 {
294 serializer.serialize_str(self.as_str())
295 }
296}
297
298#[cfg(feature = "serde")]
300mod serde_ {
301 use super::*;
302
303 use serde::de::{Deserialize, Deserializer, Visitor};
304
305 struct StringVisitor;
307
308 impl<'de> Visitor<'de> for StringVisitor {
309 type Value = SecfracDigitsString;
310
311 #[inline]
312 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
313 f.write_str("digits of fractions of a second")
314 }
315
316 #[inline]
317 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
318 where
319 E: serde::de::Error,
320 {
321 Self::Value::try_from(v).map_err(E::custom)
322 }
323
324 #[inline]
325 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
326 where
327 E: serde::de::Error,
328 {
329 Self::Value::try_from(v).map_err(E::custom)
330 }
331 }
332
333 impl<'de> Deserialize<'de> for SecfracDigitsString {
334 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
335 where
336 D: Deserializer<'de>,
337 {
338 deserializer.deserialize_any(StringVisitor)
339 }
340 }
341}
342
343#[cfg(feature = "serde")]
344#[cfg(test)]
345mod tests {
346 use super::*;
347
348 use serde_test::{assert_de_tokens, assert_tokens, Token};
349
350 #[test]
351 fn ser_de_string() {
352 let raw: &'static str = "1234";
353 assert_tokens(
354 &SecfracDigitsString::try_from(raw).unwrap(),
355 &[Token::Str(raw)],
356 );
357 }
358
359 #[test]
360 fn de_bytes() {
361 let raw: &'static [u8; 4] = b"1234";
362 assert_de_tokens(
363 &SecfracDigitsString::try_from(&raw[..]).unwrap(),
364 &[Token::Bytes(raw)],
365 );
366 }
367}