Skip to main content

dynamodb_item

Macro dynamodb_item 

Source
macro_rules! dynamodb_item {
    {
        #[table = $table:path]
        $item:ty {
            $(
                #[$attr_mod:ident]
                $modified_attr:path {$($modified_blk:tt)+}
            )+
            $(
                $attr:path {$($blk:tt)+}
            )*
        }
    } => { ... };
    {
        #[table = $table:path]
        $item:ty {
            $(
                #[$attr_mod:ident]
                $modified_attr:path {$($modified_blk:tt)+}
            )*
            $(
                $attr_before:path {$($blk_before:tt)+}
            )+
            #[$attr_mod_after:ident]
            $modified_attr_after:path {$($modified_blk_after:tt)+}
            $($rest:tt)*
        }
    } => { ... };
    {
        @modtop
        #[table = $table:path]
        $item:ty {
            #[partition_key]
            $pk_attr:path {$($pk_blk:tt)+}
            $(
                #[$attr_mod:ident]
                $modified_attr:path {$($modified_blk:tt)+}
            )*
            $(
                $attr:path {$($blk:tt)+}
            )*
        }
    } => { ... };
    {
        @modtop
        #[table = $table:path]
        $item:ty {
            #[$first_attr_mod:ident]
            $first_modified_attr:path {$($first_modified_blk:tt)+}
            $(
                #[$attr_mod:ident]
                $modified_attr:path {$($modified_blk:tt)+}
            )+
            $(
                $attr:path {$($blk:tt)+}
            )*
        }
    } => { ... };
    {
        @pktop
        #[table = $table:path]
        $item:ty {
            #[partition_key]
            $pk_attr:path {$($pk_blk:tt)+}
            #[sort_key]
            $sk_attr:path {$($sk_blk:tt)+}
            $(
                #[$attr_mod:ident]
                $modified_attr:path {$($modified_blk:tt)+}
            )*
            $(
                $attr:path {$($blk:tt)+}
            )*
            $(
                @barier
                $(
                    #[$attr_mod_after:ident]
                    $modified_attr_after:path {$($modified_blk_after:tt)+}
                )+
            )?
        }
    } => { ... };
    {
        @pktop
        #[table = $table:path]
        $item:ty {
            #[partition_key]
            $pk_attr:path {$($pk_blk:tt)+}
            #[$first_attr_mod:ident]
            $first_modified_attr:path {$($first_modified_blk:tt)+}
            $(
                #[$attr_mod:ident]
                $modified_attr:path {$($modified_blk:tt)+}
            )*
            $(
                $attr:path {$($blk:tt)+}
            )*
            $(
                @barier
                $(
                    #[$attr_mod_after:ident]
                    $modified_attr_after:path {$($modified_blk_after:tt)+}
                )+
            )?
        }
    } => { ... };
    {
        @pktop
        #[table = $table:path]
        $item:ty {
            #[partition_key]
            $pk_attr:path {$($pk_blk:tt)+}
            $(
                $attr:path {$($blk:tt)+}
            )*
            $(
                @barier
                $(
                    #[$attr_mod_after:ident]
                    $modified_attr_after:path {$($modified_blk_after:tt)+}
                )+
            )?
        }
    } => { ... };
    {
        @allsorted
        #[table = $table:path]
        $item:ty {
            #[partition_key]
            $pk_attr:path {$($pk_blk:tt)+}
            $(
                #[sort_key]
                $sk_attr:path {$($sk_blk:tt)+}
            )?
            $(
                #[marker_only]
                $marker_only_attr:path {$($marker_only_blk:tt)+}
            )*
            $(
                $attr:path {$($blk:tt)+}
            )*
        }
    } => { ... };
    {
        @dbitem $table:path; $item:ty {
            $($attr:path)*
        }
    } => { ... };
    {
        #[table = $table:path]
        $item:ty {$($tt:tt)*}
    } => { ... };
    ($($tt:tt)*) => { ... };
}
Expand description

Wires a Rust struct to a DynamoDB table by implementing DynamoDBItem and the attribute traits.

This is the primary macro for defining how a Rust type maps to a DynamoDB item. It generates:

  • DynamoDBItem<TD> — with the correct AdditionalAttributes type derived from the non-key, non-#[marker_only] attribute blocks.
  • HasAttribute or HasConstAttribute for every attribute block, including the partition key and sort key.

§Syntax

dynamodb_item! {
    #[table = TableType]
    StructType {
        #[partition_key]
        PkAttr { ... }

        #[sort_key]           // optional
        SkAttr { ... }

        #[marker_only]        // optional; implements HasAttribute but excluded from AdditionalAttributes
        OtherAttr { ... }

        AdditionalAttr { ... }
        ...
    }
}

Each attribute block uses the same syntax as has_attributes!: either const VALUE: T = expr; for constant attributes, or fn attribute_id(&self) -> T { ... } + fn attribute_value(id) -> T { ... } for dynamic attributes. The return type of attribute_id is always the input type of attribute_value — the two form a pipeline.

When attribute_id returns a reference (typically borrowing a String field to avoid cloning), annotate it with the 'id lifetime: &'id str. This lifetime is dictated by the Id<'id> associated type. See has_attributes! for a detailed explanation.

§Attribute modifiers

  • #[partition_key] — marks the partition key attribute. Required.
  • #[sort_key] — marks the sort key attribute. Optional; omit for simple-key tables.
  • #[marker_only] — implements HasAttribute for the attribute (e.g. for GSI membership) but does not add it to AdditionalAttributes, because the attribute is already serialized as part of the struct’s serde representation.

§Examples

Singleton item (constant PK + SK):

use dynamodb_facade::dynamodb_item;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
struct AppConfig {
    pub feature_flags: Vec<String>,
}

dynamodb_item! {
    #[table = PlatformTable]
    AppConfig {
        #[partition_key]
        PK { const VALUE: &'static str = "APP_CONFIG"; }
        #[sort_key]
        SK { const VALUE: &'static str = "APP_CONFIG"; }
        ItemType { const VALUE: &'static str = "APP_CONFIG"; }
    }
}

Variable PK, constant SK:

use dynamodb_facade::dynamodb_item;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
struct Course {
    pub id: String,
    pub title: String,
    pub email: String,
}

dynamodb_item! {
    #[table = PlatformTable]
    Course {
        #[partition_key]
        PK {
            // Borrows self.id as &'id str — no clone needed.
            // attribute_value then receives that same &str.
            fn attribute_id(&self) -> &'id str { &self.id }
            fn attribute_value(id) -> String { format!("COURSE#{id}") }
        }
        #[sort_key]
        SK { const VALUE: &'static str = "COURSE"; }
        // email is already part of the struct and serialized by serde,
        // so use #[marker_only] to exclude it from AdditionalAttributes
        #[marker_only]
        Email {
            fn attribute_id(&self) -> &'id str { &self.email }
            fn attribute_value(id) -> String { id.to_owned() }
        }
        // The constant ItemType attribute is part of AdditionalAttributes
        // and will be added to each Course item
        ItemType { const VALUE: &'static str = "COURSE"; }
    }
}