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
/// Zero-sized placeholder used when a key component is a compile-time constant.
///
/// `NoId` is the `PkId` or `SkId` type parameter of [`KeyId`] for item types
/// whose partition key or sort key is a constant (e.g. singleton items like
/// the `PlatformConfig` in the crate examples). It carries no data because
/// the key value is baked into the type's
/// [`HasConstAttribute`](crate::HasConstAttribute) impl.
///
/// You will encounter `NoId` as part of [`KeyId::NONE`] for singleton items,
/// and as the `SkId` of [`KeyId::pk`] for items with a variable PK but a
/// constant SK.
///
/// # Examples
///
/// ```
/// # use dynamodb_facade::test_fixtures::*;
/// use dynamodb_facade::{KeyId, NoId};
///
/// // Singleton item — both PK and SK are constants.
/// let key_id: KeyId<NoId, NoId> = KeyId::NONE;
///
/// // Variable PK, constant SK — SkId is NoId.
/// let key_id: KeyId<&str, NoId> = KeyId::pk("user-1");
/// ```
;
/// Type-safe builder for a DynamoDB partition key + sort key pair.
///
/// `KeyId<PkId, SkId>` holds the logical identifiers used to construct a
/// [`Key<TD>`](crate::Key) for a specific item. The type parameters encode
/// which key components are present:
///
/// | `PkId` | `SkId` | Meaning |
/// |---|---|---|
/// | [`NoId`] | [`NoId`] | Both keys are constants — use [`KeyId::NONE`] |
/// | `T` | [`NoId`] | Variable PK, constant SK — use [`KeyId::pk`] |
/// | `T` | `U` | Both keys are variable — use [`KeyId::pk`]`.`[`sk`](KeyId::sk) |
///
/// The concrete `PkId` and `SkId` types are determined by the item type's
/// `HasAttribute` impls. For example, a `User` whose PK is derived from a
/// `&str` user ID has `KeyId<&str, NoId>`.
///
/// # Examples
///
/// Singleton item (constant PK + SK):
///
/// ```
/// # use dynamodb_facade::test_fixtures::*;
/// use dynamodb_facade::{DynamoDBItemOp, KeyId};
///
/// # async fn example(client: dynamodb_facade::Client) -> dynamodb_facade::Result<()> {
/// // PlatformConfig has const PK and SK — use KeyId::NONE.
/// let config = PlatformConfig::get(client, KeyId::NONE).await?;
/// # Ok(())
/// # }
/// ```
///
/// Variable PK, constant SK:
///
/// ```
/// # use dynamodb_facade::test_fixtures::*;
/// use dynamodb_facade::{DynamoDBItemOp, KeyId};
///
/// # async fn example(client: dynamodb_facade::Client) -> dynamodb_facade::Result<()> {
/// // User has a PK and a const SK.
/// let user = User::get(client, KeyId::pk("user-1")).await?;
/// # Ok(())
/// # }
/// ```
///
/// Variable PK + variable SK:
///
/// ```
/// # use dynamodb_facade::test_fixtures::*;
/// use dynamodb_facade::{DynamoDBItemOp, KeyId};
///
/// # async fn example(client: dynamodb_facade::Client) -> dynamodb_facade::Result<()> {
/// // Enrollment has a PK and a SK.
/// let user_enrollment = Enrollment::get(client, KeyId::pk("user-1").sk("course-42")).await?;
/// # Ok(())
/// # }
/// ```