AWS SDK

AWS SDK

rev. 39b55ba789d23348fd70aff57161c9e5dc302333

Files changed:

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-types/src/lib.rs

@@ -3,3 +47,49 @@
   23     23   
pub mod byte_stream;
   24     24   
pub mod checksum_config;
   25     25   
/// A typemap for storing configuration.
   26     26   
pub mod config_bag;
   27     27   
pub mod date_time;
   28     28   
pub mod endpoint;
   29     29   
pub mod error;
   30     30   
pub mod event_stream;
   31     31   
pub mod primitive;
   32     32   
pub mod retry;
          33  +
/// Runtime schema types for Smithy shapes.
          34  +
pub mod schema;
   33     35   
pub mod timeout;
   34     36   
   35     37   
/// Utilities for type erasure.
   36     38   
pub mod type_erasure;
   37     39   
   38     40   
mod blob;
   39     41   
mod document;
   40     42   
mod number;
   41     43   
pub mod str_bytes;
   42     44   

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-types/src/schema.rs

@@ -0,1 +0,254 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Runtime schema types for Smithy shapes.
           7  +
//!
           8  +
//! This module provides the core types for representing Smithy schemas at runtime,
           9  +
//! enabling protocol-agnostic serialization and deserialization.
          10  +
          11  +
mod shape_id;
          12  +
mod shape_type;
          13  +
mod trait_map;
          14  +
mod trait_type;
          15  +
          16  +
pub mod prelude;
          17  +
pub mod serde;
          18  +
          19  +
pub use shape_id::ShapeId;
          20  +
pub use shape_type::ShapeType;
          21  +
pub use trait_map::TraitMap;
          22  +
pub use trait_type::Trait;
          23  +
          24  +
/// Core trait representing a Smithy schema at runtime.
          25  +
///
          26  +
/// A schema is a lightweight runtime representation of a Smithy shape,
          27  +
/// containing the shape's ID, type, traits, and references to member schemas.
          28  +
pub trait Schema: Send + Sync {
          29  +
    /// Returns the Shape ID of this schema.
          30  +
    fn shape_id(&self) -> &ShapeId;
          31  +
          32  +
    /// Returns the shape type.
          33  +
    fn shape_type(&self) -> ShapeType;
          34  +
          35  +
    /// Returns the traits associated with this schema.
          36  +
    fn traits(&self) -> &TraitMap;
          37  +
          38  +
    /// Returns the member name if this is a member schema.
          39  +
    fn member_name(&self) -> Option<&str> {
          40  +
        None
          41  +
    }
          42  +
          43  +
    /// Returns the member schema by name (for structures and unions).
          44  +
    fn member_schema(&self, _name: &str) -> Option<&dyn Schema> {
          45  +
        None
          46  +
    }
          47  +
          48  +
    /// Returns the member schema by position index (for structures and unions).
          49  +
    ///
          50  +
    /// This is an optimization for generated code to avoid string lookups.
          51  +
    /// Consumer code should not rely on specific position values as they may change.
          52  +
    fn member_schema_by_index(&self, _index: usize) -> Option<&dyn Schema> {
          53  +
        None
          54  +
    }
          55  +
          56  +
    /// Returns the member schema for collections (list member or map value).
          57  +
    fn member(&self) -> Option<&dyn Schema> {
          58  +
        None
          59  +
    }
          60  +
          61  +
    /// Returns the key schema for maps.
          62  +
    fn key(&self) -> Option<&dyn Schema> {
          63  +
        None
          64  +
    }
          65  +
          66  +
    /// Returns an iterator over member schemas (for structures and unions).
          67  +
    fn members(&self) -> Box<dyn Iterator<Item = &dyn Schema> + '_> {
          68  +
        Box::new(std::iter::empty())
          69  +
    }
          70  +
          71  +
    /// Returns the member index for member schemas.
          72  +
    ///
          73  +
    /// This is used internally by generated code for efficient member lookup.
          74  +
    /// Returns None if not applicable or not a member schema.
          75  +
    fn member_index(&self) -> Option<usize> {
          76  +
        None
          77  +
    }
          78  +
}
          79  +
          80  +
/// Helper methods for Schema trait.
          81  +
pub trait SchemaExt: Schema {
          82  +
    /// Returns true if this is a member schema.
          83  +
    fn is_member(&self) -> bool {
          84  +
        self.shape_type().is_member()
          85  +
    }
          86  +
          87  +
    /// Returns true if this is a structure schema.
          88  +
    fn is_structure(&self) -> bool {
          89  +
        self.shape_type() == ShapeType::Structure
          90  +
    }
          91  +
          92  +
    /// Returns true if this is a union schema.
          93  +
    fn is_union(&self) -> bool {
          94  +
        self.shape_type() == ShapeType::Union
          95  +
    }
          96  +
          97  +
    /// Returns true if this is a list schema.
          98  +
    fn is_list(&self) -> bool {
          99  +
        self.shape_type() == ShapeType::List
         100  +
    }
         101  +
         102  +
    /// Returns true if this is a map schema.
         103  +
    fn is_map(&self) -> bool {
         104  +
        self.shape_type() == ShapeType::Map
         105  +
    }
         106  +
         107  +
    /// Returns true if this is a blob schema.
         108  +
    fn is_blob(&self) -> bool {
         109  +
        self.shape_type() == ShapeType::Blob
         110  +
    }
         111  +
         112  +
    /// Returns true if this is a string schema.
         113  +
    fn is_string(&self) -> bool {
         114  +
        self.shape_type() == ShapeType::String
         115  +
    }
         116  +
}
         117  +
         118  +
impl<T: Schema + ?Sized> SchemaExt for T {}
         119  +
         120  +
