1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
use super::AttributeValue;
use crate::{error::ErrorImpl, Error, Item, Result};
use serde::Serialize;
mod serializer;
mod serializer_map;
mod serializer_seq;
mod serializer_struct;
mod serializer_struct_variant;
mod serializer_tuple_variant;
#[cfg(test)]
mod tests;
pub use serializer::Serializer;
use serializer_map::SerializerMap;
use serializer_seq::SerializerSeq;
use serializer_struct::SerializerStruct;
use serializer_struct_variant::SerializerStructVariant;
use serializer_tuple_variant::SerializerTupleVariant;
/// Convert a `T` into an [`AttributeValue`].
///
/// In some circumstances, building [aws_sdk_dynamodb::model::AttributeValue]s directly is required.
///
/// For example, when generating a key to supply to [get_item].
///
/// ```no_run
/// use serde_dynamo::to_attribute_value;
/// # use __aws_sdk_dynamodb_1::client::Client;
/// # use std::collections::HashMap;
/// #
/// # async fn get(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
/// #
/// # struct User { id: String };
/// # let user = User { id: "fSsgVtal8TpP".to_string() };
///
/// // Create the unique key of the record in DynamoDB in a way rusoto understands
/// let key = HashMap::from([
/// (String::from("id"), to_attribute_value(&user.id)?),
/// ]);
///
/// // And get the record
/// client.get_item().table_name("users").set_key(Some(key)).send().await?;
/// # Ok(())
/// # }
/// ```
///
/// Or when generating attribute values in a [query] call.
///
/// ```no_run
/// use serde_dynamo::to_attribute_value;
/// # use __aws_sdk_dynamodb_1::client::Client;
/// # use std::collections::HashMap;
/// #
/// # async fn query(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
/// # let user_type = "user";
/// # let yesterday = "1985-04-21";
///
/// // Declare all of the expression inputs for a query call
/// let expression_attribute_values = HashMap::from([
/// (String::from(":user_type"), to_attribute_value(user_type)?),
/// (String::from(":last_login"), to_attribute_value(yesterday)?),
/// ]);
///
/// client.query()
/// .table_name("users")
/// .index_name("by_type_and_last_login")
/// .key_condition_expression("user_type = :user_type AND last_login > :last_login")
/// .set_expression_attribute_values(Some(expression_attribute_values))
/// .send()
/// .await?;
/// # Ok(())
/// # }
/// ```
///
/// [aws-sdk-dynamodb]: https://docs.rs/aws-sdk-dynamodb
/// [get_item]: https://docs.rs/aws-sdk-dynamodb/*/aws_sdk_dynamodb/client/struct.Client.html#method.get_item
/// [put_item]: https://docs.rs/aws-sdk-dynamodb/*/aws_sdk_dynamodb/client/struct.Client.html#method.put_item
/// [query]: https://docs.rs/aws-sdk-dynamodb/*/aws_sdk_dynamodb/client/struct.Client.html#method.query
/// [aws_sdk_dynamodb::model::AttributeValue]: https://docs.rs/aws-sdk-dynamodb/*/aws_sdk_dynamodb/types/enum.AttributeValue.html
pub fn to_attribute_value<T, AV>(value: T) -> Result<AV>
where
T: Serialize,
AV: From<AttributeValue>,
{
let serializer = Serializer;
let attribute_value = value.serialize(serializer)?;
Ok(AV::from(attribute_value))
}
/// Convert a `T` into an [`Item`].
///
/// This is frequently used when serializing an entire data structure to be sent to DynamoDB.
///
/// ```no_run
/// # use __aws_sdk_dynamodb_1::client::Client;
/// # use serde_derive::{Serialize, Deserialize};
/// # use serde_dynamo::to_item;
/// #
/// # async fn put(client: &Client) -> Result<(), Box<dyn std::error::Error>> {
/// #[derive(Serialize, Deserialize)]
/// pub struct User {
/// id: String,
/// name: String,
/// age: u8,
/// };
///
/// // Create a user
/// let user = User {
/// id: "fSsgVtal8TpP".to_string(),
/// name: "Arthur Dent".to_string(),
/// age: 42,
/// };
///
/// // Turn it into an item that rusoto understands
/// let item = to_item(user)?;
///
/// // And write it!
/// client.put_item().table_name("users").set_item(Some(item)).send().await?;
/// # Ok(())
/// # }
/// ```
pub fn to_item<T, I>(value: T) -> Result<I>
where
T: Serialize,
I: From<Item>,
{
let serializer = Serializer;
let attribute_value = value.serialize(serializer)?;
if let AttributeValue::M(item) = attribute_value {
let item = Item::from(item);
Ok(I::from(item))
} else {
Err(ErrorImpl::NotMaplike.into())
}
}