diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGenerator.kt index 80d89e341ff..993914b97c8 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGenerator.kt @@ -16,12 +16,14 @@ import software.amazon.smithy.rust.codegen.core.rustlang.RustWriter import software.amazon.smithy.rust.codegen.core.rustlang.asDeref import software.amazon.smithy.rust.codegen.core.rustlang.asRef import software.amazon.smithy.rust.codegen.core.rustlang.deprecatedShape +import software.amazon.smithy.rust.codegen.core.rustlang.docs import software.amazon.smithy.rust.codegen.core.rustlang.documentShape import software.amazon.smithy.rust.codegen.core.rustlang.isCopy import software.amazon.smithy.rust.codegen.core.rustlang.isDeref import software.amazon.smithy.rust.codegen.core.rustlang.render import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rustBlock +import software.amazon.smithy.rust.codegen.core.rustlang.stripOuter import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.customize.NamedCustomization @@ -131,15 +133,26 @@ open class StructureGenerator( writer.rustBlock("impl $name") { // Render field accessor methods forEachMember(accessorMembers) { member, memberName, memberSymbol -> - writer.renderMemberDoc(member, memberSymbol) - writer.deprecatedShape(member) val memberType = memberSymbol.rustType() + var unwrapOrDefault = false val returnType = when { + // Automatically flatten vecs + memberType is RustType.Option && memberType.stripOuter() is RustType.Vec -> { + unwrapOrDefault = true + memberType.stripOuter().asDeref().asRef() + } memberType.isCopy() -> memberType memberType is RustType.Option && memberType.member.isDeref() -> memberType.asDeref() memberType.isDeref() -> memberType.asDeref().asRef() else -> memberType.asRef() } + writer.renderMemberDoc(member, memberSymbol) + if (unwrapOrDefault) { + // Add a newline + writer.docs("") + writer.docs("If no value was sent for this field, a default will be set. If you want to determine if no value was sent, use `.$memberName.is_none()`.") + } + writer.deprecatedShape(member) writer.rustBlock("pub fn $memberName(&self) -> ${returnType.render()}") { when { memberType.isCopy() -> rust("self.$memberName") @@ -148,6 +161,9 @@ open class StructureGenerator( memberType.isDeref() -> rust("use std::ops::Deref; self.$memberName.deref()") else -> rust("&self.$memberName") } + if (unwrapOrDefault) { + rust(".unwrap_or_default()") + } } } } diff --git a/design/src/rfcs/rfc0035_collection_defaults.md b/design/src/rfcs/rfc0035_collection_defaults.md index 218782f7894..2237c02b2b2 100644 --- a/design/src/rfcs/rfc0035_collection_defaults.md +++ b/design/src/rfcs/rfc0035_collection_defaults.md @@ -3,7 +3,7 @@ RFC: Collection Defaults ============= -> Status: Accepted +> Status: Implemented > > Applies to: client @@ -78,5 +78,5 @@ No, many existing APIs don't have the default trait. Changes checklist ----------------- Estimated total work: 2 days -- [ ] Update accessor method generation to auto flatten lists -- [ ] Update docs for accessors to guide users to `.field.is_some()` if they MUST determine if the field was set. +- [x] Update accessor method generation to auto flatten lists +- [x] Update docs for accessors to guide users to `.field.is_some()` if they MUST determine if the field was set.