Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions dynomite-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,12 @@ fn get_item_trait(
let partition_key_insert = partition_key_field.map(get_key_inserter).transpose()?;
let sort_key_insert = sort_key_field.map(get_key_inserter).transpose()?;

let partition_key_tuple = partition_key_field.map(get_key_tuple);
let sort_key_tuple = sort_key_field
.map(get_key_tuple)
.map(|tuple| quote! { Some(#tuple) })
.unwrap_or_else(|| quote! { None });

Ok(partition_key_field
.map(|_| {
quote! {
Expand All @@ -714,6 +720,14 @@ fn get_item_trait(
#sort_key_insert
keys
}

fn partition_key(&self) -> (String, ::dynomite::dynamodb::AttributeValue) {
#partition_key_tuple
}

fn sort_key(&self) -> Option<(String, ::dynomite::dynamodb::AttributeValue)> {
#sort_key_tuple
}
}
}
})
Expand All @@ -738,6 +752,19 @@ fn get_key_inserter(field: &ItemField) -> syn::Result<impl ToTokens> {
})
}

/// ```rust,ignore
/// ("field_deser_name", to_attribute_value(field))
/// ```
fn get_key_tuple(field: &ItemField) -> impl ToTokens {
let to_attribute_value = quote!(::dynomite::Attribute::into_attr);

let field_deser_name = field.deser_name();
let field_ident = &field.field.ident;
quote! {
(#field_deser_name.to_string(), #to_attribute_value(self.#field_ident.clone()))
}
}

/// ```rust,ignore
/// #[derive(Item, Debug, Clone, PartialEq)]
/// pub struct NameKey {
Expand Down
16 changes: 15 additions & 1 deletion dynomite/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,17 @@ pub type Attributes = HashMap<String, AttributeValue>;
/// impl Item for Person {
/// fn key(&self) -> Attributes {
/// let mut attrs = HashMap::new();
/// attrs.insert("id".into(), "123".to_string().into_attr());
/// attrs.insert("id".into(), self.id.clone().into_attr());
/// attrs
/// }
///
/// fn partition_key(&self) -> (String, AttributeValue) {
/// ("id".into(), self.id.clone().into_attr())
/// }
///
/// fn sort_key(&self) -> Option<(String, AttributeValue)> {
/// None
/// }
/// }
///
/// impl FromAttributes for Person {
Expand Down Expand Up @@ -518,6 +526,12 @@ pub trait Item: IntoAttributes + FromAttributes {
///
/// This is often used in item look ups
fn key(&self) -> Attributes;

/// Returns a tuple containing the name and value of the partition key
fn partition_key(&self) -> (String, AttributeValue);

/// Returns a tuple containing the name and value of the sort key, if this item has one
fn sort_key(&self) -> Option<(String, AttributeValue)>;
}

/// A type capable of being converted into an or from and AWS `AttributeValue`
Expand Down
27 changes: 27 additions & 0 deletions dynomite/tests/derived.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ impl Default for Category {
pub struct Book {
#[dynomite(partition_key)]
title: String,
#[dynomite(sort_key)]
category: Category,
authors: Option<Vec<Author>>,
}
Expand Down Expand Up @@ -130,6 +131,32 @@ mod tests {
servings: 1,
};
assert_eq!(value.key(), RecipeKey { id: "test".into() }.into());
assert_eq!(
value.partition_key(),
("RecipeId".to_string(), "test".to_string().into_attr())
);
assert!(value.sort_key().is_none());

let value = Book {
title: "rust".into(),
..Default::default()
};
assert_eq!(
value.key(),
BookKey {
title: "rust".into(),
category: Category::Foo,
}
.into()
);
assert_eq!(
value.partition_key(),
("title".to_string(), "rust".to_string().into_attr())
);
assert_eq!(
value.sort_key(),
Some(("category".to_string(), "Foo".to_string().into_attr()))
)
}

#[test]
Expand Down