Skip to main content

Item

Struct Item 

Source
pub struct Item<TD: TableDefinition>(/* private fields */);
Expand description

A type-safe wrapper around a DynamoDB item for a specific table.

Item<TD> is a HashMap<String, AttributeValue> branded with the TableDefinition TD. The branding enforces at compile time that items from different tables are never mixed up, and it unlocks typed attribute accessors such as pk, sk, and attribute.

An Item<TD> is guaranteed to contain the table’s key attributes (PK, and SK for composite-key tables). This invariant is upheld by all constructors.

Item<TD> implements Deref to HashMap<String, AttributeValue>, so you can call .get("field") and other map methods directly.

§Examples

Building an item and inspecting its attributes:

use dynamodb_facade::DynamoDBItem;

let user /* : User */ = sample_user();
let item /* : Item<PlatformTable> */ = user.to_item();

// Typed key accessors — always present.
assert_eq!(item.pk(), "USER#user-1");
assert_eq!(item.sk(), "USER");

// Optional typed attribute access (present for the User type).
let item_type: Option<&str> = item.attribute::<ItemType>();
assert_eq!(item_type, Some("USER"));

Consuming the item into its raw map:

use dynamodb_facade::DynamoDBItem;

let item /* : Item<PlatformTable> */ = sample_user().to_item();
let raw /* : HashMap<String, AttributeValue> */ = item.into_inner();
assert!(raw.contains_key("PK"));

§Equality and hashing

Item<TD> intentionally does not implement PartialEq, Eq, or Hash. The backing type is a HashMap<String, AttributeValue>, and while attribute-value byte-equality could be derived, it does not match DynamoDB’s semantic equality (number string normalization, set element ordering, etc.). Compare items by deserializing to T first.

Implementations§

Source§

impl<TD: TableDefinition> Item<TD>
where Self: KeyItemExtractor<TD, <TD::KeySchema as KeySchema>::Kind>,

Source

pub fn extract_key(self) -> (Key<TD>, HashMap<String, AttributeValue>)

Splits the item into its key and the remaining non-key attributes.

Returns a tuple of (Key<TD>, HashMap<String, AttributeValue>) where the key contains only the PK (and SK for composite-key tables) and the map contains every other attribute that was in the item.

This is meant to allow the direct manipulation of the attribute map while enforcing the invariant that an Item always contains valid key attributes. Use it in conjunction with Item::from_key_and_attributes to accomplish that.

§Examples
use dynamodb_facade::DynamoDBItem;

let item = sample_user().to_item();
let (key, rest) = item.extract_key();

// Key contains only PK + SK.
let raw_key = key.into_inner();
assert!(raw_key.contains_key("PK"));
assert!(raw_key.contains_key("SK"));

// Remaining map has everything else.
assert!(rest.contains_key("name"));
assert!(!rest.contains_key("PK"));
Source

pub fn into_key_only(self) -> Key<TD>

Consumes the item and returns only its key, discarding all other attributes.

This is a convenience wrapper around extract_key that drops the remaining attribute map.

§Examples
use dynamodb_facade::DynamoDBItem;

let item = sample_user().to_item();
let key = item.into_key_only();

let raw = key.into_inner();
assert!(raw.contains_key("PK"));
assert!(raw.contains_key("SK"));
assert!(!raw.contains_key("name"));
Source§

impl<TD: TableDefinition> Item<TD>

Source

pub fn pk( &self, ) -> <<<<TD as TableDefinition>::KeySchema as KeySchema>::PartitionKey as AttributeDefinition>::Type as AttributeValueRef>::Ref<'_>

Returns the partition key value of this item.

The return type is a typed reference determined by the table’s partition key attribute definition (e.g. &str for a StringAttribute PK).

§Panics

Panics if the partition key attribute is absent. This should never happen for items produced by this crate’s constructors, which always include the key attributes.

§Examples
use dynamodb_facade::DynamoDBItem;

let item /* : Item<PlatformTable> */ = sample_user().to_item();
assert_eq!(item.pk(), "USER#user-1");
Source

pub fn attribute<A: AttributeDefinition>( &self, ) -> Option<<A::Type as AttributeValueRef>::Ref<'_>>

Returns a typed reference to the named attribute, or None if absent.

The attribute is identified by the type parameter A, which must implement AttributeDefinition. The return type is a typed reference whose concrete type is determined by A::Type (e.g. &str for StringAttribute, &str for NumberAttribute).

§Examples
use dynamodb_facade::DynamoDBItem;

let item /* : Item<PlatformTable> */ = sample_user().to_item();

// Present attribute:
let item_type: Option<&str> = item.attribute::<ItemType>();
assert_eq!(item_type, Some("USER"));

// Absent attribute returns None:
let expiration: Option<&str> = item.attribute::<Expiration>();
assert!(expiration.is_none());
Source

pub fn into_inner(self) -> HashMap<String, AttributeValue>

Consumes the item and returns the underlying raw attribute map.

Use this when you need to pass the item to code that works with the raw aws-sdk-dynamodb types.

