}
}
- fn find_object_property(&self, key: &str) -> Option<(bool, &Schema)> {
+ fn find_object_property(&self, key: &str) -> Option<(bool, &PropertySchema)> {
self.as_object().and_then(|obj| obj.find_property(key))
}
- fn find_object_property_mut(&mut self, key: &str) -> Option<(&mut bool, &mut Schema)> {
+ fn find_object_property_mut(&mut self, key: &str) -> Option<(&mut bool, &mut PropertySchema)> {
self.as_object_mut()
.and_then(|obj| obj.find_property_mut(key))
}
}
}
+/// A property in an object either has its own schema or references an external schema.
+enum PropertySchema {
+ Schema(Schema),
+ Ref(ExprPath),
+}
+
+impl PropertySchema {
+ fn to_schema(&self, ts: &mut TokenStream) -> Result<(), Error> {
+ match self {
+ PropertySchema::Schema(s) => s.to_schema(ts),
+ PropertySchema::Ref(path) => {
+ ts.extend(quote! { & #path });
+ Ok(())
+ }
+ }
+ }
+}
+
#[derive(Default)]
/// Contains a sorted list of properties:
struct SchemaObject {
- properties: Vec<(String, bool, Schema)>,
+ properties: Vec<(String, bool, PropertySchema)>,
}
impl SchemaObject {
|mut properties, (key, value)| -> Result<_, syn::Error> {
let mut schema: JSONObject =
value.into_object("schema definition for field")?;
+
let optional: bool = schema
.remove("optional")
.map(|opt| -> Result<bool, syn::Error> {
})
.transpose()?
.unwrap_or(false);
- properties.push((key.to_string(), optional, schema.try_into()?));
+
+ let external_schema = schema
+ .remove("schema")
+ .map(ExprPath::try_from)
+ .transpose()?;
+
+ let schema = match external_schema {
+ Some(path) => PropertySchema::Ref(path),
+ None => PropertySchema::Schema(schema.try_into()?),
+ };
+
+ properties.push((key.to_string(), optional, schema));
+
Ok(properties)
},
)
Ok(())
}
- fn find_property(&self, key: &str) -> Option<(bool, &Schema)> {
+ fn find_property(&self, key: &str) -> Option<(bool, &PropertySchema)> {
match self
.properties
.binary_search_by(|prope| prope.0.as_str().cmp(key))
}
}
- fn find_property_mut(&mut self, key: &str) -> Option<(&mut bool, &mut Schema)> {
+ fn find_property_mut(&mut self, key: &str) -> Option<(&mut bool, &mut PropertySchema)> {
match self
.properties
.binary_search_by(|prope| prope.0.as_str().cmp(key))
use syn::spanned::Spanned;
use syn::Ident;
-use super::{Schema, SchemaItem};
+use super::{PropertySchema, Schema, SchemaItem};
use crate::util::{BareAssignment, JSONObject, SimpleIdent};
/// Parse `input`, `returns` and `protected` attributes out of an function annotated
Value,
ApiMethod,
RpcEnv,
- Other(&'a syn::Type, bool, &'a Schema),
+ Other(&'a syn::Type, bool, &'a PropertySchema),
}
fn check_input_type(input: &syn::FnArg) -> Result<(&syn::PatType, &syn::PatIdent), Error> {
let schema: &mut Schema = if let Some((_optional, schema)) =
input_schema.find_object_property_mut(&pat.ident.to_string())
{
- // ... if it has no `type` property (item = SchemaItem::Inferred), get a mutable
- // reference to the schema, so that we can...
- match &mut schema.item {
- SchemaItem::Inferred(_span) => schema,
- // other types are fine:
+ match schema {
+ PropertySchema::Schema(schema) => match &mut schema.item {
+ // ... if it has no `type` property (item = SchemaItem::Inferred), get a mutable
+ // reference to the schema, so that we can...
+ SchemaItem::Inferred(_span) => schema,
+ // other types are fine:
+ _ => continue,
+ },
_ => continue,
}
} else {
let param_type = if let Some((optional, schema)) =
input_schema.find_object_property(&pat.ident.to_string())
{
- match &schema.item {
- SchemaItem::Inferred(span) => bail!(*span, "failed to infer type"),
+ match schema {
+ PropertySchema::Schema(schema) => match &schema.item {
+ SchemaItem::Inferred(span) => bail!(*span, "failed to infer type"),
+ _ => (),
+ },
_ => (),
}
// Found an explicit parameter: extract it: