Skip to content

Commit

Permalink
Only allow upper snake case unknown enum variants
Browse files Browse the repository at this point in the history
  • Loading branch information
sfackler committed Jan 21, 2019
1 parent 8008245 commit e0c3117
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2.1

executors:
rust:
docker: [{ image: rust:1.31.1 }]
docker: [{ image: rust:1.32.0 }]

commands:
restore_target:
Expand Down
15 changes: 11 additions & 4 deletions conjure-codegen/src/enums.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,23 @@ fn generate_enum(ctx: &Context, def: &EnumDefinition) -> TokenStream {
}
});

let values = def.values().iter().map(|v| v.value());
let unknown_variant_error = quote! {
#err(de::Error::unknown_variant(v, &[#(#values, )*]))
};

let visit_str_other = if ctx.exhaustive() {
let values = def.values().iter().map(|v| v.value());
quote! {
v => #err(de::Error::unknown_variant(v, &[#(#values, )*]))
v => #unknown_variant_error,
}
} else {
quote! {
v => {
// FIXME enforce SCREAMING_SNAKE_CASE?
#ok(#name::Unknown(#unknown(v.to_string().into_boxed_str())))
if conjure_object::private::valid_enum_variant(v) {
#ok(#name::Unknown(#unknown(v.to_string().into_boxed_str())))
} else {
#unknown_variant_error
}
}
}
};
Expand Down
12 changes: 9 additions & 3 deletions conjure-codegen/src/example_types/enum_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,15 @@ impl<'de> de::Visitor<'de> for Visitor_ {
match v {
"ONE" => Ok(EnumExample::One),
"TWO" => Ok(EnumExample::Two),
v => Ok(EnumExample::Unknown(Unknown(
v.to_string().into_boxed_str(),
))),
v => {
if conjure_object::private::valid_enum_variant(v) {
Ok(EnumExample::Unknown(Unknown(
v.to_string().into_boxed_str(),
)))
} else {
Err(de::Error::unknown_variant(v, &["ONE", "TWO"]))
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion conjure-codegen/src/types/parameter_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl<'de> de::Visitor<'de> for VariantVisitor_ {
return Err(de::Error::unknown_variant(
value,
&["body", "header", "path", "query"],
))
));
}
};
Ok(v)
Expand Down
2 changes: 1 addition & 1 deletion conjure-codegen/src/types/type_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ impl<'de> de::Visitor<'de> for VariantVisitor_ {
"reference",
"external",
],
))
));
}
};
Ok(v)
Expand Down
2 changes: 1 addition & 1 deletion conjure-codegen/src/types/type_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ impl<'de> de::Visitor<'de> for VariantVisitor_ {
return Err(de::Error::unknown_variant(
value,
&["alias", "enum", "object", "union"],
))
));
}
};
Ok(v)
Expand Down
11 changes: 11 additions & 0 deletions conjure-object/src/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ use serde::de::{self, IntoDeserializer};
use std::fmt;
use std::marker::PhantomData;

pub fn valid_enum_variant(s: &str) -> bool {
if s.is_empty() {
return false;
}

s.as_bytes().iter().all(|b| match b {
b'A'..=b'Z' | b'0'..=b'9' | b'_' => true,
_ => false,
})
}

pub enum UnionField_<T> {
Type,
Value(T),
Expand Down
19 changes: 7 additions & 12 deletions conjure-test/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use conjure_object::serde::de::DeserializeOwned;
use conjure_object::serde::{Deserialize, Serialize};
use conjure_object::serde::Serialize;
use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Debug;

Expand All @@ -22,21 +22,14 @@ fn serialize<T>(value: &T) -> String
where
T: Serialize,
{
let mut buf = vec![];
value
.serialize(&mut conjure_serde::json::Serializer::new(&mut buf))
.unwrap();
String::from_utf8(buf).unwrap()
conjure_serde::json::to_string(value).unwrap()
}

fn deserialize<T>(json: &str) -> T
where
T: DeserializeOwned,
{
let mut de = conjure_serde::json::ClientDeserializer::from_str(json);
let v = T::deserialize(&mut de).unwrap();
de.end().unwrap();
v
conjure_serde::json::client_from_str(json).unwrap()
}

fn test_ser<T>(ty: &T, expected_json: &str)
Expand Down Expand Up @@ -95,6 +88,9 @@ fn enums() {
_ => panic!(),
}
test_ser(&bogus, r#""BOGUS""#);

assert!(conjure_serde::json::client_from_str::<TestEnum>(r#""""#).is_err());
assert!(conjure_serde::json::client_from_str::<TestEnum>(r#""lowercase""#).is_err());
}

#[test]
Expand Down Expand Up @@ -182,9 +178,8 @@ fn union_trailing_fields() {
}
"#;

let e = TestUnion::deserialize(&mut conjure_serde::json::ClientDeserializer::from_str(json))
let e = conjure_serde::json::client_from_str::<TestUnion>(json)
.err()
.unwrap();

assert!(e.is_data());
}

0 comments on commit e0c3117

Please sign in to comment.