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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
use crateTransform;
/// Primary entrypoint for data -> nest conversions.
///
/// You should implement this on each corresponding nest for your transform.
///
/// Implementations are on the [`Transform`] struct that you have defined to handle conversions.
///
/// # Examples
///
/// ## Standard
///
/// For regular (non-optional, without deep nesting), the `impl` should look like:
///
/// ```
/// # use shrinkwrap::{Transform, Wrap};
/// #
/// # #[derive(Debug, Clone, serde::Serialize, Wrap)]
/// # #[shrinkwrap(transform = MyTransform)]
/// # #[shrinkwrap(nest(id = "text", field_type = String))]
/// # pub struct MyData {
/// # #[shrinkwrap(nests("text"))]
/// # uptime_sec: i64,
/// # }
/// #
/// # struct MyTransform {}
/// # type MyTransformOpts = ();
/// # impl Transform for MyTransform {
/// # type Options = MyTransformOpts;
/// # }
/// use shrinkwrap::TransformToNest;
///
/// impl TransformToNest<MyDataNestedText> for MyTransform {
/// type Data = MyData;
/// fn transform_to_nest(&self, data: &MyData, _: &MyTransformOpts) -> MyDataNestedText {
/// MyDataNestedText {
/// uptime_sec: data.uptime_sec.to_string(),
/// }
/// }
/// }
/// ```
///
/// ## Optional
///
/// If your nest is optional, the `impl` should look like:
///
/// ```
/// # use shrinkwrap::{Transform, Wrap};
/// #
/// # struct MyTransform {}
/// # struct MyTransformOpts {
/// # with_text: bool,
/// # };
/// # impl Transform for MyTransform {
/// # type Options = MyTransformOpts;
/// # }
/// #
/// # #[derive(Debug, Clone, serde::Serialize, Wrap)]
/// # #[shrinkwrap(transform = MyTransform)]
/// # #[shrinkwrap(nest(id = "text", field_type = String, optional))]
/// # pub struct MyData {
/// # #[shrinkwrap(nests("text"))]
/// # uptime_sec: i64,
/// # }
/// use shrinkwrap::TransformToNest;
///
/// impl TransformToNest<Option<MyDataNestedText>> for MyTransform {
/// type Data = MyData;
///
/// fn transform_to_nest(&self, data: &MyData, options: &MyTransformOpts) -> Option<MyDataNestedText> {
/// options.with_text.then(||
/// MyDataNestedText {
/// uptime_sec: data.uptime_sec.to_string(),
/// }
/// )
/// }
/// }
/// ```
///
/// ## Deeply Nested
///
/// If the nest is layered under some other nest (deeply nested), the `impl` has a similar structure to the standard impl.
/// The only real change is instead of using the primary data source (`MyData`) as the associated data type, you would use the parent nest.
///
/// This example assumes two nests, a top-level/standard nest `usd_value`, and a deeply nested `text` under `usd_value`
///
/// ```
/// # use shrinkwrap::{Transform, Wrap};
/// #
/// # #[derive(Debug, Clone, serde::Serialize, Wrap)]
/// # #[shrinkwrap(transform = MyTransform)]
/// # #[shrinkwrap(nest(id = "text", field_type = String))]
/// # pub struct MyData {
/// # #[shrinkwrap(nests("text"))]
/// # uptime_sec: i64,
/// # }
/// #
/// # struct MyTransform {}
/// # type MyTransformOpts = ();
/// # impl Transform for MyTransform {
/// # type Options = MyTransformOpts;
/// # }
/// use shrinkwrap::TransformToNest;
///
/// impl TransformToNest<TestDataNestedUsdValueText> for MyTransform {
/// type Data = TestDataNestedUsdValue;
///
/// fn transform_to_nest(&self, data: &TestDataNestedUsdValue, _: &MyTransformOpts) -> TestDataNestedUsdValueText {
/// TestDataNestedUsdValueText {
/// amount: format!("${:.2} USD", data.amount),
/// }
/// }
/// }
/// ```
///
/// ## Optional + Deeply Nested
///
/// Nothing special here, it's a combination of the modifications used in the previous two examples.
///
/// ```
/// # use shrinkwrap::{Transform, Wrap};
/// #
/// # #[derive(Debug, Clone, serde::Serialize, Wrap)]
/// # #[shrinkwrap(transform = MyTransform)]
/// # #[shrinkwrap(nest(id = "text", field_type = String))]
/// # pub struct MyData {
/// # #[shrinkwrap(nests("text"))]
/// # uptime_sec: i64,
/// # }
/// #
/// # struct MyTransform {}
/// # type MyTransformOpts = ();
/// # impl Transform for MyTransform {
/// # type Options = MyTransformOpts;
/// # }
/// use shrinkwrap::TransformToNest;
///
/// impl TransformToNest<Option<TestDataNestedUsdValueText>> for MyTransform {
/// type Data = TestDataNestedUsdValue;
///
/// fn transform_to_nest(&self, data: &TestDataNestedUsdValue, _: &MyTransformOpts) -> Option<TestDataNestedUsdValueText> {
/// options.with_text.then(||
/// TestDataNestedUsdValueText {
/// amount: format!("${:.2} USD", data.amount),
/// }
/// )
/// }
/// }
/// ```
///
/// # Notes
///
/// When a nest has child nests layered under it (deeply nested), it's type will be swapped out with a dedicated 'injected' wrapper.
///
/// However, this does not affect the trait impls above - the `Wrap` derive macro automatically adds an implementation for the wrapper->nest translation.
///
/// The only requirement is that `TransformToNest` is implemented from the data source to the nest type.
/// Allows for converting a data struct (by reference) to a supported nest type.
///
/// This is implemented automatically when [`TransformToNest`] is implemented on the corresponding types.
///
/// ## Examples
///
/// ```rust
/// use serde::Serialize;
/// use shrinkwrap::{ToNestWith, Transform, TransformToNest, Wrap};
///
/// #[derive(Debug, Clone, Serialize, Wrap)]
/// #[shrinkwrap(transform = MyTransform)]
/// #[shrinkwrap(nest(id = "text", field_type = String))]
/// pub struct MyData {
/// #[shrinkwrap(nests("text"))]
/// uptime_sec: i64,
/// }
///
/// struct MyTransform {}
/// type MyTransformOpts = ();
/// impl Transform for MyTransform {
/// type Options = MyTransformOpts;
/// }
///
/// impl TransformToNest<MyDataNestedText> for MyTransform {
/// type Data = MyData;
/// fn transform_to_nest(&self, data: &MyData, _options: &MyTransformOpts) -> MyDataNestedText {
/// MyDataNestedText {
/// uptime_sec: data.uptime_sec.to_string(),
/// }
/// }
/// }
///
/// let transform = MyTransform {};
/// let transform_opts = ();
/// let data = MyData {
/// uptime_sec: 10
/// };
///
/// let text_variants: MyDataNestedText = data.to_nest_with(&transform, &transform_opts);
/// let uptime_text = text_variants.uptime_sec;
/// println!("Current uptime: {uptime_text}")
/// ```
/// Blanket implementation providing `to_nest_with(transform)` for data structs that have a corresponding [`TransformToNest<Nest>`] impl.