tank_core/
parse.rs

1use anyhow::Context;
2use time::{Date, OffsetDateTime, PrimitiveDateTime, Time, macros::format_description};
3
4use crate::{Error, Result};
5use std::cmp;
6
7pub trait Parse {
8    fn parse(value: impl AsRef<str>) -> Result<Self>
9    where
10        Self: Sized;
11}
12
13impl Parse for Box<[u8]> {
14    fn parse(value: impl AsRef<str>) -> Result<Self> {
15        let value = value.as_ref();
16        Err(Error::msg(format!(
17            "Could not decode blob pattern: `{}{}`",
18            &value[..cmp::min(value.len(), 497)],
19            if value.len() > 497 { "..." } else { "" }
20        )))
21    }
22}
23
24impl Parse for Date {
25    fn parse(value: impl AsRef<str>) -> Result<Self>
26    where
27        Self: Sized,
28    {
29        time::Date::parse(value.as_ref(), format_description!("[year]-[month]-[day]"))
30            .with_context(|| format!("Cannot convert '{}' to time::Time", value.as_ref()))
31    }
32}
33
34impl Parse for Time {
35    fn parse(value: impl AsRef<str>) -> Result<Self>
36    where
37        Self: Sized,
38    {
39        let value = value.as_ref();
40        time::Time::parse(
41            value,
42            format_description!("[hour]:[minute]:[second].[subsecond]"),
43        )
44        .or(time::Time::parse(
45            value,
46            format_description!("[hour]:[minute]:[second]"),
47        ))
48        .or(time::Time::parse(
49            value,
50            format_description!("[hour]:[minute]"),
51        ))
52        .with_context(|| format!("Cannot convert '{}' to time::Time", value))
53    }
54}
55
56impl Parse for PrimitiveDateTime {
57    fn parse(value: impl AsRef<str>) -> Result<Self>
58    where
59        Self: Sized,
60    {
61        let value = value.as_ref();
62        time::PrimitiveDateTime::parse(
63            value,
64            format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]"),
65        )
66        .or(time::PrimitiveDateTime::parse(
67            value,
68            format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]"),
69        ))
70        .or(time::PrimitiveDateTime::parse(
71            value,
72            format_description!("[year]-[month]-[day]T[hour]:[minute]"),
73        ))
74        .or(time::PrimitiveDateTime::parse(
75            value,
76            format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]"),
77        ))
78        .or(time::PrimitiveDateTime::parse(
79            value,
80            format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"),
81        ))
82        .or(time::PrimitiveDateTime::parse(
83            value,
84            format_description!("[year]-[month]-[day] [hour]:[minute]"),
85        ))
86        .with_context(|| format!("Cannot convert '{}' to time::PrimitiveDateTime", value))
87    }
88}
89
90impl Parse for OffsetDateTime {
91    fn parse(value: impl AsRef<str>) -> Result<Self>
92    where
93        Self: Sized,
94    {
95        let value = value.as_ref();
96        time::OffsetDateTime::parse(
97            value,
98            format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]")
99        )
100        .or(time::OffsetDateTime::parse(
101            value,
102            format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]")
103        ))
104        .or(time::OffsetDateTime::parse(
105            value,
106            format_description!("[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]")
107        ))
108        .or(time::OffsetDateTime::parse(
109            value,
110            format_description!("[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]")
111        ))
112        .or(time::OffsetDateTime::parse(
113            value,
114            format_description!("[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]:[offset_minute]")
115        ))
116        .or(time::OffsetDateTime::parse(
117            value,
118            format_description!("[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]")
119        ))
120        .with_context(|| format!("Cannot convert '{}' to time::OffsetDateTime", value))
121    }
122}