1use crate::{Decode, Encode, Layout, Result};
2
3pub mod ops {
5 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7 #[allow(non_camel_case_types)]
8 pub enum Ordering {
9 Less,
10 Equal,
11 Greater,
12 }
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17pub struct Timestamp {
18 pub microseconds: i64,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
23pub struct Date {
24 pub days_epoch: i32,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct Time {
30 pub micros_midnight: u64,
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
35pub struct Duration {
36 pub microseconds: i64,
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
41pub struct Decimal(pub i64);
42
43impl Encode for Timestamp {
44 type HeadPtr = ();
45
46 fn encode_head(&self, buf: &mut crate::bytes::BytesMut) {
47 self.microseconds.encode_head(buf)
48 }
49
50 fn encode_body(&self, _: (), _: &mut crate::bytes::BytesMut) {}
51}
52
53impl Layout for Timestamp {
54 fn head_size() -> usize {
55 i64::head_size()
56 }
57}
58
59impl Decode for Timestamp {
60 fn decode(buf: &[u8]) -> Result<Self> {
61 Ok(Self {
62 microseconds: i64::decode(buf)?,
63 })
64 }
65}
66impl Encode for Date {
67 type HeadPtr = ();
68
69 fn encode_head(&self, buf: &mut crate::bytes::BytesMut) {
70 self.days_epoch.encode_head(buf)
71 }
72
73 fn encode_body(&self, _: (), _: &mut crate::bytes::BytesMut) {}
74}
75impl Layout for Date {
76 fn head_size() -> usize {
77 i32::head_size()
78 }
79}
80impl Decode for Date {
81 fn decode(buf: &[u8]) -> Result<Self> {
82 Ok(Self {
83 days_epoch: i32::decode(buf)?,
84 })
85 }
86}
87impl Encode for Time {
88 type HeadPtr = ();
89
90 fn encode_head(&self, buf: &mut crate::bytes::BytesMut) {
91 self.micros_midnight.encode_head(buf)
92 }
93
94 fn encode_body(&self, _: (), _: &mut crate::bytes::BytesMut) {}
95}
96impl Layout for Time {
97 fn head_size() -> usize {
98 u64::head_size()
99 }
100}
101impl Decode for Time {
102 fn decode(buf: &[u8]) -> Result<Self> {
103 Ok(Self {
104 micros_midnight: u64::decode(buf)?,
105 })
106 }
107}
108impl Encode for Duration {
109 type HeadPtr = ();
110
111 fn encode_head(&self, buf: &mut crate::bytes::BytesMut) {
112 self.microseconds.encode_head(buf)
113 }
114
115 fn encode_body(&self, _: (), _: &mut crate::bytes::BytesMut) {}
116}
117impl Layout for Duration {
118 fn head_size() -> usize {
119 i64::head_size()
120 }
121}
122impl Decode for Duration {
123 fn decode(buf: &[u8]) -> Result<Self> {
124 Ok(Self {
125 microseconds: i64::decode(buf)?,
126 })
127 }
128}
129impl Encode for Decimal {
130 type HeadPtr = ();
131
132 fn encode_head(&self, buf: &mut crate::bytes::BytesMut) {
133 self.0.encode_head(buf)
134 }
135
136 fn encode_body(&self, _: (), _: &mut crate::bytes::BytesMut) {}
137}
138impl Layout for Decimal {
139 fn head_size() -> usize {
140 i64::head_size()
141 }
142}
143impl Decode for Decimal {
144 fn decode(buf: &[u8]) -> Result<Self> {
145 Ok(Self(i64::decode(buf)?))
146 }
147}
148impl Encode for ops::Ordering {
149 type HeadPtr = ();
150
151 fn encode_head(&self, buf: &mut crate::bytes::BytesMut) {
152 let tag = match self {
153 Self::Less => 0_u8,
154 Self::Equal => 1,
155 Self::Greater => 2,
156 };
157 tag.encode_head(buf)
158 }
159
160 fn encode_body(&self, _: (), _: &mut crate::bytes::BytesMut) {}
161}
162impl Layout for ops::Ordering {
163 fn head_size() -> usize {
164 8
165 }
166}
167impl Decode for ops::Ordering {
168 fn decode(buf: &[u8]) -> Result<Self> {
169 Ok(match u8::decode(buf)? {
170 0 => Self::Less,
171 1 => Self::Equal,
172 2 => Self::Greater,
173 _ => return Err(crate::Error::InvalidData),
174 })
175 }
176}
177
178#[cfg(feature = "chrono")]
179mod chrono_impls {
180 use chrono::{Datelike, Timelike};
181
182 use super::{Date, Time, Timestamp};
183
184 const EPOCH_DAYS_FROM_CE: i32 = 719_163;
185 const MICROS_PER_SECOND: u32 = 1_000_000;
186 const MICROS_PER_DAY: i64 = 86_400_000_000;
187
188 impl TryFrom<Timestamp> for chrono::DateTime<chrono::Utc> {
189 type Error = crate::Error;
190
191 fn try_from(value: Timestamp) -> core::result::Result<Self, Self::Error> {
192 chrono::DateTime::from_timestamp_micros(value.microseconds)
193 .ok_or(crate::Error::InvalidData)
194 }
195 }
196
197 impl From<chrono::DateTime<chrono::Utc>> for Timestamp {
198 fn from(value: chrono::DateTime<chrono::Utc>) -> Self {
199 Self {
200 microseconds: value.timestamp_micros(),
201 }
202 }
203 }
204
205 impl TryFrom<Date> for chrono::NaiveDate {
206 type Error = crate::Error;
207
208 fn try_from(value: Date) -> core::result::Result<Self, Self::Error> {
209 chrono::NaiveDate::from_num_days_from_ce_opt(value.days_epoch + EPOCH_DAYS_FROM_CE)
210 .ok_or(crate::Error::InvalidData)
211 }
212 }
213
214 impl TryFrom<chrono::NaiveDate> for Date {
215 type Error = crate::Error;
216
217 fn try_from(value: chrono::NaiveDate) -> core::result::Result<Self, Self::Error> {
218 let days = value.num_days_from_ce() - EPOCH_DAYS_FROM_CE;
219 Ok(Self { days_epoch: days })
220 }
221 }
222
223 impl TryFrom<Time> for chrono::NaiveTime {
224 type Error = crate::Error;
225
226 fn try_from(value: Time) -> core::result::Result<Self, Self::Error> {
227 if value.micros_midnight >= MICROS_PER_DAY as u64 {
228 return Err(crate::Error::InvalidData);
229 }
230
231 let secs = u32::try_from(value.micros_midnight / u64::from(MICROS_PER_SECOND))
232 .map_err(|_| crate::Error::InvalidData)?;
233 let micros = u32::try_from(value.micros_midnight % u64::from(MICROS_PER_SECOND))
234 .map_err(|_| crate::Error::InvalidData)?;
235
236 chrono::NaiveTime::from_num_seconds_from_midnight_opt(secs, micros * 1_000)
237 .ok_or(crate::Error::InvalidData)
238 }
239 }
240
241 impl From<chrono::NaiveTime> for Time {
242 fn from(value: chrono::NaiveTime) -> Self {
243 let secs = u64::from(value.num_seconds_from_midnight());
244 let micros = u64::from(value.nanosecond() / 1_000);
245 Self {
246 micros_midnight: secs * u64::from(MICROS_PER_SECOND) + micros,
247 }
248 }
249 }
250}