pax_runtime_api/pax_value/
mod.rs1use crate::{Color, Interpolatable, PathElement, Percent, Rotation, Size};
2use std::{any::Any, fmt::Display};
3
4use self::numeric::Numeric;
5pub use coercion_impls::CoercionRules;
6use serde::{Deserialize, Serialize};
7
8mod arithmetic;
9mod coercion_impls;
10pub mod functions;
11mod macros;
12pub mod numeric;
13mod to_from_impls;
14
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
22#[serde(crate = "crate::serde")]
23pub enum PaxValue {
24 Bool(bool),
25 Numeric(Numeric),
26 String(String),
27 Size(Size),
28 Percent(Percent),
29 Color(Box<Color>),
30 Rotation(Rotation),
31 PathElement(PathElement),
32 Option(Box<Option<PaxValue>>),
33 Vec(Vec<PaxValue>),
34 Range(Box<PaxValue>, Box<PaxValue>),
35 Object(Vec<(String, PaxValue)>),
36 Enum(String, String, Vec<PaxValue>),
37}
38
39impl Display for PaxValue {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 match self {
43 PaxValue::Bool(b) => write!(f, "{}", b),
44 PaxValue::Numeric(n) => write!(f, "{}", n),
45 PaxValue::String(s) => write!(f, "\"{}\"", s),
46 PaxValue::Size(s) => write!(f, "{}", s),
47 PaxValue::Percent(p) => write!(f, "{}", p),
48 PaxValue::Color(c) => write!(f, "{}", c),
49 PaxValue::Rotation(r) => write!(f, "{}", r),
50 PaxValue::PathElement(path_elem) => {
51 write!(f, "PathElement::")?;
52 match path_elem {
53 PathElement::Empty => write!(f, "Empty"),
54 PathElement::Point(s1, s2) => write!(f, "Point({}, {})", s1, s2),
55 PathElement::Line => write!(f, "Line"),
56 PathElement::Quadratic(s1, s2) => write!(f, "Quadratic({}, {})", s1, s2),
57 PathElement::Cubic(vals) => {
58 write!(f, "Cubic({}, {}, {}, {})", vals.0, vals.1, vals.2, vals.3)
59 }
60 PathElement::Close => write!(f, "Close"),
61 }?;
62 Ok(())
63 }
64 PaxValue::Option(o) => match o.as_ref() {
65 Some(v) => write!(f, "Some({})", v),
66 None => write!(f, "None"),
67 },
68 PaxValue::Vec(v) => {
69 write!(f, "[")?;
70 for (i, val) in v.iter().enumerate() {
71 if i != 0 {
72 write!(f, ", ")?;
73 }
74 write!(f, "{}", val)?;
75 }
76 write!(f, "]")
77 }
78 PaxValue::Range(start, end) => write!(f, "{}..{}", start, end),
79 PaxValue::Object(o) => {
80 write!(f, "{{")?;
81 for (i, (key, val)) in o.iter().enumerate() {
82 if i != 0 {
83 write!(f, ", ")?;
84 }
85 write!(f, "{}: {}", key, val)?;
86 }
87 write!(f, "}}")
88 }
89 PaxValue::Enum(name, variant, values) => {
90 if name == "Color" {
91 write!(f, "{}", variant)?;
92 } else {
93 write!(f, "{}::{}", name, variant)?;
94 }
95 if !values.is_empty() {
96 write!(f, "(")?;
97 for (i, val) in values.iter().enumerate() {
98 if i != 0 {
99 write!(f, ", ")?;
100 }
101 write!(f, "{}", val)?;
102 }
103 write!(f, ")")?;
104 }
105 Ok(())
106 }
107 }
108 }
109}
110
111impl Default for PaxValue {
112 fn default() -> Self {
113 PaxValue::Numeric(Numeric::F64(0.0))
114 }
115}
116
117pub enum PaxAny {
120 Builtin(PaxValue),
121 Any(Box<dyn Any>),
122}
123
124impl std::fmt::Debug for PaxAny {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 write!(f, "PaxAny {{ .. }}")
127 }
128}
129
130impl Interpolatable for PaxValue {}
131
132pub trait ToPaxValue {
137 fn to_pax_value(self) -> PaxValue;
138}
139
140pub trait ToFromPaxAny
147where
148 Self: Sized + 'static,
149{
150 fn to_pax_any(self) -> PaxAny;
151 fn from_pax_any(pax_any: PaxAny) -> Result<Self, String>;
152 fn ref_from_pax_any(pax_any: &PaxAny) -> Result<&Self, String>;
153 fn mut_from_pax_any(pax_any: &mut PaxAny) -> Result<&mut Self, String>;
154}
155
156impl ToFromPaxAny for PaxValue {
157 fn to_pax_any(self) -> PaxAny {
158 PaxAny::Builtin(self)
159 }
160
161 fn from_pax_any(pax_any: PaxAny) -> Result<Self, String> {
162 match pax_any {
163 PaxAny::Builtin(val) => Ok(val),
164 PaxAny::Any(_) => Err("tried to unwrap any as builtin".to_string()),
165 }
166 }
167
168 fn ref_from_pax_any(pax_any: &PaxAny) -> Result<&Self, String> {
169 match pax_any {
170 PaxAny::Builtin(val) => Ok(val),
171 PaxAny::Any(_) => Err("tried to unwrap any as builtin".to_string()),
172 }
173 }
174
175 fn mut_from_pax_any(pax_any: &mut PaxAny) -> Result<&mut Self, String> {
176 match pax_any {
177 PaxAny::Builtin(val) => Ok(val),
178 PaxAny::Any(_) => Err("tried to unwrap any as builtin".to_string()),
179 }
180 }
181}
182
183pub trait ImplToFromPaxAny: 'static {}
188
189impl<T: ImplToFromPaxAny> ToFromPaxAny for T {
192 fn to_pax_any(self) -> PaxAny {
193 PaxAny::Any(Box::new(self) as Box<dyn Any>)
194 }
195
196 fn from_pax_any(pax_any: PaxAny) -> Result<Self, String> {
197 match pax_any {
198 PaxAny::Any(v) => Ok(*v
199 .downcast::<Self>()
200 .map_err(|_e| "downcast failed".to_string())?),
201 _ => Err("wasn't any".to_string()),
202 }
203 }
204
205 fn ref_from_pax_any(pax_any: &PaxAny) -> Result<&Self, String> {
206 match pax_any {
207 PaxAny::Any(v) => v
208 .downcast_ref::<Self>()
209 .ok_or_else(|| "downcast failed".to_string()),
210 _ => Err("wasn't any".to_string()),
211 }
212 }
213
214 fn mut_from_pax_any(pax_any: &mut PaxAny) -> Result<&mut Self, String> {
215 match pax_any {
216 PaxAny::Any(v) => v
217 .downcast_mut::<Self>()
218 .ok_or_else(|| "downcast failed".to_string()),
219 _ => Err("wasn't any".to_string()),
220 }
221 }
222}
223
224impl ToFromPaxAny for PaxAny {
226 fn to_pax_any(self) -> PaxAny {
227 self
228 }
229
230 fn from_pax_any(pax_any: PaxAny) -> Result<Self, String> {
231 Ok(pax_any)
232 }
233
234 fn ref_from_pax_any(pax_any: &PaxAny) -> Result<&Self, String> {
235 Ok(pax_any)
236 }
237
238 fn mut_from_pax_any(pax_any: &mut PaxAny) -> Result<&mut Self, String> {
239 Ok(pax_any)
240 }
241}