Skip to content

Commit bc2ad09

Browse files
authored
incorrect handling of unit and newtype variants as query params (#1033)
1 parent 74c5e11 commit bc2ad09

File tree

2 files changed

+22
-12
lines changed

2 files changed

+22
-12
lines changed

progenitor-client/src/progenitor_client.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 Oxide Computer Company
1+
// Copyright 2025 Oxide Computer Company
22

33
#![allow(dead_code)]
44

@@ -9,7 +9,7 @@ use std::ops::{Deref, DerefMut};
99
use bytes::Bytes;
1010
use futures_core::Stream;
1111
use reqwest::RequestBuilder;
12-
use serde::{de::DeserializeOwned, Serialize};
12+
use serde::{de::DeserializeOwned, ser::SerializeStruct, Serialize};
1313

1414
#[cfg(not(target_arch = "wasm32"))]
1515
type InnerByteStream = std::pin::Pin<Box<dyn Stream<Item = reqwest::Result<Bytes>> + Send + Sync>>;
@@ -540,12 +540,14 @@ where
540540

541541
fn serialize_unit_variant(
542542
self,
543-
name: &'static str,
544-
variant_index: u32,
543+
_name: &'static str,
544+
_variant_index: u32,
545545
variant: &'static str,
546546
) -> Result<Self::Ok, Self::Error> {
547-
self.inner
548-
.serialize_unit_variant(name, variant_index, variant)
547+
// A query parameter with a list of enumerated values will produce an
548+
// enum with unit variants. We treat these as scalar values, ignoring
549+
// the unit variant wrapper.
550+
variant.serialize(self)
549551
}
550552

551553
fn serialize_newtype_struct<T>(
@@ -562,15 +564,21 @@ where
562564
fn serialize_newtype_variant<T>(
563565
self,
564566
name: &'static str,
565-
variant_index: u32,
567+
_variant_index: u32,
566568
variant: &'static str,
567569
value: &T,
568570
) -> Result<Self::Ok, Self::Error>
569571
where
570572
T: ?Sized + Serialize,
571573
{
572-
self.inner
573-
.serialize_newtype_variant(name, variant_index, variant, value)
574+
// As with serde_json, we treat a newtype variant like a struct with a
575+
// single field. This may seem a little weird, but if an OpenAPI
576+
// document were to specify a query parameter whose schema was a oneOf
577+
// whose elements were objects with a single field, the user would end
578+
// up with an enum like this as a parameter.
579+
let mut map = self.inner.serialize_struct(name, 1)?;
580+
map.serialize_field(variant, value)?;
581+
map.end()
574582
}
575583

576584
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {

progenitor-client/tests/client_test.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 Oxide Computer Company
1+
// Copyright 2025 Oxide Computer Company
22

33
use std::{
44
collections::{BTreeMap, BTreeSet, HashSet},
@@ -101,10 +101,12 @@ fn test_query_enum_external() {
101101
Object { a: u64, b: u64 },
102102
}
103103
let value = Value::Simple;
104-
encode_query_param("ignored", &value).expect_err("variant not supported");
104+
let result = encode_query_param("paramValue", &value).unwrap();
105+
assert_eq!(result, "paramValue=simple");
105106

106107
let value = Value::Newtype(42);
107-
encode_query_param("ignored", &value).expect_err("variant not supported");
108+
let result = encode_query_param("ignored", &value).unwrap();
109+
assert_eq!(result, "newtype=42");
108110

109111
let value = Value::Tuple(1, 2);
110112
encode_query_param("ignored", &value).expect_err("variant not supported");

0 commit comments

Comments
 (0)