Beware that you will not be able to re-construct the original Item<TD>. See Item::extract_key and Item::from_key_and_attributes if you want to manipulate the underlying HashMap and then re-create it afterward.

§Examples
use dynamodb_facade::DynamoDBItem;

let raw /* : HashMap<String, AttributeValue> */ = sample_user().to_item().into_inner();
assert!(raw.contains_key("PK"));
assert!(raw.contains_key("SK"));
Source

pub fn minimal_from<DBI: DynamoDBItem<TD>>(dynamodb_item: &DBI) -> Self

Creates a minimal Item<TD> from a DynamoDBItem value.

The resulting item contains only the key attributes (PK and SK for composite-key tables) and the type’s AdditionalAttributes (e.g. type discriminators). It does not include the serialized underlying type.

This is mainly used when you need to implement DynamoDBItem::to_item manually.

§Examples
use dynamodb_facade::{DynamoDBItem, Item};

let user = sample_user();
let minimal = Item::minimal_from(&user);

// Key attributes are present.
assert_eq!(minimal.pk(), "USER#user-1");
assert_eq!(minimal.sk(), "USER");

// The type discriminator (AdditionalAttributes) is also present.
assert_eq!(minimal.attribute::<ItemType>(), Some("USER"));

// But non-key payload fields are absent.
assert!(!minimal.contains_key("name"));
Source

pub fn with_attributes( self, attributes: impl Into<HashMap<String, AttributeValue>>, ) -> Self

Merges additional attributes into this item.

In case of an attribute name conflict, attributes already present on the item take precedence. In other words, this method cannot overwrite existing item attributes.

This is the mechanism used by DynamoDBItem::to_item’s default implementation to combine the full serde payload with the typed key attributes.

§Examples
use dynamodb_facade::{DynamoDBItem, Item, IntoAttributeValue};

let user = sample_user();
let minimal = Item::minimal_from(&user);

// Merge in extra attributes.
let enriched = minimal.with_attributes([
    ("extra".to_owned(), "hello".into_attribute_value()),
]);

assert_eq!(enriched.pk(), "USER#user-1");
assert!(enriched.contains_key("extra"));
Source

pub fn from_key_and_attributes( key: Key<TD>, attributes: impl Into<HashMap<String, AttributeValue>>, ) -> Self

Constructs an item from a Key<TD> and an additional attribute map.

The key attributes always take precedence: if attributes contains an entry with the same name as a key attribute, the key attribute wins.

§Examples
use dynamodb_facade::{DynamoDBItem, KeyBuilder, Item, IntoAttributeValue};

let key = sample_user().get_key();
let item: Item<PlatformTable> = Item::from_key_and_attributes(key, [
    ("role".to_owned(), "instructor".into_attribute_value()),
]);

assert_eq!(item.pk(), "USER#user-1");
assert!(item.contains_key("role"));
Source§

impl<TD: TableDefinition> Item<TD>

Source

pub fn sk( &self, ) -> <<<<TD as TableDefinition>::KeySchema as CompositeKeySchema>::SortKey as AttributeDefinition>::Type as AttributeValueRef>::Ref<'_>

Returns the sort key value of this item.

Only available when the table uses a CompositeKeySchema (PK + SK). The return type is a typed reference determined by the table’s sort key attribute definition (e.g. &str for a StringAttribute SK).

§Panics

Panics if the sort key attribute is absent. This should never happen for items produced by this crate’s constructors, which always include the key attributes.

§Examples
use dynamodb_facade::DynamoDBItem;

let item = sample_user().to_item();
assert_eq!(item.sk(), "USER");

let enrollment_item = sample_enrollment().to_item();
assert_eq!(enrollment_item.sk(), "ENROLL#course-42");

Methods from Deref<Target = HashMap<String, AttributeValue>>§

1.0.0 · Source

pub fn capacity(&self) -> usize

Returns the number of elements the map can hold without reallocating.

This number is a lower bound; the HashMap<K, V> might be able to hold more, but is guaranteed to be able to hold at least this many.

§Examples
use std::collections::HashMap;
let map: HashMap<i32, i32> = HashMap::with_capacity(100);
assert!(map.capacity() >= 100);
1.0.0 · Source

pub fn keys(&self) -> Keys<'_, K, V>

An iterator visiting all keys in arbitrary order. The iterator element type is &'a K.

§Examples
use std::collections::HashMap;

let map = HashMap::from([
    ("a", 1),
    ("b", 2),
    ("c", 3),
]);

for key in map.keys() {
    println!("{key}");
}
§Performance

In the current implementation, iterating over keys takes O(capacity) time instead of O(len) because it internally visits empty buckets too.

1.0.0 · Source

pub fn values(&self) -> Values<'_, K, V>

An iterator visiting all values in arbitrary order. The iterator element type is &'a V.

§Examples
use std::collections::HashMap;

let map = HashMap::from([
    ("a", 1),
    ("b", 2),
    ("c", 3),
]);

for val in map.values() {
    println!("{val}");
}
§Performance

In the current implementation, iterating over values takes O(capacity) time instead of O(len) because it internally visits empty buckets too.

1.0.0 · Source

