1use std::fmt;
2
3use gltf_v1_derive::Validate;
4use serde::{de, ser};
5use serde_derive::{Deserialize, Serialize};
6
7use super::validation::Checked;
8
9#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
10pub struct Perspective {
11 #[serde(rename = "aspectRatio")]
12 #[serde(skip_serializing_if = "Option::is_none")]
13 pub aspect_ratio: Option<f32>,
14 pub yfov: f32,
15 pub zfar: f32,
16 pub znear: f32,
17}
18
19#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
20pub struct Orthographic {
21 pub xmag: f32,
22 pub ymag: f32,
23 pub zfar: f32,
24 pub znear: f32,
25}
26
27#[derive(Clone, Copy, Debug, Eq, PartialEq)]
28pub enum CameraType {
29 Perspective,
30 Orthographic,
31}
32
33impl CameraType {
34 pub const VALID_CAMERA_TYPES: &[&str] = &["perspective", "orthographic"];
35}
36
37impl TryFrom<&str> for CameraType {
38 type Error = ();
39
40 fn try_from(value: &str) -> Result<Self, Self::Error> {
41 match value {
42 "perspective" => Ok(CameraType::Perspective),
43 "orthographic" => Ok(CameraType::Orthographic),
44 _ => Err(()),
45 }
46 }
47}
48
49impl From<CameraType> for &str {
50 fn from(value: CameraType) -> Self {
51 match value {
52 CameraType::Perspective => "perspective",
53 CameraType::Orthographic => "orthographic",
54 }
55 }
56}
57
58impl ser::Serialize for CameraType {
59 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60 where
61 S: ser::Serializer,
62 {
63 serializer.serialize_str((*self).into())
64 }
65}
66
67impl<'de> de::Deserialize<'de> for Checked<CameraType> {
68 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
69 where
70 D: de::Deserializer<'de>,
71 {
72 struct Visitor;
73 impl de::Visitor<'_> for Visitor {
74 type Value = Checked<CameraType>;
75
76 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 write!(f, "any of: {:?}", CameraType::VALID_CAMERA_TYPES)
78 }
79
80 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
81 where
82 E: de::Error,
83 {
84 Ok(value
85 .try_into()
86 .map(Checked::Valid)
87 .unwrap_or(Checked::Invalid))
88 }
89 }
90 deserializer.deserialize_str(Visitor)
91 }
92}
93
94#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
95pub struct Camera {
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub orthographic: Option<Orthographic>,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub perspective: Option<Perspective>,
100 #[serde(rename = "type")]
101 pub type_: Checked<CameraType>,
102 #[serde(skip_serializing_if = "Option::is_none")]
103 pub name: Option<String>,
104}
105
106#[test]
107fn test_camera_deserialize() {
108 let data = r#"{
109 "name" : "user-defined name of perspective camera",
110 "perspective" : {
111 "aspectRatio" : 1.77,
112 "yfov" : 0.7854,
113 "zfar" : 1000,
114 "znear" : 1
115 },
116 "type" : "perspective",
117 "extensions" : {
118 "extension_name" : {
119 "extension specific" : "value"
120 }
121 },
122 "extras" : {
123 "Application specific" : "The extra object can contain any properties."
124 }
125 }"#;
126 let camera: Result<Camera, _> = serde_json::from_str(data);
127 let camera_unwrap = camera.unwrap();
128 println!("{}", serde_json::to_string(&camera_unwrap).unwrap());
129 assert_eq!(
130 Some("user-defined name of perspective camera".to_string()),
131 camera_unwrap.name
132 );
133}