oxidecomputer / oxidecomputer/typify
Client type constructors sometimes ignore bounds in OpenAPI spec
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 898
- Forks
- 114
- Avg merge
- 4h 18m
- Merged PRs (30d)
- 14
Description
I have a custom Rust type on the server side that wraps a u8 and limits its valid values to just 0-63. With a custom JsonSchema impl, these upper/lower bounds are encoded into the OpenAPI spec:
/// DSCP value for BGP TCP connections (0-63).
///
/// RFC 4271 Appendix E recommends CS6 (48) for BGP traffic.
/// Default: CS6 (48).
634: #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
635: #[serde(try_from = "u8", into = "u8")]
636: pub struct Dscp(u8);
impl Dscp {
/// CS6 (48) — the RFC 4271 Appendix E recommended default.
pub const CS6: Self = Self(48);
/// Create a new DSCP value, returning an error if out of range.
pub fn new(val: u8) -> Result<Self, String> {
if val > 63 {
Err(format!("DSCP value {val} out of range (0-63)"))
} else {
Ok(Self(val))
}
}
/// Return the raw numeric value.
pub fn value(self) -> u8 {
self.0
}
}
impl Default for Dscp {
fn default() -> Self {
Self::CS6
}
}
impl TryFrom<u8> for Dscp {
type Error = String;
fn try_from(val: u8) -> Result<Self, Self::Error> {
Self::new(val)
}
}
impl From<Dscp> for u8 {
fn from(d: Dscp) -> u8 {
d.0
}
}
impl JsonSchema for Dscp {
fn schema_name() -> String {
"Dscp".to_string()
}
fn json_schema(
_g: &mut schemars::r#gen::SchemaGenerator,
) -> schemars::schema::Schema {
schemars::schema::SchemaObject {
instance_type: Some(schemars::schema::InstanceType::Integer.into()),
format: Some("uint8".to_string()),
number: Some(Box::new(schemars::schema::NumberValidation {
minimum: Some(0.0),
maximum: Some(63.0),
..Default::default()
})),
metadata: Some(Box::new(schemars::schema::Metadata {
description: Some(
"DSCP value (0-63). Default: CS6 (48).".to_string(),
),
..Default::default()
})),
..Default::default()
}
.into()
}
}
OpenAPI snippet:
"Dscp": {
"description": "DSCP value (0-63). Default: CS6 (48).",
"type": "integer",
"format": "uint8",
"minimum": 0,
"maximum": 63
},
However, the generated client type has an infallible constructor (impl From<u8> for Dscp) which allows the client to construct invalid values where the type invariants are not upheld.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing how the generated client type is produced from the OpenAPI bounds and where its infallible From<u8> constructor is selected. Compare the generated constructor behavior with the Dscp schema's minimum and maximum values; done means invalid values can no longer be created through an infallible constructor and the bounds are respected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100