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