Skip to content

Commit 5e36924

Browse files
committed
Better document dynomite attributes
1 parent 49955e3 commit 5e36924

File tree

1 file changed

+131
-21
lines changed

1 file changed

+131
-21
lines changed

dynomite/src/lib.rs

Lines changed: 131 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
//! AWS typed values feel more natural and ergonomic in Rust. Where a conversion is not available you can implement `Attribute` for your own
1515
//! types to leverage higher level functionality.
1616
//!
17-
//! The [Item](trait.Item.html) type
17+
//! The [Item](trait.Item.html) trait
1818
//! provides conversion interfaces for complex types which represent
1919
//! DynamoDB's notion of "items".
2020
//!
21-
//! 💡 A cargo feature named "derive" makes it easy to derive `Item` instances for your custom types. This feature is enabled by default.
21+
//! 💡 A cargo feature named `"derive"` makes it easy to derive `Item` instances for your custom types. This feature is enabled by default.
2222
//!
2323
//!
2424
//! ```rust,no_run
@@ -33,31 +33,136 @@
3333
//! order_id: Uuid,
3434
//! color: Option<String>,
3535
//! }
36+
//! ```
3637
//!
37-
//! #[derive(Item)]
38-
//! struct ShoppingCart {
39-
//! #[dynomite(partition_key)]
40-
//! id: Uuid,
41-
//! // A separate struct to store data without any id
42-
//! #[dynomite(flatten)]
43-
//! data: ShoppingCartData,
44-
//! // Collect all other additional attributes into a map
45-
//! // Beware that the order of declaration will affect the order of
46-
//! // evaluation, so this "wildcard" flatten clause should be the last member
47-
//! #[dynomite(flatten)]
48-
//! remaining_props: Attributes,
49-
//! }
38+
//! ## Attributes
39+
//!
40+
//! ### `#[derive(Item)]`
41+
//! Used to define a top-level DynamoDB item.
42+
//! Generates a `<ItemName>Key` struct with only `partition_key/sort_key`
43+
//! fields to be used for type-safe primary key construction.
44+
//! This automatically derives [`Attributes`](#deriveattributes) too.
5045
//!
51-
//! // `Attributes` doesn't require neither of #[dynomite(partition_key/sort_key)]
46+
//! For the `Order` struct from the example higher this will generate an `OrderKey`
47+
//! struct like this:
48+
//!
49+
//! ```rust
50+
//! # use uuid::Uuid;
51+
//! # use dynomite::Attributes;
5252
//! #[derive(Attributes)]
53-
//! struct ShoppingCartData {
54-
//! // use Default value of the field if it is absent in DynamoDb
55-
//! #[dynomite(default)]
56-
//! orders: Vec<Order>,
57-
//! name: String,
53+
//! struct OrderKey {
54+
//! user: Uuid,
55+
//! order_id: Uuid,
56+
//! }
57+
//! ```
58+
//!
59+
//! Use it to safely and conveniently construct the primary key:
60+
//!
61+
//! ```rust
62+
//! # #[derive(dynomite::Attributes)]
63+
//! # struct Order {}
64+
//! # #[derive(Attributes)]
65+
//! # struct OrderKey {
66+
//! # user: Uuid,
67+
//! # order_id: Uuid,
68+
//! # }
69+
//! use dynomite::{Attributes, FromAttributes, dynamodb::{GetItemInput, DynamoDb}};
70+
//! use std::error::Error;
71+
//! use uuid::Uuid;
72+
//!
73+
//! async fn get_order(
74+
//! client: impl DynamoDb,
75+
//! user: Uuid,
76+
//! order_id: Uuid,
77+
//! ) -> Result<Option<Order>, Box<dyn Error>> {
78+
//! // Use the generated `OrderKey` struct to create a primary key
79+
//! let key = OrderKey { user, order_id };
80+
//! // Convert stronly-typed `OrderKey` to a map of `rusoto_dynamodb::AttributeValue`
81+
//! let key: Attributes = key.into();
82+
//!
83+
//! let result = client.get_item(GetItemInput {
84+
//! table_name: "orders".into(),
85+
//! key,
86+
//! ..Default::default()
87+
//! }).await?;
88+
//!
89+
//! Ok(result.item.map(|item| {
90+
//! Order::from_attrs(item).expect("Invalid order, db corruption?")
91+
//! }))
5892
//! }
5993
//! ```
6094
//!
95+
//! - `#[dynomite(partition_key)]` - required attribute, expected to be applied the target
96+
//! [partition attribute][partition-key] field with a derivable DynamoDB attribute value
97+
//! of String, Number or Binary
98+
//!
99+
//! - `#[dynomite(sort_key)]` - optional attribute, may be applied to one target
100+
//! [sort attribute](sort-key) field with an derivable DynamoDB attribute value
101+
//! of String, Number or Binary
102+
//!
103+
//! - All other attributes are the same as for [`#[derive(Attributes)]`](#deriveattributes)
104+
//!
105+
//! ### `#[derive(Attributes)]`
106+
//!
107+
//! Used to derive an implementation of `From/IntoAttributes` trait to allow for
108+
//! serializing/deserializing map-like types into [`AttributeValue`]
109+
//!
110+
//! - `#[dynomite(rename = "actualName")]` - optional attribute, may be applied to any item
111+
//! attribute field, useful when the DynamoDB table you're interfacing with has
112+
//! attributes whose names don't following Rust's naming conventions
113+
//!
114+
//! - `#[dynomite(default)]` - use [`Default::default`] implementation of the field type
115+
//! if the attribute is absent when deserializing from `Attributes`
116+
//!
117+
//! ```
118+
//! use dynomite::Attributes;
119+
//!
120+
//! #[derive(Attributes)]
121+
//! struct Todos {
122+
//! // use Default value of the field if it is absent in DynamoDb (empty vector)
123+
//! #[dynomite(default)]
124+
//! items: Vec<String>,
125+
//! list_name: String,
126+
//! }
127+
//! ```
128+
//!
129+
//! - `#[dynomite(flatten)]` - flattens the fields of other struct that also derives `Attributes`
130+
//! into the current struct.
131+
//!
132+
//! 💡 If this attribute is placed onto a field, no other `dynomite` attributes
133+
//! are alowed on this field (this restriction may be relaxed in future).
134+
//!
135+
//! This is reminiscent of [`#[serde(flatten)]`](serde-flatten). The order of
136+
//! declaration of `flatten`ed fields matters, if the struct has to fields with
137+
//! `#[dynomite(flatten)]` attribute the one that appears higher in code will
138+
//! be evaluated before the other one. This is crucial when you want to collect
139+
//! additional properties into a map:
140+
//!
141+
//! ```
142+
//! use dynomite::{Attributes, Item};
143+
//!
144+
//! #[derive(Item)]
145+
//! struct ShoppingCart {
146+
//! #[dynomite(partition_key)]
147+
//! id: String,
148+
//! // A separate struct to store data without any id
149+
//! #[dynomite(flatten)]
150+
//! data: ShoppingCartData,
151+
//! // Collect all other additional attributes into a map
152+
//! // Beware that the order of declaration will affect the order of
153+
//! // evaluation, so this "wildcard" flatten clause should be the last member
154+
//! #[dynomite(flatten)]
155+
//! remaining_props: Attributes,
156+
//! }
157+
//!
158+
//! // `Attributes` doesn't require neither of #[dynomite(partition_key/sort_key)]
159+
//! #[derive(Attributes)]
160+
//! struct ShoppingCartData {
161+
//! name: String,
162+
//! total_price: u32,
163+
//! }
164+
//! ```
165+
//!
61166
//! ## Rusoto extensions
62167
//!
63168
//! By importing the [dynomite::DynamoDbExt](trait.DynamoDbExt.html) trait, dynomite
@@ -110,6 +215,11 @@
110215
//! default-features = false
111216
//! features = ["feature-you-want"]
112217
//! ```
218+
//!
219+
//! [partition-key]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey
220+
//! [sort-key]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.SecondaryIndexes
221+
//! [`Default::default`]: https://doc.rust-lang.org/stable/std/default/trait.Default.html#tymethod.default
222+
//! [`AttributeValue`]: https://docs.rs/rusoto_dynamodb/*/rusoto_dynamodb/struct.AttributeValue.html
113223
114224
#![deny(missing_docs)]
115225
// reexported

0 commit comments

Comments
 (0)