// The `x-rust-type` schema extension (upstream rust_extension.rs).
///|
priv struct RustExtension {
crate_name : String
version : String
path : String
parameters : Array[@schema.Schema]
}
///|
/// serde's derived `Deserialize` for the extension value.
fn parse_rust_extension(v : @serde_json.Value) -> RustExtension? {
guard v is Object(o) else { return None }
guard o.get("crate") is Some(String(crate_name)) else { return None }
guard o.get("version") is Some(String(version)) else { return None }
guard o.get("path") is Some(String(path)) else { return None }
let parameters = match o.get("parameters") {
None => []
Some(Array(xs)) => {
let out = []
for x in xs {
let s = @schema.decode_schema(x) catch { _ => return None }
out.push(s)
}
out
}
Some(_) => return None
}
Some({ crate_name, version, path, parameters, })
}
///|
fn TypeSpace::convert_rust_extension(
self : TypeSpace,
schema : @schema.SchemaObject,
) -> TypeEntry? raise TypifyError {
guard schema.extensions.get("x-rust-type") is Some(x_rust) else {
return None
}
guard parse_rust_extension(x_rust) is Some(ext) else { return None }
let req = try @semver.VersionReq::parse(ext.version) catch {
_ => return None
} noraise {
r => r
}
let crate_ident = ext.crate_name.replace_all(old="-", new="_")
guard ext.path.find("::") is Some(path_sep) else { return None }
if crate_ident != ext.path.unsafe_substring(start=0, end=path_sep) {
return None
}
let path = match self.settings.crates.get(ext.crate_name) {
Some(spec) => {
let ok_version = match spec.version {
Any => true
Version(v) => req.matches(v)
Never => false
}
if !ok_version {
return None
}
match spec.rename {
Some(new_crate) =>
new_crate.replace_all(old="-", new="_") +
ext.path.unsafe_substring(start=path_sep, end=ext.path.length())
None => ext.path
}
}
None =>
match self.settings.unknown_crates {
Generate | Deny => return None
Allow => ext.path
}
}
// Convert the type parameters; any failure means "don't use the type".
let param_ids = []
for p in ext.parameters {
match ok(() => self.id_for_schema(Unknown, p).0) {
Some(id) => param_ids.push(id)
None => return None
}
}
Some(TypeEntry::new_native_params("::\{path}", param_ids))
}