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>
impl<TD: TableDefinition> Item<TD>
Sourcepub fn extract_key(self) -> (Key<TD>, HashMap<String, AttributeValue>)
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"));Sourcepub fn into_key_only(self) -> Key<TD>
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>
impl<TD: TableDefinition> Item<TD>
Sourcepub fn pk(
&self,
) -> <<<<TD as TableDefinition>::KeySchema as KeySchema>::PartitionKey as AttributeDefinition>::Type as AttributeValueRef>::Ref<'_>
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");Sourcepub fn attribute<A: AttributeDefinition>(
&self,
) -> Option<<A::Type as AttributeValueRef>::Ref<'_>>
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());Sourcepub fn into_inner(self) -> HashMap<String, AttributeValue>
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"));Sourcepub fn minimal_from<DBI: DynamoDBItem<TD>>(dynamodb_item: &DBI) -> Self
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"));Sourcepub fn with_attributes(
self,
attributes: impl Into<HashMap<String, AttributeValue>>,
) -> Self
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"));Sourcepub fn from_key_and_attributes(
key: Key<TD>,
attributes: impl Into<HashMap<String, AttributeValue>>,
) -> Self
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>where
TD::KeySchema: CompositeKeySchema,
impl<TD: TableDefinition> Item<TD>where
TD::KeySchema: CompositeKeySchema,
Sourcepub fn sk(
&self,
) -> <<<<TD as TableDefinition>::KeySchema as CompositeKeySchema>::SortKey as AttributeDefinition>::Type as AttributeValueRef>::Ref<'_>
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 · Sourcepub fn capacity(&self) -> usize
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 · Sourcepub fn keys(&self) -> Keys<'_, K, V>
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 · Sourcepub fn values(&self) -> Values<'_, K, V>
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 · Sourcepub fn iter(&self) -> Iter<'_, K, V>
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 · Sourcepub fn len(&self) -> usize
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 · Sourcepub fn is_empty(&self) -> bool
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 · Sourcepub fn hasher(&self) -> &S
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 · Sourcepub fn get<Q>(&self, k: &Q) -> Option<&V>
pub fn get<Q>(&self, k: &Q) -> Option<&V>
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 · Sourcepub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
pub fn get_key_value<Q>(&self, k: &Q) -> Option<(&K, &V)>
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
&Kstored key value from a borrowed&Qlookup 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 · Sourcepub fn contains_key<Q>(&self, k: &Q) -> bool
pub fn contains_key<Q>(&self, k: &Q) -> bool
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: TableDefinition> Debug for Item<TD>
impl<TD: TableDefinition> Debug for Item<TD>
Source§impl<TD: TableDefinition> Deref for Item<TD>
impl<TD: TableDefinition> Deref for Item<TD>
Source§impl<TD: TableDefinition> IntoIterator for Item<TD>
impl<TD: TableDefinition> IntoIterator for Item<TD>
Source§type Item = <HashMap<String, AttributeValue> as IntoIterator>::Item
type Item = <HashMap<String, AttributeValue> as IntoIterator>::Item
Source§type IntoIter = <HashMap<String, AttributeValue> as IntoIterator>::IntoIter
type IntoIter = <HashMap<String, AttributeValue> as IntoIterator>::IntoIter
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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