use crate::core::types::TypeRef;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchemaManifest {
pub meta: ManifestMeta,
pub types: Vec<TypeDef>,
pub messages: Vec<MessageDef>,
pub enums: Vec<EnumManifest>,
pub type_aliases: Vec<TypeAliasManifest>,
#[serde(skip_serializing_if = "Option::is_none")]
pub router: Option<RouterManifest>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ManifestMeta {
pub name: String,
pub fingerprint: String,
pub version_byte: u8,
pub generated_at: String,
pub motto_version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeDef {
pub name: String,
pub kind: TypeKind,
pub size: Option<usize>,
pub alignment: Option<usize>,
pub docs: Option<String>,
pub generics: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum TypeKind {
Primitive {
rust_type: String,
wire_type: WireType,
},
String,
Optional { inner: String },
Array {
element: String,
fixed_size: Option<usize>,
},
Map { key: String, value: String },
Reference { target: String },
Tuple { elements: Vec<String> },
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum WireType {
Varint,
Fixed8,
Fixed16,
Fixed32,
Fixed64,
Fixed128,
LengthPrefixed,
}
impl WireType {
pub fn for_rust_type(ty: &str) -> Self {
match ty {
"u8" | "i8" | "bool" => Self::Fixed8,
"u16" | "i16" => Self::Fixed16,
"u32" | "i32" | "f32" | "char" => Self::Fixed32,
"u64" | "i64" | "f64" => Self::Fixed64,
"u128" | "i128" => Self::Fixed128,
"usize" | "isize" => Self::Fixed64, _ => Self::LengthPrefixed,
}
}
pub fn byte_size(&self) -> Option<usize> {
match self {
Self::Fixed8 => Some(1),
Self::Fixed16 => Some(2),
Self::Fixed32 => Some(4),
Self::Fixed64 => Some(8),
Self::Fixed128 => Some(16),
Self::Varint | Self::LengthPrefixed => None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageDef {
pub name: String,
pub fields: Vec<FieldManifest>,
pub fixed_size: Option<usize>,
pub min_size: usize,
pub alignment: usize,
pub docs: Option<String>,
pub generics: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FieldManifest {
pub name: String,
pub index: usize,
pub type_ref: String,
pub wire_type: WireType,
pub offset: Option<usize>,
pub size: Option<usize>,
pub optional: bool,
pub default: Option<String>,
pub docs: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnumManifest {
pub name: String,
pub repr: String,
pub variants: Vec<VariantManifest>,
pub is_simple: bool,
pub docs: Option<String>,
pub generics: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VariantManifest {
pub name: String,
pub discriminant: i64,
pub data: VariantData,
pub docs: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum VariantData {
Unit,
Tuple { types: Vec<String> },
Struct { fields: Vec<FieldManifest> },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouterManifest {
pub name: String,
pub variants: Vec<RouterVariant>,
pub docs: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RouterVariant {
pub name: String,
pub message_type: String,
pub discriminant: u16,
pub docs: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TypeAliasManifest {
pub name: String,
pub target: String,
pub docs: Option<String>,
}
impl SchemaManifest {
pub fn to_json(&self) -> serde_json::Result<String> {
serde_json::to_string_pretty(self)
}
pub fn from_json(json: &str) -> serde_json::Result<Self> {
serde_json::from_str(json)
}
pub fn to_bson(&self) -> bson::ser::Result<Vec<u8>> {
bson::to_vec(self)
}
pub fn from_bson(bytes: &[u8]) -> bson::de::Result<Self> {
bson::from_slice(bytes)
}
}
pub fn type_ref_to_string(ty: &TypeRef) -> String {
let mut s = ty.name.clone();
if !ty.generics.is_empty() {
s.push('<');
s.push_str(
&ty.generics
.iter()
.map(type_ref_to_string)
.collect::<Vec<_>>()
.join(", "),
);
s.push('>');
}
if let Some(arr) = &ty.array {
if let Some(size) = arr.size {
s = format!("[{};{}]", s, size);
} else {
s = format!("[{}]", s);
}
}
s
}