Skip to content

Commit 7acc75e

Browse files
add de/ser to date time
1 parent 70fa84f commit 7acc75e

File tree

4 files changed

+138
-2
lines changed

4 files changed

+138
-2
lines changed

rust-runtime/aws-smithy-types/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ harness = false
4141

4242
[features]
4343
serde-serialize = []
44-
serde-deserialize = []
44+
serde-deserialize = []
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
use super::*;
7+
use serde::de::Visitor;
8+
use serde::Deserialize;
9+
10+
struct DateTimeVisitor;
11+
12+
enum VisitorState {
13+
Second,
14+
SubsecondNanos,
15+
Unexpected,
16+
}
17+
18+
impl VisitorState {
19+
const UNEXPECTED_VISITOR_STATE: &'static str = "Unexpected state. This happens when visitor tries to parse something after finished parsing the `subsec_nanos`.";
20+
}
21+
22+
struct NonHumanReadableDateTimeVisitor {
23+
state: VisitorState,
24+
seconds: i64,
25+
subsecond_nanos: u32,
26+
}
27+
28+
fn fail<T, M, E>(err_message: M) -> Result<T, E>
29+
where
30+
M: std::fmt::Display,
31+
E: serde::de::Error,
32+
{
33+
Err(E::custom(err_message))
34+
}
35+
36+
impl<'de> Visitor<'de> for DateTimeVisitor {
37+
type Value = DateTime;
38+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
39+
formatter.write_str("expected RFC-3339 Date Time")
40+
}
41+
42+
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
43+
where
44+
E: serde::de::Error,
45+
{
46+
match DateTime::from_str(v, Format::DateTime) {
47+
Ok(e) => Ok(e),
48+
Err(e) => fail(e),
49+
}
50+
}
51+
}
52+
53+
impl<'de> Visitor<'de> for NonHumanReadableDateTimeVisitor {
54+
type Value = Self;
55+
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
56+
formatter.write_str("expected (i64, u32)")
57+
}
58+
59+
fn visit_i64<E>(mut self, v: i64) -> Result<Self::Value, E>
60+
where
61+
E: serde::de::Error,
62+
{
63+
match self.state {
64+
VisitorState::Unexpected => fail(VisitorState::UNEXPECTED_VISITOR_STATE),
65+
VisitorState::Second => {
66+
self.seconds = v;
67+
self.state = VisitorState::SubsecondNanos;
68+
Ok(self)
69+
}
70+
_ => fail("`seconds` value must be i64"),
71+
}
72+
}
73+
74+
fn visit_u32<E>(mut self, v: u32) -> Result<Self::Value, E>
75+
where
76+
E: serde::de::Error,
77+
{
78+
match self.state {
79+
VisitorState::Unexpected => fail(VisitorState::UNEXPECTED_VISITOR_STATE),
80+
VisitorState::SubsecondNanos => {
81+
self.subsecond_nanos = v;
82+
self.state = VisitorState::Unexpected;
83+
Ok(self)
84+
}
85+
_ => fail("`subsecond_nanos` value must be u32"),
86+
}
87+
}
88+
}
89+
90+
impl<'de> Deserialize<'de> for DateTime {
91+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
92+
where
93+
D: serde::Deserializer<'de>,
94+
{
95+
if deserializer.is_human_readable() {
96+
deserializer.deserialize_str(DateTimeVisitor)
97+
} else {
98+
let visitor = NonHumanReadableDateTimeVisitor {
99+
state: VisitorState::Second,
100+
seconds: 0,
101+
subsecond_nanos: 0,
102+
};
103+
let visitor = deserializer.deserialize_tuple(2, visitor)?;
104+
Ok(DateTime {
105+
seconds: visitor.seconds,
106+
subsecond_nanos: visitor.subsecond_nanos,
107+
})
108+
}
109+
}
110+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
use super::*;
7+
use serde::ser::SerializeTuple;
8+
9+
impl serde::Serialize for DateTime {
10+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
11+
where
12+
S: serde::Serializer,
13+
{
14+
if serializer.is_human_readable() {
15+
match self.fmt(Format::DateTime) {
16+
Ok(val) => serializer.serialize_str(&val),
17+
Err(e) => Err(serde::ser::Error::custom(e)),
18+
}
19+
} else {
20+
let mut tup_ser = serializer.serialize_tuple(2)?;
21+
tup_ser.serialize_element(&self.seconds)?;
22+
tup_ser.serialize_element(&self.subsecond_nanos)?;
23+
tup_ser.end()
24+
}
25+
}
26+
}

rust-runtime/aws-smithy-types/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ pub mod retry;
2222
pub mod timeout;
2323

2424
mod blob;
25-
mod number;
2625
mod document;
26+
mod number;
2727

2828
pub use blob::Blob;
2929
pub use date_time::DateTime;

0 commit comments

Comments
 (0)