From 7c4d16b68e3eecb765e16dc0f77e772f30527ddb Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 21 Jan 2021 17:12:50 -0800 Subject: [PATCH 1/3] Make the http method in the Websocket request struct optional. This field is optional, but the Go bindings don't mark it as such. Signed-off-by: David Calavera --- aws_lambda_events/src/custom_serde.rs | 28 +++++++++++-- aws_lambda_events/src/generated/apigw.rs | 6 ++- .../go_to_rust/src/lib.rs | 42 +++++++++++++++---- .../struct_with_http_fields/expected.txt | 9 ++++ .../struct_with_http_fields/input.txt | 4 ++ 5 files changed, 76 insertions(+), 13 deletions(-) diff --git a/aws_lambda_events/src/custom_serde.rs b/aws_lambda_events/src/custom_serde.rs index 9385488..ceca9ce 100644 --- a/aws_lambda_events/src/custom_serde.rs +++ b/aws_lambda_events/src/custom_serde.rs @@ -214,11 +214,10 @@ where pub mod http_method { use http::Method; use serde::de; - use serde::de::{Unexpected, Visitor}; + use serde::de::{Deserialize, Unexpected, Visitor}; use serde::{Deserializer, Serializer}; use std::fmt; - /// Implementation detail. Use derive annotations instead. pub fn serialize(method: &Method, ser: S) -> Result { ser.serialize_str(method.as_str()) } @@ -241,13 +240,36 @@ pub mod http_method { } } - /// Implementation detail. pub fn deserialize<'de, D>(de: D) -> Result where D: Deserializer<'de>, { de.deserialize_str(MethodVisitor) } + + pub fn deserialize_optional<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let s: Option<&str> = Option::deserialize(deserializer)?; + if let Some(val) = s { + let visitor = MethodVisitor {}; + return visitor.visit_str(val).map(Some); + } + + Ok(None) + } + + pub fn serialize_optional( + method: &Option, + ser: S, + ) -> Result { + if let Some(method) = method { + return serialize(method, ser); + } + + ser.serialize_none() + } } #[cfg(test)] diff --git a/aws_lambda_events/src/generated/apigw.rs b/aws_lambda_events/src/generated/apigw.rs index 021abba..602904f 100644 --- a/aws_lambda_events/src/generated/apigw.rs +++ b/aws_lambda_events/src/generated/apigw.rs @@ -392,9 +392,11 @@ pub struct ApiGatewayWebsocketProxyRequest { #[serde(deserialize_with = "deserialize_lambda_string")] #[serde(default)] pub path: Option, - #[serde(with = "http_method")] + #[serde(deserialize_with = "http_method::deserialize_optional")] + #[serde(serialize_with = "http_method::serialize_optional")] + #[serde(skip_serializing_if = "Option::is_none")] #[serde(rename = "httpMethod")] - pub http_method: Method, + pub http_method: Option, #[serde(deserialize_with = "http_serde::header_map::deserialize")] #[serde(serialize_with = "serialize_headers")] pub headers: HeaderMap, diff --git a/aws_lambda_events_codegen/go_to_rust/src/lib.rs b/aws_lambda_events_codegen/go_to_rust/src/lib.rs index 64e1f4d..a6b3d0b 100644 --- a/aws_lambda_events_codegen/go_to_rust/src/lib.rs +++ b/aws_lambda_events_codegen/go_to_rust/src/lib.rs @@ -156,6 +156,7 @@ struct FieldDef { struct StructureFieldDef<'a> { struct_name: &'a str, member_name: &'a str, + omit_empty: bool, } fn parse_comment(c: &str) -> String { @@ -290,6 +291,7 @@ fn parse_struct(pairs: Pairs<'_, Rule>) -> Result<(codegen::Struct, HashSet( libraries.insert("crate::custom_serde::*".to_string()); libraries.insert("http::Method".to_string()); + // Temporary patch to fix https://github.com/LegNeato/aws-lambda-events/issues/33 + // It will allow the code to be correct even after the Go bindings make the + // http method optional. + let mut value = "Method"; + let mut annotations = vec!["#[serde(with = \"http_method\")]".to_string()]; + + if let Some(def) = member_def { + if def.struct_name == "ApiGatewayWebsocketProxyRequest" { + // The Go bindings don't mark this field as an optional, but it is. + // When the Go bindings fix that problem, the following check will + // prevent us from creating an Option>, which would + // be wrong. + if !def.omit_empty { + value = "Option"; + } + annotations = vec![ + "#[serde(deserialize_with = \"http_method::deserialize_optional\")]" + .to_string(), + "#[serde(serialize_with = \"http_method::serialize_optional\")]" + .to_string(), + "#[serde(skip_serializing_if = \"Option::is_none\")]".to_string(), + ]; + } + } + RustType { - value: "Method".into(), - annotations: vec!["#[serde(with = \"http_method\")]".to_string()], - generics: vec![], + value: value.into(), + annotations, libraries, + generics: vec![], } } GoType::StringType if is_http_body(member_def) => { @@ -960,15 +987,14 @@ fn is_http_multivalue_headers<'a>(def: Option<&'a StructureFieldDef>) -> bool { fn is_http_method<'a>(def: Option<&'a StructureFieldDef>) -> bool { match def { - Some(&StructureFieldDef { member_name, .. }) if member_name == "http_method" => true, Some(&StructureFieldDef { member_name, struct_name, .. - }) if struct_name == "ApiGatewayV2httpRequestContextHttpDescription" - && member_name == "method" => - { - true + }) => { + member_name == "http_method" + || (struct_name == "ApiGatewayV2httpRequestContextHttpDescription" + && member_name == "method") } _ => false, } diff --git a/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/expected.txt b/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/expected.txt index 4afa241..b039817 100644 --- a/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/expected.txt +++ b/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/expected.txt @@ -23,4 +23,13 @@ pub struct HttpMessage { pub struct ApiGatewayProxyResponse { #[serde(skip_serializing_if = "Option::is_none")] pub body: Option, +} + +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub struct ApiGatewayWebsocketProxyRequest { + #[serde(deserialize_with = "http_method::deserialize_optional")] + #[serde(serialize_with = "http_method::serialize_optional")] + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "httpMethod")] + pub http_method: Option, } \ No newline at end of file diff --git a/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/input.txt b/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/input.txt index e0a1aa6..e9f4cfd 100644 --- a/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/input.txt +++ b/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/input.txt @@ -8,3 +8,7 @@ type HttpMessage struct { type ApiGatewayProxyResponse struct { Body string `json:"body"` } + +type ApiGatewayWebsocketProxyRequest struct { + HttpMethod string `json:"httpMethod"` +} From ccffe242a696a5e4e44a74298a89441c9c1ce917 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Tue, 2 Mar 2021 12:43:04 -0800 Subject: [PATCH 2/3] Update Go events to master(a8e138ff) Signed-off-by: David Calavera --- aws_lambda_events/src/generated/README.md | 2 +- aws_lambda_events/src/generated/cognito.rs | 4 ++++ aws_lambda_events/src/generated/lex.rs | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/aws_lambda_events/src/generated/README.md b/aws_lambda_events/src/generated/README.md index 8375779..53d9dc4 100644 --- a/aws_lambda_events/src/generated/README.md +++ b/aws_lambda_events/src/generated/README.md @@ -3,4 +3,4 @@ These types are automatically generated from the [official Go SDK](https://github.com/aws/aws-lambda-go/tree/master/events). -Generated from commit [b3dd246b7d83fd62856549646711e5328075c69a](https://github.com/aws/aws-lambda-go/commit/b3dd246b7d83fd62856549646711e5328075c69a). +Generated from commit [a8e138ffcbc1fffe8b5a615dc9d8276b844d670a](https://github.com/aws/aws-lambda-go/commit/a8e138ffcbc1fffe8b5a615dc9d8276b844d670a). diff --git a/aws_lambda_events/src/generated/cognito.rs b/aws_lambda_events/src/generated/cognito.rs index 770c6aa..35794da 100644 --- a/aws_lambda_events/src/generated/cognito.rs +++ b/aws_lambda_events/src/generated/cognito.rs @@ -265,6 +265,10 @@ pub struct CognitoEventUserPoolsMigrateUserRequest { pub password: Option, #[serde(deserialize_with = "deserialize_lambda_map")] #[serde(default)] + #[serde(rename = "validationData")] + pub validation_data: HashMap, + #[serde(deserialize_with = "deserialize_lambda_map")] + #[serde(default)] #[serde(rename = "clientMetadata")] pub client_metadata: HashMap, } diff --git a/aws_lambda_events/src/generated/lex.rs b/aws_lambda_events/src/generated/lex.rs index 90fe640..ee025d8 100644 --- a/aws_lambda_events/src/generated/lex.rs +++ b/aws_lambda_events/src/generated/lex.rs @@ -22,6 +22,8 @@ pub struct LexEvent { pub output_dialog_mode: Option, #[serde(rename = "currentIntent")] pub current_intent: Option, + #[serde(rename = "alternativeIntents")] + pub alternative_intents: Option>, #[serde(rename = "dialogAction")] pub dialog_action: Option, } @@ -36,6 +38,22 @@ pub struct LexBot { #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub struct LexCurrentIntent { pub name: Option, + #[serde(rename = "nluIntentConfidenceScore")] + pub nlu_intent_confidence_score: Option, + pub slots: Option, + #[serde(deserialize_with = "deserialize_lambda_map")] + #[serde(default)] + #[serde(rename = "slotDetails")] + pub slot_details: HashMap, + #[serde(rename = "confirmationStatus")] + pub confirmation_status: Option, +} + +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] +pub struct LexAlternativeIntents { + pub name: Option, + #[serde(rename = "nluIntentConfidenceScore")] + pub nlu_intent_confidence_score: Option, pub slots: Option, #[serde(deserialize_with = "deserialize_lambda_map")] #[serde(default)] From 0ce7e8194e2169fd1eea72d7c0434e2346e2c24d Mon Sep 17 00:00:00 2001 From: David Calavera Date: Tue, 2 Mar 2021 13:33:49 -0800 Subject: [PATCH 3/3] Update test case Signed-off-by: David Calavera --- aws_lambda_events_codegen/go_to_rust/src/lib.rs | 14 +------------- .../fixtures/struct_with_http_fields/input.txt | 2 +- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/aws_lambda_events_codegen/go_to_rust/src/lib.rs b/aws_lambda_events_codegen/go_to_rust/src/lib.rs index a6b3d0b..4da7b4d 100644 --- a/aws_lambda_events_codegen/go_to_rust/src/lib.rs +++ b/aws_lambda_events_codegen/go_to_rust/src/lib.rs @@ -731,21 +731,9 @@ fn translate_go_type_to_rust_type<'a>( libraries.insert("crate::custom_serde::*".to_string()); libraries.insert("http::Method".to_string()); - // Temporary patch to fix https://github.com/LegNeato/aws-lambda-events/issues/33 - // It will allow the code to be correct even after the Go bindings make the - // http method optional. - let mut value = "Method"; let mut annotations = vec!["#[serde(with = \"http_method\")]".to_string()]; - if let Some(def) = member_def { if def.struct_name == "ApiGatewayWebsocketProxyRequest" { - // The Go bindings don't mark this field as an optional, but it is. - // When the Go bindings fix that problem, the following check will - // prevent us from creating an Option>, which would - // be wrong. - if !def.omit_empty { - value = "Option"; - } annotations = vec![ "#[serde(deserialize_with = \"http_method::deserialize_optional\")]" .to_string(), @@ -757,7 +745,7 @@ fn translate_go_type_to_rust_type<'a>( } RustType { - value: value.into(), + value: "Method".into(), annotations, libraries, generics: vec![], diff --git a/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/input.txt b/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/input.txt index e9f4cfd..6245837 100644 --- a/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/input.txt +++ b/aws_lambda_events_codegen/go_to_rust/tests/fixtures/struct_with_http_fields/input.txt @@ -10,5 +10,5 @@ type ApiGatewayProxyResponse struct { } type ApiGatewayWebsocketProxyRequest struct { - HttpMethod string `json:"httpMethod"` + HttpMethod string `json:"httpMethod,omitempty"` }