Loading codegen/Cargo.toml +4 −0 Original line number Diff line number Diff line Loading @@ -10,3 +10,7 @@ regex = "1.8.1" serde = { version = "1.0.160", features = ["derive"] } serde_json = { version = "1.0.96", features = ["preserve_order"] } serde_urlencoded = "0.7.1" [dependencies.codegen-tools] git = "https://github.com/Nugine/codegen-tools" rev = "284bd050b9fb763509c3faf7af23b928dea1aea3" codegen/src/aws_conv.rs +50 −48 Original line number Diff line number Diff line use crate::dto::RustTypes; use crate::f; use crate::gen::Codegen; use crate::ops::Operations; use crate::rust; use codegen_tools::g; use codegen_tools::glines; use std::format as f; use std::ops::Not; use heck::ToSnakeCase; use heck::ToUpperCamelCase; pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { g.lines([ pub fn codegen(ops: &Operations, rust_types: &RustTypes) { glines![ "//! Auto generated by `codegen/src/aws_conv.rs`", // "", "use super::*;", "", ]); ]; for (name, rust_type) in rust_types { match name.as_str() { Loading @@ -39,22 +41,22 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { let s3s_path = f!("s3s::dto::{name}"); let aws_path = aws_ty_path(name, ops, rust_types); g.ln(f!("impl AwsConversion for {s3s_path} {{")); g.ln(f!(" type Target = {aws_path};")); g.ln("type Error = S3Error;"); g.lf(); g!("impl AwsConversion for {s3s_path} {{"); g!(" type Target = {aws_path};"); g!("type Error = S3Error;"); g!(); if contains_deprecated_field(name) { g.ln("#[allow(deprecated)]"); g!("#[allow(deprecated)]"); } g.ln("fn try_from_aws(x: Self::Target) -> S3Result<Self> {"); g!("fn try_from_aws(x: Self::Target) -> S3Result<Self> {{"); match rust_type { rust::Type::Struct(ty) => { if ty.fields.is_empty() { g.ln("let _ = x;"); g!("let _ = x;"); } g.ln("Ok(Self {"); g!("Ok(Self {{"); for field in &ty.fields { let s3s_field_name = field.name.as_str(); let aws_field_name = match s3s_field_name { Loading @@ -64,12 +66,12 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { }; if field.type_ == "SelectObjectContentEventStream" { g.ln(f!("{s3s_field_name}: Some(crate::event_stream::from_aws(x.{aws_field_name})),")); g!("{s3s_field_name}: Some(crate::event_stream::from_aws(x.{aws_field_name})),"); continue; } if field.type_ == "StreamingBlob" { g.ln(f!("{s3s_field_name}: Some(try_from_aws(x.{aws_field_name})?),")); g!("{s3s_field_name}: Some(try_from_aws(x.{aws_field_name})?),"); continue; } Loading @@ -81,60 +83,60 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { }; if needs_unwrap { g.ln(f!("{s3s_field_name}: unwrap_from_aws(x.{aws_field_name}, \"{s3s_field_name}\")?,")); g!("{s3s_field_name}: unwrap_from_aws(x.{aws_field_name}, \"{s3s_field_name}\")?,"); continue; } // other cases { g.ln(f!("{s3s_field_name}: try_from_aws(x.{aws_field_name})?,")); g!("{s3s_field_name}: try_from_aws(x.{aws_field_name})?,"); } } g.ln("})"); g!("}})"); } rust::Type::StrEnum(ty) => { g.ln("Ok(match x {"); g!("Ok(match x {{"); for variant in &ty.variants { let s3s_variant_name = variant.name.as_str(); let aws_variant_name = match s3s_variant_name { "CRC32C" => "Crc32C".to_owned(), _ => s3s_variant_name.to_upper_camel_case(), }; g.ln(f!("{aws_path}::{aws_variant_name} => Self::from_static(Self::{s3s_variant_name}),")); g!("{aws_path}::{aws_variant_name} => Self::from_static(Self::{s3s_variant_name}),"); } g.ln(f!("{aws_path}::Unknown(_) => Self::from(x.as_str().to_owned()),")); g.ln("_ => Self::from(x.as_str().to_owned()),"); g.ln("})"); g!("{aws_path}::Unknown(_) => Self::from(x.as_str().to_owned()),"); g!("_ => Self::from(x.as_str().to_owned()),"); g!("}})"); } rust::Type::StructEnum(ty) => { g.ln("Ok(match x {"); g!("Ok(match x {{"); for variant in &ty.variants { g.ln(f!("{aws_path}::{0}(v) => Self::{0}(try_from_aws(v)?),", variant.name)); g!("{aws_path}::{0}(v) => Self::{0}(try_from_aws(v)?),", variant.name); } g.ln(f!("_ => unimplemented!(\"unknown variant of {aws_path}: {{x:?}}\"),")); g.ln("})"); g!("_ => unimplemented!(\"unknown variant of {aws_path}: {{x:?}}\"),"); g!("}})"); } _ => panic!(), } g.ln("}"); g.lf(); g!("}}"); g!(); if contains_deprecated_field(name) { g.ln("#[allow(deprecated)]"); g!("#[allow(deprecated)]"); } g.ln("fn try_into_aws(x: Self) -> S3Result<Self::Target> {"); g!("fn try_into_aws(x: Self) -> S3Result<Self::Target> {{"); match rust_type { rust::Type::Struct(ty) if ty.name == "SelectObjectContentOutput" => { // TODO(blocking): SelectObjectContentOutput::try_into_aws g.ln("drop(x);"); g.ln("unimplemented!(\"See https://github.com/Nugine/s3s/issues/5\")"); g!("drop(x);"); g!("unimplemented!(\"See https://github.com/Nugine/s3s/issues/5\")"); } rust::Type::Struct(ty) => { if ty.fields.is_empty() { g.ln("let _ = x;"); g.ln("let y = Self::Target::builder();"); g!("let _ = x;"); g!("let y = Self::Target::builder();"); } else { g.ln("let mut y = Self::Target::builder();"); g!("let mut y = Self::Target::builder();"); } for field in &ty.fields { Loading @@ -146,35 +148,35 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { }; if field.option_type { g.ln(f!("y = y.set_{aws_field_name}(try_into_aws(x.{s3s_field_name})?);")); g!("y = y.set_{aws_field_name}(try_into_aws(x.{s3s_field_name})?);"); } else { g.ln(f!("y = y.set_{aws_field_name}(Some(try_into_aws(x.{s3s_field_name})?));")); g!("y = y.set_{aws_field_name}(Some(try_into_aws(x.{s3s_field_name})?));"); } } if is_op_input(&ty.name, ops) { g.ln("y.build().map_err(S3Error::internal_error)"); g!("y.build().map_err(S3Error::internal_error)"); } else { g.ln("Ok(y.build())"); g!("Ok(y.build())"); } } rust::Type::StrEnum(_) => { g.ln(f!("Ok({aws_path}::from(x.as_str()))")); g!("Ok({aws_path}::from(x.as_str()))"); } rust::Type::StructEnum(ty) => { g.ln("Ok(match x {"); g!("Ok(match x {{"); for variant in &ty.variants { g.ln(f!("Self::{0}(v) => {aws_path}::{0}(try_into_aws(v)?),", variant.name)); g!("Self::{0}(v) => {aws_path}::{0}(try_into_aws(v)?),", variant.name); } g.ln(f!("_ => unimplemented!(\"unknown variant of {}: {{x:?}}\"),", ty.name)); g.ln("})"); g!("_ => unimplemented!(\"unknown variant of {}: {{x:?}}\"),", ty.name); g!("}})"); } _ => panic!(), } g.ln("}"); g!("}}"); g.ln("}"); g.lf(); g!("}}"); g!(); } } Loading codegen/src/aws_proxy.rs +34 −31 Original line number Diff line number Diff line use crate::dto::RustTypes; use crate::f; use crate::gen::Codegen; use crate::ops::Operations; use crate::rust; use codegen_tools::g; use codegen_tools::glines; use std::format as f; use heck::ToSnakeCase; pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { g.lines([ pub fn codegen(ops: &Operations, rust_types: &RustTypes) { glines![ "//! Auto generated by `codegen/src/aws_proxy.rs`", "", "use super::*;", Loading @@ -20,28 +23,26 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { "", "use tracing::debug;", "", ]); ]; g.ln("#[async_trait::async_trait]"); g.ln("impl S3 for Proxy {"); g!("#[async_trait::async_trait]"); g!("impl S3 for Proxy {{"); for op in ops.values() { let method_name = op.name.to_snake_case(); let s3s_input = f!("s3s::dto::{}", op.input); let s3s_output = f!("s3s::dto::{}", op.output); g.ln("#[tracing::instrument(skip(self, req))]"); g.ln(f!( "async fn {method_name}(&self, req: S3Request<{s3s_input}>) -> S3Result<{s3s_output}> {{" )); g!("#[tracing::instrument(skip(self, req))]"); g!("async fn {method_name}(&self, req: S3Request<{s3s_input}>) -> S3Result<{s3s_output}> {{"); g.ln("let input = req.input;"); g.ln("debug!(?input);"); g!("let input = req.input;"); g!("debug!(?input);"); if op.smithy_input == "Unit" { g.ln(f!("let result = self.0.{method_name}().send().await;")); g!("let result = self.0.{method_name}().send().await;"); } else { g.ln(f!("let mut b = self.0.{method_name}();")); g!("let mut b = self.0.{method_name}();"); let rust::Type::Struct(ty) = &rust_types[op.input.as_str()] else { panic!() }; let flattened_fields = if ty.name == "SelectObjectContentInput" { Loading Loading @@ -71,31 +72,33 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { // assert!(field.option_type); // let default_val = "aws_sdk_s3::model::ChecksumAlgorithm::Sha256"; // let val = f!("try_into_aws(input.{s3s_field_name})?.or(Some({default_val}))"); // g.ln(f!("b = b.set_{aws_field_name}({val});")); // g!("b = b.set_{aws_field_name}({val});"); // continue; // } if field.option_type { g.ln(f!("b = b.set_{aws_field_name}(try_into_aws(input.{s3s_field_name})?);")); g!("b = b.set_{aws_field_name}(try_into_aws(input.{s3s_field_name})?);"); } else { g.ln(f!("b = b.set_{aws_field_name}(Some(try_into_aws(input.{s3s_field_name})?));")); g!("b = b.set_{aws_field_name}(Some(try_into_aws(input.{s3s_field_name})?));"); } } g.ln("let result = b.send().await;"); g!("let result = b.send().await;"); } g.ln("match result {"); g.ln("Ok(output) => {"); g.ln(" let output = try_from_aws(output)?;"); g.ln(" debug!(?output);"); g.ln(" Ok(output)"); g.ln("},"); g.ln("Err(e) => Err(wrap_sdk_error!(e)),"); g.ln("}"); g.ln("}"); g.lf(); glines![ "match result {", " Ok(output) => {", " let output = try_from_aws(output)?;", " debug!(?output);", " Ok(output)", " },", " Err(e) => Err(wrap_sdk_error!(e)),", "}", ]; g!("}}"); g!(); } g.ln("}"); g!("}}"); } codegen/src/dto.rs +95 −88 Original line number Diff line number Diff line use crate::gen::Codegen; use crate::default; use crate::o; use crate::ops::Operations; use crate::rust::codegen_doc; use crate::{default, f, o}; use crate::{rust, smithy}; use codegen_tools::g; use codegen_tools::glines; use std::collections::BTreeMap; use std::ops::Not; Loading Loading @@ -327,8 +330,8 @@ fn unify_operation_types(ops: &Operations, space: &mut RustTypes) { } } pub fn codegen(rust_types: &RustTypes, g: &mut Codegen) { g.lines([ pub fn codegen(rust_types: &RustTypes) { glines![ "//! Auto generated by `codegen/src/dto.rs`", "", "#![allow(clippy::empty_structs_with_brackets)]", Loading @@ -341,42 +344,42 @@ pub fn codegen(rust_types: &RustTypes, g: &mut Codegen) { "use std::fmt;", "use std::str::FromStr;", "", ]); ]; for rust_type in rust_types.values() { match rust_type { rust::Type::Alias(ty) => { codegen_doc(ty.doc.as_deref(), g); g.ln(f!("pub type {} = {};", ty.name, ty.type_)); codegen_doc(ty.doc.as_deref()); g!("pub type {} = {};", ty.name, ty.type_); } rust::Type::Provided(_) => {} rust::Type::List(ty) => { codegen_doc(ty.doc.as_deref(), g); g.ln(f!("pub type {} = List<{}>;", ty.name, ty.member.type_)); codegen_doc(ty.doc.as_deref()); g!("pub type {} = List<{}>;", ty.name, ty.member.type_); } rust::Type::Map(ty) => { codegen_doc(ty.doc.as_deref(), g); g.ln(f!("pub type {} = Map<{}, {}>;", ty.name, ty.key_type, ty.value_type)); codegen_doc(ty.doc.as_deref()); g!("pub type {} = Map<{}, {}>;", ty.name, ty.key_type, ty.value_type); } rust::Type::StrEnum(ty) => { codegen_str_enum(ty, rust_types, g); codegen_str_enum(ty, rust_types); } rust::Type::Struct(ty) => { codegen_struct(ty, rust_types, g); codegen_struct(ty, rust_types); } rust::Type::StructEnum(ty) => { codegen_struct_enum(ty, rust_types, g); codegen_struct_enum(ty, rust_types); } rust::Type::Timestamp(ty) => { codegen_doc(ty.doc.as_deref(), g); g.ln(f!("pub type {} = Timestamp;", ty.name)); codegen_doc(ty.doc.as_deref()); g!("pub type {} = Timestamp;", ty.name); } } g.lf(); g!(); } } fn codegen_struct(ty: &rust::Struct, _rust_types: &RustTypes, g: &mut Codegen) { fn codegen_struct(ty: &rust::Struct, _rust_types: &RustTypes) { let is_rust_default = |v: &Value| match v { Value::Bool(x) => !x, Value::Number(x) => x.as_i64() == Some(0), Loading @@ -393,102 +396,106 @@ fn codegen_struct(ty: &rust::Struct, _rust_types: &RustTypes, g: &mut Codegen) { is_option || has_default }); codegen_doc(ty.doc.as_deref(), g); codegen_doc(ty.doc.as_deref()); if can_derive_default { g.ln("#[derive(Default)]"); g!("#[derive(Default)]"); } // g.ln("#[non_exhaustive]"); // TODO: builder? // g!("#[non_exhaustive]"); // TODO: builder? g.ln(f!("pub struct {} {{", ty.name)); g!("pub struct {} {{", ty.name); for field in &ty.fields { codegen_doc(field.doc.as_deref(), g); codegen_doc(field.doc.as_deref()); if field.option_type { g.ln(f!(" pub {}: Option<{}>,", field.name, field.type_)); g!(" pub {}: Option<{}>,", field.name, field.type_); } else { g.ln(f!(" pub {}: {},", field.name, field.type_)); g!(" pub {}: {},", field.name, field.type_); } } g.ln("}"); g.lf(); g!("}}"); g!(); g.ln(f!("impl fmt::Debug for {} {{", ty.name)); g.ln("fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {"); g.ln(f!("let mut d = f.debug_struct(\"{}\");", ty.name)); g!("impl fmt::Debug for {} {{", ty.name); g!("fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {{"); g!("let mut d = f.debug_struct(\"{}\");", ty.name); for field in &ty.fields { if field.option_type { g.ln(f!("if let Some(ref val) = self.{} {{", field.name)); g.ln(f!("d.field(\"{}\", val);", field.name)); g.ln("}"); g!("if let Some(ref val) = self.{} {{", field.name); g!("d.field(\"{}\", val);", field.name); g!("}}"); } else { g.ln(f!("d.field(\"{0}\", &self.{0});", field.name)); g!("d.field(\"{0}\", &self.{0});", field.name); } } g.ln("d.finish_non_exhaustive()"); g.ln("}"); g.ln("}"); g!("d.finish_non_exhaustive()"); g!("}}"); g!("}}"); } fn codegen_str_enum(ty: &rust::StrEnum, _rust_types: &RustTypes, g: &mut Codegen) { codegen_doc(ty.doc.as_deref(), g); g.ln("#[derive(Debug, Clone, PartialEq, Eq)]"); g.ln(f!("pub struct {}(Cow<'static, str>);", ty.name)); g.lf(); fn codegen_str_enum(ty: &rust::StrEnum, _rust_types: &RustTypes) { codegen_doc(ty.doc.as_deref()); g!("#[derive(Debug, Clone, PartialEq, Eq)]"); g!("pub struct {}(Cow<'static, str>);", ty.name); g!(); g.ln(f!("impl {} {{", ty.name)); g!("impl {} {{", ty.name); { for variant in &ty.variants { codegen_doc(variant.doc.as_deref(), g); g.ln(f!("pub const {}: &str = \"{}\";", variant.name, variant.value)); g.lf(); } g.ln("#[must_use]"); g.ln("pub fn as_str(&self) -> &str {"); g.ln("&self.0"); g.ln("}"); g.lf(); g.ln("#[must_use]"); g.ln("pub fn from_static(s: &'static str) -> Self {"); g.ln("Self(Cow::from(s))"); g.ln("}"); g.lf(); } g.ln("}"); g.lf(); g.ln(f!("impl From<String> for {} {{", ty.name)); g.ln("fn from(s: String) -> Self {"); g.ln("Self(Cow::from(s))"); g.ln("}"); g.ln("}"); g.lf(); g.ln(f!("impl From<{}> for Cow<'static, str> {{", ty.name)); g.ln(f!("fn from(s: {}) -> Self {{", ty.name)); g.ln("s.0"); g.ln("}"); g.ln("}"); g.lf(); g.ln(f!("impl FromStr for {} {{", ty.name)); g.ln("type Err = Infallible;"); g.ln("fn from_str(s: &str) -> Result<Self, Self::Err> {"); g.ln("Ok(Self::from(s.to_owned()))"); g.ln("}"); g.ln("}"); } fn codegen_struct_enum(ty: &rust::StructEnum, _rust_types: &RustTypes, g: &mut Codegen) { codegen_doc(ty.doc.as_deref(), g); g.ln("#[derive(Debug)]"); g.ln("#[non_exhaustive]"); g.ln(f!("pub enum {} {{", ty.name)); codegen_doc(variant.doc.as_deref()); g!("pub const {}: &str = \"{}\";", variant.name, variant.value); g!(); } glines![ "#[must_use]", // "pub fn as_str(&self) -> &str {", "&self.0", "}", "", ]; glines![ "#[must_use]", "pub fn from_static(s: &'static str) -> Self {", "Self(Cow::from(s))", "}", "", ]; } g!("}}"); g!(); g!("impl From<String> for {} {{", ty.name); g!("fn from(s: String) -> Self {{"); g!("Self(Cow::from(s))"); g!("}}"); g!("}}"); g!(); g!("impl From<{}> for Cow<'static, str> {{", ty.name); g!("fn from(s: {}) -> Self {{", ty.name); g!("s.0"); g!("}}"); g!("}}"); g!(); g!("impl FromStr for {} {{", ty.name); g!("type Err = Infallible;"); g!("fn from_str(s: &str) -> Result<Self, Self::Err> {{"); g!("Ok(Self::from(s.to_owned()))"); g!("}}"); g!("}}"); } fn codegen_struct_enum(ty: &rust::StructEnum, _rust_types: &RustTypes) { codegen_doc(ty.doc.as_deref()); g!("#[derive(Debug)]"); g!("#[non_exhaustive]"); g!("pub enum {} {{", ty.name); for variant in &ty.variants { codegen_doc(variant.doc.as_deref(), g); g.ln(f!(" {}({}),", variant.name, variant.type_)); codegen_doc(variant.doc.as_deref()); g!(" {}({}),", variant.name, variant.type_); } g.ln("}"); g!("}}"); } codegen/src/error.rs +59 −56 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
codegen/Cargo.toml +4 −0 Original line number Diff line number Diff line Loading @@ -10,3 +10,7 @@ regex = "1.8.1" serde = { version = "1.0.160", features = ["derive"] } serde_json = { version = "1.0.96", features = ["preserve_order"] } serde_urlencoded = "0.7.1" [dependencies.codegen-tools] git = "https://github.com/Nugine/codegen-tools" rev = "284bd050b9fb763509c3faf7af23b928dea1aea3"
codegen/src/aws_conv.rs +50 −48 Original line number Diff line number Diff line use crate::dto::RustTypes; use crate::f; use crate::gen::Codegen; use crate::ops::Operations; use crate::rust; use codegen_tools::g; use codegen_tools::glines; use std::format as f; use std::ops::Not; use heck::ToSnakeCase; use heck::ToUpperCamelCase; pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { g.lines([ pub fn codegen(ops: &Operations, rust_types: &RustTypes) { glines![ "//! Auto generated by `codegen/src/aws_conv.rs`", // "", "use super::*;", "", ]); ]; for (name, rust_type) in rust_types { match name.as_str() { Loading @@ -39,22 +41,22 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { let s3s_path = f!("s3s::dto::{name}"); let aws_path = aws_ty_path(name, ops, rust_types); g.ln(f!("impl AwsConversion for {s3s_path} {{")); g.ln(f!(" type Target = {aws_path};")); g.ln("type Error = S3Error;"); g.lf(); g!("impl AwsConversion for {s3s_path} {{"); g!(" type Target = {aws_path};"); g!("type Error = S3Error;"); g!(); if contains_deprecated_field(name) { g.ln("#[allow(deprecated)]"); g!("#[allow(deprecated)]"); } g.ln("fn try_from_aws(x: Self::Target) -> S3Result<Self> {"); g!("fn try_from_aws(x: Self::Target) -> S3Result<Self> {{"); match rust_type { rust::Type::Struct(ty) => { if ty.fields.is_empty() { g.ln("let _ = x;"); g!("let _ = x;"); } g.ln("Ok(Self {"); g!("Ok(Self {{"); for field in &ty.fields { let s3s_field_name = field.name.as_str(); let aws_field_name = match s3s_field_name { Loading @@ -64,12 +66,12 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { }; if field.type_ == "SelectObjectContentEventStream" { g.ln(f!("{s3s_field_name}: Some(crate::event_stream::from_aws(x.{aws_field_name})),")); g!("{s3s_field_name}: Some(crate::event_stream::from_aws(x.{aws_field_name})),"); continue; } if field.type_ == "StreamingBlob" { g.ln(f!("{s3s_field_name}: Some(try_from_aws(x.{aws_field_name})?),")); g!("{s3s_field_name}: Some(try_from_aws(x.{aws_field_name})?),"); continue; } Loading @@ -81,60 +83,60 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { }; if needs_unwrap { g.ln(f!("{s3s_field_name}: unwrap_from_aws(x.{aws_field_name}, \"{s3s_field_name}\")?,")); g!("{s3s_field_name}: unwrap_from_aws(x.{aws_field_name}, \"{s3s_field_name}\")?,"); continue; } // other cases { g.ln(f!("{s3s_field_name}: try_from_aws(x.{aws_field_name})?,")); g!("{s3s_field_name}: try_from_aws(x.{aws_field_name})?,"); } } g.ln("})"); g!("}})"); } rust::Type::StrEnum(ty) => { g.ln("Ok(match x {"); g!("Ok(match x {{"); for variant in &ty.variants { let s3s_variant_name = variant.name.as_str(); let aws_variant_name = match s3s_variant_name { "CRC32C" => "Crc32C".to_owned(), _ => s3s_variant_name.to_upper_camel_case(), }; g.ln(f!("{aws_path}::{aws_variant_name} => Self::from_static(Self::{s3s_variant_name}),")); g!("{aws_path}::{aws_variant_name} => Self::from_static(Self::{s3s_variant_name}),"); } g.ln(f!("{aws_path}::Unknown(_) => Self::from(x.as_str().to_owned()),")); g.ln("_ => Self::from(x.as_str().to_owned()),"); g.ln("})"); g!("{aws_path}::Unknown(_) => Self::from(x.as_str().to_owned()),"); g!("_ => Self::from(x.as_str().to_owned()),"); g!("}})"); } rust::Type::StructEnum(ty) => { g.ln("Ok(match x {"); g!("Ok(match x {{"); for variant in &ty.variants { g.ln(f!("{aws_path}::{0}(v) => Self::{0}(try_from_aws(v)?),", variant.name)); g!("{aws_path}::{0}(v) => Self::{0}(try_from_aws(v)?),", variant.name); } g.ln(f!("_ => unimplemented!(\"unknown variant of {aws_path}: {{x:?}}\"),")); g.ln("})"); g!("_ => unimplemented!(\"unknown variant of {aws_path}: {{x:?}}\"),"); g!("}})"); } _ => panic!(), } g.ln("}"); g.lf(); g!("}}"); g!(); if contains_deprecated_field(name) { g.ln("#[allow(deprecated)]"); g!("#[allow(deprecated)]"); } g.ln("fn try_into_aws(x: Self) -> S3Result<Self::Target> {"); g!("fn try_into_aws(x: Self) -> S3Result<Self::Target> {{"); match rust_type { rust::Type::Struct(ty) if ty.name == "SelectObjectContentOutput" => { // TODO(blocking): SelectObjectContentOutput::try_into_aws g.ln("drop(x);"); g.ln("unimplemented!(\"See https://github.com/Nugine/s3s/issues/5\")"); g!("drop(x);"); g!("unimplemented!(\"See https://github.com/Nugine/s3s/issues/5\")"); } rust::Type::Struct(ty) => { if ty.fields.is_empty() { g.ln("let _ = x;"); g.ln("let y = Self::Target::builder();"); g!("let _ = x;"); g!("let y = Self::Target::builder();"); } else { g.ln("let mut y = Self::Target::builder();"); g!("let mut y = Self::Target::builder();"); } for field in &ty.fields { Loading @@ -146,35 +148,35 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { }; if field.option_type { g.ln(f!("y = y.set_{aws_field_name}(try_into_aws(x.{s3s_field_name})?);")); g!("y = y.set_{aws_field_name}(try_into_aws(x.{s3s_field_name})?);"); } else { g.ln(f!("y = y.set_{aws_field_name}(Some(try_into_aws(x.{s3s_field_name})?));")); g!("y = y.set_{aws_field_name}(Some(try_into_aws(x.{s3s_field_name})?));"); } } if is_op_input(&ty.name, ops) { g.ln("y.build().map_err(S3Error::internal_error)"); g!("y.build().map_err(S3Error::internal_error)"); } else { g.ln("Ok(y.build())"); g!("Ok(y.build())"); } } rust::Type::StrEnum(_) => { g.ln(f!("Ok({aws_path}::from(x.as_str()))")); g!("Ok({aws_path}::from(x.as_str()))"); } rust::Type::StructEnum(ty) => { g.ln("Ok(match x {"); g!("Ok(match x {{"); for variant in &ty.variants { g.ln(f!("Self::{0}(v) => {aws_path}::{0}(try_into_aws(v)?),", variant.name)); g!("Self::{0}(v) => {aws_path}::{0}(try_into_aws(v)?),", variant.name); } g.ln(f!("_ => unimplemented!(\"unknown variant of {}: {{x:?}}\"),", ty.name)); g.ln("})"); g!("_ => unimplemented!(\"unknown variant of {}: {{x:?}}\"),", ty.name); g!("}})"); } _ => panic!(), } g.ln("}"); g!("}}"); g.ln("}"); g.lf(); g!("}}"); g!(); } } Loading
codegen/src/aws_proxy.rs +34 −31 Original line number Diff line number Diff line use crate::dto::RustTypes; use crate::f; use crate::gen::Codegen; use crate::ops::Operations; use crate::rust; use codegen_tools::g; use codegen_tools::glines; use std::format as f; use heck::ToSnakeCase; pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { g.lines([ pub fn codegen(ops: &Operations, rust_types: &RustTypes) { glines![ "//! Auto generated by `codegen/src/aws_proxy.rs`", "", "use super::*;", Loading @@ -20,28 +23,26 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { "", "use tracing::debug;", "", ]); ]; g.ln("#[async_trait::async_trait]"); g.ln("impl S3 for Proxy {"); g!("#[async_trait::async_trait]"); g!("impl S3 for Proxy {{"); for op in ops.values() { let method_name = op.name.to_snake_case(); let s3s_input = f!("s3s::dto::{}", op.input); let s3s_output = f!("s3s::dto::{}", op.output); g.ln("#[tracing::instrument(skip(self, req))]"); g.ln(f!( "async fn {method_name}(&self, req: S3Request<{s3s_input}>) -> S3Result<{s3s_output}> {{" )); g!("#[tracing::instrument(skip(self, req))]"); g!("async fn {method_name}(&self, req: S3Request<{s3s_input}>) -> S3Result<{s3s_output}> {{"); g.ln("let input = req.input;"); g.ln("debug!(?input);"); g!("let input = req.input;"); g!("debug!(?input);"); if op.smithy_input == "Unit" { g.ln(f!("let result = self.0.{method_name}().send().await;")); g!("let result = self.0.{method_name}().send().await;"); } else { g.ln(f!("let mut b = self.0.{method_name}();")); g!("let mut b = self.0.{method_name}();"); let rust::Type::Struct(ty) = &rust_types[op.input.as_str()] else { panic!() }; let flattened_fields = if ty.name == "SelectObjectContentInput" { Loading Loading @@ -71,31 +72,33 @@ pub fn codegen(ops: &Operations, rust_types: &RustTypes, g: &mut Codegen) { // assert!(field.option_type); // let default_val = "aws_sdk_s3::model::ChecksumAlgorithm::Sha256"; // let val = f!("try_into_aws(input.{s3s_field_name})?.or(Some({default_val}))"); // g.ln(f!("b = b.set_{aws_field_name}({val});")); // g!("b = b.set_{aws_field_name}({val});"); // continue; // } if field.option_type { g.ln(f!("b = b.set_{aws_field_name}(try_into_aws(input.{s3s_field_name})?);")); g!("b = b.set_{aws_field_name}(try_into_aws(input.{s3s_field_name})?);"); } else { g.ln(f!("b = b.set_{aws_field_name}(Some(try_into_aws(input.{s3s_field_name})?));")); g!("b = b.set_{aws_field_name}(Some(try_into_aws(input.{s3s_field_name})?));"); } } g.ln("let result = b.send().await;"); g!("let result = b.send().await;"); } g.ln("match result {"); g.ln("Ok(output) => {"); g.ln(" let output = try_from_aws(output)?;"); g.ln(" debug!(?output);"); g.ln(" Ok(output)"); g.ln("},"); g.ln("Err(e) => Err(wrap_sdk_error!(e)),"); g.ln("}"); g.ln("}"); g.lf(); glines![ "match result {", " Ok(output) => {", " let output = try_from_aws(output)?;", " debug!(?output);", " Ok(output)", " },", " Err(e) => Err(wrap_sdk_error!(e)),", "}", ]; g!("}}"); g!(); } g.ln("}"); g!("}}"); }
codegen/src/dto.rs +95 −88 Original line number Diff line number Diff line use crate::gen::Codegen; use crate::default; use crate::o; use crate::ops::Operations; use crate::rust::codegen_doc; use crate::{default, f, o}; use crate::{rust, smithy}; use codegen_tools::g; use codegen_tools::glines; use std::collections::BTreeMap; use std::ops::Not; Loading Loading @@ -327,8 +330,8 @@ fn unify_operation_types(ops: &Operations, space: &mut RustTypes) { } } pub fn codegen(rust_types: &RustTypes, g: &mut Codegen) { g.lines([ pub fn codegen(rust_types: &RustTypes) { glines![ "//! Auto generated by `codegen/src/dto.rs`", "", "#![allow(clippy::empty_structs_with_brackets)]", Loading @@ -341,42 +344,42 @@ pub fn codegen(rust_types: &RustTypes, g: &mut Codegen) { "use std::fmt;", "use std::str::FromStr;", "", ]); ]; for rust_type in rust_types.values() { match rust_type { rust::Type::Alias(ty) => { codegen_doc(ty.doc.as_deref(), g); g.ln(f!("pub type {} = {};", ty.name, ty.type_)); codegen_doc(ty.doc.as_deref()); g!("pub type {} = {};", ty.name, ty.type_); } rust::Type::Provided(_) => {} rust::Type::List(ty) => { codegen_doc(ty.doc.as_deref(), g); g.ln(f!("pub type {} = List<{}>;", ty.name, ty.member.type_)); codegen_doc(ty.doc.as_deref()); g!("pub type {} = List<{}>;", ty.name, ty.member.type_); } rust::Type::Map(ty) => { codegen_doc(ty.doc.as_deref(), g); g.ln(f!("pub type {} = Map<{}, {}>;", ty.name, ty.key_type, ty.value_type)); codegen_doc(ty.doc.as_deref()); g!("pub type {} = Map<{}, {}>;", ty.name, ty.key_type, ty.value_type); } rust::Type::StrEnum(ty) => { codegen_str_enum(ty, rust_types, g); codegen_str_enum(ty, rust_types); } rust::Type::Struct(ty) => { codegen_struct(ty, rust_types, g); codegen_struct(ty, rust_types); } rust::Type::StructEnum(ty) => { codegen_struct_enum(ty, rust_types, g); codegen_struct_enum(ty, rust_types); } rust::Type::Timestamp(ty) => { codegen_doc(ty.doc.as_deref(), g); g.ln(f!("pub type {} = Timestamp;", ty.name)); codegen_doc(ty.doc.as_deref()); g!("pub type {} = Timestamp;", ty.name); } } g.lf(); g!(); } } fn codegen_struct(ty: &rust::Struct, _rust_types: &RustTypes, g: &mut Codegen) { fn codegen_struct(ty: &rust::Struct, _rust_types: &RustTypes) { let is_rust_default = |v: &Value| match v { Value::Bool(x) => !x, Value::Number(x) => x.as_i64() == Some(0), Loading @@ -393,102 +396,106 @@ fn codegen_struct(ty: &rust::Struct, _rust_types: &RustTypes, g: &mut Codegen) { is_option || has_default }); codegen_doc(ty.doc.as_deref(), g); codegen_doc(ty.doc.as_deref()); if can_derive_default { g.ln("#[derive(Default)]"); g!("#[derive(Default)]"); } // g.ln("#[non_exhaustive]"); // TODO: builder? // g!("#[non_exhaustive]"); // TODO: builder? g.ln(f!("pub struct {} {{", ty.name)); g!("pub struct {} {{", ty.name); for field in &ty.fields { codegen_doc(field.doc.as_deref(), g); codegen_doc(field.doc.as_deref()); if field.option_type { g.ln(f!(" pub {}: Option<{}>,", field.name, field.type_)); g!(" pub {}: Option<{}>,", field.name, field.type_); } else { g.ln(f!(" pub {}: {},", field.name, field.type_)); g!(" pub {}: {},", field.name, field.type_); } } g.ln("}"); g.lf(); g!("}}"); g!(); g.ln(f!("impl fmt::Debug for {} {{", ty.name)); g.ln("fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {"); g.ln(f!("let mut d = f.debug_struct(\"{}\");", ty.name)); g!("impl fmt::Debug for {} {{", ty.name); g!("fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {{"); g!("let mut d = f.debug_struct(\"{}\");", ty.name); for field in &ty.fields { if field.option_type { g.ln(f!("if let Some(ref val) = self.{} {{", field.name)); g.ln(f!("d.field(\"{}\", val);", field.name)); g.ln("}"); g!("if let Some(ref val) = self.{} {{", field.name); g!("d.field(\"{}\", val);", field.name); g!("}}"); } else { g.ln(f!("d.field(\"{0}\", &self.{0});", field.name)); g!("d.field(\"{0}\", &self.{0});", field.name); } } g.ln("d.finish_non_exhaustive()"); g.ln("}"); g.ln("}"); g!("d.finish_non_exhaustive()"); g!("}}"); g!("}}"); } fn codegen_str_enum(ty: &rust::StrEnum, _rust_types: &RustTypes, g: &mut Codegen) { codegen_doc(ty.doc.as_deref(), g); g.ln("#[derive(Debug, Clone, PartialEq, Eq)]"); g.ln(f!("pub struct {}(Cow<'static, str>);", ty.name)); g.lf(); fn codegen_str_enum(ty: &rust::StrEnum, _rust_types: &RustTypes) { codegen_doc(ty.doc.as_deref()); g!("#[derive(Debug, Clone, PartialEq, Eq)]"); g!("pub struct {}(Cow<'static, str>);", ty.name); g!(); g.ln(f!("impl {} {{", ty.name)); g!("impl {} {{", ty.name); { for variant in &ty.variants { codegen_doc(variant.doc.as_deref(), g); g.ln(f!("pub const {}: &str = \"{}\";", variant.name, variant.value)); g.lf(); } g.ln("#[must_use]"); g.ln("pub fn as_str(&self) -> &str {"); g.ln("&self.0"); g.ln("}"); g.lf(); g.ln("#[must_use]"); g.ln("pub fn from_static(s: &'static str) -> Self {"); g.ln("Self(Cow::from(s))"); g.ln("}"); g.lf(); } g.ln("}"); g.lf(); g.ln(f!("impl From<String> for {} {{", ty.name)); g.ln("fn from(s: String) -> Self {"); g.ln("Self(Cow::from(s))"); g.ln("}"); g.ln("}"); g.lf(); g.ln(f!("impl From<{}> for Cow<'static, str> {{", ty.name)); g.ln(f!("fn from(s: {}) -> Self {{", ty.name)); g.ln("s.0"); g.ln("}"); g.ln("}"); g.lf(); g.ln(f!("impl FromStr for {} {{", ty.name)); g.ln("type Err = Infallible;"); g.ln("fn from_str(s: &str) -> Result<Self, Self::Err> {"); g.ln("Ok(Self::from(s.to_owned()))"); g.ln("}"); g.ln("}"); } fn codegen_struct_enum(ty: &rust::StructEnum, _rust_types: &RustTypes, g: &mut Codegen) { codegen_doc(ty.doc.as_deref(), g); g.ln("#[derive(Debug)]"); g.ln("#[non_exhaustive]"); g.ln(f!("pub enum {} {{", ty.name)); codegen_doc(variant.doc.as_deref()); g!("pub const {}: &str = \"{}\";", variant.name, variant.value); g!(); } glines![ "#[must_use]", // "pub fn as_str(&self) -> &str {", "&self.0", "}", "", ]; glines![ "#[must_use]", "pub fn from_static(s: &'static str) -> Self {", "Self(Cow::from(s))", "}", "", ]; } g!("}}"); g!(); g!("impl From<String> for {} {{", ty.name); g!("fn from(s: String) -> Self {{"); g!("Self(Cow::from(s))"); g!("}}"); g!("}}"); g!(); g!("impl From<{}> for Cow<'static, str> {{", ty.name); g!("fn from(s: {}) -> Self {{", ty.name); g!("s.0"); g!("}}"); g!("}}"); g!(); g!("impl FromStr for {} {{", ty.name); g!("type Err = Infallible;"); g!("fn from_str(s: &str) -> Result<Self, Self::Err> {{"); g!("Ok(Self::from(s.to_owned()))"); g!("}}"); g!("}}"); } fn codegen_struct_enum(ty: &rust::StructEnum, _rust_types: &RustTypes) { codegen_doc(ty.doc.as_deref()); g!("#[derive(Debug)]"); g!("#[non_exhaustive]"); g!("pub enum {} {{", ty.name); for variant in &ty.variants { codegen_doc(variant.doc.as_deref(), g); g.ln(f!(" {}({}),", variant.name, variant.type_)); codegen_doc(variant.doc.as_deref()); g!(" {}({}),", variant.name, variant.type_); } g.ln("}"); g!("}}"); }
codegen/src/error.rs +59 −56 File changed.Preview size limit exceeded, changes collapsed. Show changes