From 8dfe5a1f70526b413ce3c82a7bc84e50258afc06 Mon Sep 17 00:00:00 2001 From: John DiSanti Date: Tue, 15 Nov 2022 15:21:46 -0800 Subject: [PATCH] Revamp errors in `aws-smithy-types-convert` and `aws-smithy-xml` (#1917) --- .../rustsdk/customize/s3/S3Decorator.kt | 4 +- .../codegen/core/smithy/protocols/AwsQuery.kt | 6 +- .../codegen/core/smithy/protocols/Ec2Query.kt | 6 +- .../codegen/core/smithy/protocols/RestXml.kt | 6 +- .../parse/AwsQueryParserGenerator.kt | 10 +-- .../parse/Ec2QueryParserGenerator.kt | 4 +- .../protocols/parse/RestXmlParserGenerator.kt | 4 +- .../parse/StructuredDataParserGenerator.kt | 6 +- .../parse/XmlBindingTraitParserGenerator.kt | 62 +++++++-------- .../ServerHttpBoundProtocolGenerator.kt | 2 +- .../aws-smithy-http-server/src/rejection.rs | 2 +- .../aws-smithy-types-convert/src/date_time.rs | 71 +++++++++++------ rust-runtime/aws-smithy-xml/src/decode.rs | 76 +++++++++++++------ rust-runtime/aws-smithy-xml/src/encode.rs | 10 ++- rust-runtime/aws-smithy-xml/src/unescape.rs | 34 ++++----- .../tests/handwritten_parsers.rs | 24 +++--- .../tests/handwritten_serializers.rs | 13 ++-- .../inlineable/src/ec2_query_errors.rs | 16 ++-- .../src/rest_xml_unwrapped_errors.rs | 12 +-- .../inlineable/src/rest_xml_wrapped_errors.rs | 18 +++-- 20 files changed, 219 insertions(+), 167 deletions(-) diff --git a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt index 230cf8491ae..31533979dab 100644 --- a/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt +++ b/aws/sdk-codegen/src/main/kotlin/software/amazon/smithy/rustsdk/customize/s3/S3Decorator.kt @@ -96,7 +96,7 @@ class S3(codegenContext: CodegenContext) : RestXml(codegenContext) { "Error" to RuntimeType.GenericError(runtimeConfig), "HeaderMap" to RuntimeType.http.member("HeaderMap"), "Response" to RuntimeType.http.member("Response"), - "XmlError" to CargoDependency.smithyXml(runtimeConfig).asType().member("decode::XmlError"), + "XmlDecodeError" to CargoDependency.smithyXml(runtimeConfig).asType().member("decode::XmlDecodeError"), "base_errors" to restXmlErrors, "s3_errors" to AwsRuntimeType.S3Errors, ) @@ -104,7 +104,7 @@ class S3(codegenContext: CodegenContext) : RestXml(codegenContext) { override fun parseHttpGenericError(operationShape: OperationShape): RuntimeType { return RuntimeType.forInlineFun("parse_http_generic_error", RustModule.private("xml_deser")) { rustBlockTemplate( - "pub fn parse_http_generic_error(response: &#{Response}<#{Bytes}>) -> Result<#{Error}, #{XmlError}>", + "pub fn parse_http_generic_error(response: &#{Response}<#{Bytes}>) -> Result<#{Error}, #{XmlDecodeError}>", *errorScope, ) { rustTemplate( diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQuery.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQuery.kt index 5bd7c2ab604..6b6d1d46c55 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQuery.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/AwsQuery.kt @@ -50,7 +50,7 @@ class AwsQueryProtocol(private val codegenContext: CodegenContext) : Protocol { "Error" to RuntimeType.GenericError(runtimeConfig), "HeaderMap" to RuntimeType.http.member("HeaderMap"), "Response" to RuntimeType.http.member("Response"), - "XmlError" to CargoDependency.smithyXml(runtimeConfig).asType().member("decode::XmlError"), + "XmlDecodeError" to CargoDependency.smithyXml(runtimeConfig).asType().member("decode::XmlDecodeError"), ) private val xmlDeserModule = RustModule.private("xml_deser") @@ -70,7 +70,7 @@ class AwsQueryProtocol(private val codegenContext: CodegenContext) : Protocol { override fun parseHttpGenericError(operationShape: OperationShape): RuntimeType = RuntimeType.forInlineFun("parse_http_generic_error", xmlDeserModule) { rustBlockTemplate( - "pub fn parse_http_generic_error(response: &#{Response}<#{Bytes}>) -> Result<#{Error}, #{XmlError}>", + "pub fn parse_http_generic_error(response: &#{Response}<#{Bytes}>) -> Result<#{Error}, #{XmlDecodeError}>", *errorScope, ) { rust("#T::parse_generic_error(response.body().as_ref())", awsQueryErrors) @@ -80,7 +80,7 @@ class AwsQueryProtocol(private val codegenContext: CodegenContext) : Protocol { override fun parseEventStreamGenericError(operationShape: OperationShape): RuntimeType = RuntimeType.forInlineFun("parse_event_stream_generic_error", xmlDeserModule) { rustBlockTemplate( - "pub fn parse_event_stream_generic_error(payload: &#{Bytes}) -> Result<#{Error}, #{XmlError}>", + "pub fn parse_event_stream_generic_error(payload: &#{Bytes}) -> Result<#{Error}, #{XmlDecodeError}>", *errorScope, ) { rust("#T::parse_generic_error(payload.as_ref())", awsQueryErrors) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/Ec2Query.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/Ec2Query.kt index 5f5ab09ef07..0786e76c911 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/Ec2Query.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/Ec2Query.kt @@ -32,7 +32,7 @@ class Ec2QueryProtocol(private val codegenContext: CodegenContext) : Protocol { "Error" to RuntimeType.GenericError(runtimeConfig), "HeaderMap" to RuntimeType.http.member("HeaderMap"), "Response" to RuntimeType.http.member("Response"), - "XmlError" to CargoDependency.smithyXml(runtimeConfig).asType().member("decode::XmlError"), + "XmlDecodeError" to CargoDependency.smithyXml(runtimeConfig).asType().member("decode::XmlDecodeError"), ) private val xmlDeserModule = RustModule.private("xml_deser") @@ -61,7 +61,7 @@ class Ec2QueryProtocol(private val codegenContext: CodegenContext) : Protocol { override fun parseHttpGenericError(operationShape: OperationShape): RuntimeType = RuntimeType.forInlineFun("parse_http_generic_error", xmlDeserModule) { rustBlockTemplate( - "pub fn parse_http_generic_error(response: &#{Response}<#{Bytes}>) -> Result<#{Error}, #{XmlError}>", + "pub fn parse_http_generic_error(response: &#{Response}<#{Bytes}>) -> Result<#{Error}, #{XmlDecodeError}>", *errorScope, ) { rust("#T::parse_generic_error(response.body().as_ref())", ec2QueryErrors) @@ -71,7 +71,7 @@ class Ec2QueryProtocol(private val codegenContext: CodegenContext) : Protocol { override fun parseEventStreamGenericError(operationShape: OperationShape): RuntimeType = RuntimeType.forInlineFun("parse_event_stream_generic_error", xmlDeserModule) { rustBlockTemplate( - "pub fn parse_event_stream_generic_error(payload: &#{Bytes}) -> Result<#{Error}, #{XmlError}>", + "pub fn parse_event_stream_generic_error(payload: &#{Bytes}) -> Result<#{Error}, #{XmlDecodeError}>", *errorScope, ) { rust("#T::parse_generic_error(payload.as_ref())", ec2QueryErrors) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt index 3108b98dd88..153088e53e7 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/RestXml.kt @@ -32,7 +32,7 @@ open class RestXml(val codegenContext: CodegenContext) : Protocol { "Error" to RuntimeType.GenericError(runtimeConfig), "HeaderMap" to RuntimeType.http.member("HeaderMap"), "Response" to RuntimeType.http.member("Response"), - "XmlError" to CargoDependency.smithyXml(runtimeConfig).asType().member("decode::XmlError"), + "XmlDecodeError" to CargoDependency.smithyXml(runtimeConfig).asType().member("decode::XmlDecodeError"), ) private val xmlDeserModule = RustModule.private("xml_deser") @@ -60,7 +60,7 @@ open class RestXml(val codegenContext: CodegenContext) : Protocol { override fun parseHttpGenericError(operationShape: OperationShape): RuntimeType = RuntimeType.forInlineFun("parse_http_generic_error", xmlDeserModule) { rustBlockTemplate( - "pub fn parse_http_generic_error(response: &#{Response}<#{Bytes}>) -> Result<#{Error}, #{XmlError}>", + "pub fn parse_http_generic_error(response: &#{Response}<#{Bytes}>) -> Result<#{Error}, #{XmlDecodeError}>", *errorScope, ) { rust("#T::parse_generic_error(response.body().as_ref())", restXmlErrors) @@ -70,7 +70,7 @@ open class RestXml(val codegenContext: CodegenContext) : Protocol { override fun parseEventStreamGenericError(operationShape: OperationShape): RuntimeType = RuntimeType.forInlineFun("parse_event_stream_generic_error", xmlDeserModule) { rustBlockTemplate( - "pub fn parse_event_stream_generic_error(payload: &#{Bytes}) -> Result<#{Error}, #{XmlError}>", + "pub fn parse_event_stream_generic_error(payload: &#{Bytes}) -> Result<#{Error}, #{XmlDecodeError}>", *errorScope, ) { rust("#T::parse_generic_error(payload.as_ref())", restXmlErrors) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGenerator.kt index a53bc2ab1b6..2dbe6d72fbe 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/AwsQueryParserGenerator.kt @@ -42,24 +42,24 @@ class AwsQueryParserGenerator( rustTemplate( """ if !(${XmlBindingTraitParserGenerator.XmlName(responseWrapperName).matchExpression("start_el")}) { - return Err(#{XmlError}::custom(format!("invalid root, expected $responseWrapperName got {:?}", start_el))) + return Err(#{XmlDecodeError}::custom(format!("invalid root, expected $responseWrapperName got {:?}", start_el))) } if let Some(mut result_tag) = decoder.next_tag() { let start_el = result_tag.start_el(); if !(${XmlBindingTraitParserGenerator.XmlName(resultWrapperName).matchExpression("start_el")}) { - return Err(#{XmlError}::custom(format!("invalid result, expected $resultWrapperName got {:?}", start_el))) + return Err(#{XmlDecodeError}::custom(format!("invalid result, expected $resultWrapperName got {:?}", start_el))) } """, - "XmlError" to context.xmlErrorType, + "XmlDecodeError" to context.xmlDecodeErrorType, ) inner("result_tag") rustTemplate( """ } else { - return Err(#{XmlError}::custom("expected $resultWrapperName tag")) + return Err(#{XmlDecodeError}::custom("expected $resultWrapperName tag")) }; """, - "XmlError" to context.xmlErrorType, + "XmlDecodeError" to context.xmlDecodeErrorType, ) }, ) : StructuredDataParserGenerator by xmlBindingTraitParserGenerator diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGenerator.kt index f59f2df556c..e7be46f3bdc 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/Ec2QueryParserGenerator.kt @@ -39,10 +39,10 @@ class Ec2QueryParserGenerator( rustTemplate( """ if !(${XmlBindingTraitParserGenerator.XmlName(responseWrapperName).matchExpression("start_el")}) { - return Err(#{XmlError}::custom(format!("invalid root, expected $responseWrapperName got {:?}", start_el))) + return Err(#{XmlDecodeError}::custom(format!("invalid root, expected $responseWrapperName got {:?}", start_el))) } """, - "XmlError" to context.xmlErrorType, + "XmlDecodeError" to context.xmlDecodeErrorType, ) inner("decoder") }, diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/RestXmlParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/RestXmlParserGenerator.kt index 156d025b9b4..f09598e6f17 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/RestXmlParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/RestXmlParserGenerator.kt @@ -40,13 +40,13 @@ class RestXmlParserGenerator( """ if !${XmlBindingTraitParserGenerator.XmlName(shapeName).matchExpression("start_el")} { return Err( - #{XmlError}::custom( + #{XmlDecodeError}::custom( format!("encountered invalid XML root: expected $shapeName but got {:?}. This is likely a bug in the SDK.", start_el) ) ) } """, - "XmlError" to context.xmlErrorType, + "XmlDecodeError" to context.xmlDecodeErrorType, ) } diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/StructuredDataParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/StructuredDataParserGenerator.kt index 2bd6c923e0d..f8b053d80f7 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/StructuredDataParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/StructuredDataParserGenerator.kt @@ -16,7 +16,7 @@ interface StructuredDataParserGenerator { * Entry point for payload-based parsing. * Roughly: * ```rust - * fn parse_my_struct(input: &[u8]) -> Result { + * fn parse_my_struct(input: &[u8]) -> Result { * ... * } * ``` @@ -29,7 +29,7 @@ interface StructuredDataParserGenerator { * through: * * ```rust - * fn parse_some_operation(inp: &[u8], builder: my_operation::Builder) -> Result { + * fn parse_some_operation(inp: &[u8], builder: my_operation::Builder) -> Result { * ... * } * ``` @@ -41,7 +41,7 @@ interface StructuredDataParserGenerator { * through: * * ```rust - * fn parse_some_error(inp: &[u8], builder: my_operation::Builder) -> Result { + * fn parse_some_error(inp: &[u8], builder: my_operation::Builder) -> Result { * ... * } */ diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt index 37b0d1e6166..b70cb55efba 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/protocols/parse/XmlBindingTraitParserGenerator.kt @@ -64,7 +64,7 @@ typealias OperationInnerWriteable = RustWriter.(String) -> Unit data class OperationWrapperContext( val shape: OperationShape, val outputShapeName: String, - val xmlErrorType: RuntimeType, + val xmlDecodeErrorType: RuntimeType, val model: Model, ) @@ -98,7 +98,7 @@ class XmlBindingTraitParserGenerator( private val symbolProvider = codegenContext.symbolProvider private val smithyXml = CargoDependency.smithyXml(codegenContext.runtimeConfig).asType() - private val xmlError = smithyXml.member("decode::XmlError") + private val xmlDecodeError = smithyXml.member("decode::XmlDecodeError") private val scopedDecoder = smithyXml.member("decode::ScopedDecoder") private val runtimeConfig = codegenContext.runtimeConfig @@ -107,7 +107,7 @@ class XmlBindingTraitParserGenerator( private val codegenScope = arrayOf( "Blob" to RuntimeType.Blob(runtimeConfig), "Document" to smithyXml.member("decode::Document"), - "XmlError" to xmlError, + "XmlDecodeError" to xmlDecodeError, "next_start_element" to smithyXml.member("decode::next_start_element"), "try_data" to smithyXml.member("decode::try_data"), "ScopedDecoder" to scopedDecoder, @@ -124,7 +124,7 @@ class XmlBindingTraitParserGenerator( * Entry point for payload-based parsing. * Roughly: * ```rust - * fn parse_my_struct(input: &[u8]) -> Result { + * fn parse_my_struct(input: &[u8]) -> Result { * ... * } * ``` @@ -137,7 +137,7 @@ class XmlBindingTraitParserGenerator( rustBlock( "pub fn $fnName(inp: &[u8]) -> Result<#1T, #2T>", symbolProvider.toSymbol(shape), - xmlError, + xmlDecodeError, ) { // for payloads, first look at the member trait // next, look to see if this structure was renamed @@ -150,7 +150,7 @@ class XmlBindingTraitParserGenerator( let mut decoder = doc.root_element()?; let start_el = decoder.start_el(); if !(${shapeName.matchExpression("start_el")}) { - return Err(#{XmlError}::custom(format!("invalid root, expected $shapeName got {:?}", start_el))) + return Err(#{XmlDecodeError}::custom(format!("invalid root, expected $shapeName got {:?}", start_el))) } """, *codegenScope, @@ -171,7 +171,7 @@ class XmlBindingTraitParserGenerator( * through: * * ```rust - * fn parse_some_operation(inp: &[u8], builder: my_operation::Builder) -> Result { + * fn parse_some_operation(inp: &[u8], builder: my_operation::Builder) -> Result { * ... * } * ``` @@ -189,7 +189,7 @@ class XmlBindingTraitParserGenerator( rustBlock( "pub fn $fnName(inp: &[u8], mut builder: #1T) -> Result<#1T, #2T>", builderSymbol(outputShape), - xmlError, + xmlDecodeError, ) { rustTemplate( """ @@ -202,7 +202,7 @@ class XmlBindingTraitParserGenerator( """, *codegenScope, ) - val context = OperationWrapperContext(operationShape, shapeName, xmlError, model) + val context = OperationWrapperContext(operationShape, shapeName, xmlDecodeError, model) if (operationShape.hasTrait()) { unwrappedResponseParser("builder", "decoder", "start_el", outputShape.members()) } else { @@ -222,7 +222,7 @@ class XmlBindingTraitParserGenerator( rustBlock( "pub fn $fnName(inp: &[u8], mut builder: #1T) -> Result<#1T, #2T>", builderSymbol(errorShape), - xmlError, + xmlDecodeError, ) { val members = errorShape.errorXmlMembers() rust("if inp.is_empty() { return Ok(builder) }") @@ -256,7 +256,7 @@ class XmlBindingTraitParserGenerator( rustBlock( "pub fn $fnName(inp: &[u8], mut builder: #1T) -> Result<#1T, #2T>", builderSymbol(inputShape), - xmlError, + xmlDecodeError, ) { rustTemplate( """ @@ -268,7 +268,7 @@ class XmlBindingTraitParserGenerator( """, *codegenScope, ) - val context = OperationWrapperContext(operationShape, shapeName, xmlError, model) + val context = OperationWrapperContext(operationShape, shapeName, xmlDecodeError, model) writeOperationWrapper(context) { tagName -> parseStructureInner(members, builder = "builder", Ctx(tag = tagName, accum = null)) } @@ -298,7 +298,7 @@ class XmlBindingTraitParserGenerator( } rust("$builder = $builder.${member.setterName()}($temp);") } - rustTemplate("_ => return Err(#{XmlError}::custom(\"expected ${member.xmlName()} tag\"))", *codegenScope) + rustTemplate("_ => return Err(#{XmlDecodeError}::custom(\"expected ${member.xmlName()} tag\"))", *codegenScope) } } @@ -412,7 +412,7 @@ class XmlBindingTraitParserGenerator( val symbol = symbolProvider.toSymbol(shape) val nestedParser = RuntimeType.forInlineFun(fnName, xmlDeserModule) { rustBlockTemplate( - "pub fn $fnName(decoder: &mut #{ScopedDecoder}) -> Result<#{Shape}, #{XmlError}>", + "pub fn $fnName(decoder: &mut #{ScopedDecoder}) -> Result<#{Shape}, #{XmlDecodeError}>", *codegenScope, "Shape" to symbol, ) { val members = shape.members() @@ -426,7 +426,7 @@ class XmlBindingTraitParserGenerator( (match base.take() { None => None, Some(${format(symbol)}::$variantName(inner)) => Some(inner), - Some(_) => return Err(#{XmlError}::custom("mixed variants")) + Some(_) => return Err(#{XmlDecodeError}::custom("mixed variants")) }) """ withBlock("let tmp =", ";") { @@ -437,10 +437,10 @@ class XmlBindingTraitParserGenerator( } when (target.renderUnknownVariant()) { true -> rust("_unknown => base = Some(#T::${UnionGenerator.UnknownVariantName}),", symbol) - false -> rustTemplate("""variant => return Err(#{XmlError}::custom(format!("unexpected union variant: {:?}", variant)))""", *codegenScope) + false -> rustTemplate("""variant => return Err(#{XmlDecodeError}::custom(format!("unexpected union variant: {:?}", variant)))""", *codegenScope) } } - rustTemplate("""base.ok_or_else(||#{XmlError}::custom("expected union, got nothing"))""", *codegenScope) + rustTemplate("""base.ok_or_else(||#{XmlDecodeError}::custom("expected union, got nothing"))""", *codegenScope) } } rust("#T(&mut ${ctx.tag})", nestedParser) @@ -465,7 +465,7 @@ class XmlBindingTraitParserGenerator( val symbol = symbolProvider.toSymbol(shape) val nestedParser = RuntimeType.forInlineFun(fnName, xmlDeserModule) { rustBlockTemplate( - "pub fn $fnName(decoder: &mut #{ScopedDecoder}) -> Result<#{Shape}, #{XmlError}>", + "pub fn $fnName(decoder: &mut #{ScopedDecoder}) -> Result<#{Shape}, #{XmlDecodeError}>", *codegenScope, "Shape" to symbol, ) { Attribute.AllowUnusedMut.render(this) @@ -484,7 +484,7 @@ class XmlBindingTraitParserGenerator( // I'm leaving this branch here so that the binding trait parser generator would work for a server // side implementation in the future. - rustTemplate(""".map_err(|_|#{XmlError}::custom("missing field"))?""", *codegenScope) + rustTemplate(""".map_err(|_|#{XmlDecodeError}::custom("missing field"))?""", *codegenScope) } } } @@ -497,7 +497,7 @@ class XmlBindingTraitParserGenerator( val member = target.member val listParser = RuntimeType.forInlineFun(fnName, xmlDeserModule) { rustBlockTemplate( - "pub fn $fnName(decoder: &mut #{ScopedDecoder}) -> Result<#{List}, #{XmlError}>", + "pub fn $fnName(decoder: &mut #{ScopedDecoder}) -> Result<#{List}, #{XmlDecodeError}>", *codegenScope, "List" to symbolProvider.toSymbol(target), ) { @@ -517,7 +517,7 @@ class XmlBindingTraitParserGenerator( private fun RustWriter.parseFlatList(target: CollectionShape, ctx: Ctx) { val list = safeName("list") - withBlock("Result::<#T, #T>::Ok({", "})", symbolProvider.toSymbol(target), xmlError) { + withBlock("Result::<#T, #T>::Ok({", "})", symbolProvider.toSymbol(target), xmlDecodeError) { val accum = ctx.accum ?: throw CodegenException("Need accum to parse flat list") rustTemplate("""let mut $list = $accum.unwrap_or_default();""", *codegenScope) withBlock("$list.push(", ");") { @@ -531,7 +531,7 @@ class XmlBindingTraitParserGenerator( val fnName = symbolProvider.deserializeFunctionName(target) val mapParser = RuntimeType.forInlineFun(fnName, xmlDeserModule) { rustBlockTemplate( - "pub fn $fnName(decoder: &mut #{ScopedDecoder}) -> Result<#{Map}, #{XmlError}>", + "pub fn $fnName(decoder: &mut #{ScopedDecoder}) -> Result<#{Map}, #{XmlDecodeError}>", *codegenScope, "Map" to symbolProvider.toSymbol(target), ) { @@ -550,7 +550,7 @@ class XmlBindingTraitParserGenerator( private fun RustWriter.parseFlatMap(target: MapShape, ctx: Ctx) { val map = safeName("map") val entryDecoder = mapEntryParser(target, ctx) - withBlock("Result::<#T, #T>::Ok({", "})", symbolProvider.toSymbol(target), xmlError) { + withBlock("Result::<#T, #T>::Ok({", "})", symbolProvider.toSymbol(target), xmlDecodeError) { val accum = ctx.accum ?: throw CodegenException("need accum to parse flat map") rustTemplate( """ @@ -568,7 +568,7 @@ class XmlBindingTraitParserGenerator( val fnName = symbolProvider.deserializeFunctionName(target) + "_entry" return RuntimeType.forInlineFun(fnName, xmlDeserModule) { rustBlockTemplate( - "pub fn $fnName(decoder: &mut #{ScopedDecoder}, out: &mut #{Map}) -> Result<(), #{XmlError}>", + "pub fn $fnName(decoder: &mut #{ScopedDecoder}, out: &mut #{Map}) -> Result<(), #{XmlDecodeError}>", *codegenScope, "Map" to symbolProvider.toSymbol(target), ) { @@ -593,8 +593,8 @@ class XmlBindingTraitParserGenerator( rustTemplate( """ - let k = k.ok_or_else(||#{XmlError}::custom("missing key map entry"))?; - let v = v.ok_or_else(||#{XmlError}::custom("missing value map entry"))?; + let k = k.ok_or_else(||#{XmlDecodeError}::custom("missing key map entry"))?; + let v = v.ok_or_else(||#{XmlDecodeError}::custom("missing value map entry"))?; out.insert(k, v); Ok(()) """, @@ -622,7 +622,7 @@ class XmlBindingTraitParserGenerator( provider() } rustTemplate( - """.map_err(|_|#{XmlError}::custom("expected ${escape(shape.toString())}"))""", + """.map_err(|_|#{XmlDecodeError}::custom("expected ${escape(shape.toString())}"))""", *codegenScope, ) } @@ -640,7 +640,7 @@ class XmlBindingTraitParserGenerator( rust(", #T", timestampFormatType) } rustTemplate( - """.map_err(|_|#{XmlError}::custom("expected ${escape(shape.toString())}"))""", + """.map_err(|_|#{XmlDecodeError}::custom("expected ${escape(shape.toString())}"))""", *codegenScope, ) } @@ -649,7 +649,7 @@ class XmlBindingTraitParserGenerator( provider() } rustTemplate( - """.map_err(|err|#{XmlError}::custom(format!("invalid base64: {:?}", err))).map(#{Blob}::new)""", + """.map_err(|err|#{XmlDecodeError}::custom(format!("invalid base64: {:?}", err))).map(#{Blob}::new)""", *codegenScope, ) } @@ -658,14 +658,14 @@ class XmlBindingTraitParserGenerator( } private fun RustWriter.parseStringInner(shape: StringShape, provider: Writable) { - withBlock("Result::<#T, #T>::Ok(", ")", symbolProvider.toSymbol(shape), xmlError) { + withBlock("Result::<#T, #T>::Ok(", ")", symbolProvider.toSymbol(shape), xmlDecodeError) { if (shape.hasTrait()) { val enumSymbol = symbolProvider.toSymbol(shape) if (convertsToEnumInServer(shape)) { withBlock("#T::try_from(", ")", enumSymbol) { provider() } - rustTemplate(""".map_err(|e| #{XmlError}::custom(format!("unknown variant {}", e)))?""", *codegenScope) + rustTemplate(""".map_err(|e| #{XmlDecodeError}::custom(format!("unknown variant {}", e)))?""", *codegenScope) } else { withBlock("#T::from(", ")", enumSymbol) { provider() diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt index 3543d96782f..9a0c3653d48 100644 --- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt +++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/protocols/ServerHttpBoundProtocolGenerator.kt @@ -1251,7 +1251,7 @@ private class ServerHttpBoundProtocolTraitImplGenerator( CargoDependency.smithyJson(runtimeConfig).asType().member("deserialize::error::DeserializeError") } RestXmlTrait.ID -> { - CargoDependency.smithyXml(runtimeConfig).asType().member("decode").member("XmlError") + CargoDependency.smithyXml(runtimeConfig).asType().member("decode").member("XmlDecodeError") } else -> { TODO("Protocol ${codegenContext.protocol} not supported yet") diff --git a/rust-runtime/aws-smithy-http-server/src/rejection.rs b/rust-runtime/aws-smithy-http-server/src/rejection.rs index f714b314fc3..c75b3e466c5 100644 --- a/rust-runtime/aws-smithy-http-server/src/rejection.rs +++ b/rust-runtime/aws-smithy-http-server/src/rejection.rs @@ -233,7 +233,7 @@ impl From for RequestRejection { // bubble up instead of having to sprinkle things like [`Result::map_err`] everywhere. convert_to_request_rejection!(aws_smithy_json::deserialize::error::DeserializeError, JsonDeserialize); -convert_to_request_rejection!(aws_smithy_xml::decode::XmlError, XmlDeserialize); +convert_to_request_rejection!(aws_smithy_xml::decode::XmlDecodeError, XmlDeserialize); convert_to_request_rejection!(aws_smithy_http::header::ParseError, HeaderParse); convert_to_request_rejection!(aws_smithy_types::date_time::DateTimeParseError, DateTimeParse); convert_to_request_rejection!(aws_smithy_types::primitive::PrimitiveParseError, PrimitiveParse); diff --git a/rust-runtime/aws-smithy-types-convert/src/date_time.rs b/rust-runtime/aws-smithy-types-convert/src/date_time.rs index 32984b3d78d..905dcbfc133 100644 --- a/rust-runtime/aws-smithy-types-convert/src/date_time.rs +++ b/rust-runtime/aws-smithy-types-convert/src/date_time.rs @@ -12,25 +12,41 @@ use aws_smithy_types::DateTime; use std::error::Error as StdError; use std::fmt; -/// Conversion error -#[non_exhaustive] #[derive(Debug)] -pub enum Error { +enum ErrorKind { /// Conversion failed because the value being converted is out of range for its destination - #[non_exhaustive] OutOfRange(Box), } -impl StdError for Error {} +/// Conversion error +#[derive(Debug)] +pub struct Error { + kind: ErrorKind, +} + +impl Error { + fn out_of_range(source: impl Into>) -> Self { + Self { + kind: ErrorKind::OutOfRange(source.into()), + } + } +} + +impl StdError for Error { + fn source(&self) -> Option<&(dyn StdError + 'static)> { + match &self.kind { + ErrorKind::OutOfRange(source) => Some(source.as_ref() as _), + } + } +} impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::OutOfRange(cause) => { + match self.kind { + ErrorKind::OutOfRange(_) => { write!( f, - "conversion failed because the value is out of range for its destination: {}", - cause + "conversion failed because the value is out of range for its destination", ) } } @@ -101,7 +117,7 @@ pub trait DateTimeExt { /// Converts a [`DateTime`] to a [`time::OffsetDateTime`]. /// - /// Returns an [`Error::OutOfRange`] if the time is after + /// Returns an [`Error`] if the time is after /// `9999-12-31T23:59:59.999Z` or before `-9999-01-01T00:00:00.000Z`. #[cfg(feature = "convert-time")] fn to_time(&self) -> Result; @@ -115,15 +131,11 @@ impl DateTimeExt for DateTime { #[cfg(feature = "convert-chrono")] fn to_chrono_utc(&self) -> Result, Error> { match chrono::NaiveDateTime::from_timestamp_opt(self.secs(), self.subsec_nanos()) { - None => { - let err: Box = format!( - "Out-of-range seconds {} or invalid nanoseconds {}", - self.secs(), - self.subsec_nanos() - ) - .into(); - Err(Error::OutOfRange(err)) - } + None => Err(Error::out_of_range(format!( + "out-of-range seconds {} or invalid nanoseconds {}", + self.secs(), + self.subsec_nanos() + ))), Some(dt) => Ok(chrono::DateTime::::from_utc(dt, chrono::Utc)), } } @@ -140,8 +152,9 @@ impl DateTimeExt for DateTime { #[cfg(feature = "convert-time")] fn to_time(&self) -> Result { - time::OffsetDateTime::from_unix_timestamp_nanos(self.as_nanos()) - .map_err(|err| Error::OutOfRange(err.into())) + time::OffsetDateTime::from_unix_timestamp_nanos(self.as_nanos()).map_err(|err| Error { + kind: ErrorKind::OutOfRange(err.into()), + }) } #[cfg(feature = "convert-time")] @@ -158,7 +171,7 @@ mod test { use chrono::Timelike; #[cfg(feature = "convert-time")] - use super::Error; + use super::{Error, ErrorKind}; #[test] #[cfg(feature = "convert-chrono")] @@ -257,8 +270,18 @@ mod test { assert_eq!(expected, date_time.to_time().unwrap()); let date_time = DateTime::from_secs_and_nanos(i64::MAX, 0); - assert!(matches!(date_time.to_time(), Err(Error::OutOfRange(_)))); + assert!(matches!( + date_time.to_time(), + Err(Error { + kind: ErrorKind::OutOfRange(_) + }) + )); let date_time = DateTime::from_secs_and_nanos(i64::MIN, 0); - assert!(matches!(date_time.to_time(), Err(Error::OutOfRange(_)))); + assert!(matches!( + date_time.to_time(), + Err(Error { + kind: ErrorKind::OutOfRange(_) + }) + )); } } diff --git a/rust-runtime/aws-smithy-xml/src/decode.rs b/rust-runtime/aws-smithy-xml/src/decode.rs index d30358bfe26..c567fbd9d9a 100644 --- a/rust-runtime/aws-smithy-xml/src/decode.rs +++ b/rust-runtime/aws-smithy-xml/src/decode.rs @@ -16,38 +16,64 @@ pub type Depth = usize; // much value in lots of different match variants #[derive(Debug)] -pub enum XmlError { +enum XmlDecodeErrorKind { InvalidXml(xmlparser::Error), InvalidEscape { esc: String }, Custom(Cow<'static, str>), Unhandled(Box), } -impl From for XmlError { +#[derive(Debug)] +pub struct XmlDecodeError { + kind: XmlDecodeErrorKind, +} + +impl From for XmlDecodeError { fn from(error: xmlparser::Error) -> Self { - Self::InvalidXml(error) + Self { + kind: XmlDecodeErrorKind::InvalidXml(error), + } } } -impl Display for XmlError { +impl Display for XmlDecodeError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - match self { - XmlError::InvalidXml(err) => write!(f, "XML parse error: {}", err), - XmlError::InvalidEscape { esc } => write!(f, "Invalid XML escape: {}", esc), - XmlError::Custom(msg) => write!(f, "Error parsing XML: {}", msg), - XmlError::Unhandled(err) => write!(f, "Error parsing XML: {}", err), + match &self.kind { + XmlDecodeErrorKind::InvalidXml(_) => write!(f, "XML parse error"), + XmlDecodeErrorKind::InvalidEscape { esc } => write!(f, "invalid XML escape: {}", esc), + XmlDecodeErrorKind::Custom(msg) => write!(f, "error parsing XML: {}", msg), + XmlDecodeErrorKind::Unhandled(_) => write!(f, "error parsing XML"), } } } -impl Error for XmlError {} +impl Error for XmlDecodeError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match &self.kind { + XmlDecodeErrorKind::InvalidXml(source) => Some(source as _), + XmlDecodeErrorKind::Unhandled(source) => Some(source.as_ref() as _), + XmlDecodeErrorKind::InvalidEscape { .. } | XmlDecodeErrorKind::Custom(..) => None, + } + } +} + +impl XmlDecodeError { + pub(crate) fn invalid_escape(esc: impl Into) -> Self { + Self { + kind: XmlDecodeErrorKind::InvalidEscape { esc: esc.into() }, + } + } -impl XmlError { pub fn custom(msg: impl Into>) -> Self { - XmlError::Custom(msg.into()) + Self { + kind: XmlDecodeErrorKind::Custom(msg.into()), + } } + pub fn unhandled(error: impl Into>) -> Self { - Self::Unhandled(error.into()) + Self { + kind: XmlDecodeErrorKind::Unhandled(error.into()), + } } } @@ -168,11 +194,11 @@ pub struct Document<'a> { } impl<'a> TryFrom<&'a [u8]> for Document<'a> { - type Error = XmlError; + type Error = XmlDecodeError; fn try_from(value: &'a [u8]) -> Result { Ok(Document::new( - std::str::from_utf8(value).map_err(|err| XmlError::Unhandled(Box::new(err)))?, + std::str::from_utf8(value).map_err(XmlDecodeError::unhandled)?, )) } } @@ -205,10 +231,10 @@ impl<'inp> Document<'inp> { } /// A scoped reader for the entire document - pub fn root_element<'a>(&'a mut self) -> Result, XmlError> { + pub fn root_element<'a>(&'a mut self) -> Result, XmlDecodeError> { let start_el = self .next_start_element() - .ok_or_else(|| XmlError::custom("no root element"))?; + .ok_or_else(|| XmlDecodeError::custom("no root element"))?; Ok(ScopedDecoder { doc: self, start_el, @@ -241,8 +267,8 @@ impl<'inp> Document<'inp> { /// <- endel depth 0 /// ``` impl<'inp> Iterator for Document<'inp> { - type Item = Result<(Token<'inp>, Depth), XmlError>; - fn next<'a>(&'a mut self) -> Option, Depth), XmlError>> { + type Item = Result<(Token<'inp>, Depth), XmlDecodeError>; + fn next<'a>(&'a mut self) -> Option, Depth), XmlDecodeError>> { let tok = self.tokenizer.next()?; let tok = match tok { Err(e) => return Some(Err(e.into())), @@ -325,7 +351,7 @@ impl<'inp> ScopedDecoder<'inp, '_> { } impl<'inp, 'a> Iterator for ScopedDecoder<'inp, 'a> { - type Item = Result<(Token<'inp>, Depth), XmlError>; + type Item = Result<(Token<'inp>, Depth), XmlDecodeError>; fn next(&mut self) -> Option { if self.start_el.closed { @@ -352,7 +378,7 @@ impl<'inp, 'a> Iterator for ScopedDecoder<'inp, 'a> { /// Load the next start element out of a depth-tagged token iterator fn next_start_element<'a, 'inp>( - tokens: &'a mut impl Iterator, Depth), XmlError>>, + tokens: &'a mut impl Iterator, Depth), XmlDecodeError>>, ) -> Option> { let mut out = StartEl::new("", "", 0); loop { @@ -405,15 +431,15 @@ fn next_start_element<'a, 'inp>( /// If the current position is not a data element (and is instead a ) an error /// will be returned pub fn try_data<'a, 'inp>( - tokens: &'a mut impl Iterator, Depth), XmlError>>, -) -> Result, XmlError> { + tokens: &'a mut impl Iterator, Depth), XmlDecodeError>>, +) -> Result, XmlDecodeError> { loop { match tokens.next().map(|opt| opt.map(|opt| opt.0)) { None => return Ok(Cow::Borrowed("")), Some(Ok(Token::Text { text })) => return unescape(text.as_str()), Some(Ok(e @ Token::ElementStart { .. })) => { - return Err(XmlError::custom(format!( - "Looking for a data element, found: {:?}", + return Err(XmlDecodeError::custom(format!( + "looking for a data element, found: {:?}", e ))) } diff --git a/rust-runtime/aws-smithy-xml/src/encode.rs b/rust-runtime/aws-smithy-xml/src/encode.rs index 7179865d249..358ec7cc447 100644 --- a/rust-runtime/aws-smithy-xml/src/encode.rs +++ b/rust-runtime/aws-smithy-xml/src/encode.rs @@ -7,18 +7,22 @@ //! generating malformed XML a compile error use crate::escape::escape; +use std::error::Error as StdError; use std::fmt::{self, Display, Formatter, Write}; // currently there's actually no way that encoding can fail but give it time :-) +#[non_exhaustive] #[derive(Debug)] -pub enum Error {} +pub struct XmlEncodeError {} -impl Display for Error { +impl Display for XmlEncodeError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - write!(f, "Xml Encoding Error") + write!(f, "error encoding XML") } } +impl StdError for XmlEncodeError {} + /// XmlWriter Abstraction /// /// XmlWriter (and friends) make generating an invalid XML document a type error. Nested branches diff --git a/rust-runtime/aws-smithy-xml/src/unescape.rs b/rust-runtime/aws-smithy-xml/src/unescape.rs index 3f779ebc0c3..41951649467 100644 --- a/rust-runtime/aws-smithy-xml/src/unescape.rs +++ b/rust-runtime/aws-smithy-xml/src/unescape.rs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -use crate::decode::XmlError; +use crate::decode::XmlDecodeError; use std::borrow::Cow; /// Unescape XML encoded characters @@ -15,7 +15,7 @@ use std::borrow::Cow; /// /// If no escape sequences are present, Cow<&'str> will be returned, avoiding the need /// to copy the String. -pub fn unescape(s: &str) -> Result, XmlError> { +pub fn unescape(s: &str) -> Result, XmlDecodeError> { // no &, no need to escape anything if !s.contains('&') { return Ok(Cow::Borrowed(s)); @@ -47,33 +47,27 @@ pub fn unescape(s: &str) -> Result, XmlError> { // e.g. { (entity, 10) } else { - return Err(XmlError::InvalidEscape { - esc: entity.to_string(), - }); + return Err(XmlDecodeError::invalid_escape(entity)); }; let char_code = u32::from_str_radix(entity, radix).map_err(|_| { - XmlError::InvalidEscape { - esc: format!( - "Expected numeric escape in base {}; got: {}", - radix, &entity - ), - } + XmlDecodeError::invalid_escape(format!( + "expected numeric escape in base {}; got: {}", + radix, &entity + )) + })?; + let chr = std::char::from_u32(char_code).ok_or_else(|| { + XmlDecodeError::invalid_escape(format!( + "invalid char code: {}", + char_code + )) })?; - let chr = - std::char::from_u32(char_code).ok_or(XmlError::InvalidEscape { - esc: format!("invalid char code: {}", char_code), - })?; res.push(chr); } } // push everything from the `;` to the next `&` res.push_str(§ion[idx + 1..]) } - None => { - return Err(XmlError::InvalidEscape { - esc: "Unterminated pattern".to_string(), - }) - } + None => return Err(XmlDecodeError::invalid_escape("unterminated pattern")), } } Ok(Cow::Owned(res)) diff --git a/rust-runtime/aws-smithy-xml/tests/handwritten_parsers.rs b/rust-runtime/aws-smithy-xml/tests/handwritten_parsers.rs index a58f0b3241a..8db9e202c06 100644 --- a/rust-runtime/aws-smithy-xml/tests/handwritten_parsers.rs +++ b/rust-runtime/aws-smithy-xml/tests/handwritten_parsers.rs @@ -10,7 +10,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_xml::decode::{try_data, Document, ScopedDecoder, XmlError}; +use aws_smithy_xml::decode::{try_data, Document, ScopedDecoder, XmlDecodeError}; use std::collections::HashMap; #[derive(Eq, PartialEq, Debug)] @@ -40,7 +40,7 @@ struct XmlAttribute { bar: String, } -fn deserialize_xml_attribute(inp: &str) -> Result { +fn deserialize_xml_attribute(inp: &str) -> Result { let mut doc = Document::new(inp); let mut root = doc.root_element()?; #[allow(unused_assignments)] @@ -54,12 +54,12 @@ fn deserialize_xml_attribute(inp: &str) -> Result { } } Ok(XmlAttribute { - foo: foo.ok_or_else(|| XmlError::custom("missing foo"))?, - bar: bar.ok_or_else(|| XmlError::custom("missing bar"))?, + foo: foo.ok_or_else(|| XmlDecodeError::custom("missing foo"))?, + bar: bar.ok_or_else(|| XmlDecodeError::custom("missing bar"))?, }) } -fn deserialize_flat_xml_map(inp: &str) -> Result { +fn deserialize_flat_xml_map(inp: &str) -> Result { let mut doc = Document::new(inp); let mut root = doc.root_element()?; let mut my_map: Option> = None; @@ -75,7 +75,7 @@ fn deserialize_flat_xml_map(inp: &str) -> Result { }) } -fn deserialize_xml_map(inp: &str) -> Result { +fn deserialize_xml_map(inp: &str) -> Result { let mut doc = Document::new(inp); let mut root = doc.root_element()?; let mut my_map: Option> = None; @@ -85,13 +85,13 @@ fn deserialize_xml_map(inp: &str) -> Result { } } Ok(XmlMap { - values: my_map.ok_or_else(|| XmlError::custom("missing map"))?, + values: my_map.ok_or_else(|| XmlDecodeError::custom("missing map"))?, }) } fn deserialize_foo_enum_map( decoder: &mut ScopedDecoder, -) -> Result, XmlError> { +) -> Result, XmlDecodeError> { let mut out: HashMap = HashMap::new(); while let Some(mut tag) = decoder.next_tag() { if tag.start_el().matches("entry") { @@ -104,7 +104,7 @@ fn deserialize_foo_enum_map( fn deserialize_foo_enum_map_entry( decoder: &mut ScopedDecoder, out: &mut HashMap, -) -> Result<(), XmlError> { +) -> Result<(), XmlDecodeError> { let mut k: Option = None; let mut v: Option = None; while let Some(mut tag) = decoder.next_tag() { @@ -118,7 +118,7 @@ fn deserialize_foo_enum_map_entry( (Some(k), Some(v)) => { out.insert(k, v); } - _ => return Err(XmlError::custom("missing key value in map")), + _ => return Err(XmlDecodeError::custom("missing key value in map")), } Ok(()) } @@ -150,7 +150,7 @@ fn deserialize_map_test() { pub fn deserialize_nested_string_list( decoder: &mut ScopedDecoder, -) -> Result>, XmlError> { +) -> Result>, XmlDecodeError> { let mut out = std::vec::Vec::new(); while let Some(mut tag) = decoder.next_tag() { match tag.start_el() { @@ -165,7 +165,7 @@ pub fn deserialize_nested_string_list( pub fn deserialize_string_list( decoder: &mut ScopedDecoder, -) -> Result, XmlError> { +) -> Result, XmlDecodeError> { let mut out = std::vec::Vec::new(); while let Some(mut tag) = decoder.next_tag() { match dbg!(tag.start_el()) { diff --git a/rust-runtime/aws-smithy-xml/tests/handwritten_serializers.rs b/rust-runtime/aws-smithy-xml/tests/handwritten_serializers.rs index 2ca9c129482..e6f0f3967e2 100644 --- a/rust-runtime/aws-smithy-xml/tests/handwritten_serializers.rs +++ b/rust-runtime/aws-smithy-xml/tests/handwritten_serializers.rs @@ -4,8 +4,7 @@ */ use aws_smithy_protocol_test::{validate_body, MediaType}; -use aws_smithy_xml::encode; -use aws_smithy_xml::encode::ScopeWriter; +use aws_smithy_xml::encode::{ScopeWriter, XmlEncodeError, XmlWriter}; // @namespace http://www.example.com struct WithNamespace { @@ -19,10 +18,10 @@ struct Nested { inner: WithNamespace, } -fn serialize_nested(nested: &Nested) -> Result { +fn serialize_nested(nested: &Nested) -> Result { let mut out = String::new(); { - let mut writer = encode::XmlWriter::new(&mut out); + let mut writer = XmlWriter::new(&mut out); let mut start_el = writer.start_el("Nested"); start_el.write_attribute("a", &nested.a); let mut tag = start_el.finish(); @@ -32,12 +31,10 @@ fn serialize_nested(nested: &Nested) -> Result Result { +fn serialize_with_namespace(with_namespace: &WithNamespace) -> Result { let mut out = String::new(); { - let mut writer = encode::XmlWriter::new(&mut out); + let mut writer = XmlWriter::new(&mut out); let root = writer.start_el("MyStructure"); let mut root_scope = root.write_ns("http://foo.com", None).finish(); with_namespace_inner(&mut root_scope, with_namespace); diff --git a/rust-runtime/inlineable/src/ec2_query_errors.rs b/rust-runtime/inlineable/src/ec2_query_errors.rs index 76152c97ad7..a7fc1b11631 100644 --- a/rust-runtime/inlineable/src/ec2_query_errors.rs +++ b/rust-runtime/inlineable/src/ec2_query_errors.rs @@ -3,17 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_xml::decode::{try_data, Document, ScopedDecoder, XmlError}; +use aws_smithy_xml::decode::{try_data, Document, ScopedDecoder, XmlDecodeError}; use std::convert::TryFrom; #[allow(unused)] -pub fn body_is_error(body: &[u8]) -> Result { +pub fn body_is_error(body: &[u8]) -> Result { let mut doc = Document::try_from(body)?; let scoped = doc.root_element()?; Ok(scoped.start_el().matches("Response")) } -pub fn parse_generic_error(body: &[u8]) -> Result { +pub fn parse_generic_error(body: &[u8]) -> Result { let mut doc = Document::try_from(body)?; let mut root = doc.root_element()?; let mut err_builder = aws_smithy_types::Error::builder(); @@ -46,12 +46,14 @@ pub fn parse_generic_error(body: &[u8]) -> Result(doc: &'a mut Document<'b>) -> Result, XmlError> { +pub fn error_scope<'a, 'b>( + doc: &'a mut Document<'b>, +) -> Result, XmlDecodeError> { let root = doc .next_start_element() - .ok_or_else(|| XmlError::custom("no root found searching for an Error"))?; + .ok_or_else(|| XmlDecodeError::custom("no root found searching for an Error"))?; if !root.matches("Response") { - return Err(XmlError::custom("expected Response as root")); + return Err(XmlDecodeError::custom("expected Response as root")); } while let Some(el) = doc.next_start_element() { @@ -64,7 +66,7 @@ pub fn error_scope<'a, 'b>(doc: &'a mut Document<'b>) -> Result Result { +pub fn body_is_error(body: &[u8]) -> Result { let mut doc = Document::try_from(body)?; let scoped = doc.root_element()?; Ok(scoped.start_el().matches("Error")) } -pub fn error_scope<'a, 'b>(doc: &'a mut Document<'b>) -> Result, XmlError> { +pub fn error_scope<'a, 'b>( + doc: &'a mut Document<'b>, +) -> Result, XmlDecodeError> { let scoped = doc.root_element()?; if !scoped.start_el().matches("Error") { - return Err(XmlError::custom("expected error as root")); + return Err(XmlDecodeError::custom("expected error as root")); } Ok(scoped) } -pub fn parse_generic_error(body: &[u8]) -> Result { +pub fn parse_generic_error(body: &[u8]) -> Result { let mut doc = Document::try_from(body)?; let mut root = doc.root_element()?; let mut err = aws_smithy_types::Error::builder(); diff --git a/rust-runtime/inlineable/src/rest_xml_wrapped_errors.rs b/rust-runtime/inlineable/src/rest_xml_wrapped_errors.rs index b1aadf3e45e..c90301bf396 100644 --- a/rust-runtime/inlineable/src/rest_xml_wrapped_errors.rs +++ b/rust-runtime/inlineable/src/rest_xml_wrapped_errors.rs @@ -3,17 +3,17 @@ * SPDX-License-Identifier: Apache-2.0 */ -use aws_smithy_xml::decode::{try_data, Document, ScopedDecoder, XmlError}; +use aws_smithy_xml::decode::{try_data, Document, ScopedDecoder, XmlDecodeError}; use std::convert::TryFrom; #[allow(unused)] -pub fn body_is_error(body: &[u8]) -> Result { +pub fn body_is_error(body: &[u8]) -> Result { let mut doc = Document::try_from(body)?; let scoped = doc.root_element()?; Ok(scoped.start_el().matches("ErrorResponse")) } -pub fn parse_generic_error(body: &[u8]) -> Result { +pub fn parse_generic_error(body: &[u8]) -> Result { let mut doc = Document::try_from(body)?; let mut root = doc.root_element()?; let mut err_builder = aws_smithy_types::Error::builder(); @@ -42,12 +42,14 @@ pub fn parse_generic_error(body: &[u8]) -> Result(doc: &'a mut Document<'b>) -> Result, XmlError> { +pub fn error_scope<'a, 'b>( + doc: &'a mut Document<'b>, +) -> Result, XmlDecodeError> { let root = doc .next_start_element() - .ok_or_else(|| XmlError::custom("no root found searching for an Error"))?; + .ok_or_else(|| XmlDecodeError::custom("no root found searching for an Error"))?; if !root.matches("ErrorResponse") { - return Err(XmlError::custom("expected ErrorResponse as root")); + return Err(XmlDecodeError::custom("expected ErrorResponse as root")); } while let Some(el) = doc.next_start_element() { @@ -56,7 +58,9 @@ pub fn error_scope<'a, 'b>(doc: &'a mut Document<'b>) -> Result