1use std::{borrow::Cow, collections::HashMap, fmt::Debug};
7
8use anyhow::Result;
9use bytemuck::{Pod, Zeroable};
10use strum::{Display, EnumCount, FromRepr};
11
12mod path;
13pub mod schema;
14mod value;
15
16pub use path::{path, Path};
17pub use schema::{ChildrenKey, FieldKey};
18pub use value::{Value, ValueConversionError};
19
20#[repr(u32)]
23#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, FromRepr, EnumCount, Display)]
24pub enum SpecType {
25 #[default]
27 Unknown = 0,
28
29 Attribute = 1,
31 Connection = 2,
32 Expression = 3,
33 Mapper = 4,
34 MapperArg = 5,
35 Prim = 6,
36 PseudoRoot = 7,
37 Relationship = 8,
38 RelationshipTarget = 9,
39 Variant = 10,
40 VariantSet = 11,
41}
42
43#[repr(i32)]
44#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromRepr)]
45#[cfg_attr(feature = "serde", derive(serde::Serialize))]
46#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
47pub enum Specifier {
48 Def,
49 Over,
50 Class,
51}
52
53#[repr(i32)]
60#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromRepr)]
61#[cfg_attr(feature = "serde", derive(serde::Serialize))]
62#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
63pub enum Permission {
64 Public,
65 Private,
66}
67
68#[repr(i32)]
73#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, FromRepr)]
74#[cfg_attr(feature = "serde", derive(serde::Serialize))]
75#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
76pub enum Variability {
77 #[default]
78 Varying,
79 Uniform,
80}
81
82#[repr(C)]
84#[derive(Debug, Clone, Copy, PartialEq, Pod, Zeroable)]
85#[cfg_attr(feature = "serde", derive(serde::Serialize))]
86pub struct LayerOffset {
87 pub offset: f64,
89 pub scale: f64,
91}
92
93impl Default for LayerOffset {
94 fn default() -> Self {
95 Self {
96 offset: 0.0,
97 scale: 1.0,
98 }
99 }
100}
101
102impl LayerOffset {
103 #[inline]
104 pub fn new(offset: f64, scale: f64) -> Self {
105 Self { offset, scale }
106 }
107
108 #[inline]
109 pub fn is_valid(&self) -> bool {
110 self.offset.is_finite() && self.scale.is_finite()
111 }
112}
113
114#[derive(Debug, Default, Clone, PartialEq)]
124#[cfg_attr(feature = "serde", derive(serde::Serialize))]
125pub struct Payload {
126 #[cfg_attr(feature = "serde", serde(rename = "asset", skip_serializing_if = "String::is_empty"))]
128 pub asset_path: String,
129 #[cfg_attr(feature = "serde", serde(rename = "path", skip_serializing_if = "Path::is_empty"))]
131 pub prim_path: Path,
132 #[cfg_attr(
134 feature = "serde",
135 serde(rename = "layerOffset", skip_serializing_if = "Option::is_none")
136 )]
137 pub layer_offset: Option<LayerOffset>,
138}
139
140#[derive(Debug, Default, Clone, PartialEq)]
147#[cfg_attr(feature = "serde", derive(serde::Serialize))]
148pub struct Reference {
149 #[cfg_attr(feature = "serde", serde(rename = "asset", skip_serializing_if = "String::is_empty"))]
151 pub asset_path: String,
152 #[cfg_attr(feature = "serde", serde(rename = "path", skip_serializing_if = "Path::is_empty"))]
154 pub prim_path: Path,
155 #[cfg_attr(feature = "serde", serde(rename = "layerOffset"))]
157 pub layer_offset: LayerOffset,
158 #[cfg_attr(
160 feature = "serde",
161 serde(rename = "customData", skip_serializing_if = "HashMap::is_empty")
162 )]
163 pub custom_data: HashMap<String, Value>,
164}
165
166mod list_op;
167
168pub use list_op::ListOp;
169
170pub type IntListOp = ListOp<i32>;
171pub type UintListOp = ListOp<u32>;
172
173pub type Int64ListOp = ListOp<i64>;
174pub type Uint64ListOp = ListOp<u64>;
175
176pub type StringListOp = ListOp<String>;
177pub type TokenListOp = ListOp<String>;
178pub type PathListOp = ListOp<Path>;
179pub type ReferenceListOp = ListOp<Reference>;
180pub type PayloadListOp = ListOp<Payload>;
181
182pub type TimeSampleMap = Vec<(f64, Value)>;
183
184pub trait AbstractData {
190 fn has_spec(&self, path: &Path) -> bool;
192
193 fn has_field(&self, path: &Path, field: &str) -> bool;
195
196 fn spec_type(&self, path: &Path) -> Option<SpecType>;
198
199 fn get(&self, path: &Path, field: &str) -> Result<Cow<'_, Value>>;
212
213 fn list(&self, path: &Path) -> Option<Vec<String>>;
215}
216
217pub type LayerData = Box<dyn AbstractData>;
219
220#[derive(Debug, Clone)]
224pub struct Spec {
225 pub ty: SpecType,
227 pub fields: HashMap<String, Value>,
229}
230
231impl Spec {
232 pub fn new(ty: SpecType) -> Self {
234 Self {
235 ty,
236 fields: Default::default(),
237 }
238 }
239
240 #[inline]
242 pub fn add(&mut self, key: impl AsRef<str>, value: impl Into<Value>) {
243 self.fields.insert(key.as_ref().to_owned(), value.into());
244 }
245}