@@ -23,14 +23,12 @@ to different `serde` tagging strategies, and we handle each of them differently.
2323
2424### Tagged union
2525
26- When a ` oneOf ` has:
26+ When a ` oneOf ` has exactly one discriminator property (a field with a single enum value per
27+ variant), we generate an ** interface with variant types** pattern. This covers both
28+ ` serde(tag = "type", content = "value") ` unions (where variants carry data in a ` value ` field) and
29+ ` serde(tag = "type") ` unions (where variant fields are inlined at the top level).
2730
28- 1 . Exactly one discriminator property (a field with a single enum value per variant)
29- 2 . Exactly one multi-type property (a field whose type varies across variants)
30-
31- We generate an ** interface with variant wrapper types** pattern.
32-
33- ** Example: ` PrivateIpStack ` **
31+ ** Example: ` PrivateIpStack ` ** (using serde's ` tag ` and ` content ` )
3432
3533In Rust, ` PrivateIpStack ` is defined as:
3634
@@ -210,13 +208,7 @@ confusing to end users than consistent use of wrappers.
210208Note: we can reconsider this choice if we're able to drop the use of ` interface{} ` types and
211209pointers to primitives for variants, and if we're confident that those cases won't emerge again.
212210
213- ### Discriminator with multiple value fields
214-
215- When a ` oneOf ` has a discriminator field and _ multiple_ value fields, we use a flat struct that
216- contains all properties from all variants. Properties that have different types across variants
217- become ` any ` .
218-
219- ** Example: ` DiskSource ` **
211+ ** Example: ` DiskSource ` ** (using serde's ` tag ` only)
220212
221213In Rust, ` DiskSource ` is defined as:
222214
@@ -253,20 +245,65 @@ DiskSource:
253245 block_size : { $ref: "#/components/schemas/BlockSize" }
254246` ` `
255247
256- This has a discriminator (` type`) but no multi-type property. Each variant has different fields
257- (`block_size`, `snapshot_id`, `image_id`), not different types for the same field. So we generate a
258- flat struct :
248+ This has a discriminator (` type`) and each variant has different fields. Each variant struct contains
249+ only its own fields (without the discriminator) :
259250
260251` ` ` go
252+ type diskSourceVariant interface {
253+ isDiskSourceVariant()
254+ }
255+
256+ type DiskSourceBlank struct {
257+ BlockSize BlockSize ` json:"block_size,omitempty"`
258+ }
259+ func (DiskSourceBlank) isDiskSourceVariant() {}
260+
261+ type DiskSourceSnapshot struct {
262+ SnapshotId string `json:"snapshot_id,omitempty"`
263+ }
264+ func (DiskSourceSnapshot) isDiskSourceVariant() {}
265+
266+ type DiskSourceImage struct {
267+ ImageId string `json:"image_id,omitempty"`
268+ }
269+ func (DiskSourceImage) isDiskSourceVariant() {}
270+
271+ type DiskSourceImportingBlocks struct {
272+ BlockSize BlockSize `json:"block_size,omitempty"`
273+ }
274+ func (DiskSourceImportingBlocks) isDiskSourceVariant() {}
275+
261276type DiskSource struct {
262- BlockSize BlockSize ` json:"block_size,omitempty"`
263- Type DiskSourceType `json:"type,omitempty"`
264- SnapshotId string `json:"snapshot_id,omitempty"`
265- ImageId string `json:"image_id,omitempty"`
277+ Value diskSourceVariant
266278}
267279```
268280
269- If any property had different types across variants, it would become ` any ` .
281+ ** Usage examples:**
282+
283+ ``` go
284+ // Creating a disk from a snapshot
285+ params := oxide.DiskCreateParams {
286+ Body : &oxide.DiskCreate {
287+ Name: " my-disk" ,
288+ DiskSource: oxide.DiskSource {
289+ Value: &oxide.DiskSourceSnapshot {
290+ SnapshotId: " snapshot-uuid" ,
291+ },
292+ },
293+ },
294+ }
295+ ```
296+
297+ ``` go
298+ // Reading a disk source from the API
299+ disk , _ := client.DiskView (ctx, params)
300+ switch v := disk.DiskSource .Value .(type ) {
301+ case *oxide.DiskSourceSnapshot :
302+ fmt.Printf (" From snapshot: %s \n " , v.SnapshotId )
303+ case *oxide.DiskSourceImage :
304+ fmt.Printf (" From image: %s \n " , v.ImageId )
305+ }
306+ ```
270307
271308### Untagged union
272309
0 commit comments