use crate::manifest::ImplKind;
use crate::registry::{RegisteredTransform, Registry};
use crate::types::ColumnSpec;
use serde::Serialize;
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct FieldInfo {
pub name: String,
#[serde(rename = "type")]
pub dtype: String,
}
impl From<&ColumnSpec> for FieldInfo {
fn from(c: &ColumnSpec) -> Self {
let dtype = serde_json::to_value(c.dtype)
.ok()
.and_then(|v| v.as_str().map(str::to_string))
.unwrap_or_else(|| "unknown".into());
FieldInfo {
name: c.name.clone(),
dtype,
}
}
}
#[derive(Debug, Clone, Serialize, PartialEq)]
pub struct TransformDescriptor {
pub id: String,
pub version: String,
pub key: String,
pub root: String,
#[serde(rename = "impl")]
pub impl_kind: String,
pub inputs: Vec<FieldInfo>,
pub outputs: Vec<FieldInfo>,
pub hardware: String,
pub deterministic: bool,
pub io: bool,
pub streaming: bool,
pub artifact: Option<String>,
}
fn enum_str<T: Serialize>(v: T) -> Option<String> {
serde_json::to_value(v)
.ok()
.and_then(|v| v.as_str().map(str::to_string))
}
impl From<&RegisteredTransform> for TransformDescriptor {
fn from(r: &RegisteredTransform) -> Self {
let m = &r.manifest;
let inputs = m
.inputs
.first()
.map(|s| s.columns.iter().map(FieldInfo::from).collect())
.unwrap_or_default();
let outputs = m.output.columns.iter().map(FieldInfo::from).collect();
TransformDescriptor {
id: m.id.clone(),
version: m.version.clone(),
key: r.key(),
root: r.root.clone(),
impl_kind: enum_str(m.impl_kind).unwrap_or_else(|| "builtin".into()),
inputs,
outputs,
hardware: enum_str(m.capabilities.hardware).unwrap_or_else(|| "cpu".into()),
deterministic: m.capabilities.deterministic,
io: m.capabilities.io,
streaming: m.capabilities.streaming,
artifact: m.entry.clone(),
}
}
}
pub fn descriptors(registry: &Registry) -> Vec<TransformDescriptor> {
let mut out: Vec<TransformDescriptor> = registry.iter().map(TransformDescriptor::from).collect();
out.sort_by(|a, b| a.key.cmp(&b.key));
out
}
pub fn model_descriptors(registry: &Registry) -> Vec<TransformDescriptor> {
let mut out: Vec<TransformDescriptor> = registry
.iter()
.filter(|r| r.manifest.impl_kind == ImplKind::Onnx)
.map(TransformDescriptor::from)
.collect();
out.sort_by(|a, b| a.key.cmp(&b.key));
out
}
pub fn catalog_json(registry: &Registry) -> String {
serde_json::json!({ "transforms": descriptors(registry) }).to_string()
}
pub fn models_json(registry: &Registry) -> String {
serde_json::json!({ "models": model_descriptors(registry) }).to_string()
}