pub fn iter(&self) -> Iter<'_, K, V>

An iterator visiting all key-value pairs in arbitrary order. The iterator element type is (&'a K, &'a V).

§Examples
use std::collections::HashMap;

let map = HashMap::from([
    ("a", 1),
    ("b", 2),
    ("c", 3),
]);

for (key, val) in map.iter() {
    println!("key: {key} val: {val}");
}
§Performance

In the current implementation, iterating over map takes O(capacity) time instead of O(len) because it internally visits empty buckets too.

1.0.0 · Source

pub fn len(&self) -> usize

Returns the number of elements in the map.

§Examples
use std::collections::HashMap;

let mut a = HashMap::new();
assert_eq!(a.len(), 0);
a.insert(1, "a");
assert_eq!(a.len(), 1);
1.0.0 · Source

pub fn is_empty(&self) -> bool

Returns true if the map contains no elements.

§Examples
use std::collections::HashMap;

let mut a = HashMap::new();
assert!(a.is_empty());
a.insert(1, "a");
assert!(!a.is_empty());
1.9.0 · Source

pub fn hasher(&self) -> &S

Returns a reference to the map’s BuildHasher.

§Examples
use std::collections::HashMap;
use std::hash::RandomState;

let hasher = RandomState::new();
let map: HashMap<i32, i32> = HashMap::with_hasher(hasher);
let hasher: &RandomState = map.hasher();
1.0.0 · Source

pub fn get<Q>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>, Q: Hash + Eq + ?Sized,

Returns a reference to the value corresponding to the key.

The key may be any borrowed form of the map’s key type, but Hash and Eq on the borrowed form must match those for the key type.

§Examples
use std::collections::HashMap;

let mut map = HashMap::new();
map.insert(1, "a");
assert_eq!(map.get(&1), Some(&"a"));
assert_eq!(map.get(&2), None);
1.40.0 · Source

pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
where K: Borrow<Q>, Q: Hash + Eq + ?Sized,

Returns the key-value pair corresponding to the supplied key. This is potentially useful:

  • for key types where non-identical keys can be considered equal;
  • for getting the &K stored key value from a borrowed &Q lookup key; or
  • for getting a reference to a key with the same lifetime as the collection.

The supplied key may be any borrowed form of the map’s key type, but Hash and Eq on the borrowed form must match those for the key type.

§Examples
use std::collections::HashMap;
use std::hash::{Hash, Hasher};

#[derive(Clone, Copy, Debug)]
struct S {
    id: u32,
    name: &'static str, // ignored by equality and hashing operations
}

impl PartialEq for S {
    fn eq(&self, other: &S) -> bool {
        self.id == other.id
    }
}

impl Eq for S {}

impl Hash for S {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id.hash(state);
    }
}

let j_a = S { id: 1, name: "Jessica" };
let j_b = S { id: 1, name: "Jess" };
let p = S { id: 2, name: "Paul" };
assert_eq!(j_a, j_b);

let mut map = HashMap::new();
map.insert(j_a, "Paris");
assert_eq!(map.get_key_value(&j_a), Some((&j_a, &"Paris")));
assert_eq!(map.get_key_value(&j_b), Some((&j_a, &"Paris"))); // the notable case
assert_eq!(map.get_key_value(&p), None);
1.0.0 · Source

pub fn contains_key<Q>(&self, k: &Q) -> bool
where K: Borrow<Q>, Q: Hash + Eq + ?Sized,

Returns true if the map contains a value for the specified key.

The key may be any borrowed form of the map’s key type, but Hash and Eq on the borrowed form must match those for the key type.

§Examples
use std::collections::HashMap;

let mut map = HashMap::new();
map.insert(1, "a");
assert_eq!(map.contains_key(&1), true);
assert_eq!(map.contains_key(&2), false);

Trait Implementations§

Source§

impl<TD: Clone + TableDefinition> Clone for Item<TD>

Source§

fn clone(&self) -> Item<TD>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<TD: TableDefinition> Debug for Item<TD>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<TD: TableDefinition> Deref for Item<TD>

Source§

type Target = HashMap<String, AttributeValue>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<TD: TableDefinition> From<Key<TD>> for Item<TD>

Source§

fn from(value: Key<TD>) -> Self

Converts to this type from the input type.
Source§

impl<TD: TableDefinition> IntoIterator for Item<TD>

Source§

type Item = <HashMap<String, AttributeValue> as IntoIterator>::Item

The type of the elements being iterated over.
Source§

type IntoIter = <HashMap<String, AttributeValue> as IntoIterator>::IntoIter

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more

Auto Trait Implementations§

§

impl<TD> Freeze for Item<TD>

§

impl<TD> RefUnwindSafe for Item<TD>
where TD: RefUnwindSafe,

§

impl<TD> Send for Item<TD>
where TD: Send,

§

impl<TD> Sync for Item<TD>
where TD: Sync,

§

impl<TD> Unpin for Item<TD>
where TD: Unpin,

§

impl<TD> UnsafeUnpin for Item<TD>

§

impl<TD> UnwindSafe for Item<TD>
where TD: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more