dynamodb_facade/values/typed.rs
1use crate::{AttributeType, BinaryAttribute, NumberAttribute, StringAttribute};
2
3use super::*;
4
5mod sealed_traits {
6 /// Seals [`IntoTypedAttributeValue`](super::IntoTypedAttributeValue) so it can only be implemented via the marker sub-traits.
7 pub trait IntoTypedAttributeValueSeal<KA: super::AttributeType> {}
8}
9
10/// A type-safe variant of [`IntoAttributeValue`] that guarantees the produced
11/// [`AttributeValue`] matches a specific DynamoDB
12/// scalar type.
13///
14/// This trait is sealed and cannot be implemented directly. It is automatically
15/// implemented for any type that implements both [`IntoAttributeValue`] and the
16/// corresponding internal marker trait:
17///
18/// | Rust type | `KA` parameter |
19/// |---|---|
20/// | [`String`], [`&str`], `&String` | [`StringAttribute`] |
21/// | Integer and float primitives, [`String`], [`&str`] | [`NumberAttribute`] |
22/// | [`Vec<u8>`], [`&[u8]`] | [`BinaryAttribute`] |
23///
24/// `IntoTypedAttributeValue<KA>` is used as the bound on
25/// [`HasAttribute::Value`](crate::HasAttribute::Value) and
26/// [`HasConstAttribute::Value`](crate::HasConstAttribute::Value), ensuring at compile
27/// time that the value type for an attribute matches the declared
28/// [`AttributeDefinition::Type`](crate::AttributeDefinition::Type). For
29/// example, you cannot accidentally store a number in a `StringAttribute`
30/// column.
31///
32/// # Examples
33///
34/// ```
35/// use dynamodb_facade::{IntoTypedAttributeValue, StringAttribute, NumberAttribute};
36///
37/// // String implements IntoTypedAttributeValue<StringAttribute>
38/// fn accepts_string_attr<V: IntoTypedAttributeValue<StringAttribute>>(_v: V) {}
39/// accepts_string_attr("alice@example.com");
40/// accepts_string_attr("user-1".to_owned());
41///
42/// // u32 implements IntoTypedAttributeValue<NumberAttribute>
43/// fn accepts_number_attr<V: IntoTypedAttributeValue<NumberAttribute>>(_v: V) {}
44/// accepts_number_attr(42);
45/// accepts_number_attr(3.14);
46/// ```
47pub trait IntoTypedAttributeValue<KA: AttributeType>:
48 IntoAttributeValue + sealed_traits::IntoTypedAttributeValueSeal<KA>
49{
50}
51
52/// Marker for types that produce a DynamoDB `S` (string) attribute value.
53pub(super) trait IntoStringAttributeValue {}
54impl<T: IntoStringAttributeValue + IntoAttributeValue>
55 sealed_traits::IntoTypedAttributeValueSeal<StringAttribute> for T
56{
57}
58impl<T: IntoStringAttributeValue + IntoAttributeValue> IntoTypedAttributeValue<StringAttribute>
59 for T
60{
61}
62
63/// Marker for types that produce a DynamoDB `N` (number) attribute value.
64pub(super) trait IntoNumberAttributeValue {}
65impl<T: IntoNumberAttributeValue + IntoAttributeValue>
66 sealed_traits::IntoTypedAttributeValueSeal<NumberAttribute> for T
67{
68}
69impl<T: IntoNumberAttributeValue + IntoAttributeValue> IntoTypedAttributeValue<NumberAttribute>
70 for T
71{
72}
73
74/// Marker for types that produce a DynamoDB `B` (binary) attribute value.
75pub(super) trait IntoBinaryAttributeValue {}
76impl<T: IntoBinaryAttributeValue + IntoAttributeValue>
77 sealed_traits::IntoTypedAttributeValueSeal<BinaryAttribute> for T
78{
79}
80impl<T: IntoBinaryAttributeValue + IntoAttributeValue> IntoTypedAttributeValue<BinaryAttribute>
81 for T
82{
83}