1use crate::validation::{Checked, Error, Validate};
2use crate::{extensions, Path, Root};
3use serde::{de, ser};
4use serde_derive::{Deserialize, Serialize};
5use std::fmt;
6
7pub const VALID_CAMERA_TYPES: &[&str] = &["perspective", "orthographic"];
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub enum Type {
13 Perspective = 1,
15
16 Orthographic,
18}
19
20#[derive(Clone, Debug, Deserialize, Serialize)]
25pub struct Camera {
26 #[serde(skip_serializing_if = "Option::is_none")]
29 pub orthographic: Option<Orthographic>,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
34 pub perspective: Option<Perspective>,
35
36 #[serde(rename = "type")]
38 pub type_: Checked<Type>,
39
40 #[serde(default, skip_serializing_if = "Option::is_none")]
42 pub extensions: Option<extensions::camera::Camera>,
43}
44
45#[derive(Clone, Debug, Deserialize, Serialize)]
47pub struct Orthographic {
48 pub xmag: f32,
50
51 pub ymag: f32,
53
54 pub zfar: f32,
56
57 pub znear: f32,
59
60 #[serde(default, skip_serializing_if = "Option::is_none")]
62 pub extensions: Option<extensions::camera::Orthographic>,
63}
64
65#[derive(Clone, Debug, Deserialize, Serialize)]
67pub struct Perspective {
68 #[serde(rename = "aspectRatio")]
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub aspect_ratio: Option<f32>,
72
73 pub yfov: f32,
75
76 #[serde(skip_serializing_if = "Option::is_none")]
78 pub zfar: Option<f32>,
79
80 pub znear: f32,
82
83 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub extensions: Option<extensions::camera::Perspective>,
86}
87
88impl Validate for Camera {
89 fn validate_minimally<P, R>(&self, root: &Root, path: P, report: &mut R)
90 where
91 P: Fn() -> Path,
92 R: FnMut(&dyn Fn() -> Path, Error),
93 {
94 if self.orthographic.is_none() && self.perspective.is_none() {
95 report(&path, Error::Missing);
96 }
97
98 self.orthographic
99 .validate_minimally(root, || path().field("orthographic"), report);
100 self.perspective
101 .validate_minimally(root, || path().field("perspective"), report);
102 self.type_.validate_minimally(root, || path().field("type"), report);
103 self.extensions
104 .validate_minimally(root, || path().field("extensions"), report);
105 }
106}
107
108impl Validate for Orthographic {
109 fn validate_completely<P, R>(&self, root: &Root, path: P, report: &mut R)
110 where
111 P: Fn() -> Path,
112 R: FnMut(&dyn Fn() -> Path, Error),
113 {
114 if self.znear < 0.0 {
115 report(&path, Error::Invalid);
116 }
117
118 if self.zfar < 0.0 || self.zfar < self.znear {
119 report(&path, Error::Invalid);
120 }
121
122 self.extensions
123 .validate_completely(root, || path().field("extensions"), report);
124 }
125}
126
127impl Validate for Perspective {
128 fn validate_completely<P, R>(&self, root: &Root, path: P, report: &mut R)
129 where
130 P: Fn() -> Path,
131 R: FnMut(&dyn Fn() -> Path, Error),
132 {
133 if let Some(aspect_ratio) = self.aspect_ratio {
134 if aspect_ratio < 0.0 {
135 report(&path, Error::Invalid);
136 }
137 }
138
139 if self.yfov < 0.0 {
140 report(&path, Error::Invalid);
141 }
142
143 if self.znear < 0.0 {
144 report(&path, Error::Invalid);
145 }
146
147 if let Some(zfar) = self.zfar {
148 if zfar < 0.0 || zfar < self.znear {
149 report(&path, Error::Invalid);
150 }
151 }
152
153 self.extensions
154 .validate_completely(root, || path().field("extensions"), report);
155 }
156}
157
158impl<'de> de::Deserialize<'de> for Checked<Type> {
159 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
160 where
161 D: de::Deserializer<'de>,
162 {
163 struct Visitor;
164 impl<'de> de::Visitor<'de> for Visitor {
165 type Value = Checked<Type>;
166
167 fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168 write!(f, "any of: {:?}", VALID_CAMERA_TYPES)
169 }
170
171 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
172 where
173 E: de::Error,
174 {
175 use self::Type::*;
176 use crate::validation::Checked::*;
177 Ok(match value {
178 "perspective" => Valid(Perspective),
179 "orthographic" => Valid(Orthographic),
180 _ => Invalid,
181 })
182 }
183 }
184 deserializer.deserialize_str(Visitor)
185 }
186}
187
188impl ser::Serialize for Type {
189 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
190 where
191 S: ser::Serializer,
192 {
193 match *self {
194 Type::Perspective => serializer.serialize_str("perspective"),
195 Type::Orthographic => serializer.serialize_str("orthographic"),
196 }
197 }
198}