Add features to enable serde

This commit is contained in:
2024-11-06 20:18:06 +01:00
parent 465aa8dfab
commit fa161be227
5 changed files with 113 additions and 46 deletions

View File

@@ -56,8 +56,15 @@ chrono = { version = "0.4.*", default-features = false, features = [
serde = { version = "1.*", default-features = false, features = [ serde = { version = "1.*", default-features = false, features = [
"std", "std",
"derive", "derive",
] } ], optional = true }
serde_json = { version = "1.*", default-features = false, features = ["std"] } serde_json = { version = "1.*", default-features = false, features = [
"std",
], optional = true }
[features]
default = []
serde = ["dep:serde"]
serde-tags = ["dep:serde", "dep:serde_json"]
[workspace] [workspace]
resolver = "2" resolver = "2"

View File

@@ -11,6 +11,7 @@ use std::{
use aws_config::retry::RetryConfig; use aws_config::retry::RetryConfig;
use aws_sdk_ec2::client::Waiters; use aws_sdk_ec2::client::Waiters;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
mod error; mod error;
@@ -40,6 +41,7 @@ macro_rules! wrap_aws_enum {
} }
} }
#[cfg(feature = "serde")]
impl Serialize for $name { impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where
@@ -49,6 +51,7 @@ macro_rules! wrap_aws_enum {
} }
} }
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for $name { impl<'de> Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where where
@@ -196,11 +199,12 @@ impl Instance {
} }
} }
#[derive(Serialize, Deserialize, Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Region { pub enum Region {
#[serde(rename = "eu-central-1")] #[cfg_attr(feature = "serde", serde(rename = "eu-central-1"))]
EuCentral1, EuCentral1,
#[serde(rename = "us-east-1")] #[cfg_attr(feature = "serde", serde(rename = "us-east-1"))]
UsEast1, UsEast1,
} }
@@ -269,7 +273,8 @@ pub struct RegionClient {
pub cdn: RegionClientCdn, pub cdn: RegionClientCdn,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct InstanceProfileName(String); pub struct InstanceProfileName(String);
impl InstanceProfileName { impl InstanceProfileName {
@@ -278,7 +283,8 @@ impl InstanceProfileName {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct InstanceKeypairName(String); pub struct InstanceKeypairName(String);
impl InstanceKeypairName { impl InstanceKeypairName {
@@ -287,7 +293,8 @@ impl InstanceKeypairName {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct SecurityGroupId(String); pub struct SecurityGroupId(String);
impl SecurityGroupId { impl SecurityGroupId {
@@ -296,12 +303,14 @@ impl SecurityGroupId {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct SecurityGroup { pub struct SecurityGroup {
id: SecurityGroupId, id: SecurityGroupId,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct SubnetId(String); pub struct SubnetId(String);
impl SubnetId { impl SubnetId {
@@ -328,8 +337,9 @@ impl fmt::Display for SubnetId {
macro_rules! string_newtype { macro_rules! string_newtype {
($name:ident) => { ($name:ident) => {
#[Tag(translate = serde)] #[Tag(translate = transparent)]
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct $name(String); pub struct $name(String);
impl std::fmt::Display for $name { impl std::fmt::Display for $name {
@@ -342,7 +352,8 @@ macro_rules! string_newtype {
string_newtype!(AvailabilityZone); string_newtype!(AvailabilityZone);
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct Subnet { pub struct Subnet {
pub id: SubnetId, pub id: SubnetId,
pub availability_zone: AvailabilityZone, pub availability_zone: AvailabilityZone,
@@ -383,7 +394,8 @@ impl AmiId {
} }
} }
#[derive(Debug, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug)]
pub struct Ami { pub struct Ami {
pub id: AmiId, pub id: AmiId,
pub tags: TagList, pub tags: TagList,
@@ -411,7 +423,8 @@ impl TryFrom<aws_sdk_ec2::types::Image> for Ami {
} }
#[Tag(translate = manual)] #[Tag(translate = manual)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
pub struct Timestamp(DateTime<Utc>); pub struct Timestamp(DateTime<Utc>);
impl Timestamp { impl Timestamp {
@@ -468,7 +481,8 @@ impl TryFrom<RawImageCreationDate> for Timestamp {
} }
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct Ip(net::IpAddr); pub struct Ip(net::IpAddr);
impl Ip { impl Ip {
@@ -499,7 +513,8 @@ impl EipAllocationId {
} }
} }
#[derive(Debug, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug)]
pub struct Eip { pub struct Eip {
pub allocation_id: EipAllocationId, pub allocation_id: EipAllocationId,
pub ip: Ip, pub ip: Ip,
@@ -568,8 +583,9 @@ impl Eip {
string_newtype!(CloudfrontDistributionId); string_newtype!(CloudfrontDistributionId);
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[serde(rename_all = "lowercase")] #[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum CloudfrontDistributionStatus { pub enum CloudfrontDistributionStatus {
Deployed, Deployed,
Other(String), Other(String),
@@ -597,10 +613,12 @@ impl From<String> for CloudfrontDistributionStatus {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct EfsId(String); pub struct EfsId(String);
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct Efs { pub struct Efs {
id: EfsId, id: EfsId,
region: Region, region: Region,
@@ -633,7 +651,8 @@ impl From<String> for CloudfrontDistributionDomain {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct CloudfrontOrigin { pub struct CloudfrontOrigin {
id: CloudfrontOriginId, id: CloudfrontOriginId,
domain: CloudfrontOriginDomain, domain: CloudfrontOriginDomain,
@@ -679,7 +698,8 @@ impl From<aws_sdk_cloudfront::types::Origin> for CloudfrontOrigin {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct CloudfrontDistribution { pub struct CloudfrontDistribution {
pub id: CloudfrontDistributionId, pub id: CloudfrontDistributionId,
pub status: CloudfrontDistributionStatus, pub status: CloudfrontDistributionStatus,
@@ -793,7 +813,8 @@ pub async fn load_sdk_clients<const C: usize>(
region_clients region_clients
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct Account { pub struct Account {
id: String, id: String,
} }
@@ -808,7 +829,8 @@ impl Account {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct HostedZoneId(String); pub struct HostedZoneId(String);
impl HostedZoneId { impl HostedZoneId {
@@ -821,7 +843,8 @@ impl HostedZoneId {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone)]
pub struct Route53Zone { pub struct Route53Zone {
hosted_zone_id: HostedZoneId, hosted_zone_id: HostedZoneId,
name: String, name: String,

View File

@@ -56,14 +56,10 @@ in a struct that is using `#[Tags]`:
```rust ```rust
use aws_lib::tags::{Tag, Tags}; use aws_lib::tags::{Tag, Tags};
use serde::{Serialize, Deserialize};
#[Tag(translate = serde)] #[Tag(translate = transparent)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq)]
struct MyTag { struct MyTag(String);
foo: String,
bar: bool,
}
#[Tags] #[Tags]
struct MyTags { struct MyTags {

View File

@@ -1,7 +1,12 @@
#![doc = include_str!("README.md")] #![doc = include_str!("README.md")]
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use serde::{de::DeserializeOwned, Deserialize, Serialize}; #[cfg(feature = "serde-tags")]
use serde::de::DeserializeOwned;
#[cfg(feature = "serde")]
use serde::Deserialize;
#[cfg(any(feature = "serde-tags", feature = "serde"))]
use serde::Serialize;
mod error; mod error;
mod helpers; mod helpers;
@@ -43,10 +48,12 @@ where
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct RawTagValue(String); pub struct RawTagValue(String);
helpers::impl_string_wrapper!(RawTagValue); helpers::impl_string_wrapper!(RawTagValue);
#[cfg(feature = "serde-tags")]
pub struct TranslateSerde; pub struct TranslateSerde;
pub struct TranslateManual; pub struct TranslateManual;
@@ -57,6 +64,7 @@ pub trait Translator<S: ?Sized, T> {
fn into_raw_tag(value: T) -> RawTagValue; fn into_raw_tag(value: T) -> RawTagValue;
} }
#[cfg(feature = "serde-tags")]
pub trait TranslatableSerde: Serialize + DeserializeOwned {} pub trait TranslatableSerde: Serialize + DeserializeOwned {}
pub trait TranslatableManual: pub trait TranslatableManual:
TryFrom<RawTagValue, Error: Into<ParseTagValueError>> + Into<RawTagValue> TryFrom<RawTagValue, Error: Into<ParseTagValueError>> + Into<RawTagValue>
@@ -76,6 +84,7 @@ pub trait TagValue<V> {
} }
} }
#[cfg(feature = "serde-tags")]
impl<S, T> Translator<S, T> for TranslateSerde impl<S, T> Translator<S, T> for TranslateSerde
where where
T: TranslatableSerde, T: TranslatableSerde,
@@ -118,7 +127,8 @@ where
} }
} }
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RawTag { pub struct RawTag {
key: TagKey, key: TagKey,
value: RawTagValue, value: RawTagValue,
@@ -155,7 +165,8 @@ where
} }
} }
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct TagKey(String); pub struct TagKey(String);
helpers::impl_string_wrapper!(TagKey); helpers::impl_string_wrapper!(TagKey);
@@ -252,7 +263,8 @@ where
} }
} }
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TagList(Vec<RawTag>); pub struct TagList(Vec<RawTag>);
impl TagList { impl TagList {
@@ -292,6 +304,7 @@ impl TagList {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[cfg(feature = "serde-tags")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::*; use super::*;
@@ -303,6 +316,7 @@ mod tests {
B, B,
} }
#[cfg(feature = "serde-tags")]
#[Tag(translate = serde)] #[Tag(translate = serde)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
struct MyStructTag { struct MyStructTag {
@@ -358,7 +372,9 @@ mod tests {
#[tag(key = "anothername")] #[tag(key = "anothername")]
tag6: Option<MyTag>, tag6: Option<MyTag>,
tag7: Option<MyTag>, tag7: Option<MyTag>,
#[cfg(feature = "serde-tags")]
tag8: MyStructTag, tag8: MyStructTag,
#[cfg(feature = "serde-tags")]
tag9: Option<MyStructTag>, tag9: Option<MyStructTag>,
} }
@@ -368,6 +384,7 @@ mod tests {
RawTag::new("tag3".to_owned(), "false".to_owned()), RawTag::new("tag3".to_owned(), "false".to_owned()),
RawTag::new("myname".to_owned(), "A".to_owned()), RawTag::new("myname".to_owned(), "A".to_owned()),
RawTag::new("anothername".to_owned(), "B".to_owned()), RawTag::new("anothername".to_owned(), "B".to_owned()),
#[cfg(feature = "serde-tags")]
RawTag::new("tag8".to_owned(), r#"{"foo":"hi","bar":false}"#.to_owned()), RawTag::new("tag8".to_owned(), r#"{"foo":"hi","bar":false}"#.to_owned()),
]); ]);
@@ -380,6 +397,7 @@ mod tests {
assert!(tags.tag5 == MyTag::A); assert!(tags.tag5 == MyTag::A);
assert!(tags.tag6 == Some(MyTag::B)); assert!(tags.tag6 == Some(MyTag::B));
assert!(tags.tag7.is_none()); assert!(tags.tag7.is_none());
#[cfg(feature = "serde-tags")]
assert!( assert!(
tags.tag8 tags.tag8
== MyStructTag { == MyStructTag {
@@ -387,6 +405,7 @@ mod tests {
bar: false bar: false
} }
); );
#[cfg(feature = "serde-tags")]
assert!(tags.tag9.is_none()); assert!(tags.tag9.is_none());
let into_tags = tags.into_tags(); let into_tags = tags.into_tags();
@@ -399,6 +418,7 @@ mod tests {
RawTag::new("tag3".to_owned(), "false".to_owned()), RawTag::new("tag3".to_owned(), "false".to_owned()),
RawTag::new("myname".to_owned(), "A".to_owned()), RawTag::new("myname".to_owned(), "A".to_owned()),
RawTag::new("anothername".to_owned(), "B".to_owned()), RawTag::new("anothername".to_owned(), "B".to_owned()),
#[cfg(feature = "serde-tags")]
RawTag::new("tag8".to_owned(), r#"{"foo":"hi","bar":false}"#.to_owned(),), RawTag::new("tag8".to_owned(), r#"{"foo":"hi","bar":false}"#.to_owned(),),
]) ])
); );
@@ -407,7 +427,7 @@ mod tests {
#[test] #[test]
fn test_transparent_tag() { fn test_transparent_tag() {
#[Tag(translate = transparent)] #[Tag(translate = transparent)]
#[derive(Serialize, Deserialize, PartialEq, Debug)] #[derive(PartialEq, Debug)]
struct MyTag(String); struct MyTag(String);
assert_eq!( assert_eq!(

View File

@@ -1,14 +1,35 @@
use super::{ use super::{ParseTagValueError, RawTagValue, TagValue, TranslatableManual, TranslateManual};
ParseTagValueError, TagValue, TranslatableManual, TranslatableSerde, TranslateManual,
TranslateSerde,
};
// Bools can just be handled by serde. impl TranslatableManual for bool {}
impl TranslatableSerde for bool {}
const TRUE_STR: &str = "true";
const FALSE_STR: &str = "false";
impl TagValue<Self> for bool { impl TagValue<Self> for bool {
type Error = ParseTagValueError; type Error = ParseTagValueError;
type Translator = TranslateSerde; type Translator = TranslateManual;
}
impl TryFrom<RawTagValue> for bool {
type Error = ParseTagValueError;
fn try_from(value: RawTagValue) -> Result<Self, Self::Error> {
match value.as_str() {
TRUE_STR => Ok(true),
FALSE_STR => Ok(false),
_ => Err(ParseTagValueError::InvalidBoolValue { value }),
}
}
}
impl From<bool> for RawTagValue {
fn from(value: bool) -> Self {
if value {
Self::new(TRUE_STR.to_owned())
} else {
Self::new(FALSE_STR.to_owned())
}
}
} }
// Due to quoting, we cannot use serde here. It would produce quoted // Due to quoting, we cannot use serde here. It would produce quoted