Skip to main content

pulumi_gestalt_rust/
oneof.rs

1use pulumi_gestalt_model::__private::rootcause::{Result, bail};
2use pulumi_gestalt_model::{FromPulumiValue, PulumiValue, ToPulumiValue};
3use serde::{Deserialize, Serialize};
4use std::fmt::Debug;
5
6#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
7#[serde(untagged)]
8pub enum OneOf2<A: Debug, B: Debug> {
9    Left(A),
10    Right(B),
11}
12
13impl<A: Debug, B: Debug> OneOf2<A, B> {
14    pub fn left(a: A) -> Self {
15        OneOf2::Left(a)
16    }
17    pub fn right(b: B) -> Self {
18        OneOf2::Right(b)
19    }
20}
21
22impl<A, B> ToPulumiValue for OneOf2<A, B>
23where
24    A: Debug + ToPulumiValue + Sync,
25    B: Debug + ToPulumiValue + Sync,
26{
27    async fn to_pulumi_value(&self) -> PulumiValue {
28        match self {
29            OneOf2::Left(a) => a.to_pulumi_value().await,
30            OneOf2::Right(b) => b.to_pulumi_value().await,
31        }
32    }
33}
34
35impl<A, B> FromPulumiValue for OneOf2<A, B>
36where
37    A: Debug + FromPulumiValue,
38    B: Debug + FromPulumiValue,
39{
40    fn from_pulumi_value(value: &PulumiValue) -> Result<Self> {
41        match A::from_pulumi_value(value) {
42            Ok(v) => Ok(Self::Left(v)),
43            Err(err_a) => match B::from_pulumi_value(value) {
44                Ok(v) => Ok(Self::Right(v)),
45                Err(err_b) => bail!(
46                    "Failed to convert PulumiValue to OneOf2<{}, {}>: left variant failed: {}; right variant failed: {}",
47                    std::any::type_name::<A>(),
48                    std::any::type_name::<B>(),
49                    err_a,
50                    err_b
51                ),
52            },
53        }
54    }
55}
56
57#[derive(Debug, Serialize, Deserialize)]
58#[serde(untagged)]
59pub enum OneOf3<A: Debug, B: Debug, C: Debug> {
60    Left(A),
61    Middle(B),
62    Right(C),
63}
64
65impl<A: Debug, B: Debug, C: Debug> OneOf3<A, B, C> {
66    pub fn left(a: A) -> Self {
67        OneOf3::Left(a)
68    }
69    pub fn middle(b: B) -> Self {
70        OneOf3::Middle(b)
71    }
72    pub fn right(c: C) -> Self {
73        OneOf3::Right(c)
74    }
75}
76
77impl<A, B, C> ToPulumiValue for OneOf3<A, B, C>
78where
79    A: Debug + ToPulumiValue + Sync,
80    B: Debug + ToPulumiValue + Sync,
81    C: Debug + ToPulumiValue + Sync,
82{
83    async fn to_pulumi_value(&self) -> PulumiValue {
84        match self {
85            OneOf3::Left(a) => a.to_pulumi_value().await,
86            OneOf3::Middle(b) => b.to_pulumi_value().await,
87            OneOf3::Right(c) => c.to_pulumi_value().await,
88        }
89    }
90}
91
92impl<A, B, C> FromPulumiValue for OneOf3<A, B, C>
93where
94    A: Debug + FromPulumiValue,
95    B: Debug + FromPulumiValue,
96    C: Debug + FromPulumiValue,
97{
98    fn from_pulumi_value(value: &PulumiValue) -> Result<Self> {
99        match A::from_pulumi_value(value) {
100            Ok(v) => Ok(Self::Left(v)),
101            Err(err_a) => match B::from_pulumi_value(value) {
102                Ok(v) => Ok(Self::Middle(v)),
103                Err(err_b) => match C::from_pulumi_value(value) {
104                    Ok(v) => Ok(Self::Right(v)),
105                    Err(err_c) => bail!(
106                        "Failed to convert PulumiValue to OneOf3<{}, {}, {}>: left variant failed: {}; middle variant failed: {}; right variant failed: {}",
107                        std::any::type_name::<A>(),
108                        std::any::type_name::<B>(),
109                        std::any::type_name::<C>(),
110                        err_a,
111                        err_b,
112                        err_c
113                    ),
114                },
115            },
116        }
117    }
118}
119
120#[derive(Debug, Serialize, Deserialize)]
121#[serde(untagged)]
122pub enum OneOf4<A: Debug, B: Debug, C: Debug, D: Debug> {
123    Left(A),
124    Middle1(B),
125    Middle2(C),
126    Right(D),
127}
128
129impl<A: Debug, B: Debug, C: Debug, D: Debug> OneOf4<A, B, C, D> {
130    pub fn left(a: A) -> Self {
131        OneOf4::Left(a)
132    }
133    pub fn middle1(b: B) -> Self {
134        OneOf4::Middle1(b)
135    }
136    pub fn middle2(c: C) -> Self {
137        OneOf4::Middle2(c)
138    }
139    pub fn right(d: D) -> Self {
140        OneOf4::Right(d)
141    }
142}
143
144impl<A, B, C, D> ToPulumiValue for OneOf4<A, B, C, D>
145where
146    A: Debug + ToPulumiValue + Sync,
147    B: Debug + ToPulumiValue + Sync,
148    C: Debug + ToPulumiValue + Sync,
149    D: Debug + ToPulumiValue + Sync,
150{
151    async fn to_pulumi_value(&self) -> PulumiValue {
152        match self {
153            OneOf4::Left(a) => a.to_pulumi_value().await,
154            OneOf4::Middle1(b) => b.to_pulumi_value().await,
155            OneOf4::Middle2(c) => c.to_pulumi_value().await,
156            OneOf4::Right(d) => d.to_pulumi_value().await,
157        }
158    }
159}
160
161impl<A, B, C, D> FromPulumiValue for OneOf4<A, B, C, D>
162where
163    A: Debug + FromPulumiValue,
164    B: Debug + FromPulumiValue,
165    C: Debug + FromPulumiValue,
166    D: Debug + FromPulumiValue,
167{
168    fn from_pulumi_value(value: &PulumiValue) -> Result<Self> {
169        match A::from_pulumi_value(value) {
170            Ok(v) => Ok(Self::Left(v)),
171            Err(err_a) => match B::from_pulumi_value(value) {
172                Ok(v) => Ok(Self::Middle1(v)),
173                Err(err_b) => match C::from_pulumi_value(value) {
174                    Ok(v) => Ok(Self::Middle2(v)),
175                    Err(err_c) => match D::from_pulumi_value(value) {
176                        Ok(v) => Ok(Self::Right(v)),
177                        Err(err_d) => bail!(
178                            "Failed to convert PulumiValue to OneOf4<{}, {}, {}, {}>: left variant failed: {}; middle1 variant failed: {}; middle2 variant failed: {}; right variant failed: {}",
179                            std::any::type_name::<A>(),
180                            std::any::type_name::<B>(),
181                            std::any::type_name::<C>(),
182                            std::any::type_name::<D>(),
183                            err_a,
184                            err_b,
185                            err_c,
186                            err_d
187                        ),
188                    },
189                },
190            },
191        }
192    }
193}
194
195#[cfg(test)]
196mod tests {
197    use super::*;
198    use pulumi_gestalt_model::__private::futures::executor::block_on;
199    use pulumi_gestalt_model::PulumiValueContent;
200    use std::collections::HashSet;
201
202    fn string_value(value: &str) -> PulumiValue {
203        PulumiValue {
204            content: PulumiValueContent::String(value.to_string()),
205            secret: false,
206            dependencies: HashSet::new(),
207        }
208    }
209
210    #[test]
211    fn to_pulumi_value_oneof2_uses_active_variant() {
212        let value: OneOf2<i32, String> = OneOf2::right("hello".to_string());
213        let pulumi = block_on(value.to_pulumi_value());
214        assert_eq!(
215            pulumi.content,
216            PulumiValueContent::String("hello".to_string())
217        );
218    }
219
220    #[test]
221    fn to_pulumi_value_oneof3_uses_active_variant() {
222        let value: OneOf3<i32, String, bool> = OneOf3::middle("hello".to_string());
223        let pulumi = block_on(value.to_pulumi_value());
224        assert_eq!(
225            pulumi.content,
226            PulumiValueContent::String("hello".to_string())
227        );
228    }
229
230    #[test]
231    fn to_pulumi_value_oneof4_uses_active_variant() {
232        let value: OneOf4<i32, bool, String, f64> = OneOf4::middle2("hello".to_string());
233        let pulumi = block_on(value.to_pulumi_value());
234        assert_eq!(
235            pulumi.content,
236            PulumiValueContent::String("hello".to_string())
237        );
238    }
239
240    #[test]
241    fn from_pulumi_value_oneof2_success() {
242        let parsed: OneOf2<i32, String> =
243            OneOf2::from_pulumi_value(&string_value("hello")).unwrap();
244        match parsed {
245            OneOf2::Right(value) => assert_eq!(value, "hello"),
246            _ => panic!("Expected Right variant"),
247        }
248    }
249
250    #[test]
251    fn from_pulumi_value_oneof3_success() {
252        let parsed: OneOf3<i32, String, bool> =
253            OneOf3::from_pulumi_value(&string_value("hello")).unwrap();
254        match parsed {
255            OneOf3::Middle(value) => assert_eq!(value, "hello"),
256            _ => panic!("Expected Middle variant"),
257        }
258    }
259
260    #[test]
261    fn from_pulumi_value_oneof4_success() {
262        let parsed: OneOf4<i32, bool, String, f64> =
263            OneOf4::from_pulumi_value(&string_value("hello")).unwrap();
264        match parsed {
265            OneOf4::Middle2(value) => assert_eq!(value, "hello"),
266            _ => panic!("Expected Middle2 variant"),
267        }
268    }
269
270    #[test]
271    fn from_pulumi_value_ambiguous_prefers_left_to_right() {
272        let parsed: OneOf2<String, String> =
273            OneOf2::from_pulumi_value(&string_value("hello")).unwrap();
274        match parsed {
275            OneOf2::Left(value) => assert_eq!(value, "hello"),
276            _ => panic!("Expected Left variant"),
277        }
278    }
279
280    #[test]
281    fn from_pulumi_value_failure_includes_oneof_context() {
282        let value = PulumiValue {
283            content: PulumiValueContent::Boolean(true),
284            secret: false,
285            dependencies: HashSet::new(),
286        };
287
288        let result: Result<OneOf3<i32, String, f64>> = OneOf3::from_pulumi_value(&value);
289        assert!(result.is_err());
290        let message = result.err().unwrap().to_string();
291        assert!(message.contains("Failed to convert PulumiValue to OneOf3"));
292        assert!(message.contains("left variant failed"));
293        assert!(message.contains("middle variant failed"));
294        assert!(message.contains("right variant failed"));
295    }
296}