hdbconnect_impl/serde_db_impl/time/
hana_time.rs1use crate::ToHana;
2use serde::ser::Error as _;
3use std::str::FromStr;
4use time::{Time, format_description::FormatItem, macros::format_description};
5
6#[derive(Debug)]
31pub struct HanaTime(pub Time);
32impl HanaTime {
33 #[must_use]
35 pub fn into_inner(self) -> Time {
36 self.0
37 }
38}
39impl std::ops::Deref for HanaTime {
40 type Target = Time;
41 fn deref(&self) -> &Self::Target {
42 &self.0
43 }
44}
45
46impl<'de> serde::de::Deserialize<'de> for HanaTime {
50 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
51 where
52 D: serde::de::Deserializer<'de>,
53 {
54 deserializer.deserialize_str(HanaTimeVisitor)
55 }
56}
57impl FromStr for HanaTime {
58 type Err = time::error::Parse;
59 fn from_str(s: &str) -> Result<Self, Self::Err> {
60 const DATE_T_TIME: &[FormatItem<'static>] = format_description!("[hour]:[minute]:[second]");
62 const DATE_T_TIME_SUB: &[FormatItem<'static>] =
63 format_description!("[hour]:[minute]:[second].[subsecond]");
64
65 Time::parse(s, &DATE_T_TIME_SUB)
66 .or_else(|_| Time::parse(s, &DATE_T_TIME))
67 .map(HanaTime)
68 }
69}
70
71pub(in crate::serde_db_impl) struct HanaTimeVisitor;
72impl serde::de::Visitor<'_> for HanaTimeVisitor {
73 type Value = HanaTime;
74
75 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
76 write!(
77 formatter,
78 "a String in the form [hour]:[minute]:[second].[subsecond]"
79 )
80 }
81
82 fn visit_str<E>(self, value: &str) -> Result<HanaTime, E>
83 where
84 E: serde::de::Error,
85 {
86 HanaTime::from_str(value).map_err(E::custom)
87 }
88}
89
90#[allow(clippy::missing_errors_doc)]
112pub fn to_time<'de, D>(input: D) -> Result<Time, D::Error>
113where
114 D: serde::de::Deserializer<'de>,
115{
116 input
117 .deserialize_str(HanaTimeVisitor)
118 .map(HanaTime::into_inner)
119}
120
121impl ToHana<HanaTime> for Time {
126 fn to_hana(self) -> HanaTime {
127 HanaTime(self)
128 }
129}
130
131impl serde::ser::Serialize for HanaTime {
132 fn serialize<S: serde::ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
133 const TIME_9: &[FormatItem<'static>] =
134 format_description!("[hour]:[minute]:[second].[subsecond digits:9]");
135
136 serializer.serialize_str(
137 &self
138 .0
139 .format(TIME_9)
140 .map_err(|_| S::Error::custom("failed formatting `Time`"))?,
141 )
142 }
143}