Skip to content

Commit f6548ec

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

File tree

4 files changed

+137
-2
lines changed

4 files changed

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