Skip to content

Commit

Permalink
add de/ser to date time
Browse files Browse the repository at this point in the history
  • Loading branch information
thomas-k-cameron committed Apr 21, 2023
1 parent 70fa84f commit f6548ec
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 2 deletions.
2 changes: 1 addition & 1 deletion rust-runtime/aws-smithy-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ harness = false

[features]
serde-serialize = []
serde-deserialize = []
serde-deserialize = []
109 changes: 109 additions & 0 deletions rust-runtime/aws-smithy-types/src/date_time/de.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use super::*;
use serde::de::Visitor;
use serde::Deserialize;
struct DateTimeVisitor;

enum VisitorState {
Second,
SubsecondNanos,
Unexpected,
}

impl VisitorState {
const UNEXPECTED_VISITOR_STATE: &'static str = "Unexpected state. This happens when visitor tries to parse something after finished parsing the `subsec_nanos`.";
}

struct NonHumanReadableDateTimeVisitor {
state: VisitorState,
seconds: i64,
subsecond_nanos: u32,
}

fn fail<T, M, E>(err_message: M) -> Result<T, E>
where
M: std::fmt::Display,
E: serde::de::Error,
{
Err(serde::de::Error::custom(err_message))
}

impl<'de> Visitor<'de> for DateTimeVisitor {
type Value = DateTime;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("expected RFC-3339 Date Time")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
match DateTime::from_str(v, Format::DateTime) {
Ok(e) => Ok(e),
Err(e) => fail(e),
}
}
}

impl<'de> Visitor<'de> for NonHumanReadableDateTimeVisitor {
type Value = Self;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("expected (i64, u32)")
}

fn visit_i64<E>(mut self, v: i64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
match self.state {
VisitorState::Unexpected => fail(VisitorState::UNEXPECTED_VISITOR_STATE),
VisitorState::Second => {
self.seconds = v;
self.state = VisitorState::SubsecondNanos;
Ok(self)
}
_ => fail("`seconds` value must be i64"),
}
}

fn visit_u32<E>(mut self, v: u32) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
match self.state {
VisitorState::Unexpected => fail(VisitorState::UNEXPECTED_VISITOR_STATE),
VisitorState::SubsecondNanos => {
self.subsecond_nanos = v;
self.state = VisitorState::Unexpected;
Ok(self)
}
_ => fail("`subsecond_nanos` value must be u32"),
}
}
}

impl<'de> Deserialize<'de> for DateTime {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
if deserializer.is_human_readable() {
deserializer.deserialize_str(DateTimeVisitor)
} else {
let visitor = NonHumanReadableDateTimeVisitor {
state: VisitorState::Second,
seconds: 0,
subsecond_nanos: 0,
};
let visitor = deserializer.deserialize_tuple(2, visitor)?;
Ok(DateTime {
seconds: visitor.seconds,
subsecond_nanos: visitor.subsecond_nanos,
})
}
}
}
26 changes: 26 additions & 0 deletions rust-runtime/aws-smithy-types/src/date_time/ser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

use super::*;
use serde::ser::SerializeTuple;

impl serde::Serialize for DateTime {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
if serializer.is_human_readable() {
match self.fmt(Format::DateTime) {
Ok(val) => serializer.serialize_str(&val),
Err(e) => Err(serde::ser::Error::custom(e)),
}
} else {
let mut tup_ser = serializer.serialize_tuple(2)?;
tup_ser.serialize_element(&self.seconds)?;
tup_ser.serialize_element(&self.subsecond_nanos)?;
tup_ser.end()
}
}
}
2 changes: 1 addition & 1 deletion rust-runtime/aws-smithy-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ pub mod retry;
pub mod timeout;

mod blob;
mod number;
mod document;
mod number;

pub use blob::Blob;
pub use date_time::DateTime;
Expand Down

0 comments on commit f6548ec

Please sign in to comment.