use serde::Deserialize;
use std::collections::HashMap;
#[derive(Debug, Clone, Deserialize)]
pub struct TorchIr {
pub format: String,
pub version: u32,
pub model_name: String,
#[serde(default)]
pub producer: String,
pub inputs: Vec<IoDef>,
pub weights: Vec<WeightDef>,
pub nodes: Vec<NodeDef>,
pub outputs: Vec<OutputDef>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct IoDef {
pub id: String,
pub shape: Vec<i64>,
pub dtype: String,
#[serde(default)]
pub dynamic: Option<Vec<i64>>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct WeightDef {
pub id: String,
pub key: String,
pub shape: Vec<i64>,
pub dtype: String,
#[serde(default)]
pub kind: String, }
#[derive(Debug, Clone, Deserialize)]
pub struct NodeDef {
pub id: String,
pub op: String,
#[serde(default)]
pub args: Vec<Arg>,
#[serde(default)]
pub kwargs: HashMap<String, Arg>,
#[serde(default)]
pub out: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct OutputDef {
#[serde(rename = "ref")]
pub reference: Option<String>,
pub shape: Option<Vec<i64>>,
pub dtype: Option<String>,
#[serde(default)]
pub konst: Option<Arg>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum Arg {
Ref {
#[serde(rename = "ref")]
reference: String,
},
Bool {
#[serde(rename = "bool")]
v: bool,
},
Int {
#[serde(rename = "int")]
v: i64,
},
Float {
#[serde(rename = "float")]
v: f64,
},
Str {
#[serde(rename = "str")]
v: String,
},
Dtype {
dtype: String,
},
None {
none: bool,
},
List {
list: Vec<Arg>,
},
}
impl Arg {
pub fn as_ref_name(&self) -> Option<&str> {
match self {
Arg::Ref { reference } => Some(reference.as_str()),
_ => None,
}
}
pub fn as_int(&self) -> Option<i64> {
match self {
Arg::Int { v } => Some(*v),
Arg::Bool { v } => Some(*v as i64),
_ => None,
}
}
pub fn as_float(&self) -> Option<f64> {
match self {
Arg::Float { v } => Some(*v),
Arg::Int { v } => Some(*v as f64),
_ => None,
}
}
pub fn as_bool(&self) -> Option<bool> {
match self {
Arg::Bool { v } => Some(*v),
_ => None,
}
}
pub fn is_none(&self) -> bool {
matches!(self, Arg::None { .. })
}
pub fn as_int_list(&self) -> Option<Vec<i64>> {
match self {
Arg::List { list } => list.iter().map(|a| a.as_int()).collect(),
_ => None,
}
}
pub fn as_ref_list(&self) -> Option<Vec<String>> {
match self {
Arg::List { list } => list
.iter()
.map(|a| a.as_ref_name().map(|s| s.to_string()))
.collect(),
_ => None,
}
}
}
pub fn primary_out(out: &Option<serde_json::Value>) -> Option<(Vec<i64>, String)> {
let v = out.as_ref()?;
let obj = match v {
serde_json::Value::Array(items) => items.first()?,
other => other,
};
let shape = obj.get("shape")?.as_array()?;
let dims: Vec<i64> = shape.iter().filter_map(|d| d.as_i64()).collect();
let dtype = obj.get("dtype")?.as_str()?.to_string();
Some((dims, dtype))
}
pub fn all_outs(out: &Option<serde_json::Value>) -> Vec<Option<(Vec<i64>, String)>> {
let Some(v) = out.as_ref() else {
return vec![];
};
let items: Vec<&serde_json::Value> = match v {
serde_json::Value::Array(items) => items.iter().collect(),
other => vec![other],
};
items
.into_iter()
.map(|obj| {
let shape = obj.get("shape")?.as_array()?;
let dims: Vec<i64> = shape.iter().filter_map(|d| d.as_i64()).collect();
let dtype = obj.get("dtype")?.as_str()?.to_string();
Some((dims, dtype))
})
.collect()
}