#[cfg(test)]
         121  +
mod test {
         122  +
    use crate::schema::{Schema, SchemaExt, ShapeId, ShapeType, Trait, TraitMap};
         123  +
         124  +
    // Simple test trait implementation
         125  +
    #[derive(Debug)]
         126  +
    struct TestTrait {
         127  +
        id: ShapeId,
         128  +
        #[allow(dead_code)]
         129  +
        value: String,
         130  +
    }
         131  +
         132  +
    impl Trait for TestTrait {
         133  +
        fn trait_id(&self) -> &ShapeId {
         134  +
            &self.id
         135  +
        }
         136  +
         137  +
        fn as_any(&self) -> &dyn std::any::Any {
         138  +
            self
         139  +
        }
         140  +
    }
         141  +
         142  +
    // Simple test schema implementation
         143  +
    struct TestSchema {
         144  +
        id: ShapeId,
         145  +
        shape_type: ShapeType,
         146  +
        traits: TraitMap,
         147  +
    }
         148  +
         149  +
    impl Schema for TestSchema {
         150  +
        fn shape_id(&self) -> &ShapeId {
         151  +
            &self.id
         152  +
        }
         153  +
         154  +
        fn shape_type(&self) -> ShapeType {
         155  +
            self.shape_type
         156  +
        }
         157  +
         158  +
        fn traits(&self) -> &TraitMap {
         159  +
            &self.traits
         160  +
        }
         161  +
    }
         162  +
         163  +
    #[test]
         164  +
    fn test_shape_type_simple() {
         165  +
        assert!(ShapeType::String.is_simple());
         166  +
        assert!(ShapeType::Integer.is_simple());
         167  +
        assert!(ShapeType::Boolean.is_simple());
         168  +
        assert!(!ShapeType::Structure.is_simple());
         169  +
        assert!(!ShapeType::List.is_simple());
         170  +
    }
         171  +
         172  +
    #[test]
         173  +
    fn test_shape_type_aggregate() {
         174  +
        assert!(ShapeType::Structure.is_aggregate());
         175  +
        assert!(ShapeType::Union.is_aggregate());
         176  +
        assert!(ShapeType::List.is_aggregate());
         177  +
        assert!(ShapeType::Map.is_aggregate());
         178  +
        assert!(!ShapeType::String.is_aggregate());
         179  +
    }
         180  +
         181  +
    #[test]
         182  +
    fn test_shape_type_member() {
         183  +
        assert!(ShapeType::Member.is_member());
         184  +
        assert!(!ShapeType::String.is_member());
         185  +
        assert!(!ShapeType::Structure.is_member());
         186  +
    }
         187  +
         188  +
    #[test]
         189  +
    fn test_shape_id_parsing() {
         190  +
        let id = ShapeId::new("smithy.api#String");
         191  +
        assert_eq!(id.namespace(), Some("smithy.api"));
         192  +
        assert_eq!(id.shape_name(), Some("String"));
         193  +
        assert_eq!(id.member_name(), None);
         194  +
    }
         195  +
         196  +
    #[test]
         197  +
    fn test_shape_id_with_member() {
         198  +
        let id = ShapeId::new("com.example#MyStruct$member");
         199  +
        assert_eq!(id.namespace(), Some("com.example"));
         200  +
        assert_eq!(id.shape_name(), Some("MyStruct"));
         201  +
        assert_eq!(id.member_name(), Some("member"));
         202  +
    }
         203  +
         204  +
    #[test]
         205  +
    fn test_trait_map() {
         206  +
        let mut map = TraitMap::new();
         207  +
        assert!(map.is_empty());
         208  +
        assert_eq!(map.len(), 0);
         209  +
         210  +
        let trait_id = ShapeId::new("smithy.api#required");
         211  +
        let test_trait = Box::new(TestTrait {
         212  +
            id: trait_id.clone(),
         213  +
            value: "test".to_string(),
         214  +
        });
         215  +
         216  +
        map.insert(test_trait);
         217  +
        assert!(!map.is_empty());
         218  +
        assert_eq!(map.len(), 1);
         219  +
        assert!(map.contains(&trait_id));
         220  +
         221  +
        let retrieved = map.get(&trait_id);
         222  +
        assert!(retrieved.is_some());
         223  +
    }
         224  +
         225  +
    #[test]
         226  +
    fn test_schema_ext() {
         227  +
        let schema = TestSchema {
         228  +
            id: ShapeId::new("com.example#MyStruct"),
         229  +
            shape_type: ShapeType::Structure,
         230  +
            traits: TraitMap::new(),
         231  +
        };
         232  +
         233  +
        assert!(schema.is_structure());
         234  +
        assert!(!schema.is_union());
         235  +
        assert!(!schema.is_list());
         236  +
        assert!(!schema.is_member());
         237  +
    }
         238  +
         239  +
    #[test]
         240  +
    fn test_schema_basic() {
         241  +
        let schema = TestSchema {
         242  +
            id: ShapeId::new("smithy.api#String"),
         243  +
            shape_type: ShapeType::String,
         244  +
            traits: TraitMap::new(),
         245  +
        };
         246  +
         247  +
        assert_eq!(schema.shape_id().as_str(), "smithy.api#String");
         248  +
        assert_eq!(schema.shape_type(), ShapeType::String);
         249  +
        assert!(schema.traits().is_empty());
         250  +
        assert!(schema.member_name().is_none());
         251  +
        assert!(schema.member_schema("test").is_none());
         252  +
        assert!(schema.member_schema_by_index(0).is_none());
         253  +
    }
         254  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-types/src/schema/prelude.rs

@@ -0,1 +0,176 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Prelude schemas for built-in Smithy types.
           7  +
//!
           8  +
//! This module provides const schemas for Smithy's prelude types,
           9  +
//! which are the fundamental types available in all Smithy models.
          10  +
          11  +
use crate::schema::{Schema, ShapeId, ShapeType, TraitMap};
          12  +
          13  +
/// A simple schema implementation for prelude types.
          14  +
#[derive(Debug)]
          15  +
pub struct PreludeSchema {
          16  +
    id: ShapeId,
          17  +
    shape_type: ShapeType,
          18  +
}
          19  +
          20  +
impl PreludeSchema {
          21  +
    /// Creates a new prelude schema.
          22  +
    pub const fn new(id: ShapeId, shape_type: ShapeType) -> Self {
          23  +
        Self { id, shape_type }
          24  +
    }
          25  +
}
          26  +
          27  +
impl Schema for PreludeSchema {
          28  +
    fn shape_id(&self) -> &ShapeId {
          29  +
        &self.id
          30  +
    }
          31  +
          32  +
    fn shape_type(&self) -> ShapeType {
          33  +
        self.shape_type
          34  +
    }
          35  +
          36  +
    fn traits(&self) -> &TraitMap {
          37  +
        static EMPTY_TRAITS: TraitMap = TraitMap::empty();
          38  +
        &EMPTY_TRAITS
          39  +
    }
          40  +
}
          41  +
          42  +
// TODO(schema): We should probably test with these as `pub static` too since that could
          43  +
// theoretically cut down on binary size (at the expense of some runtime performance)
          44  +
          45  +
/// Schema for `smithy.api#String`
          46  +
pub const STRING: PreludeSchema =
          47  +
    PreludeSchema::new(ShapeId::from_static("smithy.api#String"), ShapeType::String);
          48  +
          49  +
/// Schema for `smithy.api#Boolean`
          50  +
pub const BOOLEAN: PreludeSchema = PreludeSchema::new(
          51  +
    ShapeId::from_static("smithy.api#Boolean"),
          52  +
    ShapeType::Boolean,
          53  +
);
          54  +
          55  +
/// Schema for `smithy.api#Byte`
          56  +
pub const BYTE: PreludeSchema =
          57  +
    PreludeSchema::new(ShapeId::from_static("smithy.api#Byte"), ShapeType::Byte);
          58  +
          59  +
/// Schema for `smithy.api#Short`
          60  +
pub const SHORT: PreludeSchema =
          61  +
    PreludeSchema::new(ShapeId::from_static("smithy.api#Short"), ShapeType::Short);
          62  +
          63  +
/// Schema for `smithy.api#Integer`
          64  +
pub const INTEGER: PreludeSchema = PreludeSchema::new(
          65  +
    ShapeId::from_static("smithy.api#Integer"),
          66  +
    ShapeType::Integer,
          67  +
);
          68  +
          69  +
/// Schema for `smithy.api#Long`
          70  +
pub const LONG: PreludeSchema =
          71  +
    PreludeSchema::new(ShapeId::from_static("smithy.api#Long"), ShapeType::Long);
          72  +
          73  +
/// Schema for `smithy.api#Float`
          74  +
pub const FLOAT: PreludeSchema =
          75  +
    PreludeSchema::new(ShapeId::from_static("smithy.api#Float"), ShapeType::Float);
          76  +
          77  +
/// Schema for `smithy.api#Double`
          78  +
pub const DOUBLE: PreludeSchema =
          79  +
    PreludeSchema::new(ShapeId::from_static("smithy.api#Double"), ShapeType::Double);
          80  +
          81  +
/// Schema for `smithy.api#BigInteger`
          82  +
pub const BIG_INTEGER: PreludeSchema = PreludeSchema::new(
          83  +
    ShapeId::from_static("smithy.api#BigInteger"),
          84  +
    ShapeType::BigInteger,
          85  +
);
          86  +
          87  +
/// Schema for `smithy.api#BigDecimal`
          88  +
pub const BIG_DECIMAL: PreludeSchema = PreludeSchema::new(
          89  +
    ShapeId::from_static("smithy.api#BigDecimal"),
          90  +
    ShapeType::BigDecimal,
          91  +
);
          92  +
          93  +
/// Schema for `smithy.api#Blob`
          94  +
pub const BLOB: PreludeSchema =
          95  +
    PreludeSchema::new(ShapeId::from_static("smithy.api#Blob"), ShapeType::Blob);
          96  +
          97  +
/// Schema for `smithy.api#Timestamp`
          98  +
pub const TIMESTAMP: PreludeSchema = PreludeSchema::new(
          99  +
    ShapeId::from_static("smithy.api#Timestamp"),
         100  +
    ShapeType::Timestamp,
         101  +
);
         102  +
         103  +
/// Schema for `smithy.api#Document`
         104  +
pub const DOCUMENT: PreludeSchema = PreludeSchema::new(
         105  +
    ShapeId::from_static("smithy.api#Document"),
         106  +
    ShapeType::Document,
         107  +
);
         108  +
         109  +
#[cfg(test)]
         110  +
mod tests {
         111  +
    use super::*;
         112  +
    use crate::schema::SchemaExt;
         113  +
         114  +
    #[test]
         115  +
    fn test_string_schema() {
         116  +
        assert_eq!(STRING.shape_id().as_str(), "smithy.api#String");
         117  +
        assert_eq!(STRING.shape_type(), ShapeType::String);
         118  +
        assert!(STRING.is_string());
         119  +
        assert!(STRING.traits().is_empty());
         120  +
    }
         121  +
         122  +
    #[test]
         123  +
    fn test_boolean_schema() {
         124  +
        assert_eq!(BOOLEAN.shape_id().as_str(), "smithy.api#Boolean");
         125  +
        assert_eq!(BOOLEAN.shape_type(), ShapeType::Boolean);
         126  +
        assert!(BOOLEAN.traits().is_empty());
         127  +
    }
         128  +
         129  +
    #[test]
         130  +
    fn test_numeric_schemas() {
         131  +
        assert_eq!(BYTE.shape_type(), ShapeType::Byte);
         132  +
        assert_eq!(SHORT.shape_type(), ShapeType::Short);
         133  +
        assert_eq!(INTEGER.shape_type(), ShapeType::Integer);
         134  +
        assert_eq!(LONG.shape_type(), ShapeType::Long);
         135  +
        assert_eq!(FLOAT.shape_type(), ShapeType::Float);
         136  +
        assert_eq!(DOUBLE.shape_type(), ShapeType::Double);
         137  +
        assert_eq!(BIG_INTEGER.shape_type(), ShapeType::BigInteger);
         138  +
        assert_eq!(BIG_DECIMAL.shape_type(), ShapeType::BigDecimal);
         139  +
    }
         140  +
         141  +
    #[test]
         142  +
    fn test_blob_schema() {
         143  +
        assert_eq!(BLOB.shape_id().as_str(), "smithy.api#Blob");
         144  +
        assert_eq!(BLOB.shape_type(), ShapeType::Blob);
         145  +
        assert!(BLOB.is_blob());
         146  +
    }
         147  +
         148  +
    #[test]
         149  +
    fn test_timestamp_schema() {
         150  +
        assert_eq!(TIMESTAMP.shape_id().as_str(), "smithy.api#Timestamp");
         151  +
        assert_eq!(TIMESTAMP.shape_type(), ShapeType::Timestamp);
         152  +
    }
         153  +
         154  +
    #[test]
         155  +
    fn test_document_schema() {
         156  +
        assert_eq!(DOCUMENT.shape_id().as_str(), "smithy.api#Document");
         157  +
        assert_eq!(DOCUMENT.shape_type(), ShapeType::Document);
         158  +
    }
         159  +
         160  +
    #[test]
         161  +
    fn test_all_prelude_types_are_simple() {
         162  +
        assert!(STRING.shape_type().is_simple());
         163  +
        assert!(BOOLEAN.shape_type().is_simple());
         164  +
        assert!(BYTE.shape_type().is_simple());
         165  +
        assert!(SHORT.shape_type().is_simple());
         166  +
        assert!(INTEGER.shape_type().is_simple());
         167  +
        assert!(LONG.shape_type().is_simple());
         168  +
        assert!(FLOAT.shape_type().is_simple());
         169  +
        assert!(DOUBLE.shape_type().is_simple());
         170  +
        assert!(BIG_INTEGER.shape_type().is_simple());
         171  +
        assert!(BIG_DECIMAL.shape_type().is_simple());
         172  +
        assert!(BLOB.shape_type().is_simple());
         173  +
        assert!(TIMESTAMP.shape_type().is_simple());
         174  +
        assert!(DOCUMENT.shape_type().is_simple());
         175  +
    }
         176  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-types/src/schema/serde.rs

@@ -0,1 +0,412 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Serialization and deserialization interfaces for the Smithy data model.
           7  +
           8  +
mod deserializer;
           9  +
mod serializer;
          10  +
          11  +
pub use deserializer::ShapeDeserializer;
          12  +
pub use serializer::{SerializableStruct, ShapeSerializer};
          13  +
          14  +
#[cfg(test)]
          15  +
mod test {
          16  +
    use crate::schema::serde::{ShapeDeserializer, ShapeSerializer};
          17  +
    use crate::schema::{prelude::*, Schema};
          18  +
    use std::fmt;
          19  +
          20  +
    // Mock error type for testing
          21  +
    #[derive(Debug)]
          22  +
    struct MockError(String);
          23  +
          24  +
    impl fmt::Display for MockError {
          25  +
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
          26  +
            write!(f, "{}", self.0)
          27  +
        }
          28  +
    }
          29  +
          30  +
    impl std::error::Error for MockError {}
          31  +
          32  +
    // Mock serializer for testing
          33  +
    struct MockSerializer {
          34  +
        output: Vec<String>,
          35  +
    }
          36  +
          37  +
    impl ShapeSerializer for MockSerializer {
          38  +
        type Output = Vec<String>;
          39  +
        type Error = MockError;
          40  +
          41  +
        fn finish(self) -> Result<Self::Output, Self::Error> {
          42  +
            Ok(self.output)
          43  +
        }
          44  +
          45  +
        fn write_struct<F>(
          46  +
            &mut self,
          47  +
            schema: &dyn Schema,
          48  +
            write_members: F,
          49  +
        ) -> Result<(), Self::Error>
          50  +
        where
          51  +
            F: FnOnce(&mut Self) -> Result<(), Self::Error>,
          52  +
        {
          53  +
            self.output
          54  +
                .push(format!("struct({})", schema.shape_id().as_str()));
          55  +
            write_members(self)?;
          56  +
            self.output.push("end_struct".to_string());
          57  +
            Ok(())
          58  +
        }
          59  +
          60  +
        fn write_list<F>(
          61  +
            &mut self,
          62  +
            schema: &dyn Schema,
          63  +
            write_elements: F,
          64  +
        ) -> Result<(), Self::Error>
          65  +
        where
          66  +
            F: FnOnce(&mut Self) -> Result<(), Self::Error>,
          67  +
        {
          68  +
            self.output
          69  +
                .push(format!("list({})", schema.shape_id().as_str()));
          70  +
            write_elements(self)?;
          71  +
            self.output.push("end_list".to_string());
          72  +
            Ok(())
          73  +
        }
          74  +
          75  +
        fn write_map<F>(&mut self, schema: &dyn Schema, write_entries: F) -> Result<(), Self::Error>
          76  +
        where
          77  +
            F: FnOnce(&mut Self) -> Result<(), Self::Error>,
          78  +
        {
          79  +
            self.output
          80  +
                .push(format!("map({})", schema.shape_id().as_str()));
          81  +
            write_entries(self)?;
          82  +
            self.output.push("end_map".to_string());
          83  +
            Ok(())
          84  +
        }
          85  +
          86  +
        fn write_boolean(&mut self, _schema: &dyn Schema, value: bool) -> Result<(), Self::Error> {
          87  +
            self.output.push(format!("bool({})", value));
          88  +
            Ok(())
          89  +
        }
          90  +
          91  +
        fn write_byte(&mut self, _schema: &dyn Schema, value: i8) -> Result<(), Self::Error> {
          92  +
            self.output.push(format!("byte({})", value));
          93  +
            Ok(())
          94  +
        }
          95  +
          96  +
        fn write_short(&mut self, _schema: &dyn Schema, value: i16) -> Result<(), Self::Error> {
          97  +
            self.output.push(format!("short({})", value));
          98  +
            Ok(())
          99  +
        }
         100  +
         101  +
        fn write_integer(&mut self, _schema: &dyn Schema, value: i32) -> Result<(), Self::Error> {
         102  +
            self.output.push(format!("int({})", value));
         103  +
            Ok(())
         104  +
        }
         105  +
         106  +
        fn write_long(&mut self, _schema: &dyn Schema, value: i64) -> Result<(), Self::Error> {
         107  +
            self.output.push(format!("long({})", value));
         108  +
            Ok(())
         109  +
        }
         110  +
         111  +
        fn write_float(&mut self, _schema: &dyn Schema, value: f32) -> Result<(), Self::Error> {
         112  +
            self.output.push(format!("float({})", value));
         113  +
            Ok(())
         114  +
        }
         115  +
         116  +
        fn write_double(&mut self, _schema: &dyn Schema, value: f64) -> Result<(), Self::Error> {
         117  +
            self.output.push(format!("double({})", value));
         118  +
            Ok(())
         119  +
        }
         120  +
         121  +
        fn write_big_integer(
         122  +
            &mut self,
         123  +
            _schema: &dyn Schema,
         124  +
            value: &crate::BigInteger,
         125  +
        ) -> Result<(), Self::Error> {
         126  +
            self.output.push(format!("bigint({})", value.as_ref()));
         127  +
            Ok(())
         128  +
        }
         129  +
         130  +
        fn write_big_decimal(
         131  +
            &mut self,
         132  +
            _schema: &dyn Schema,
         133  +
            value: &crate::BigDecimal,
         134  +
        ) -> Result<(), Self::Error> {
         135  +
            self.output.push(format!("bigdec({})", value.as_ref()));
         136  +
            Ok(())
         137  +
        }
         138  +
         139  +
        fn write_string(&mut self, _schema: &dyn Schema, value: &str) -> Result<(), Self::Error> {
         140  +
            self.output.push(format!("string({})", value));
         141  +
            Ok(())
         142  +
        }
         143  +
         144  +
        fn write_blob(
         145  +
            &mut self,
         146  +
            _schema: &dyn Schema,
         147  +
            value: &crate::Blob,
         148  +
        ) -> Result<(), Self::Error> {
         149  +
            self.output
         150  +
                .push(format!("blob({} bytes)", value.as_ref().len()));
         151  +
            Ok(())
         152  +
        }
         153  +
         154  +
        fn write_timestamp(
         155  +
            &mut self,
         156  +
            _schema: &dyn Schema,
         157  +
            value: &crate::DateTime,
         158  +
        ) -> Result<(), Self::Error> {
         159  +
            self.output.push(format!("timestamp({})", value));
         160  +
            Ok(())
         161  +
        }
         162  +
         163  +
        fn write_document(
         164  +
            &mut self,
         165  +
            _schema: &dyn Schema,
         166  +
            _value: &crate::Document,
         167  +
        ) -> Result<(), Self::Error> {
         168  +
            self.output.push("document".to_string());
         169  +
            Ok(())
         170  +
        }
         171  +
         172  +
        fn write_null(&mut self, _schema: &dyn Schema) -> Result<(), Self::Error> {
         173  +
            self.output.push("null".to_string());
         174  +
            Ok(())
         175  +
        }
         176  +
    }
         177  +
         178  +
    // Mock deserializer for testing
         179  +
    struct MockDeserializer {
         180  +
        values: Vec<String>,
         181  +
        index: usize,
         182  +
    }
         183  +
         184  +
    impl MockDeserializer {
         185  +
        fn new(values: Vec<String>) -> Self {
         186  +
            Self { values, index: 0 }
         187  +
        }
         188  +
    }
         189  +
         190  +
    impl ShapeDeserializer for MockDeserializer {
         191  +
        type Error = MockError;
         192  +
         193  +
        fn read_struct<T, F>(
         194  +
            &mut self,
         195  +
            _schema: &dyn Schema,
         196  +
            state: T,
         197  +
            mut consumer: F,
         198  +
        ) -> Result<T, Self::Error>
         199  +
        where
         200  +
            F: FnMut(T, &dyn Schema, &mut Self) -> Result<T, Self::Error>,
         201  +
        {
         202  +
            // Simulate reading 2 members
         203  +
            let state = consumer(state, &STRING, self)?;
         204  +
            let state = consumer(state, &INTEGER, self)?;
         205  +
            Ok(state)
         206  +
        }
         207  +
         208  +
        fn read_list<T, F>(
         209  +
            &mut self,
         210  +
            _schema: &dyn Schema,
         211  +
            mut state: T,
         212  +
            mut consumer: F,
         213  +
        ) -> Result<T, Self::Error>
         214  +
        where
         215  +
            F: FnMut(T, &mut Self) -> Result<T, Self::Error>,
         216  +
        {
         217  +
            // Simulate reading 3 elements
         218  +
            for _ in 0..3 {
         219  +
                state = consumer(state, self)?;
         220  +
            }
         221  +
            Ok(state)
         222  +
        }
         223  +
         224  +
        fn read_map<T, F>(
         225  +
            &mut self,
         226  +
            _schema: &dyn Schema,
         227  +
            mut state: T,
         228  +
            mut consumer: F,
         229  +
        ) -> Result<T, Self::Error>
         230  +
        where
         231  +
            F: FnMut(T, String, &mut Self) -> Result<T, Self::Error>,
         232  +
        {
         233  +
            // Simulate reading 2 entries
         234  +
            state = consumer(state, "key1".to_string(), self)?;
         235  +
            state = consumer(state, "key2".to_string(), self)?;
         236  +
            Ok(state)
         237  +
        }
         238  +
         239  +
        fn read_boolean(&mut self, _schema: &dyn Schema) -> Result<bool, Self::Error> {
         240  +
            Ok(true)
         241  +
        }
         242  +
         243  +
        fn read_byte(&mut self, _schema: &dyn Schema) -> Result<i8, Self::Error> {
         244  +
            Ok(42)
         245  +
        }
         246  +
         247  +
        fn read_short(&mut self, _schema: &dyn Schema) -> Result<i16, Self::Error> {
         248  +
            Ok(1000)
         249  +
        }
         250  +
         251  +
        fn read_integer(&mut self, _schema: &dyn Schema) -> Result<i32, Self::Error> {
         252  +
            Ok(123456)
         253  +
        }
         254  +
         255  +
        fn read_long(&mut self, _schema: &dyn Schema) -> Result<i64, Self::Error> {
         256  +
            Ok(9876543210)
         257  +
        }
         258  +
         259  +
        fn read_float(&mut self, _schema: &dyn Schema) -> Result<f32, Self::Error> {
         260  +
            Ok(3.14)
         261  +
        }
         262  +
         263  +
        fn read_double(&mut self, _schema: &dyn Schema) -> Result<f64, Self::Error> {
         264  +
            Ok(2.71828)
         265  +
        }
         266  +
         267  +
        fn read_big_integer(
         268  +
            &mut self,
         269  +
            _schema: &dyn Schema,
         270  +
        ) -> Result<crate::BigInteger, Self::Error> {
         271  +
            use std::str::FromStr;
         272  +
            Ok(crate::BigInteger::from_str("12345").unwrap())
         273  +
        }
         274  +
         275  +
        fn read_big_decimal(
         276  +
            &mut self,
         277  +
            _schema: &dyn Schema,
         278  +
        ) -> Result<crate::BigDecimal, Self::Error> {
         279  +
            use std::str::FromStr;
         280  +
            Ok(crate::BigDecimal::from_str("123.45").unwrap())
         281  +
        }
         282  +
         283  +
        fn read_string(&mut self, _schema: &dyn Schema) -> Result<String, Self::Error> {
         284  +
            if self.index < self.values.len() {
         285  +
                let value = self.values[self.index].clone();
         286  +
                self.index += 1;
         287  +
                Ok(value)
         288  +
            } else {
         289  +
                Ok("default".to_string())
         290  +
            }
         291  +
        }
         292  +
         293  +
        fn read_blob(&mut self, _schema: &dyn Schema) -> Result<crate::Blob, Self::Error> {
         294  +
            Ok(crate::Blob::new(vec![1, 2, 3, 4]))
         295  +
        }
         296  +
         297  +
        fn read_timestamp(&mut self, _schema: &dyn Schema) -> Result<crate::DateTime, Self::Error> {
         298  +
            Ok(crate::DateTime::from_secs(1234567890))
         299  +
        }
         300  +
         301  +
        fn read_document(&mut self, _schema: &dyn Schema) -> Result<crate::Document, Self::Error> {
         302  +
            Ok(crate::Document::Null)
         303  +
        }
         304  +
         305  +
        fn is_null(&mut self) -> bool {
         306  +
            false
         307  +
        }
         308  +
         309  +
        fn container_size(&mut self) -> Option<usize> {
         310  +
            Some(10)
         311  +
        }
         312  +
    }
         313  +
         314  +
    #[test]
         315  +
    fn test_serializer_simple_types() {
         316  +
        let mut ser = MockSerializer { output: Vec::new() };
         317  +
         318  +
        ser.write_boolean(&BOOLEAN, true).unwrap();
         319  +
        ser.write_integer(&INTEGER, 42).unwrap();
         320  +
        ser.write_string(&STRING, "hello").unwrap();
         321  +
         322  +
        let output = ser.finish().unwrap();
         323  +
        assert_eq!(output, vec!["bool(true)", "int(42)", "string(hello)"]);
         324  +
    }
         325  +
         326  +
    #[test]
         327  +
    fn test_serializer_struct() {
         328  +
        let mut ser = MockSerializer { output: Vec::new() };
         329  +
         330  +
        ser.write_struct(&STRING, |s| {
         331  +
            s.write_string(&STRING, "field1")?;
         332  +
            s.write_integer(&INTEGER, 123)?;
         333  +
            Ok(())
         334  +
        })
         335  +
        .unwrap();
         336  +
         337  +
        let output = ser.finish().unwrap();
         338  +
        assert_eq!(
         339  +
            output,
         340  +
            vec![
         341  +
                "struct(smithy.api#String)",
         342  +
                "string(field1)",
         343  +
                "int(123)",
         344  +
                "end_struct"
         345  +
            ]
         346  +
        );
         347  +
    }
         348  +
         349  +
    #[test]
         350  +
    fn test_deserializer_simple_types() {
         351  +
        let mut deser = MockDeserializer::new(vec!["test".to_string()]);
         352  +
         353  +
        assert_eq!(deser.read_boolean(&BOOLEAN).unwrap(), true);
         354  +
        assert_eq!(deser.read_integer(&INTEGER).unwrap(), 123456);
         355  +
        assert_eq!(deser.read_string(&STRING).unwrap(), "test");
         356  +
        assert_eq!(deser.container_size(), Some(10));
         357  +
        assert!(!deser.is_null());
         358  +
    }
         359  +
         360  +
    #[test]
         361  +
    fn test_deserializer_struct() {
         362  +
        let mut deser = MockDeserializer::new(vec!["value1".to_string(), "value2".to_string()]);
         363  +
         364  +
        let mut fields = Vec::new();
         365  +
        deser
         366  +
            .read_struct(&STRING, &mut fields, |fields, _member, d| {
         367  +
                fields.push(d.read_string(&STRING)?);
         368  +
                Ok(fields)
         369  +
            })
         370  +
            .unwrap();
         371  +
         372  +
        assert_eq!(fields, vec!["value1", "value2"]);
         373  +
    }
         374  +
         375  +
    #[test]
         376  +
    fn test_deserializer_list() {
         377  +
        let mut deser =
         378  +
            MockDeserializer::new(vec!["a".to_string(), "b".to_string(), "c".to_string()]);
         379  +
         380  +
        let mut elements = Vec::new();
         381  +
        deser
         382  +
            .read_list(&STRING, &mut elements, |elements, d| {
         383  +
                elements.push(d.read_string(&STRING)?);
         384  +
                Ok(elements)
         385  +
            })
         386  +
            .unwrap();
         387  +
         388  +
        assert_eq!(elements, vec!["a", "b", "c"]);
         389  +
    }
         390  +
         391  +
    #[test]
         392  +
    fn test_deserializer_map() {
         393  +
        let mut deser = MockDeserializer::new(vec!["val1".to_string(), "val2".to_string()]);
         394  +
         395  +
        let mut entries = Vec::new();
         396  +
        deser
         397  +
            .read_map(&STRING, &mut entries, |entries, key, d| {
         398  +
                let value = d.read_string(&STRING)?;
         399  +
                entries.push((key, value));
         400  +
                Ok(entries)
         401  +
            })
         402  +
            .unwrap();
         403  +
         404  +
        assert_eq!(
         405  +
            entries,
         406  +
            vec![
         407  +
                ("key1".to_string(), "val1".to_string()),
         408  +
                ("key2".to_string(), "val2".to_string())
         409  +
            ]
         410  +
        );
         411  +
    }
         412  +
}

tmp-codegen-diff/aws-sdk/sdk/aws-smithy-types/src/schema/serde/deserializer.rs

@@ -0,1 +0,176 @@
           1  +
/*
           2  +
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
           3  +
 * SPDX-License-Identifier: Apache-2.0
           4  +
 */
           5  +
           6  +
//! Shape deserialization interfaces for the Smithy data model.
           7  +
           8  +
use crate::schema::Schema;
           9  +
use crate::{BigDecimal, BigInteger, Blob, DateTime, Document};
          10  +
use std::error::Error;
          11  +
          12  +
/// Deserializes Smithy shapes from a serial format.
          13  +
///
          14  +
/// This trait provides a format-agnostic API for deserializing the Smithy data model.
          15  +
/// Implementations read from a serial format and create data objects based on schemas.
          16  +
///
          17  +
/// The deserializer uses a consumer pattern for aggregate types (structures, lists, maps)
          18  +
/// to avoid trait object limitations and enable efficient deserialization without
          19  +
/// intermediate allocations.
          20  +
///
          21  +
/// # Consumer Pattern
          22  +
///
          23  +
/// For aggregate types, the deserializer calls a consumer function for each element/member.
          24  +
/// The consumer receives mutable state and updates it with each deserialized value.
          25  +
/// This pattern:
          26  +
/// - Avoids trait object issues with generic methods
          27  +
/// - Enables zero-cost abstractions (closures can be inlined)
          28  +
/// - Allows caller to control deserialization order and state management
          29  +
/// - Matches the SEP's recommendation for compiled typed languages
          30  +
///
          31  +
/// # Example
          32  +
///
          33  +
/// ```ignore
          34  +
/// // Deserializing a structure
          35  +
/// let mut builder = MyStructBuilder::default();
          36  +
/// deserializer.read_struct(
          37  +
///     &MY_STRUCT_SCHEMA,
          38  +
///     builder,
          39  +
///     |mut builder, member, deser| {
          40  +
///         match member.member_index() {
          41  +
///             0 => builder.field1 = Some(deser.read_string(member)?),
          42  +
///             1 => builder.field2 = Some(deser.read_i32(member)?),
          43  +
///             _ => {}
          44  +
///         }
          45  +
///         Ok(builder)
          46  +
///     },
          47  +
/// )?;
          48  +
/// let my_struct = builder.build();
          49  +
/// ```
          50  +
pub trait ShapeDeserializer {
          51  +
    /// The error type returned by deserialization operations.
          52  +
    type Error: Error;
          53  +
          54  +
    /// Reads a structure from the deserializer.
          55  +
    ///
          56  +
    /// The structure deserialization is driven by a consumer callback that is called
          57  +
    /// for each member. The consumer receives the current state, the member schema,
          58  +
    /// and the deserializer, and returns the updated state.
          59  +
    ///
          60  +
    /// # Arguments
          61  +
    ///
          62  +
    /// * `schema` - The schema of the structure being deserialized
          63  +
    /// * `state` - Initial state (typically a builder)
          64  +
    /// * `consumer` - Callback invoked for each member with (state, member_schema, deserializer)
          65  +
    ///
          66  +
    /// # Returns
          67  +
    ///
          68  +
    /// The final state after processing all members
          69  +
    fn read_struct<T, F>(
          70  +
        &mut self,
          71  +
        schema: &dyn Schema,
          72  +
        state: T,
          73  +
        consumer: F,
          74  +
    ) -> Result<T, Self::Error>
          75  +
    where
          76  +
        F: FnMut(T, &dyn Schema, &mut Self) -> Result<T, Self::Error>;
          77  +
          78  +
    /// Reads a list from the deserializer.
          79  +
    ///
          80  +
    /// The list deserialization is driven by a consumer callback that is called
          81  +
    /// for each element. The consumer receives the current state and the deserializer,
          82  +
    /// and returns the updated state.
          83  +
    ///
          84  +
    /// # Arguments
          85  +
    ///
          86  +
    /// * `schema` - The schema of the list being deserialized
          87  +
    /// * `state` - Initial state (typically a Vec or collection)
          88  +
    /// * `consumer` - Callback invoked for each element with (state, deserializer)
          89  +
    ///
          90  +
    /// # Returns
          91  +
    ///
          92  +
    /// The final state after processing all elements
          93  +
    fn read_list<T, F>(
          94  +
        &mut self,
          95  +
        schema: &dyn Schema,
          96  +
        state: T,
          97  +
        consumer: F,
          98  +
    ) -> Result<T, Self::Error>
          99  +
    where
         100  +
        F: FnMut(T, &mut Self) -> Result<T, Self::Error>;
         101  +
         102  +
    /// Reads a map from the deserializer.
         103  +
    ///
         104  +
    /// The map deserialization is driven by a consumer callback that is called
         105  +
    /// for each entry. The consumer receives the current state, the key, and the
         106  +
    /// deserializer, and returns the updated state.
         107  +
    ///
         108  +
    /// # Arguments
         109  +
    ///
         110  +
    /// * `schema` - The schema of the map being deserialized
         111  +
    /// * `state` - Initial state (typically a HashMap or collection)
         112  +
    /// * `consumer` - Callback invoked for each entry with (state, key, deserializer)
         113  +
    ///
         114  +
    /// # Returns
         115  +
    ///
         116  +
    /// The final state after processing all entries
         117  +
    fn read_map<T, F>(
         118  +
        &mut self,
         119  +
        schema: &dyn Schema,
         120  +
        state: T,
         121  +
        consumer: F,
         122  +
    ) -> Result<T, Self::Error>
         123  +
    where
         124  +
        F: FnMut(T, String, &mut Self) -> Result<T, Self::Error>;
         125  +
         126  +
    /// Reads a boolean value.
         127  +
    fn read_boolean(&mut self, schema: &dyn Schema) -> Result<bool, Self::Error>;
         128  +
         129  +
    /// Reads a byte (i8) value.
         130  +
    fn read_byte(&mut self, schema: &dyn Schema) -> Result<i8, Self::Error>;
         131  +
         132  +
    /// Reads a short (i16) value.
         133  +
    fn read_short(&mut self, schema: &dyn Schema) -> Result<i16, Self::Error>;
         134  +
         135  +
    /// Reads an integer (i32) value.
         136  +
    fn read_integer(&mut self, schema: &dyn Schema) -> Result<i32, Self::Error>;
         137  +
         138  +
    /// Reads a long (i64) value.
         139  +
    fn read_long(&mut self, schema: &dyn Schema) -> Result<i64, Self::Error>;
         140  +
         141  +
    /// Reads a float (f32) value.
         142  +
    fn read_float(&mut self, schema: &dyn Schema) -> Result<f32, Self::Error>;
         143  +
         144  +
    /// Reads a double (f64) value.
         145  +
    fn read_double(&mut self, schema: &dyn Schema) -> Result<f64, Self::Error>;
         146  +
         147  +
    /// Reads a big integer value.
         148  +
    fn read_big_integer(&mut self, schema: &dyn Schema) -> Result<BigInteger, Self::Error>;
         149  +
         150  +
    /// Reads a big decimal value.
         151  +
    fn read_big_decimal(&mut self, schema: &dyn Schema) -> Result<BigDecimal, Self::Error>;
         152  +
         153  +
    /// Reads a string value.
         154  +
    fn read_string(&mut self, schema: &dyn Schema) -> Result<String, Self::Error>;
         155  +
         156  +
    /// Reads a blob (byte array) value.
         157  +
    fn read_blob(&mut self, schema: &dyn Schema) -> Result<Blob, Self::Error>;
         158  +
         159  +
    /// Reads a timestamp value.
         160  +
    fn read_timestamp(&mut self, schema: &dyn Schema) -> Result<DateTime, Self::Error>;
         161  +
         162  +
    /// Reads a document value.
         163  +
    fn read_document(&mut self, schema: &dyn Schema) -> Result<Document, Self::Error>;
         164  +
         165  +
    /// Checks if the current value is null.
         166  +
    ///
         167  +
    /// This is used for sparse collections where null values are significant.
         168  +
    fn is_null(&mut self) -> bool;
         169  +
         170  +
    /// Returns the size of the current container if known.
         171  +
    ///
         172  +
    /// This is an optimization hint that allows pre-allocating collections
         173  +
    /// with the correct capacity. Returns `None` if the size is unknown or
         174  +
    /// not applicable.
         175  +
    fn container_size(&mut self) -> Option<usize>;
         176  +
}