Introduce indirection for fields.

This commit is contained in:
KtorZ 2023-03-10 09:37:39 +01:00 committed by Lucas
parent 3a7aac0a33
commit f67e049dc2
1 changed files with 27 additions and 6 deletions

View File

@ -61,7 +61,15 @@ pub enum Items<T> {
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct Constructor { pub struct Constructor {
pub index: usize, pub index: usize,
pub fields: Vec<Annotated<Data>>, pub fields: Vec<Field>,
}
/// A field of a constructor. Can be either an inlined Data schema or a reference to another type.
/// References are mostly only used for recursive types.
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Field {
Inline(Annotated<Data>),
Reference { path: String },
} }
impl<T> From<T> for Annotated<T> { impl<T> From<T> for Annotated<T> {
@ -179,7 +187,7 @@ impl Annotated<Schema> {
description: Some("An optional value.".to_string()), description: Some("An optional value.".to_string()),
annotated: Constructor { annotated: Constructor {
index: 0, index: 0,
fields: vec![generic], fields: vec![Field::Inline(generic)],
}, },
}, },
Annotated { Annotated {
@ -308,7 +316,7 @@ impl Data {
schema.description = field.doc.clone().map(|s| s.trim().to_string()); schema.description = field.doc.clone().map(|s| s.trim().to_string());
} }
fields.push(schema); fields.push(Field::Inline(schema));
} }
let variant = Annotated { let variant = Annotated {
@ -324,7 +332,7 @@ impl Data {
// are erased completely at compilation time. // are erased completely at compilation time.
if data_type.opaque { if data_type.opaque {
if let [variant] = &variants[..] { if let [variant] = &variants[..] {
if let [field] = &variant.annotated.fields[..] { if let [Field::Inline(field)] = &variant.annotated.fields[..] {
return Ok(field.annotated.clone()); return Ok(field.annotated.clone());
} }
} }
@ -453,6 +461,19 @@ impl Serialize for Constructor {
} }
} }
impl Serialize for Field {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Field::Inline(schema) => schema.serialize(serializer),
Field::Reference { path } => {
let mut s = serializer.serialize_struct("$ref", 1)?;
s.serialize_field("$ref", path)?;
s.end()
}
}
}
}
#[derive(Debug, PartialEq, Clone, thiserror::Error)] #[derive(Debug, PartialEq, Clone, thiserror::Error)]
#[error("{}", context)] #[error("{}", context)]
pub struct Error { pub struct Error {
@ -743,12 +764,12 @@ pub mod test {
let schema = Schema::Data(Data::AnyOf(vec![ let schema = Schema::Data(Data::AnyOf(vec![
Constructor { Constructor {
index: 0, index: 0,
fields: vec![Data::Integer.into()], fields: vec![Field::Inline(Data::Integer.into())],
} }
.into(), .into(),
Constructor { Constructor {
index: 1, index: 1,
fields: vec![Data::Bytes.into()], fields: vec![Field::Inline(Data::Bytes.into())],
} }
.into(), .into(),
])); ]));