Skip to main content

pax_runtime_api/pax_value/
to_from_impls.rs

1use std::ops::Range;
2use std::rc::Rc;
3
4use std::cell::RefCell;
5
6use super::ImplToFromPaxAny;
7use super::Numeric;
8use super::PaxValue;
9use super::ToPaxValue;
10use crate::impl_to_pax_value;
11use crate::math::Space;
12use crate::math::Transform2;
13use crate::math::Vector2;
14use crate::properties::PropertyValue;
15use crate::Color;
16use crate::ColorChannel;
17use crate::Depth;
18use crate::Duration;
19use crate::Fill;
20use crate::GradientStop;
21use crate::LayoutRole;
22use crate::LightShape;
23use crate::LinearGradient;
24use crate::Material;
25use crate::MaterialParams;
26use crate::Opacity;
27use crate::PathElement;
28use crate::PathSmoothing;
29use crate::Percent;
30use crate::Property;
31use crate::RadialGradient;
32use crate::Rotation;
33use crate::SceneAmbientLight;
34use crate::SceneLight;
35use crate::SceneLighting;
36use crate::Size;
37use crate::Stroke;
38use crate::StrokeCap;
39use crate::StrokeJoin;
40use crate::Transform2D;
41use crate::UnitValue;
42use crate::Vector3;
43
44// Primitive types
45impl_to_pax_value!(bool, PaxValue::Bool);
46
47impl_to_pax_value!(u8, PaxValue::Numeric, Numeric::U8);
48impl_to_pax_value!(u16, PaxValue::Numeric, Numeric::U16);
49impl_to_pax_value!(u32, PaxValue::Numeric, Numeric::U32);
50impl_to_pax_value!(u64, PaxValue::Numeric, Numeric::U64);
51
52impl_to_pax_value!(i8, PaxValue::Numeric, Numeric::I8);
53impl_to_pax_value!(i16, PaxValue::Numeric, Numeric::I16);
54impl_to_pax_value!(i32, PaxValue::Numeric, Numeric::I32);
55impl_to_pax_value!(i64, PaxValue::Numeric, Numeric::I64);
56
57impl_to_pax_value!(f32, PaxValue::Numeric, Numeric::F32);
58impl_to_pax_value!(f64, PaxValue::Numeric, Numeric::F64);
59
60impl_to_pax_value!(isize, PaxValue::Numeric, Numeric::ISize);
61impl_to_pax_value!(usize, PaxValue::Numeric, Numeric::USize);
62
63// don't allow to be serialized/deserialized successfully, just store it as a dyn Any
64impl ImplToFromPaxAny for () {}
65
66// for now. TBD how to handle this when we join Transform2D with Transform2 at some point
67impl<F: Space, T: Space> ImplToFromPaxAny for Transform2<F, T> {}
68
69impl_to_pax_value!(String, PaxValue::String);
70
71// Pax internal types
72impl_to_pax_value!(Numeric, PaxValue::Numeric);
73impl_to_pax_value!(Size, PaxValue::Size);
74impl_to_pax_value!(Rotation, PaxValue::Rotation);
75impl_to_pax_value!(Duration, PaxValue::Duration);
76impl_to_pax_value!(Percent, PaxValue::Percent);
77
78impl ToPaxValue for Depth {
79    fn to_pax_value(self) -> PaxValue {
80        PaxValue::Size(Size::Pixels(self.0))
81    }
82}
83
84impl ToPaxValue for LayoutRole {
85    fn to_pax_value(self) -> PaxValue {
86        let variant = match self {
87            LayoutRole::Default => "Default",
88            LayoutRole::Breakout => "Breakout",
89        };
90        PaxValue::Enum(Box::new((
91            "LayoutRole".to_string(),
92            variant.to_string(),
93            vec![],
94        )))
95    }
96}
97
98impl ToPaxValue for PathElement {
99    fn to_pax_value(self) -> PaxValue {
100        PaxValue::PathElement(Box::new(self))
101    }
102}
103
104impl ToPaxValue for Color {
105    fn to_pax_value(self) -> PaxValue {
106        PaxValue::Color(Box::new(self))
107    }
108}
109
110// Pax Vec type
111impl<T: ToPaxValue> ToPaxValue for Vec<T> {
112    fn to_pax_value(self) -> PaxValue {
113        PaxValue::Vec(
114            self.into_iter()
115                .map(|v| v.to_pax_value())
116                .collect::<Vec<_>>(),
117        )
118    }
119}
120
121impl<T: ToPaxValue> ToPaxValue for Option<T> {
122    fn to_pax_value(self) -> PaxValue {
123        match self {
124            Some(v) => PaxValue::Option(Box::new(Some(v.to_pax_value()))),
125            None => PaxValue::Option(Box::new(None)),
126        }
127    }
128}
129
130impl<T: ToPaxValue> ToPaxValue for Range<T> {
131    fn to_pax_value(self) -> PaxValue {
132        PaxValue::Range(
133            Box::new(self.start.to_pax_value()),
134            Box::new(self.end.to_pax_value()),
135        )
136    }
137}
138
139impl<T: ToPaxValue + Clone> ToPaxValue for Rc<RefCell<T>> {
140    fn to_pax_value(self) -> PaxValue {
141        crate::borrow!(self).clone().to_pax_value()
142    }
143}
144
145impl ToPaxValue for PaxValue {
146    fn to_pax_value(self) -> PaxValue {
147        self
148    }
149}
150
151impl<T: ToPaxValue + PropertyValue> ToPaxValue for Property<T> {
152    fn to_pax_value(self) -> PaxValue {
153        self.get().to_pax_value()
154    }
155}
156
157impl ToPaxValue for Fill {
158    fn to_pax_value(self) -> PaxValue {
159        match self {
160            Fill::Solid(color) => PaxValue::Enum(Box::new((
161                "Fill".to_string(),
162                "Solid".to_string(),
163                vec![color.to_pax_value()],
164            ))),
165            Fill::LinearGradient(gradient) => PaxValue::Enum(Box::new((
166                "Fill".to_string(),
167                "LinearGradient".to_string(),
168                vec![gradient.to_pax_value()],
169            ))),
170            Fill::RadialGradient(gradient) => PaxValue::Enum(Box::new((
171                "Fill".to_string(),
172                "RadialGradient".to_string(),
173                vec![gradient.to_pax_value()],
174            ))),
175        }
176    }
177}
178
179impl ToPaxValue for ColorChannel {
180    fn to_pax_value(self) -> PaxValue {
181        match self {
182            ColorChannel::Rotation(rot) => PaxValue::Enum(Box::new((
183                "ColorChannel".to_string(),
184                "Rotation".to_string(),
185                vec![rot.to_pax_value()],
186            ))),
187            ColorChannel::Percent(perc) => PaxValue::Enum(Box::new((
188                "ColorChannel".to_string(),
189                "Percent".to_string(),
190                vec![perc.to_pax_value()],
191            ))),
192            ColorChannel::Integer(num) => PaxValue::Enum(Box::new((
193                "ColorChannel".to_string(),
194                "Integer".to_string(),
195                vec![num.to_pax_value()],
196            ))),
197        }
198    }
199}
200
201impl ToPaxValue for Opacity {
202    fn to_pax_value(self) -> PaxValue {
203        match self {
204            Opacity::Alpha(value) => PaxValue::Enum(Box::new((
205                "Opacity".to_string(),
206                "Alpha".to_string(),
207                vec![value.to_pax_value()],
208            ))),
209            Opacity::Percent(value) => PaxValue::Enum(Box::new((
210                "Opacity".to_string(),
211                "Percent".to_string(),
212                vec![value.to_pax_value()],
213            ))),
214        }
215    }
216}
217
218impl ToPaxValue for UnitValue {
219    fn to_pax_value(self) -> PaxValue {
220        match self {
221            UnitValue::Unitless(value) => PaxValue::Enum(Box::new((
222                "UnitValue".to_string(),
223                "Unitless".to_string(),
224                vec![value.to_pax_value()],
225            ))),
226            UnitValue::Percent(value) => PaxValue::Enum(Box::new((
227                "UnitValue".to_string(),
228                "Percent".to_string(),
229                vec![value.to_pax_value()],
230            ))),
231        }
232    }
233}
234
235impl ToPaxValue for Stroke {
236    fn to_pax_value(self) -> PaxValue {
237        PaxValue::Object(
238            vec![
239                ("color".to_string(), self.color.get().to_pax_value()),
240                ("width".to_string(), self.width.to_pax_value()),
241                ("cap".to_string(), self.cap.get().to_pax_value()),
242                ("join".to_string(), self.join.get().to_pax_value()),
243            ]
244            .into_iter()
245            .collect(),
246        )
247    }
248}
249
250impl ToPaxValue for StrokeCap {
251    fn to_pax_value(self) -> PaxValue {
252        let variant = match self {
253            StrokeCap::Butt => "Butt",
254            StrokeCap::Round => "Round",
255            StrokeCap::Square => "Square",
256        };
257        PaxValue::Enum(Box::new((
258            "StrokeCap".to_string(),
259            variant.to_string(),
260            vec![],
261        )))
262    }
263}
264
265impl ToPaxValue for PathSmoothing {
266    fn to_pax_value(self) -> PaxValue {
267        let variant = match self {
268            PathSmoothing::None => "None",
269            PathSmoothing::Light => "Light",
270            PathSmoothing::Strong => "Strong",
271        };
272        PaxValue::Enum(Box::new((
273            "PathSmoothing".to_string(),
274            variant.to_string(),
275            vec![],
276        )))
277    }
278}
279
280impl ToPaxValue for StrokeJoin {
281    fn to_pax_value(self) -> PaxValue {
282        let variant = match self {
283            StrokeJoin::Miter => "Miter",
284            StrokeJoin::Round => "Round",
285            StrokeJoin::Bevel => "Bevel",
286        };
287        PaxValue::Enum(Box::new((
288            "StrokeJoin".to_string(),
289            variant.to_string(),
290            vec![],
291        )))
292    }
293}
294
295impl ToPaxValue for LightShape {
296    fn to_pax_value(self) -> PaxValue {
297        let variant = match self {
298            LightShape::Point => "Point",
299            LightShape::Directional => "Directional",
300        };
301        PaxValue::Enum(Box::new((
302            "LightShape".to_string(),
303            variant.to_string(),
304            vec![],
305        )))
306    }
307}
308
309impl ToPaxValue for Vector3 {
310    fn to_pax_value(self) -> PaxValue {
311        PaxValue::Object(
312            vec![
313                ("x".to_string(), self.x.to_pax_value()),
314                ("y".to_string(), self.y.to_pax_value()),
315                ("z".to_string(), self.z.to_pax_value()),
316            ]
317            .into_iter()
318            .collect(),
319        )
320    }
321}
322
323impl ToPaxValue for MaterialParams {
324    fn to_pax_value(self) -> PaxValue {
325        PaxValue::Object(
326            vec![
327                ("ambient".to_string(), self.ambient.get().to_pax_value()),
328                ("diffuse".to_string(), self.diffuse.get().to_pax_value()),
329                ("specular".to_string(), self.specular.get().to_pax_value()),
330                ("roughness".to_string(), self.roughness.get().to_pax_value()),
331                ("metallic".to_string(), self.metallic.get().to_pax_value()),
332                ("emissive".to_string(), self.emissive.get().to_pax_value()),
333                (
334                    "emissive_intensity".to_string(),
335                    self.emissive_intensity.get().to_pax_value(),
336                ),
337            ]
338            .into_iter()
339            .collect(),
340        )
341    }
342}
343
344impl ToPaxValue for Material {
345    fn to_pax_value(self) -> PaxValue {
346        match self {
347            Material::Lit(params) => PaxValue::Enum(Box::new((
348                "Material".to_string(),
349                "Lit".to_string(),
350                vec![params.to_pax_value()],
351            ))),
352            Material::Unlit => PaxValue::Enum(Box::new((
353                "Material".to_string(),
354                "Unlit".to_string(),
355                vec![],
356            ))),
357        }
358    }
359}
360
361impl ToPaxValue for SceneAmbientLight {
362    fn to_pax_value(self) -> PaxValue {
363        PaxValue::Object(
364            vec![
365                ("color".to_string(), self.color.to_pax_value()),
366                ("intensity".to_string(), self.intensity.to_pax_value()),
367            ]
368            .into_iter()
369            .collect(),
370        )
371    }
372}
373
374impl ToPaxValue for SceneLight {
375    fn to_pax_value(self) -> PaxValue {
376        PaxValue::Object(
377            vec![
378                ("shape".to_string(), self.shape.to_pax_value()),
379                ("position".to_string(), self.position.to_pax_value()),
380                ("direction".to_string(), self.direction.to_pax_value()),
381                ("color".to_string(), self.color.to_pax_value()),
382                ("intensity".to_string(), self.intensity.to_pax_value()),
383                ("radius".to_string(), self.radius.to_pax_value()),
384                ("enabled".to_string(), self.enabled.to_pax_value()),
385            ]
386            .into_iter()
387            .collect(),
388        )
389    }
390}
391
392impl ToPaxValue for SceneLighting {
393    fn to_pax_value(self) -> PaxValue {
394        PaxValue::Object(
395            vec![
396                ("active".to_string(), self.active.to_pax_value()),
397                (
398                    "ambient_is_authored".to_string(),
399                    self.ambient_is_authored.to_pax_value(),
400                ),
401                ("ambient".to_string(), self.ambient.to_pax_value()),
402                ("lights".to_string(), self.lights.to_pax_value()),
403            ]
404            .into_iter()
405            .collect(),
406        )
407    }
408}
409
410impl ToPaxValue for GradientStop {
411    fn to_pax_value(self) -> PaxValue {
412        PaxValue::Object(
413            vec![
414                ("position".to_string(), self.position.to_pax_value()),
415                ("color".to_string(), self.color.to_pax_value()),
416            ]
417            .into_iter()
418            .collect(),
419        )
420    }
421}
422
423impl ToPaxValue for LinearGradient {
424    fn to_pax_value(self) -> PaxValue {
425        PaxValue::Object(
426            vec![
427                (
428                    "start".to_string(),
429                    PaxValue::Vec(vec![
430                        self.start.0.to_pax_value(),
431                        self.start.1.to_pax_value(),
432                    ]),
433                ),
434                (
435                    "end".to_string(),
436                    PaxValue::Vec(vec![self.end.0.to_pax_value(), self.end.1.to_pax_value()]),
437                ),
438                ("stops".to_string(), self.stops.to_pax_value()),
439            ]
440            .into_iter()
441            .collect(),
442        )
443    }
444}
445
446impl ToPaxValue for RadialGradient {
447    fn to_pax_value(self) -> PaxValue {
448        PaxValue::Object(
449            vec![
450                (
451                    "start".to_string(),
452                    PaxValue::Vec(vec![
453                        self.start.0.to_pax_value(),
454                        self.start.1.to_pax_value(),
455                    ]),
456                ),
457                (
458                    "end".to_string(),
459                    PaxValue::Vec(vec![self.end.0.to_pax_value(), self.end.1.to_pax_value()]),
460                ),
461                ("radius".to_string(), self.radius.to_pax_value()),
462                ("stops".to_string(), self.stops.to_pax_value()),
463            ]
464            .into_iter()
465            .collect(),
466        )
467    }
468}
469
470impl ToPaxValue for Transform2D {
471    fn to_pax_value(self) -> PaxValue {
472        PaxValue::Object(
473            vec![
474                (
475                    "previous".to_string(),
476                    self.previous
477                        .map(|p| p.to_pax_value())
478                        .unwrap_or(PaxValue::Option(Box::new(None))),
479                ),
480                (
481                    "rotate".to_string(),
482                    self.rotate
483                        .map(|r| r.to_pax_value())
484                        .unwrap_or(PaxValue::Option(Box::new(None))),
485                ),
486                (
487                    "translate".to_string(),
488                    self.translate
489                        .map(|t| PaxValue::Option(Box::new(Some(t.to_vec().to_pax_value()))))
490                        .unwrap_or(PaxValue::Option(Box::new(None))),
491                ),
492                (
493                    "anchor".to_string(),
494                    self.anchor
495                        .map(|a| PaxValue::Option(Box::new(Some(a.to_vec().to_pax_value()))))
496                        .unwrap_or(PaxValue::Option(Box::new(None))),
497                ),
498                (
499                    "scale".to_string(),
500                    self.scale
501                        .map(|s| PaxValue::Option(Box::new(Some(s.to_vec().to_pax_value()))))
502                        .unwrap_or(PaxValue::Option(Box::new(None))),
503                ),
504                (
505                    "skew".to_string(),
506                    self.skew
507                        .map(|s| PaxValue::Option(Box::new(Some(s.to_vec().to_pax_value()))))
508                        .unwrap_or(PaxValue::Option(Box::new(None))),
509                ),
510            ]
511            .into_iter()
512            .collect(),
513        )
514    }
515}
516
517impl ToPaxValue for Transform2 {
518    fn to_pax_value(self) -> PaxValue {
519        PaxValue::Object(
520            vec![(
521                "m".to_string(),
522                PaxValue::Vec(self.m.iter().map(|v| v.to_pax_value()).collect::<Vec<_>>()),
523            )]
524            .into_iter()
525            .collect(),
526        )
527    }
528}
529
530impl ToPaxValue for Vector2 {
531    fn to_pax_value(self) -> PaxValue {
532        PaxValue::Object(
533            vec![
534                ("x".to_string(), self.x.to_pax_value()),
535                ("y".to_string(), self.y.to_pax_value()),
536            ]
537            .into_iter()
538            .collect(),
539        )
540    }
541}