From bc55504b8741bedbf2bac2e214dc7796cf5b9a85 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 20 Apr 2023 19:56:01 +0000 Subject: [PATCH 01/31] add serde support on meta data --- rust-runtime/aws-smithy-types/src/error/metadata.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/rust-runtime/aws-smithy-types/src/error/metadata.rs b/rust-runtime/aws-smithy-types/src/error/metadata.rs index 06925e13f9..9036dc94ec 100644 --- a/rust-runtime/aws-smithy-types/src/error/metadata.rs +++ b/rust-runtime/aws-smithy-types/src/error/metadata.rs @@ -6,6 +6,7 @@ //! Error metadata use crate::retry::{ErrorKind, ProvideErrorKind}; +use std::borrow::Cow; use std::collections::HashMap; use std::fmt; @@ -39,11 +40,19 @@ pub const EMPTY_ERROR_METADATA: ErrorMetadata = ErrorMetadata { /// For many services, Errors are modeled. However, many services only partially model errors or don't /// model errors at all. In these cases, the SDK will return this generic error type to expose the /// `code`, `message` and `request_id`. +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-serialize"), + derive(serde::Serialize) +)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-deserialize"), + derive(serde::Deserialize) +)] #[derive(Debug, Eq, PartialEq, Default, Clone)] pub struct ErrorMetadata { code: Option, message: Option, - extras: Option>, + extras: Option, String>>, } /// Builder for [`ErrorMetadata`]. @@ -98,7 +107,7 @@ impl Builder { .extras .as_mut() .unwrap() - .insert(key, value.into()); + .insert(Cow::Borrowed(key), value.into()); self } From 931a23e9d450dee61b913be48b1b47c736b66df0 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 20 Apr 2023 19:56:01 +0000 Subject: [PATCH 02/31] add serde support to - blob - document - datetime - number number, blob and document moves to another file --- rust-runtime/aws-smithy-types/Cargo.toml | 5 + rust-runtime/aws-smithy-types/src/blob.rs | 160 ++++++ .../aws-smithy-types/src/date_time/mod.rs | 51 ++ rust-runtime/aws-smithy-types/src/document.rs | 145 +++++ rust-runtime/aws-smithy-types/src/lib.rs | 543 +----------------- rust-runtime/aws-smithy-types/src/number.rs | 494 ++++++++++++++++ 6 files changed, 859 insertions(+), 539 deletions(-) create mode 100644 rust-runtime/aws-smithy-types/src/blob.rs create mode 100644 rust-runtime/aws-smithy-types/src/document.rs create mode 100644 rust-runtime/aws-smithy-types/src/number.rs diff --git a/rust-runtime/aws-smithy-types/Cargo.toml b/rust-runtime/aws-smithy-types/Cargo.toml index 7ebd3ece23..a0a62f4bf4 100644 --- a/rust-runtime/aws-smithy-types/Cargo.toml +++ b/rust-runtime/aws-smithy-types/Cargo.toml @@ -14,6 +14,11 @@ ryu = "1.0.5" time = { version = "0.3.4", features = ["parsing"] } base64-simd = "0.8" + +[target."cfg(aws_sdk_unstable)".dependencies.serde] +version = "1" +features = ["derive"] + [dev-dependencies] base64 = "0.13.0" lazy_static = "1.4" diff --git a/rust-runtime/aws-smithy-types/src/blob.rs b/rust-runtime/aws-smithy-types/src/blob.rs new file mode 100644 index 0000000000..0364727d4f --- /dev/null +++ b/rust-runtime/aws-smithy-types/src/blob.rs @@ -0,0 +1,160 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#[cfg(all( + aws_sdk_unstable, + any(feature = "serde-deserialize", feature = "serde-serialize") +))] +use crate::base64; +#[cfg(all(aws_sdk_unstable, feature = "serde-serialize"))] +use serde::Serialize; +#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))] +use serde::{de::Visitor, Deserialize}; +/// Binary Blob Type +/// +/// Blobs represent protocol-agnostic binary content. +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub struct Blob { + inner: Vec, +} + +impl Blob { + /// Creates a new blob from the given `input`. + pub fn new>>(input: T) -> Self { + Blob { + inner: input.into(), + } + } + + /// Consumes the `Blob` and returns a `Vec` with its contents. + pub fn into_inner(self) -> Vec { + self.inner + } +} + +impl AsRef<[u8]> for Blob { + fn as_ref(&self) -> &[u8] { + &self.inner + } +} + +#[cfg(all(aws_sdk_unstable, feature = "serde-serialize"))] +impl Serialize for Blob { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + if serializer.is_human_readable() { + serializer.serialize_str(&crate::base64::encode(&self.inner)) + } else { + serializer.serialize_bytes(&self.inner) + } + } +} + +#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))] +struct HumanReadableBlobVisitor; + +#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))] +impl<'de> Visitor<'de> for HumanReadableBlobVisitor { + type Value = Blob; + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("expected base64 encoded string") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + match base64::decode(v) { + Ok(inner) => Ok(Blob { inner }), + Err(e) => Err(serde::de::Error::custom(e)), + } + } +} + +#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))] +struct NotHumanReadableBlobVisitor; + +#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))] +impl<'de> Visitor<'de> for NotHumanReadableBlobVisitor { + type Value = Blob; + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("expected base64 encoded string") + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: serde::de::Error, + { + Ok(Blob { inner: v }) + } +} + +#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))] +impl<'de> Deserialize<'de> for Blob { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + if deserializer.is_human_readable() { + deserializer.deserialize_str(HumanReadableBlobVisitor) + } else { + deserializer.deserialize_byte_buf(NotHumanReadableBlobVisitor) + } + } +} + +#[cfg(test)] +#[cfg(all( + aws_sdk_unstable, + feature = "serde-serialize", + feature = "serde-deserialize" +))] +mod test { + use crate::Blob; + use serde::{Deserialize, Serialize}; + use std::collections::HashMap; + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct ForTest { + blob: Blob, + } + + #[test] + fn human_readable_blob() { + let aws_in_base64 = r#"{"blob":"QVdT"}"#; + let for_test = ForTest { + blob: Blob { + inner: vec![b'A', b'W', b'S'], + }, + }; + assert_eq!(for_test, serde_json::from_str(aws_in_base64).unwrap()); + assert_eq!(serde_json::to_string(&for_test).unwrap(), aws_in_base64); + } + + #[test] + fn not_human_readable_blob() { + use std::ffi::CString; + + let for_test = ForTest { + blob: Blob { + inner: vec![b'A', b'W', b'S'], + }, + }; + let mut buf = vec![]; + let res = ciborium::ser::into_writer(&for_test, &mut buf); + assert!(res.is_ok()); + + // checks whether the bytes are deserialiezd properly + let n: HashMap = + ciborium::de::from_reader(std::io::Cursor::new(buf.clone())).unwrap(); + assert!(n.get("blob").is_some()); + assert!(n.get("blob") == CString::new([65, 87, 83]).ok().as_ref()); + + let de: ForTest = ciborium::de::from_reader(std::io::Cursor::new(buf)).unwrap(); + assert_eq!(for_test, de); + } +} diff --git a/rust-runtime/aws-smithy-types/src/date_time/mod.rs b/rust-runtime/aws-smithy-types/src/date_time/mod.rs index 0459619998..9739bce0f2 100644 --- a/rust-runtime/aws-smithy-types/src/date_time/mod.rs +++ b/rust-runtime/aws-smithy-types/src/date_time/mod.rs @@ -16,7 +16,12 @@ use std::time::Duration; use std::time::SystemTime; use std::time::UNIX_EPOCH; +#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))] +mod de; mod format; +#[cfg(all(aws_sdk_unstable, feature = "serde-serialize"))] +mod ser; + pub use self::format::DateTimeFormatError; pub use self::format::DateTimeParseError; @@ -552,4 +557,50 @@ mod test { SystemTime::try_from(date_time).unwrap() ); } + + #[cfg(all( + test, + aws_sdk_unstable, + feature = "serde-deserialize", + feature = "serde-serialize" + ))] + #[test] + fn human_readable_datetime() { + use serde::{Deserialize, Serialize}; + + let datetime = DateTime::from_secs(1576540098); + #[derive(Serialize, Deserialize, PartialEq)] + struct Test { + datetime: DateTime, + } + let datetime_json = r#"{"datetime":"2019-12-16T23:48:18Z"}"#; + assert!(serde_json::to_string(&Test { datetime }).ok() == Some(datetime_json.to_string())); + + let test = serde_json::from_str::(&datetime_json).ok(); + assert!(test.is_some()); + assert!(test.unwrap().datetime == datetime); + } + + /// checks that they are serialized into tuples + #[cfg(all( + test, + aws_sdk_unstable, + feature = "serde-deserialize", + feature = "serde-serialize" + ))] + #[test] + fn not_human_readable_datetime() { + let cbor = ciborium::value::Value::Array(vec![ + ciborium::value::Value::Integer(1576540098i64.into()), + ciborium::value::Value::Integer(0u32.into()), + ]); + let datetime = DateTime::from_secs(1576540098); + + let mut buf1 = vec![]; + let mut buf2 = vec![]; + let res1 = ciborium::ser::into_writer(&datetime, &mut buf1); + let res2 = ciborium::ser::into_writer(&cbor, &mut buf2); + assert!(res1.is_ok() && res2.is_ok()); + assert!(buf1 == buf2, "{:#?}", (buf1, buf2)); + } } diff --git a/rust-runtime/aws-smithy-types/src/document.rs b/rust-runtime/aws-smithy-types/src/document.rs new file mode 100644 index 0000000000..8cbae5b380 --- /dev/null +++ b/rust-runtime/aws-smithy-types/src/document.rs @@ -0,0 +1,145 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use crate::Number; +use std::collections::HashMap; + +/* ANCHOR: document */ + +/// Document Type +/// +/// Document types represents protocol-agnostic open content that is accessed like JSON data. +/// Open content is useful for modeling unstructured data that has no schema, data that can't be +/// modeled using rigid types, or data that has a schema that evolves outside of the purview of a model. +/// The serialization format of a document is an implementation detail of a protocol. +#[derive(Debug, Clone, PartialEq)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-serialize"), + derive(serde::Serialize) +)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-deserialize"), + derive(serde::Deserialize) +)] +#[cfg_attr( + any( + all(aws_sdk_unstable, feature = "serde-deserialize"), + all(aws_sdk_unstable, feature = "serde-serialize") + ), + serde(untagged) +)] +pub enum Document { + /// JSON object + Object(HashMap), + /// JSON array + Array(Vec), + /// JSON number + Number(Number), + /// JSON string + String(String), + /// JSON boolean + Bool(bool), + /// JSON null + Null, +} + +impl From for Document { + fn from(value: bool) -> Self { + Document::Bool(value) + } +} + +impl From for Document { + fn from(value: String) -> Self { + Document::String(value) + } +} + +impl From> for Document { + fn from(values: Vec) -> Self { + Document::Array(values) + } +} + +impl From> for Document { + fn from(values: HashMap) -> Self { + Document::Object(values) + } +} + +impl From for Document { + fn from(value: u64) -> Self { + Document::Number(Number::PosInt(value)) + } +} + +impl From for Document { + fn from(value: i64) -> Self { + Document::Number(Number::NegInt(value)) + } +} + +impl From for Document { + fn from(value: i32) -> Self { + Document::Number(Number::NegInt(value as i64)) + } +} + +/* ANCHOR END: document */ + +#[cfg(test)] +mod test { + /// checks if a) serialization of json suceeds and b) it is compatible with serde_json + #[test] + #[cfg(all( + aws_sdk_unstable, + feature = "serde-serialize", + feature = "serde-deserialize" + ))] + fn serialize_json() { + use crate::Document; + use crate::Number; + use std::collections::HashMap; + let mut map: HashMap = HashMap::new(); + // string + map.insert("hello".into(), "world".to_string().into()); + // numbers + map.insert("pos_int".into(), Document::Number(Number::PosInt(1).into())); + map.insert( + "neg_int".into(), + Document::Number(Number::NegInt(-1).into()), + ); + map.insert( + "float".into(), + Document::Number(Number::Float(0.1 + 0.2).into()), + ); + // booleans + map.insert("true".into(), true.into()); + map.insert("false".into(), false.into()); + // check if array with different datatypes would succeed + map.insert( + "array".into(), + vec![ + map.clone().into(), + "hello-world".to_string().into(), + true.into(), + false.into(), + ] + .into(), + ); + // map + map.insert("map".into(), map.clone().into()); + // null + map.insert("null".into(), Document::Null); + let obj = Document::Object(map); + // comparing string isnt going to work since there is no gurantee for the ordering of the keys + let target_file = include_str!("../test_data/serialize_document.json"); + let json: Result = serde_json::from_str(target_file); + // serializer + assert_eq!(serde_json::to_value(&obj).unwrap(), json.unwrap()); + let doc: Result = serde_json::from_str(target_file); + assert_eq!(obj, doc.unwrap()); + } +} diff --git a/rust-runtime/aws-smithy-types/src/lib.rs b/rust-runtime/aws-smithy-types/src/lib.rs index 2634ff7f39..3bfd303319 100644 --- a/rust-runtime/aws-smithy-types/src/lib.rs +++ b/rust-runtime/aws-smithy-types/src/lib.rs @@ -25,543 +25,8 @@ pub mod primitive; pub mod retry; pub mod timeout; -pub use crate::date_time::DateTime; - -// TODO(deprecated): Remove deprecated re-export -/// Use [error::ErrorMetadata] instead. -#[deprecated( - note = "`aws_smithy_types::Error` has been renamed to `aws_smithy_types::error::ErrorMetadata`" -)] +pub use blob::Blob; +pub use date_time::DateTime; +pub use document::Document; pub use error::ErrorMetadata as Error; - -/// Binary Blob Type -/// -/// Blobs represent protocol-agnostic binary content. -#[derive(Debug, PartialEq, Eq, Hash, Clone)] -pub struct Blob { - inner: Vec, -} - -impl Blob { - /// Creates a new blob from the given `input`. - pub fn new>>(input: T) -> Self { - Blob { - inner: input.into(), - } - } - - /// Consumes the `Blob` and returns a `Vec` with its contents. - pub fn into_inner(self) -> Vec { - self.inner - } -} - -impl AsRef<[u8]> for Blob { - fn as_ref(&self) -> &[u8] { - &self.inner - } -} - -/* ANCHOR: document */ - -/// Document Type -/// -/// Document types represents protocol-agnostic open content that is accessed like JSON data. -/// Open content is useful for modeling unstructured data that has no schema, data that can't be -/// modeled using rigid types, or data that has a schema that evolves outside of the purview of a model. -/// The serialization format of a document is an implementation detail of a protocol. -#[derive(Debug, Clone, PartialEq)] -pub enum Document { - /// JSON object - Object(HashMap), - /// JSON array - Array(Vec), - /// JSON number - Number(Number), - /// JSON string - String(String), - /// JSON boolean - Bool(bool), - /// JSON null - Null, -} - -impl From for Document { - fn from(value: bool) -> Self { - Document::Bool(value) - } -} - -impl From for Document { - fn from(value: String) -> Self { - Document::String(value) - } -} - -impl From> for Document { - fn from(values: Vec) -> Self { - Document::Array(values) - } -} - -impl From> for Document { - fn from(values: HashMap) -> Self { - Document::Object(values) - } -} - -impl From for Document { - fn from(value: u64) -> Self { - Document::Number(Number::PosInt(value)) - } -} - -impl From for Document { - fn from(value: i64) -> Self { - Document::Number(Number::NegInt(value)) - } -} - -impl From for Document { - fn from(value: i32) -> Self { - Document::Number(Number::NegInt(value as i64)) - } -} - -/// A number type that implements Javascript / JSON semantics, modeled on serde_json: -/// -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Number { - /// Unsigned 64-bit integer value. - PosInt(u64), - /// Signed 64-bit integer value. The wrapped value is _always_ negative. - NegInt(i64), - /// 64-bit floating-point value. - Float(f64), -} - -/* ANCHOR_END: document */ - -impl Number { - /// Converts to an `f64` lossily. - /// Use `Number::try_from` to make the conversion only if it is not lossy. - pub fn to_f64_lossy(self) -> f64 { - match self { - Number::PosInt(v) => v as f64, - Number::NegInt(v) => v as f64, - Number::Float(v) => v, - } - } - - /// Converts to an `f32` lossily. - /// Use `Number::try_from` to make the conversion only if it is not lossy. - pub fn to_f32_lossy(self) -> f32 { - match self { - Number::PosInt(v) => v as f32, - Number::NegInt(v) => v as f32, - Number::Float(v) => v as f32, - } - } -} - -macro_rules! to_unsigned_integer_converter { - ($typ:ident, $styp:expr) => { - #[doc = "Converts to a `"] - #[doc = $styp] - #[doc = "`. This conversion fails if it is lossy."] - impl TryFrom for $typ { - type Error = TryFromNumberError; - - fn try_from(value: Number) -> Result { - match value { - Number::PosInt(v) => Ok(Self::try_from(v)?), - Number::NegInt(v) => { - Err(TryFromNumberErrorKind::NegativeToUnsignedLossyConversion(v).into()) - } - Number::Float(v) => { - Err(TryFromNumberErrorKind::FloatToIntegerLossyConversion(v).into()) - } - } - } - } - }; - - ($typ:ident) => { - to_unsigned_integer_converter!($typ, stringify!($typ)); - }; -} - -macro_rules! to_signed_integer_converter { - ($typ:ident, $styp:expr) => { - #[doc = "Converts to a `"] - #[doc = $styp] - #[doc = "`. This conversion fails if it is lossy."] - impl TryFrom for $typ { - type Error = TryFromNumberError; - - fn try_from(value: Number) -> Result { - match value { - Number::PosInt(v) => Ok(Self::try_from(v)?), - Number::NegInt(v) => Ok(Self::try_from(v)?), - Number::Float(v) => { - Err(TryFromNumberErrorKind::FloatToIntegerLossyConversion(v).into()) - } - } - } - } - }; - - ($typ:ident) => { - to_signed_integer_converter!($typ, stringify!($typ)); - }; -} - -/// Converts to a `u64`. The conversion fails if it is lossy. -impl TryFrom for u64 { - type Error = TryFromNumberError; - - fn try_from(value: Number) -> Result { - match value { - Number::PosInt(v) => Ok(v), - Number::NegInt(v) => { - Err(TryFromNumberErrorKind::NegativeToUnsignedLossyConversion(v).into()) - } - Number::Float(v) => { - Err(TryFromNumberErrorKind::FloatToIntegerLossyConversion(v).into()) - } - } - } -} -to_unsigned_integer_converter!(u32); -to_unsigned_integer_converter!(u16); -to_unsigned_integer_converter!(u8); - -impl TryFrom for i64 { - type Error = TryFromNumberError; - - fn try_from(value: Number) -> Result { - match value { - Number::PosInt(v) => Ok(Self::try_from(v)?), - Number::NegInt(v) => Ok(v), - Number::Float(v) => { - Err(TryFromNumberErrorKind::FloatToIntegerLossyConversion(v).into()) - } - } - } -} -to_signed_integer_converter!(i32); -to_signed_integer_converter!(i16); -to_signed_integer_converter!(i8); - -/// Converts to an `f64`. The conversion fails if it is lossy. -impl TryFrom for f64 { - type Error = TryFromNumberError; - - fn try_from(value: Number) -> Result { - match value { - // Integers can only be represented with full precision in a float if they fit in the - // significand, which is 24 bits in `f32` and 53 bits in `f64`. - // https://github.com/rust-lang/rust/blob/58f11791af4f97572e7afd83f11cffe04bbbd12f/library/core/src/convert/num.rs#L151-L153 - Number::PosInt(v) => { - if v <= (1 << 53) { - Ok(v as Self) - } else { - Err(TryFromNumberErrorKind::U64ToFloatLossyConversion(v).into()) - } - } - Number::NegInt(v) => { - if (-(1 << 53)..=(1 << 53)).contains(&v) { - Ok(v as Self) - } else { - Err(TryFromNumberErrorKind::I64ToFloatLossyConversion(v).into()) - } - } - Number::Float(v) => Ok(v), - } - } -} - -/// Converts to an `f64`. The conversion fails if it is lossy. -impl TryFrom for f32 { - type Error = TryFromNumberError; - - fn try_from(value: Number) -> Result { - match value { - Number::PosInt(v) => { - if v <= (1 << 24) { - Ok(v as Self) - } else { - Err(TryFromNumberErrorKind::U64ToFloatLossyConversion(v).into()) - } - } - Number::NegInt(v) => { - if (-(1 << 24)..=(1 << 24)).contains(&v) { - Ok(v as Self) - } else { - Err(TryFromNumberErrorKind::I64ToFloatLossyConversion(v).into()) - } - } - Number::Float(v) => Err(TryFromNumberErrorKind::F64ToF32LossyConversion(v).into()), - } - } -} - -#[cfg(test)] -mod number { - use super::*; - use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; - - macro_rules! to_unsigned_converter_tests { - ($typ:ident) => { - assert_eq!($typ::try_from(Number::PosInt(69u64)).unwrap(), 69); - - assert!(matches!( - $typ::try_from(Number::PosInt(($typ::MAX as u64) + 1u64)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::OutsideIntegerRange(..) - } - )); - - assert!(matches!( - $typ::try_from(Number::NegInt(-1i64)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::NegativeToUnsignedLossyConversion(..) - } - )); - - for val in [69.69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { - assert!(matches!( - $typ::try_from(Number::Float(val)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::FloatToIntegerLossyConversion(..) - } - )); - } - }; - } - - #[test] - fn to_u64() { - assert_eq!(u64::try_from(Number::PosInt(69u64)).unwrap(), 69u64); - - assert!(matches!( - u64::try_from(Number::NegInt(-1i64)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::NegativeToUnsignedLossyConversion(..) - } - )); - - for val in [69.69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { - assert!(matches!( - u64::try_from(Number::Float(val)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::FloatToIntegerLossyConversion(..) - } - )); - } - } - - #[test] - fn to_u32() { - to_unsigned_converter_tests!(u32); - } - - #[test] - fn to_u16() { - to_unsigned_converter_tests!(u16); - } - - #[test] - fn to_u8() { - to_unsigned_converter_tests!(u8); - } - - macro_rules! to_signed_converter_tests { - ($typ:ident) => { - assert_eq!($typ::try_from(Number::PosInt(69u64)).unwrap(), 69); - assert_eq!($typ::try_from(Number::NegInt(-69i64)).unwrap(), -69); - - assert!(matches!( - $typ::try_from(Number::PosInt(($typ::MAX as u64) + 1u64)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::OutsideIntegerRange(..) - } - )); - - assert!(matches!( - $typ::try_from(Number::NegInt(($typ::MIN as i64) - 1i64)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::OutsideIntegerRange(..) - } - )); - - for val in [69.69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { - assert!(matches!( - u64::try_from(Number::Float(val)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::FloatToIntegerLossyConversion(..) - } - )); - } - }; - } - - #[test] - fn to_i64() { - assert_eq!(i64::try_from(Number::PosInt(69u64)).unwrap(), 69); - assert_eq!(i64::try_from(Number::NegInt(-69i64)).unwrap(), -69); - - for val in [69.69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { - assert!(matches!( - u64::try_from(Number::Float(val)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::FloatToIntegerLossyConversion(..) - } - )); - } - } - - #[test] - fn to_i32() { - to_signed_converter_tests!(i32); - } - - #[test] - fn to_i16() { - to_signed_converter_tests!(i16); - } - - #[test] - fn to_i8() { - to_signed_converter_tests!(i8); - } - - #[test] - fn to_f64() { - assert_eq!(f64::try_from(Number::PosInt(69u64)).unwrap(), 69f64); - assert_eq!(f64::try_from(Number::NegInt(-69i64)).unwrap(), -69f64); - assert_eq!(f64::try_from(Number::Float(-69f64)).unwrap(), -69f64); - assert!(f64::try_from(Number::Float(f64::NAN)).unwrap().is_nan()); - assert_eq!( - f64::try_from(Number::Float(f64::INFINITY)).unwrap(), - f64::INFINITY - ); - assert_eq!( - f64::try_from(Number::Float(f64::NEG_INFINITY)).unwrap(), - f64::NEG_INFINITY - ); - - let significand_max_u64: u64 = 1 << 53; - let significand_max_i64: i64 = 1 << 53; - - assert_eq!( - f64::try_from(Number::PosInt(significand_max_u64)).unwrap(), - 9007199254740992f64 - ); - - assert_eq!( - f64::try_from(Number::NegInt(significand_max_i64)).unwrap(), - 9007199254740992f64 - ); - assert_eq!( - f64::try_from(Number::NegInt(-significand_max_i64)).unwrap(), - -9007199254740992f64 - ); - - assert!(matches!( - f64::try_from(Number::PosInt(significand_max_u64 + 1)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::U64ToFloatLossyConversion(..) - } - )); - - assert!(matches!( - f64::try_from(Number::NegInt(significand_max_i64 + 1)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::I64ToFloatLossyConversion(..) - } - )); - assert!(matches!( - f64::try_from(Number::NegInt(-significand_max_i64 - 1)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::I64ToFloatLossyConversion(..) - } - )); - } - - #[test] - fn to_f32() { - assert_eq!(f32::try_from(Number::PosInt(69u64)).unwrap(), 69f32); - assert_eq!(f32::try_from(Number::NegInt(-69i64)).unwrap(), -69f32); - - let significand_max_u64: u64 = 1 << 24; - let significand_max_i64: i64 = 1 << 24; - - assert_eq!( - f32::try_from(Number::PosInt(significand_max_u64)).unwrap(), - 16777216f32 - ); - - assert_eq!( - f32::try_from(Number::NegInt(significand_max_i64)).unwrap(), - 16777216f32 - ); - assert_eq!( - f32::try_from(Number::NegInt(-significand_max_i64)).unwrap(), - -16777216f32 - ); - - assert!(matches!( - f32::try_from(Number::PosInt(significand_max_u64 + 1)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::U64ToFloatLossyConversion(..) - } - )); - - assert!(matches!( - f32::try_from(Number::NegInt(significand_max_i64 + 1)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::I64ToFloatLossyConversion(..) - } - )); - assert!(matches!( - f32::try_from(Number::NegInt(-significand_max_i64 - 1)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::I64ToFloatLossyConversion(..) - } - )); - - for val in [69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { - assert!(matches!( - f32::try_from(Number::Float(val)).unwrap_err(), - TryFromNumberError { - kind: TryFromNumberErrorKind::F64ToF32LossyConversion(..) - } - )); - } - } - - #[test] - fn to_f64_lossy() { - assert_eq!(Number::PosInt(69u64).to_f64_lossy(), 69f64); - assert_eq!( - Number::PosInt((1 << 53) + 1).to_f64_lossy(), - 9007199254740992f64 - ); - assert_eq!( - Number::NegInt(-(1 << 53) - 1).to_f64_lossy(), - -9007199254740992f64 - ); - } - - #[test] - fn to_f32_lossy() { - assert_eq!(Number::PosInt(69u64).to_f32_lossy(), 69f32); - assert_eq!(Number::PosInt((1 << 24) + 1).to_f32_lossy(), 16777216f32); - assert_eq!(Number::NegInt(-(1 << 24) - 1).to_f32_lossy(), -16777216f32); - assert_eq!( - Number::Float(1452089033.7674935).to_f32_lossy(), - 1452089100f32 - ); - } -} +pub use number::Number; diff --git a/rust-runtime/aws-smithy-types/src/number.rs b/rust-runtime/aws-smithy-types/src/number.rs new file mode 100644 index 0000000000..80527cfc10 --- /dev/null +++ b/rust-runtime/aws-smithy-types/src/number.rs @@ -0,0 +1,494 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! A number type that implements Javascript / JSON semantics, modeled on serde_json: +//! + +use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; +#[cfg(all( + aws_sdk_unstable, + any(feature = "serde-serialize", feature = "serde-deserialize") +))] +use serde; + +/// A number type that implements Javascript / JSON semantics, modeled on serde_json: +/// +#[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-deserialize"), + derive(serde::Deserialize) +)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-serialize"), + derive(serde::Serialize) +)] +#[cfg_attr( + any( + all(aws_sdk_unstable, feature = "serde-deserialize"), + all(aws_sdk_unstable, feature = "serde-serialize") + ), + serde(untagged) +)] +pub enum Number { + /// Unsigned 64-bit integer value. + PosInt(u64), + /// Signed 64-bit integer value. The wrapped value is _always_ negative. + NegInt(i64), + /// 64-bit floating-point value. + Float(f64), +} + +/* ANCHOR_END: document */ + +impl Number { + /// Converts to an `f64` lossily. + /// Use `Number::try_from` to make the conversion only if it is not lossy. + pub fn to_f64_lossy(self) -> f64 { + match self { + Number::PosInt(v) => v as f64, + Number::NegInt(v) => v as f64, + Number::Float(v) => v, + } + } + + /// Converts to an `f32` lossily. + /// Use `Number::try_from` to make the conversion only if it is not lossy. + pub fn to_f32_lossy(self) -> f32 { + match self { + Number::PosInt(v) => v as f32, + Number::NegInt(v) => v as f32, + Number::Float(v) => v as f32, + } + } +} + +macro_rules! to_unsigned_integer_converter { + ($typ:ident, $styp:expr) => { + #[doc = "Converts to a `"] + #[doc = $styp] + #[doc = "`. This conversion fails if it is lossy."] + impl TryFrom for $typ { + type Error = TryFromNumberError; + + fn try_from(value: Number) -> Result { + match value { + Number::PosInt(v) => Ok(Self::try_from(v)?), + Number::NegInt(v) => { + Err(TryFromNumberErrorKind::NegativeToUnsignedLossyConversion(v).into()) + } + Number::Float(v) => { + Err(TryFromNumberErrorKind::FloatToIntegerLossyConversion(v).into()) + } + } + } + } + }; + + ($typ:ident) => { + to_unsigned_integer_converter!($typ, stringify!($typ)); + }; +} + +macro_rules! to_signed_integer_converter { + ($typ:ident, $styp:expr) => { + #[doc = "Converts to a `"] + #[doc = $styp] + #[doc = "`. This conversion fails if it is lossy."] + impl TryFrom for $typ { + type Error = TryFromNumberError; + + fn try_from(value: Number) -> Result { + match value { + Number::PosInt(v) => Ok(Self::try_from(v)?), + Number::NegInt(v) => Ok(Self::try_from(v)?), + Number::Float(v) => { + Err(TryFromNumberErrorKind::FloatToIntegerLossyConversion(v).into()) + } + } + } + } + }; + + ($typ:ident) => { + to_signed_integer_converter!($typ, stringify!($typ)); + }; +} + +/// Converts to a `u64`. The conversion fails if it is lossy. +impl TryFrom for u64 { + type Error = TryFromNumberError; + + fn try_from(value: Number) -> Result { + match value { + Number::PosInt(v) => Ok(v), + Number::NegInt(v) => { + Err(TryFromNumberErrorKind::NegativeToUnsignedLossyConversion(v).into()) + } + Number::Float(v) => { + Err(TryFromNumberErrorKind::FloatToIntegerLossyConversion(v).into()) + } + } + } +} +to_unsigned_integer_converter!(u32); +to_unsigned_integer_converter!(u16); +to_unsigned_integer_converter!(u8); + +impl TryFrom for i64 { + type Error = TryFromNumberError; + + fn try_from(value: Number) -> Result { + match value { + Number::PosInt(v) => Ok(Self::try_from(v)?), + Number::NegInt(v) => Ok(v), + Number::Float(v) => { + Err(TryFromNumberErrorKind::FloatToIntegerLossyConversion(v).into()) + } + } + } +} +to_signed_integer_converter!(i32); +to_signed_integer_converter!(i16); +to_signed_integer_converter!(i8); + +/// Converts to an `f64`. The conversion fails if it is lossy. +impl TryFrom for f64 { + type Error = TryFromNumberError; + + fn try_from(value: Number) -> Result { + match value { + // Integers can only be represented with full precision in a float if they fit in the + // significand, which is 24 bits in `f32` and 53 bits in `f64`. + // https://github.com/rust-lang/rust/blob/58f11791af4f97572e7afd83f11cffe04bbbd12f/library/core/src/convert/num.rs#L151-L153 + Number::PosInt(v) => { + if v <= (1 << 53) { + Ok(v as Self) + } else { + Err(TryFromNumberErrorKind::U64ToFloatLossyConversion(v).into()) + } + } + Number::NegInt(v) => { + if (-(1 << 53)..=(1 << 53)).contains(&v) { + Ok(v as Self) + } else { + Err(TryFromNumberErrorKind::I64ToFloatLossyConversion(v).into()) + } + } + Number::Float(v) => Ok(v), + } + } +} + +/// Converts to an `f64`. The conversion fails if it is lossy. +impl TryFrom for f32 { + type Error = TryFromNumberError; + + fn try_from(value: Number) -> Result { + match value { + Number::PosInt(v) => { + if v <= (1 << 24) { + Ok(v as Self) + } else { + Err(TryFromNumberErrorKind::U64ToFloatLossyConversion(v).into()) + } + } + Number::NegInt(v) => { + if (-(1 << 24)..=(1 << 24)).contains(&v) { + Ok(v as Self) + } else { + Err(TryFromNumberErrorKind::I64ToFloatLossyConversion(v).into()) + } + } + Number::Float(v) => Err(TryFromNumberErrorKind::F64ToF32LossyConversion(v).into()), + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; + + macro_rules! to_unsigned_converter_tests { + ($typ:ident) => { + assert_eq!($typ::try_from(Number::PosInt(69u64)).unwrap(), 69); + + assert!(matches!( + $typ::try_from(Number::PosInt(($typ::MAX as u64) + 1u64)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::OutsideIntegerRange(..) + } + )); + + assert!(matches!( + $typ::try_from(Number::NegInt(-1i64)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::NegativeToUnsignedLossyConversion(..) + } + )); + + for val in [69.69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { + assert!(matches!( + $typ::try_from(Number::Float(val)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::FloatToIntegerLossyConversion(..) + } + )); + } + }; + } + + #[test] + fn to_u64() { + assert_eq!(u64::try_from(Number::PosInt(69u64)).unwrap(), 69u64); + + assert!(matches!( + u64::try_from(Number::NegInt(-1i64)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::NegativeToUnsignedLossyConversion(..) + } + )); + + for val in [69.69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { + assert!(matches!( + u64::try_from(Number::Float(val)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::FloatToIntegerLossyConversion(..) + } + )); + } + } + + #[test] + fn to_u32() { + to_unsigned_converter_tests!(u32); + } + + #[test] + fn to_u16() { + to_unsigned_converter_tests!(u16); + } + + #[test] + fn to_u8() { + to_unsigned_converter_tests!(u8); + } + + macro_rules! to_signed_converter_tests { + ($typ:ident) => { + assert_eq!($typ::try_from(Number::PosInt(69u64)).unwrap(), 69); + assert_eq!($typ::try_from(Number::NegInt(-69i64)).unwrap(), -69); + + assert!(matches!( + $typ::try_from(Number::PosInt(($typ::MAX as u64) + 1u64)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::OutsideIntegerRange(..) + } + )); + + assert!(matches!( + $typ::try_from(Number::NegInt(($typ::MIN as i64) - 1i64)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::OutsideIntegerRange(..) + } + )); + + for val in [69.69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { + assert!(matches!( + u64::try_from(Number::Float(val)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::FloatToIntegerLossyConversion(..) + } + )); + } + }; + } + + #[test] + fn to_i64() { + assert_eq!(i64::try_from(Number::PosInt(69u64)).unwrap(), 69); + assert_eq!(i64::try_from(Number::NegInt(-69i64)).unwrap(), -69); + + for val in [69.69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { + assert!(matches!( + u64::try_from(Number::Float(val)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::FloatToIntegerLossyConversion(..) + } + )); + } + } + + #[test] + fn to_i32() { + to_signed_converter_tests!(i32); + } + + #[test] + fn to_i16() { + to_signed_converter_tests!(i16); + } + + #[test] + fn to_i8() { + to_signed_converter_tests!(i8); + } + + #[test] + fn to_f64() { + assert_eq!(f64::try_from(Number::PosInt(69u64)).unwrap(), 69f64); + assert_eq!(f64::try_from(Number::NegInt(-69i64)).unwrap(), -69f64); + assert_eq!(f64::try_from(Number::Float(-69f64)).unwrap(), -69f64); + assert!(f64::try_from(Number::Float(f64::NAN)).unwrap().is_nan()); + assert_eq!( + f64::try_from(Number::Float(f64::INFINITY)).unwrap(), + f64::INFINITY + ); + assert_eq!( + f64::try_from(Number::Float(f64::NEG_INFINITY)).unwrap(), + f64::NEG_INFINITY + ); + + let significand_max_u64: u64 = 1 << 53; + let significand_max_i64: i64 = 1 << 53; + + assert_eq!( + f64::try_from(Number::PosInt(significand_max_u64)).unwrap(), + 9007199254740992f64 + ); + + assert_eq!( + f64::try_from(Number::NegInt(significand_max_i64)).unwrap(), + 9007199254740992f64 + ); + assert_eq!( + f64::try_from(Number::NegInt(-significand_max_i64)).unwrap(), + -9007199254740992f64 + ); + + assert!(matches!( + f64::try_from(Number::PosInt(significand_max_u64 + 1)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::U64ToFloatLossyConversion(..) + } + )); + + assert!(matches!( + f64::try_from(Number::NegInt(significand_max_i64 + 1)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::I64ToFloatLossyConversion(..) + } + )); + assert!(matches!( + f64::try_from(Number::NegInt(-significand_max_i64 - 1)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::I64ToFloatLossyConversion(..) + } + )); + } + + #[test] + fn to_f32() { + assert_eq!(f32::try_from(Number::PosInt(69u64)).unwrap(), 69f32); + assert_eq!(f32::try_from(Number::NegInt(-69i64)).unwrap(), -69f32); + + let significand_max_u64: u64 = 1 << 24; + let significand_max_i64: i64 = 1 << 24; + + assert_eq!( + f32::try_from(Number::PosInt(significand_max_u64)).unwrap(), + 16777216f32 + ); + + assert_eq!( + f32::try_from(Number::NegInt(significand_max_i64)).unwrap(), + 16777216f32 + ); + assert_eq!( + f32::try_from(Number::NegInt(-significand_max_i64)).unwrap(), + -16777216f32 + ); + + assert!(matches!( + f32::try_from(Number::PosInt(significand_max_u64 + 1)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::U64ToFloatLossyConversion(..) + } + )); + + assert!(matches!( + f32::try_from(Number::NegInt(significand_max_i64 + 1)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::I64ToFloatLossyConversion(..) + } + )); + assert!(matches!( + f32::try_from(Number::NegInt(-significand_max_i64 - 1)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::I64ToFloatLossyConversion(..) + } + )); + + for val in [69f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY] { + assert!(matches!( + f32::try_from(Number::Float(val)).unwrap_err(), + TryFromNumberError { + kind: TryFromNumberErrorKind::F64ToF32LossyConversion(..) + } + )); + } + } + + #[test] + fn to_f64_lossy() { + assert_eq!(Number::PosInt(69u64).to_f64_lossy(), 69f64); + assert_eq!( + Number::PosInt((1 << 53) + 1).to_f64_lossy(), + 9007199254740992f64 + ); + assert_eq!( + Number::NegInt(-(1 << 53) - 1).to_f64_lossy(), + -9007199254740992f64 + ); + } + + #[test] + fn to_f32_lossy() { + assert_eq!(Number::PosInt(69u64).to_f32_lossy(), 69f32); + assert_eq!(Number::PosInt((1 << 24) + 1).to_f32_lossy(), 16777216f32); + assert_eq!(Number::NegInt(-(1 << 24) - 1).to_f32_lossy(), -16777216f32); + assert_eq!( + Number::Float(1452089033.7674935).to_f32_lossy(), + 1452089100f32 + ); + } + + #[test] + #[cfg(all( + test, + aws_sdk_unstable, + feature = "serde-deserialize", + feature = "serde-serialize" + ))] + /// ensures that numbers are deserialized as expected + /// 0 <= PosInt + /// 0 > NegInt + /// non integer values == Float + fn number_serde() { + let n: Number = serde_json::from_str("1.1").unwrap(); + assert_eq!(n, Number::Float(1.1)); + let n: Number = serde_json::from_str("1").unwrap(); + assert_eq!(n, Number::PosInt(1)); + let n: Number = serde_json::from_str("0").unwrap(); + assert_eq!(n, Number::PosInt(0)); + let n: Number = serde_json::from_str("-1").unwrap(); + assert_eq!(n, Number::NegInt(-1)); + + assert_eq!("1.1", serde_json::to_string(&Number::Float(1.1)).unwrap()); + assert_eq!("1", serde_json::to_string(&Number::PosInt(1)).unwrap()); + assert_eq!("0", serde_json::to_string(&Number::PosInt(0)).unwrap()); + assert_eq!("-1", serde_json::to_string(&Number::NegInt(-1)).unwrap()); + } +} From f7715fbffd056f5688dfd3970a94dfbeb0c78df1 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 20 Apr 2023 23:07:46 +0000 Subject: [PATCH 03/31] update lib.rs --- rust-runtime/aws-smithy-types/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rust-runtime/aws-smithy-types/src/lib.rs b/rust-runtime/aws-smithy-types/src/lib.rs index 3bfd303319..d7ec6337d3 100644 --- a/rust-runtime/aws-smithy-types/src/lib.rs +++ b/rust-runtime/aws-smithy-types/src/lib.rs @@ -28,5 +28,10 @@ pub mod timeout; pub use blob::Blob; pub use date_time::DateTime; pub use document::Document; +// TODO(deprecated): Remove deprecated re-export +/// Use [error::ErrorMetadata] instead. +#[deprecated( + note = "`aws_smithy_types::Error` has been renamed to `aws_smithy_types::error::ErrorMetadata`" +)] pub use error::ErrorMetadata as Error; pub use number::Number; From 8cf5e3ce573364cd0ab05020c682daf9d744f714 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 20 Apr 2023 23:08:07 +0000 Subject: [PATCH 04/31] remove unused imports --- rust-runtime/aws-smithy-types/src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rust-runtime/aws-smithy-types/src/lib.rs b/rust-runtime/aws-smithy-types/src/lib.rs index d7ec6337d3..eba2a3a3ac 100644 --- a/rust-runtime/aws-smithy-types/src/lib.rs +++ b/rust-runtime/aws-smithy-types/src/lib.rs @@ -13,10 +13,6 @@ rust_2018_idioms, unreachable_pub )] - -use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; -use std::collections::HashMap; - pub mod base64; pub mod date_time; pub mod endpoint; From eef5b35a22c4f3c70a7e2387c2cf129da637ef3f Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Fri, 21 Apr 2023 00:15:58 +0000 Subject: [PATCH 05/31] - add RUSTFLAGS --- buildSrc/src/main/kotlin/CodegenTestCommon.kt | 4 ++++ buildSrc/src/main/kotlin/RustBuildTool.kt | 1 + 2 files changed, 5 insertions(+) diff --git a/buildSrc/src/main/kotlin/CodegenTestCommon.kt b/buildSrc/src/main/kotlin/CodegenTestCommon.kt index 2173c237a6..e42d7e5ed2 100644 --- a/buildSrc/src/main/kotlin/CodegenTestCommon.kt +++ b/buildSrc/src/main/kotlin/CodegenTestCommon.kt @@ -244,12 +244,14 @@ fun Project.registerCargoCommandsTasks( this.tasks.register(Cargo.CHECK.toString) { dependsOn(dependentTasks) workingDir(outputDir) + environment("RUSTFLAGS", "--cfg aws_sdk_unstable") commandLine("cargo", "check", "--lib", "--tests", "--benches", "--all-features") } this.tasks.register(Cargo.TEST.toString) { dependsOn(dependentTasks) workingDir(outputDir) + environment("RUSTFLAGS", "--cfg aws_sdk_unstable") commandLine("cargo", "test", "--all-features") } @@ -257,12 +259,14 @@ fun Project.registerCargoCommandsTasks( dependsOn(dependentTasks) workingDir(outputDir) environment("RUSTDOCFLAGS", defaultRustDocFlags) + environment("RUSTFLAGS", "--cfg aws_sdk_unstable") commandLine("cargo", "doc", "--no-deps", "--document-private-items") } this.tasks.register(Cargo.CLIPPY.toString) { dependsOn(dependentTasks) workingDir(outputDir) + environment("RUSTFLAGS", "--cfg aws_sdk_unstable") commandLine("cargo", "clippy") } } diff --git a/buildSrc/src/main/kotlin/RustBuildTool.kt b/buildSrc/src/main/kotlin/RustBuildTool.kt index 1e67995648..b8a1a15fb1 100644 --- a/buildSrc/src/main/kotlin/RustBuildTool.kt +++ b/buildSrc/src/main/kotlin/RustBuildTool.kt @@ -28,6 +28,7 @@ private fun runCli( } } .copyTo(action) + action.environment("RUSTFLAGS", "--cfg aws_sdk_unstable") action.execute() } } From c203d2e3eed2b989281346455757a467329fbfa2 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Fri, 21 Apr 2023 01:40:07 +0000 Subject: [PATCH 06/31] FIX --- rust-runtime/aws-smithy-types/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/rust-runtime/aws-smithy-types/src/lib.rs b/rust-runtime/aws-smithy-types/src/lib.rs index eba2a3a3ac..5042988f60 100644 --- a/rust-runtime/aws-smithy-types/src/lib.rs +++ b/rust-runtime/aws-smithy-types/src/lib.rs @@ -21,6 +21,10 @@ pub mod primitive; pub mod retry; pub mod timeout; +mod blob; +mod number; +mod document; + pub use blob::Blob; pub use date_time::DateTime; pub use document::Document; From 17ab7ffa0306c78c40c0b6ac963d5666eef2ca26 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Fri, 21 Apr 2023 08:39:10 +0000 Subject: [PATCH 07/31] serde support for error metadata --- .../aws-smithy-types/src/error/metadata.rs | 56 +++++++++++++++++++ .../test_data/error_meta_data.json | 7 +++ .../test_data/error_meta_data_empty.json | 5 ++ 3 files changed, 68 insertions(+) create mode 100644 rust-runtime/aws-smithy-types/test_data/error_meta_data.json create mode 100644 rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json diff --git a/rust-runtime/aws-smithy-types/src/error/metadata.rs b/rust-runtime/aws-smithy-types/src/error/metadata.rs index 06925e13f9..70fdc999d7 100644 --- a/rust-runtime/aws-smithy-types/src/error/metadata.rs +++ b/rust-runtime/aws-smithy-types/src/error/metadata.rs @@ -39,6 +39,14 @@ pub const EMPTY_ERROR_METADATA: ErrorMetadata = ErrorMetadata { /// For many services, Errors are modeled. However, many services only partially model errors or don't /// model errors at all. In these cases, the SDK will return this generic error type to expose the /// `code`, `message` and `request_id`. +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-serialize"), + derive(serde::Serialize) +)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-deserialize"), + derive(serde::Deserialize) +)] #[derive(Debug, Eq, PartialEq, Default, Clone)] pub struct ErrorMetadata { code: Option, @@ -47,8 +55,23 @@ pub struct ErrorMetadata { } /// Builder for [`ErrorMetadata`]. +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-serialize"), + derive(serde::Serialize) +)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-deserialize"), + derive(serde::Deserialize) +)] #[derive(Debug, Default)] pub struct Builder { + #[cfg_attr( + any( + all(aws_sdk_unstable, feature = "serde-deserialize"), + all(aws_sdk_unstable, feature = "serde-serialize") + ), + serde(flatten) + )] inner: ErrorMetadata, } @@ -164,3 +187,36 @@ impl fmt::Display for ErrorMetadata { } impl std::error::Error for ErrorMetadata {} + +#[cfg(all( + test, + any( + all(aws_sdk_unstable, feature = "serde-deserialize"), + all(aws_sdk_unstable, feature = "serde-serialize") + ) +))] +mod test { + use super::*; + + #[test] + /// tests de/ser on ErrorMetaData. + fn test_error_meta_data() { + let mut data = Builder::default() + .code("code") + .message("message") + .custom("hello", "world"); + let ok = serde_json::to_string_pretty(&EMPTY_ERROR_METADATA).unwrap(); + assert_eq!( + &ok, + include_str!("../../test-data/error_meta_data_empty.json") + ); + assert_eq!( + serde_json::from_str(include_str!("../../test-data/error_meta_data.json")).unwrap(), + &data + ); + assert_eq!( + serde_json::from_str(include_str!("../../test-data/error_meta_data.json")).unwrap(), + data.build() + ); + } +} diff --git a/rust-runtime/aws-smithy-types/test_data/error_meta_data.json b/rust-runtime/aws-smithy-types/test_data/error_meta_data.json new file mode 100644 index 0000000000..db7067d86e --- /dev/null +++ b/rust-runtime/aws-smithy-types/test_data/error_meta_data.json @@ -0,0 +1,7 @@ +{ + "code": "code", + "message": "message", + "extras": { + "hello": "world" + } +} diff --git a/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json b/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json new file mode 100644 index 0000000000..41165f4a49 --- /dev/null +++ b/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json @@ -0,0 +1,5 @@ +{ + "code": null, + "message": null, + "extras": null +} From 81ccbbf992735930d358a54259e06116e34afa7a Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Wed, 26 Apr 2023 11:09:48 +0000 Subject: [PATCH 08/31] chore: update CHANGELOG.next.toml --- CHANGELOG.next.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 1832de5613..3856c9e46d 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -11,6 +11,13 @@ # meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client | server | all"} # author = "rcoh" + +[[aws-sdk-rust]] +message = "Implements serde support for ErrorMetaData on aws-smithy-types crate." +references = ["smithy-rs#2637"] +meta = { "breaking" = false, "tada" = false, "bug" = true } +author = "thomas-k-cameron" + [[aws-sdk-rust]] message = "The outputs for event stream operations (for example, S3's SelectObjectContent) now implement the `Sync` auto-trait." references = ["smithy-rs#2496"] From 5747deb8a069ca3451c162c8713ce27dba7da6fa Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Wed, 26 Apr 2023 11:10:27 +0000 Subject: [PATCH 09/31] Merge commit 'eef5b35a22c4f3c70a7e2387c2cf129da637ef3f' --- buildSrc/src/main/kotlin/CodegenTestCommon.kt | 4 ++++ buildSrc/src/main/kotlin/RustBuildTool.kt | 1 + 2 files changed, 5 insertions(+) diff --git a/buildSrc/src/main/kotlin/CodegenTestCommon.kt b/buildSrc/src/main/kotlin/CodegenTestCommon.kt index 2173c237a6..e42d7e5ed2 100644 --- a/buildSrc/src/main/kotlin/CodegenTestCommon.kt +++ b/buildSrc/src/main/kotlin/CodegenTestCommon.kt @@ -244,12 +244,14 @@ fun Project.registerCargoCommandsTasks( this.tasks.register(Cargo.CHECK.toString) { dependsOn(dependentTasks) workingDir(outputDir) + environment("RUSTFLAGS", "--cfg aws_sdk_unstable") commandLine("cargo", "check", "--lib", "--tests", "--benches", "--all-features") } this.tasks.register(Cargo.TEST.toString) { dependsOn(dependentTasks) workingDir(outputDir) + environment("RUSTFLAGS", "--cfg aws_sdk_unstable") commandLine("cargo", "test", "--all-features") } @@ -257,12 +259,14 @@ fun Project.registerCargoCommandsTasks( dependsOn(dependentTasks) workingDir(outputDir) environment("RUSTDOCFLAGS", defaultRustDocFlags) + environment("RUSTFLAGS", "--cfg aws_sdk_unstable") commandLine("cargo", "doc", "--no-deps", "--document-private-items") } this.tasks.register(Cargo.CLIPPY.toString) { dependsOn(dependentTasks) workingDir(outputDir) + environment("RUSTFLAGS", "--cfg aws_sdk_unstable") commandLine("cargo", "clippy") } } diff --git a/buildSrc/src/main/kotlin/RustBuildTool.kt b/buildSrc/src/main/kotlin/RustBuildTool.kt index 1e67995648..b8a1a15fb1 100644 --- a/buildSrc/src/main/kotlin/RustBuildTool.kt +++ b/buildSrc/src/main/kotlin/RustBuildTool.kt @@ -28,6 +28,7 @@ private fun runCli( } } .copyTo(action) + action.environment("RUSTFLAGS", "--cfg aws_sdk_unstable") action.execute() } } From 6edcd1a418d73c1a6b4244bace78856d5d1a2fa5 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Wed, 26 Apr 2023 11:19:21 +0000 Subject: [PATCH 10/31] chore: update CHANGELOG.next.toml --- CHANGELOG.next.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 29b405f52a..dbb4772750 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -11,12 +11,6 @@ # meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "client | server | all"} # author = "rcoh" -[[aws-sdk-rust]] -message = "Implements serde support for ErrorMetaData on aws-smithy-types crate." -references = ["smithy-rs#2637"] -meta = { "breaking" = false, "tada" = false, "bug" = true } -author = "thomas-k-cameron" - [[smithy-rs]] message = """ Implement layer for servers to handle [ALB health checks](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html). @@ -177,3 +171,9 @@ message = "Update MSRV to Rust 1.67.1" references = ["smithy-rs#2611"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} author = "jdisanti" + +[[smithy-rs]] +message = "Add RUSTFLAGS = aws_sdk_unstable as environment variable when running Cargo from kotlin." +references = ["smithy-rs#2614"] +meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} +author = "thomas-k-cameron" From b219038472291c9741bc6ebda7ea32a97de1c451 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Wed, 26 Apr 2023 11:36:34 +0000 Subject: [PATCH 11/31] update --- rust-runtime/aws-smithy-types/Cargo.toml | 5 + rust-runtime/aws-smithy-types/src/blob.rs | 2 +- .../aws-smithy-types/src/date_time/de.rs | 110 ++++++++++++++++++ .../aws-smithy-types/src/date_time/ser.rs | 27 +++++ rust-runtime/aws-smithy-types/src/document.rs | 6 +- .../aws-smithy-types/src/error/metadata.rs | 48 ++++++++ rust-runtime/aws-smithy-types/src/lib.rs | 2 +- .../test_data/error_meta_data.json | 7 ++ .../test_data/error_meta_data_empty.json | 5 + .../test_data/serialize_document.json | 43 +++++++ 10 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 rust-runtime/aws-smithy-types/src/date_time/de.rs create mode 100644 rust-runtime/aws-smithy-types/src/date_time/ser.rs create mode 100644 rust-runtime/aws-smithy-types/test_data/error_meta_data.json create mode 100644 rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json create mode 100644 rust-runtime/aws-smithy-types/test_data/serialize_document.json diff --git a/rust-runtime/aws-smithy-types/Cargo.toml b/rust-runtime/aws-smithy-types/Cargo.toml index a0a62f4bf4..b2992210ab 100644 --- a/rust-runtime/aws-smithy-types/Cargo.toml +++ b/rust-runtime/aws-smithy-types/Cargo.toml @@ -27,6 +27,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" criterion = "0.4" rand = "0.8.4" +ciborium = "0.2.0" [package.metadata.docs.rs] all-features = true @@ -37,3 +38,7 @@ rustdoc-args = ["--cfg", "docsrs"] [[bench]] name = "base64" harness = false + +[features] +serde-serialize = [] +serde-deserialize = [] diff --git a/rust-runtime/aws-smithy-types/src/blob.rs b/rust-runtime/aws-smithy-types/src/blob.rs index 0364727d4f..f4f1da94d8 100644 --- a/rust-runtime/aws-smithy-types/src/blob.rs +++ b/rust-runtime/aws-smithy-types/src/blob.rs @@ -70,7 +70,7 @@ impl<'de> Visitor<'de> for HumanReadableBlobVisitor { { match base64::decode(v) { Ok(inner) => Ok(Blob { inner }), - Err(e) => Err(serde::de::Error::custom(e)), + Err(e) => Err(E::custom(e)), } } } diff --git a/rust-runtime/aws-smithy-types/src/date_time/de.rs b/rust-runtime/aws-smithy-types/src/date_time/de.rs new file mode 100644 index 0000000000..6f346ea8de --- /dev/null +++ b/rust-runtime/aws-smithy-types/src/date_time/de.rs @@ -0,0 +1,110 @@ +/* + * 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(err_message: M) -> Result +where + M: std::fmt::Display, + E: serde::de::Error, +{ + Err(E::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(self, v: &str) -> Result + 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(mut self, v: i64) -> Result + 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(mut self, v: u32) -> Result + 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(deserializer: D) -> Result + 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, + }) + } + } +} diff --git a/rust-runtime/aws-smithy-types/src/date_time/ser.rs b/rust-runtime/aws-smithy-types/src/date_time/ser.rs new file mode 100644 index 0000000000..bd8ed29a04 --- /dev/null +++ b/rust-runtime/aws-smithy-types/src/date_time/ser.rs @@ -0,0 +1,27 @@ +/* + * 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(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::Error; + if serializer.is_human_readable() { + match self.fmt(Format::DateTime) { + Ok(val) => serializer.serialize_str(&val), + Err(e) => Err(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() + } + } +} diff --git a/rust-runtime/aws-smithy-types/src/document.rs b/rust-runtime/aws-smithy-types/src/document.rs index 8cbae5b380..9515d26c2d 100644 --- a/rust-runtime/aws-smithy-types/src/document.rs +++ b/rust-runtime/aws-smithy-types/src/document.rs @@ -4,8 +4,12 @@ */ use crate::Number; +#[cfg(any( + all(aws_sdk_unstable, feature = "serde-deserialize"), + all(aws_sdk_unstable, feature = "serde-serialize") +))] +use serde; use std::collections::HashMap; - /* ANCHOR: document */ /// Document Type diff --git a/rust-runtime/aws-smithy-types/src/error/metadata.rs b/rust-runtime/aws-smithy-types/src/error/metadata.rs index 94af60aaf9..5681fb1d02 100644 --- a/rust-runtime/aws-smithy-types/src/error/metadata.rs +++ b/rust-runtime/aws-smithy-types/src/error/metadata.rs @@ -62,8 +62,23 @@ impl ProvideErrorMetadata for ErrorMetadata { } /// Builder for [`ErrorMetadata`]. +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-serialize"), + derive(serde::Serialize) +)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-deserialize"), + derive(serde::Deserialize) +)] #[derive(Debug, Default)] pub struct Builder { + #[cfg_attr( + any( + all(aws_sdk_unstable, feature = "serde-deserialize"), + all(aws_sdk_unstable, feature = "serde-serialize") + ), + serde(flatten) + )] inner: ErrorMetadata, } @@ -179,3 +194,36 @@ impl fmt::Display for ErrorMetadata { } impl std::error::Error for ErrorMetadata {} + +#[cfg(all( + test, + any( + all(aws_sdk_unstable, feature = "serde-deserialize"), + all(aws_sdk_unstable, feature = "serde-serialize") + ) +))] +mod test { + use super::*; + + #[test] + /// tests de/ser on ErrorMetaData. + fn test_error_meta_data() { + let mut data = Builder::default() + .code("code") + .message("message") + .custom("hello", "world"); + let ok = serde_json::to_string_pretty(&EMPTY_ERROR_METADATA).unwrap(); + assert_eq!( + &ok, + include_str!("../../test-data/error_meta_data_empty.json") + ); + assert_eq!( + serde_json::from_str(include_str!("../../test-data/error_meta_data.json")).unwrap(), + &data + ); + assert_eq!( + serde_json::from_str(include_str!("../../test-data/error_meta_data.json")).unwrap(), + data.build() + ); + } +} diff --git a/rust-runtime/aws-smithy-types/src/lib.rs b/rust-runtime/aws-smithy-types/src/lib.rs index 5042988f60..ffa1c86ea5 100644 --- a/rust-runtime/aws-smithy-types/src/lib.rs +++ b/rust-runtime/aws-smithy-types/src/lib.rs @@ -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; diff --git a/rust-runtime/aws-smithy-types/test_data/error_meta_data.json b/rust-runtime/aws-smithy-types/test_data/error_meta_data.json new file mode 100644 index 0000000000..db7067d86e --- /dev/null +++ b/rust-runtime/aws-smithy-types/test_data/error_meta_data.json @@ -0,0 +1,7 @@ +{ + "code": "code", + "message": "message", + "extras": { + "hello": "world" + } +} diff --git a/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json b/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json new file mode 100644 index 0000000000..41165f4a49 --- /dev/null +++ b/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json @@ -0,0 +1,5 @@ +{ + "code": null, + "message": null, + "extras": null +} diff --git a/rust-runtime/aws-smithy-types/test_data/serialize_document.json b/rust-runtime/aws-smithy-types/test_data/serialize_document.json new file mode 100644 index 0000000000..dcbac2986a --- /dev/null +++ b/rust-runtime/aws-smithy-types/test_data/serialize_document.json @@ -0,0 +1,43 @@ +{ + "null": null, + "true": true, + "pos_int": 1, + "false": false, + "map": { + "array": [ + { + "pos_int": 1, + "float": 0.30000000000000004, + "neg_int": -1, + "hello": "world", + "false": false, + "true": true + }, + "hello-world", + true, + false + ], + "pos_int": 1, + "float": 0.30000000000000004, + "neg_int": -1, + "hello": "world", + "false": false, + "true": true + }, + "float": 0.30000000000000004, + "neg_int": -1, + "hello": "world", + "array": [ + { + "pos_int": 1, + "float": 0.30000000000000004, + "neg_int": -1, + "hello": "world", + "false": false, + "true": true + }, + "hello-world", + true, + false + ] +} From 6138ccdcc88e2a24db95247b7cb026f50e4e31a5 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Wed, 26 Apr 2023 11:43:58 +0000 Subject: [PATCH 12/31] chore: update CHANGELOG.next.toml --- CHANGELOG.next.toml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index dbb4772750..4c4ad74ff9 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -177,3 +177,21 @@ message = "Add RUSTFLAGS = aws_sdk_unstable as environment variable when running references = ["smithy-rs#2614"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} author = "thomas-k-cameron" + +[[smithy-rs]] +message = """ +- Implements serde support to Number, Blob, Document, DateTime and ErrorMetaData. +- &'static str on Error type is replaced with Cow to allow serde support. No breaking changes are introduced. +""" +references = ["smithy-rs#2616"] +meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} +author = "thomas-k-cameron" + +[[aws-sdk-rust]] +message = """ +- Implements serde support to Number, Blob, Document, DateTime and ErrorMetaData. +- &'static str on Error type is replaced with Cow to allow serde support. No breaking changes are introduced. +""" +references = ["smithy-rs#2616"] +meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} +author = "thomas-k-cameron" From caaa19355cf5578ae377f1438e1b78221d2add7d Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Wed, 26 Apr 2023 22:06:21 +0900 Subject: [PATCH 13/31] Update CHANGELOG.next.toml --- CHANGELOG.next.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 4c4ad74ff9..4b112c2f04 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -175,7 +175,7 @@ author = "jdisanti" [[smithy-rs]] message = "Add RUSTFLAGS = aws_sdk_unstable as environment variable when running Cargo from kotlin." references = ["smithy-rs#2614"] -meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} +meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "all"} author = "thomas-k-cameron" [[smithy-rs]] @@ -184,7 +184,7 @@ message = """ - &'static str on Error type is replaced with Cow to allow serde support. No breaking changes are introduced. """ references = ["smithy-rs#2616"] -meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} +meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "all"} author = "thomas-k-cameron" [[aws-sdk-rust]] @@ -193,5 +193,5 @@ message = """ - &'static str on Error type is replaced with Cow to allow serde support. No breaking changes are introduced. """ references = ["smithy-rs#2616"] -meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} +meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "all"} author = "thomas-k-cameron" From 8b3b6407ef8db13aaf4b27b8cf30b09f211e68a4 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Wed, 26 Apr 2023 22:33:34 +0900 Subject: [PATCH 14/31] Update CHANGELOG.next.toml --- CHANGELOG.next.toml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 4b112c2f04..3686ce2182 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -172,12 +172,6 @@ references = ["smithy-rs#2611"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "all"} author = "jdisanti" -[[smithy-rs]] -message = "Add RUSTFLAGS = aws_sdk_unstable as environment variable when running Cargo from kotlin." -references = ["smithy-rs#2614"] -meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "all"} -author = "thomas-k-cameron" - [[smithy-rs]] message = """ - Implements serde support to Number, Blob, Document, DateTime and ErrorMetaData. From de7971ff1500abef3031471898f8cc9120c3b740 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Thu, 27 Apr 2023 02:01:50 +0000 Subject: [PATCH 15/31] Add serde support to number type --- rust-runtime/aws-smithy-types/src/number.rs | 55 ++++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/rust-runtime/aws-smithy-types/src/number.rs b/rust-runtime/aws-smithy-types/src/number.rs index 76fc08a218..680e382592 100644 --- a/rust-runtime/aws-smithy-types/src/number.rs +++ b/rust-runtime/aws-smithy-types/src/number.rs @@ -3,11 +3,35 @@ * SPDX-License-Identifier: Apache-2.0 */ +//! A number type that implements Javascript / JSON semantics, modeled on serde_json: +//! + +use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; +#[cfg(all( + aws_sdk_unstable, + any(feature = "serde-serialize", feature = "serde-deserialize") +))] +use serde; use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; /// A number type that implements Javascript / JSON semantics, modeled on serde_json: /// #[derive(Debug, Clone, Copy, PartialEq)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-deserialize"), + derive(serde::Deserialize) +)] +#[cfg_attr( + all(aws_sdk_unstable, feature = "serde-serialize"), + derive(serde::Serialize) +)] +#[cfg_attr( + any( + all(aws_sdk_unstable, feature = "serde-deserialize"), + all(aws_sdk_unstable, feature = "serde-serialize") + ), + serde(untagged) +)] pub enum Number { /// Unsigned 64-bit integer value. PosInt(u64), @@ -184,7 +208,7 @@ impl TryFrom for f32 { } #[cfg(test)] -mod number { +mod test { use super::*; use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; @@ -441,4 +465,31 @@ mod number { 1452089100f32 ); } -} + + #[test] + #[cfg(all( + test, + aws_sdk_unstable, + feature = "serde-deserialize", + feature = "serde-serialize" + ))] + /// ensures that numbers are deserialized as expected + /// 0 <= PosInt + /// 0 > NegInt + /// non integer values == Float + fn number_serde() { + let n: Number = serde_json::from_str("1.1").unwrap(); + assert_eq!(n, Number::Float(1.1)); + let n: Number = serde_json::from_str("1").unwrap(); + assert_eq!(n, Number::PosInt(1)); + let n: Number = serde_json::from_str("0").unwrap(); + assert_eq!(n, Number::PosInt(0)); + let n: Number = serde_json::from_str("-1").unwrap(); + assert_eq!(n, Number::NegInt(-1)); + + assert_eq!("1.1", serde_json::to_string(&Number::Float(1.1)).unwrap()); + assert_eq!("1", serde_json::to_string(&Number::PosInt(1)).unwrap()); + assert_eq!("0", serde_json::to_string(&Number::PosInt(0)).unwrap()); + assert_eq!("-1", serde_json::to_string(&Number::NegInt(-1)).unwrap()); + } +} \ No newline at end of file From bf7347a1e8d062704f3b6ccc2ddf1abdbbe35324 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Thu, 27 Apr 2023 02:15:09 +0000 Subject: [PATCH 16/31] pre-commit --- rust-runtime/aws-smithy-types/src/number.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rust-runtime/aws-smithy-types/src/number.rs b/rust-runtime/aws-smithy-types/src/number.rs index 680e382592..80527cfc10 100644 --- a/rust-runtime/aws-smithy-types/src/number.rs +++ b/rust-runtime/aws-smithy-types/src/number.rs @@ -12,7 +12,6 @@ use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; any(feature = "serde-serialize", feature = "serde-deserialize") ))] use serde; -use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; /// A number type that implements Javascript / JSON semantics, modeled on serde_json: /// @@ -492,4 +491,4 @@ mod test { assert_eq!("0", serde_json::to_string(&Number::PosInt(0)).unwrap()); assert_eq!("-1", serde_json::to_string(&Number::NegInt(-1)).unwrap()); } -} \ No newline at end of file +} From 6e4b68a061637f7407be2cc633d43be24e4225e7 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 27 Apr 2023 11:17:01 +0900 Subject: [PATCH 17/31] Update number.rs --- rust-runtime/aws-smithy-types/src/number.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-types/src/number.rs b/rust-runtime/aws-smithy-types/src/number.rs index 80527cfc10..5ae57a0810 100644 --- a/rust-runtime/aws-smithy-types/src/number.rs +++ b/rust-runtime/aws-smithy-types/src/number.rs @@ -207,7 +207,7 @@ impl TryFrom for f32 { } #[cfg(test)] -mod test { +mod number { use super::*; use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; From d89e8f473896a6e54d8321554d4e8f4eb8141b88 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:17:12 +0900 Subject: [PATCH 18/31] Update metadata.rs --- .../aws-smithy-types/src/error/metadata.rs | 61 +------------------ 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/rust-runtime/aws-smithy-types/src/error/metadata.rs b/rust-runtime/aws-smithy-types/src/error/metadata.rs index 5681fb1d02..25aa4e1eb4 100644 --- a/rust-runtime/aws-smithy-types/src/error/metadata.rs +++ b/rust-runtime/aws-smithy-types/src/error/metadata.rs @@ -6,7 +6,6 @@ //! Error metadata use crate::retry::{ErrorKind, ProvideErrorKind}; -use std::borrow::Cow; use std::collections::HashMap; use std::fmt; @@ -40,19 +39,11 @@ pub const EMPTY_ERROR_METADATA: ErrorMetadata = ErrorMetadata { /// For many services, Errors are modeled. However, many services only partially model errors or don't /// model errors at all. In these cases, the SDK will return this generic error type to expose the /// `code`, `message` and `request_id`. -#[cfg_attr( - all(aws_sdk_unstable, feature = "serde-serialize"), - derive(serde::Serialize) -)] -#[cfg_attr( - all(aws_sdk_unstable, feature = "serde-deserialize"), - derive(serde::Deserialize) -)] #[derive(Debug, Eq, PartialEq, Default, Clone)] pub struct ErrorMetadata { code: Option, message: Option, - extras: Option, String>>, + extras: Option } impl ProvideErrorMetadata for ErrorMetadata { @@ -62,23 +53,8 @@ impl ProvideErrorMetadata for ErrorMetadata { } /// Builder for [`ErrorMetadata`]. -#[cfg_attr( - all(aws_sdk_unstable, feature = "serde-serialize"), - derive(serde::Serialize) -)] -#[cfg_attr( - all(aws_sdk_unstable, feature = "serde-deserialize"), - derive(serde::Deserialize) -)] #[derive(Debug, Default)] pub struct Builder { - #[cfg_attr( - any( - all(aws_sdk_unstable, feature = "serde-deserialize"), - all(aws_sdk_unstable, feature = "serde-serialize") - ), - serde(flatten) - )] inner: ErrorMetadata, } @@ -128,7 +104,7 @@ impl Builder { .extras .as_mut() .unwrap() - .insert(Cow::Borrowed(key), value.into()); + .insert(key, value.into()); self } @@ -194,36 +170,3 @@ impl fmt::Display for ErrorMetadata { } impl std::error::Error for ErrorMetadata {} - -#[cfg(all( - test, - any( - all(aws_sdk_unstable, feature = "serde-deserialize"), - all(aws_sdk_unstable, feature = "serde-serialize") - ) -))] -mod test { - use super::*; - - #[test] - /// tests de/ser on ErrorMetaData. - fn test_error_meta_data() { - let mut data = Builder::default() - .code("code") - .message("message") - .custom("hello", "world"); - let ok = serde_json::to_string_pretty(&EMPTY_ERROR_METADATA).unwrap(); - assert_eq!( - &ok, - include_str!("../../test-data/error_meta_data_empty.json") - ); - assert_eq!( - serde_json::from_str(include_str!("../../test-data/error_meta_data.json")).unwrap(), - &data - ); - assert_eq!( - serde_json::from_str(include_str!("../../test-data/error_meta_data.json")).unwrap(), - data.build() - ); - } -} From 3d62a68987950506bb74ec43858b6e3a270ba020 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:18:57 +0900 Subject: [PATCH 19/31] Update metadata.rs --- rust-runtime/aws-smithy-types/src/error/metadata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-types/src/error/metadata.rs b/rust-runtime/aws-smithy-types/src/error/metadata.rs index 25aa4e1eb4..5cc044a173 100644 --- a/rust-runtime/aws-smithy-types/src/error/metadata.rs +++ b/rust-runtime/aws-smithy-types/src/error/metadata.rs @@ -43,7 +43,7 @@ pub const EMPTY_ERROR_METADATA: ErrorMetadata = ErrorMetadata { pub struct ErrorMetadata { code: Option, message: Option, - extras: Option + extras: Option, } impl ProvideErrorMetadata for ErrorMetadata { From 5d850d938ecc288724aa4e6aee11cad8d6afda98 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:39:38 +0900 Subject: [PATCH 20/31] Update metadata.rs --- rust-runtime/aws-smithy-types/src/error/metadata.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-types/src/error/metadata.rs b/rust-runtime/aws-smithy-types/src/error/metadata.rs index 5cc044a173..6629753733 100644 --- a/rust-runtime/aws-smithy-types/src/error/metadata.rs +++ b/rust-runtime/aws-smithy-types/src/error/metadata.rs @@ -43,7 +43,7 @@ pub const EMPTY_ERROR_METADATA: ErrorMetadata = ErrorMetadata { pub struct ErrorMetadata { code: Option, message: Option, - extras: Option, + extras: Option>, } impl ProvideErrorMetadata for ErrorMetadata { From e27abc135ac42ad417d147266c9e4c3a8ab88074 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:39:58 +0900 Subject: [PATCH 21/31] Delete error_meta_data.json --- .../aws-smithy-types/test_data/error_meta_data.json | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 rust-runtime/aws-smithy-types/test_data/error_meta_data.json diff --git a/rust-runtime/aws-smithy-types/test_data/error_meta_data.json b/rust-runtime/aws-smithy-types/test_data/error_meta_data.json deleted file mode 100644 index db7067d86e..0000000000 --- a/rust-runtime/aws-smithy-types/test_data/error_meta_data.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "code": "code", - "message": "message", - "extras": { - "hello": "world" - } -} From b69160d73652a89a437612e260810ec35b7fcee9 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:40:12 +0900 Subject: [PATCH 22/31] Delete error_meta_data_empty.json --- .../aws-smithy-types/test_data/error_meta_data_empty.json | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json diff --git a/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json b/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json deleted file mode 100644 index 41165f4a49..0000000000 --- a/rust-runtime/aws-smithy-types/test_data/error_meta_data_empty.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "code": null, - "message": null, - "extras": null -} From 54fa8340cb75aaa3e2b362fb14067acaa91273f7 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Thu, 27 Apr 2023 03:55:59 +0000 Subject: [PATCH 23/31] FIX --- CHANGELOG.next.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 121601565e..f0ae279af4 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -16,3 +16,4 @@ message = "The `Debug` implementation for `PropertyBag` now prints a list of the author = "rcoh" references = ["smithy-rs#2612"] meta = { "breaking" = false, "tada" = false, "bug" = false } + From c8acea15fe25067fcb93955c6ee4bdee067faea1 Mon Sep 17 00:00:00 2001 From: Thomas Cameron <68596478+thomas-k-cameron@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:56:36 +0900 Subject: [PATCH 24/31] Update number.rs --- rust-runtime/aws-smithy-types/src/number.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-types/src/number.rs b/rust-runtime/aws-smithy-types/src/number.rs index 80527cfc10..5ae57a0810 100644 --- a/rust-runtime/aws-smithy-types/src/number.rs +++ b/rust-runtime/aws-smithy-types/src/number.rs @@ -207,7 +207,7 @@ impl TryFrom for f32 { } #[cfg(test)] -mod test { +mod number { use super::*; use crate::error::{TryFromNumberError, TryFromNumberErrorKind}; From cc4ba983b44b581aad68a3492a17cc4405bfae03 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Thu, 27 Apr 2023 05:08:33 +0000 Subject: [PATCH 25/31] FIX? --- rust-runtime/aws-smithy-types/src/blob.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust-runtime/aws-smithy-types/src/blob.rs b/rust-runtime/aws-smithy-types/src/blob.rs index 501b3a7f19..23a782ca74 100644 --- a/rust-runtime/aws-smithy-types/src/blob.rs +++ b/rust-runtime/aws-smithy-types/src/blob.rs @@ -41,7 +41,6 @@ impl AsRef<[u8]> for Blob { } } - #[cfg(all(aws_sdk_unstable, feature = "serde-serialize"))] impl Serialize for Blob { fn serialize(&self, serializer: S) -> Result From 4996788d8f31894e278555dae5750050a7302265 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Mon, 5 Jun 2023 21:41:04 +0000 Subject: [PATCH 26/31] update --- rust-runtime/aws-smithy-types/Cargo.toml | 15 --------- .../aws-smithy-types/src/date_time/mod.rs | 3 -- .../aws-smithy-types/src/date_time/ser.rs | 11 ------- rust-runtime/aws-smithy-types/src/document.rs | 33 ++++++++----------- 4 files changed, 13 insertions(+), 49 deletions(-) diff --git a/rust-runtime/aws-smithy-types/Cargo.toml b/rust-runtime/aws-smithy-types/Cargo.toml index bb47882746..f141089708 100644 --- a/rust-runtime/aws-smithy-types/Cargo.toml +++ b/rust-runtime/aws-smithy-types/Cargo.toml @@ -19,7 +19,6 @@ ryu = "1.0.5" time = { version = "0.3.4", features = ["parsing"] } base64-simd = "0.8" - [target."cfg(aws_sdk_unstable)".dependencies.serde] version = "1" features = ["derive"] @@ -32,11 +31,7 @@ serde = { version = "1", features = ["derive"] } serde_json = "1" criterion = "0.4" rand = "0.8.4" -<<<<<<< HEAD -ciborium = "0.2.0" -======= ciborium = { version = "0.2.1" } ->>>>>>> 74a7204123555ff68c841b42cbe273e08cef1c16 [package.metadata.docs.rs] all-features = true @@ -47,13 +42,3 @@ rustdoc-args = ["--cfg", "docsrs"] [[bench]] name = "base64" harness = false - -<<<<<<< HEAD -[features] -serde-serialize = [] -serde-deserialize = [] -======= -[target."cfg(aws_sdk_unstable)".dependencies.serde] -version = "1" -features = ["derive"] ->>>>>>> 74a7204123555ff68c841b42cbe273e08cef1c16 diff --git a/rust-runtime/aws-smithy-types/src/date_time/mod.rs b/rust-runtime/aws-smithy-types/src/date_time/mod.rs index 7799bf098e..8dcdc53067 100644 --- a/rust-runtime/aws-smithy-types/src/date_time/mod.rs +++ b/rust-runtime/aws-smithy-types/src/date_time/mod.rs @@ -587,8 +587,6 @@ mod test { SystemTime::try_from(date_time).unwrap() ); } -<<<<<<< HEAD -======= #[test] fn ord() { @@ -648,5 +646,4 @@ mod test { assert_eq!(left.cmp(&right), left_str.cmp(&right_str)); } } ->>>>>>> 74a7204123555ff68c841b42cbe273e08cef1c16 } diff --git a/rust-runtime/aws-smithy-types/src/date_time/ser.rs b/rust-runtime/aws-smithy-types/src/date_time/ser.rs index 0a377e8f14..5ea5f55dcd 100644 --- a/rust-runtime/aws-smithy-types/src/date_time/ser.rs +++ b/rust-runtime/aws-smithy-types/src/date_time/ser.rs @@ -11,18 +11,10 @@ impl serde::Serialize for DateTime { where S: serde::Serializer, { -<<<<<<< HEAD - use serde::ser::Error; - if serializer.is_human_readable() { - match self.fmt(Format::DateTime) { - Ok(val) => serializer.serialize_str(&val), - Err(e) => Err(Error::custom(e)), -======= if serializer.is_human_readable() { match self.fmt(Format::DateTime) { Ok(val) => serializer.serialize_str(&val), Err(e) => Err(serde::ser::Error::custom(e)), ->>>>>>> 74a7204123555ff68c841b42cbe273e08cef1c16 } } else { let mut tup_ser = serializer.serialize_tuple(2)?; @@ -32,8 +24,6 @@ impl serde::Serialize for DateTime { } } } -<<<<<<< HEAD -======= #[cfg(test)] mod test { @@ -93,4 +83,3 @@ mod test { }; } } ->>>>>>> 74a7204123555ff68c841b42cbe273e08cef1c16 diff --git a/rust-runtime/aws-smithy-types/src/document.rs b/rust-runtime/aws-smithy-types/src/document.rs index 8cec813d45..c827f005b0 100644 --- a/rust-runtime/aws-smithy-types/src/document.rs +++ b/rust-runtime/aws-smithy-types/src/document.rs @@ -4,18 +4,15 @@ */ use crate::Number; -<<<<<<< HEAD -======= use std::borrow::Cow; use std::collections::HashMap; ->>>>>>> 74a7204123555ff68c841b42cbe273e08cef1c16 #[cfg(any( all(aws_sdk_unstable, feature = "serde-deserialize"), all(aws_sdk_unstable, feature = "serde-serialize") ))] use serde; -use std::collections::HashMap; + /* ANCHOR: document */ /// Document Type @@ -24,7 +21,6 @@ use std::collections::HashMap; /// Open content is useful for modeling unstructured data that has no schema, data that can't be /// modeled using rigid types, or data that has a schema that evolves outside of the purview of a model. /// The serialization format of a document is an implementation detail of a protocol. -<<<<<<< HEAD #[derive(Debug, Clone, PartialEq)] #[cfg_attr( all(aws_sdk_unstable, feature = "serde-serialize"), @@ -41,9 +37,6 @@ use std::collections::HashMap; ), serde(untagged) )] -======= -#[derive(Clone, Debug, PartialEq)] ->>>>>>> 74a7204123555ff68c841b42cbe273e08cef1c16 pub enum Document { /// JSON object Object(HashMap), @@ -224,7 +217,18 @@ impl From for Document { } } -<<<<<<< HEAD +impl From for Document { + fn from(value: f64) -> Self { + Document::Number(Number::Float(value)) + } +} + +impl From for Document { + fn from(value: Number) -> Self { + Document::Number(value) + } +} + /* ANCHOR END: document */ #[cfg(test)] @@ -279,16 +283,5 @@ mod test { assert_eq!(serde_json::to_value(&obj).unwrap(), json.unwrap()); let doc: Result = serde_json::from_str(target_file); assert_eq!(obj, doc.unwrap()); -======= -impl From for Document { - fn from(value: f64) -> Self { - Document::Number(Number::Float(value)) - } -} - -impl From for Document { - fn from(value: Number) -> Self { - Document::Number(value) ->>>>>>> 74a7204123555ff68c841b42cbe273e08cef1c16 } } From 0a8dfef153bb574199a028cff36850dea4f7a92c Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Tue, 6 Jun 2023 06:42:09 +0900 Subject: [PATCH 27/31] Update Cargo.toml --- rust-runtime/aws-smithy-types/Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rust-runtime/aws-smithy-types/Cargo.toml b/rust-runtime/aws-smithy-types/Cargo.toml index f141089708..60af72da0f 100644 --- a/rust-runtime/aws-smithy-types/Cargo.toml +++ b/rust-runtime/aws-smithy-types/Cargo.toml @@ -19,10 +19,6 @@ ryu = "1.0.5" time = { version = "0.3.4", features = ["parsing"] } base64-simd = "0.8" -[target."cfg(aws_sdk_unstable)".dependencies.serde] -version = "1" -features = ["derive"] - [dev-dependencies] base64 = "0.13.0" lazy_static = "1.4" @@ -42,3 +38,7 @@ rustdoc-args = ["--cfg", "docsrs"] [[bench]] name = "base64" harness = false + +[target."cfg(aws_sdk_unstable)".dependencies.serde] +version = "1" +features = ["derive"] From efac2c59f6a9c7eb3e24a3e260f8961ef1560314 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Tue, 6 Jun 2023 07:20:32 +0900 Subject: [PATCH 28/31] Update document.rs --- rust-runtime/aws-smithy-types/src/document.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-runtime/aws-smithy-types/src/document.rs b/rust-runtime/aws-smithy-types/src/document.rs index c827f005b0..2f13f895f8 100644 --- a/rust-runtime/aws-smithy-types/src/document.rs +++ b/rust-runtime/aws-smithy-types/src/document.rs @@ -21,7 +21,7 @@ use serde; /// Open content is useful for modeling unstructured data that has no schema, data that can't be /// modeled using rigid types, or data that has a schema that evolves outside of the purview of a model. /// The serialization format of a document is an implementation detail of a protocol. -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] #[cfg_attr( all(aws_sdk_unstable, feature = "serde-serialize"), derive(serde::Serialize) From 875b6210b27bd04e4c71a1d158ffab1cab572c32 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Tue, 13 Jun 2023 07:10:39 +0000 Subject: [PATCH 29/31] update --- rust-runtime/aws-smithy-types/src/blob.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/rust-runtime/aws-smithy-types/src/blob.rs b/rust-runtime/aws-smithy-types/src/blob.rs index ff37e0bc29..5365b91249 100644 --- a/rust-runtime/aws-smithy-types/src/blob.rs +++ b/rust-runtime/aws-smithy-types/src/blob.rs @@ -3,16 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#[cfg(all( - aws_sdk_unstable, - any(feature = "serde-deserialize", feature = "serde-serialize") -))] -use crate::base64; -#[cfg(all(aws_sdk_unstable, feature = "serde-serialize"))] -use serde::Serialize; -#[cfg(all(aws_sdk_unstable, feature = "serde-deserialize"))] -use serde::{de::Visitor, Deserialize}; - /// Binary Blob Type /// /// Blobs represent protocol-agnostic binary content. From ba06f04a20eb835841f9b157e64e5c3a4b383c57 Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Tue, 13 Jun 2023 07:11:27 +0000 Subject: [PATCH 30/31] asdf --- rust-runtime/aws-smithy-types/src/blob.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rust-runtime/aws-smithy-types/src/blob.rs b/rust-runtime/aws-smithy-types/src/blob.rs index 5365b91249..f765cfe519 100644 --- a/rust-runtime/aws-smithy-types/src/blob.rs +++ b/rust-runtime/aws-smithy-types/src/blob.rs @@ -34,7 +34,6 @@ impl AsRef<[u8]> for Blob { #[cfg(all(aws_sdk_unstable, feature = "serde-serialize"))] mod serde_serialize { use super::*; - use crate::base64; use serde::Serialize; impl Serialize for Blob { From ddefd70959f3a22c818d6aa3c7285b7f73559dff Mon Sep 17 00:00:00 2001 From: Thomas Cameron Date: Thu, 15 Jun 2023 01:59:21 +0900 Subject: [PATCH 31/31] Update blob.rs --- rust-runtime/aws-smithy-types/src/blob.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rust-runtime/aws-smithy-types/src/blob.rs b/rust-runtime/aws-smithy-types/src/blob.rs index f765cfe519..5365b91249 100644 --- a/rust-runtime/aws-smithy-types/src/blob.rs +++ b/rust-runtime/aws-smithy-types/src/blob.rs @@ -34,6 +34,7 @@ impl AsRef<[u8]> for Blob { #[cfg(all(aws_sdk_unstable, feature = "serde-serialize"))] mod serde_serialize { use super::*; + use crate::base64; use serde::Serialize; impl Serialize for Blob {