1use std::fmt;
2
3use gltf_v1_derive::Validate;
4use serde::de;
5use serde::{Deserialize, Serialize};
6
7use super::common::StringIndex;
8use super::validation::Checked;
9
10pub const FRAGMENT_SHADER: u32 = 35632;
11pub const VERTEX_SHADER: u32 = 35633;
12
13#[derive(Clone, Debug, Copy, Default)]
14pub enum ShaderType {
15 #[default]
16 FragmentShader,
17 VertexShader,
18}
19
20impl ShaderType {
21 pub const VALID_SHADER_TYPE: &[u32] = &[FRAGMENT_SHADER, VERTEX_SHADER];
22}
23
24impl From<ShaderType> for u32 {
25 fn from(value: ShaderType) -> Self {
26 match value {
27 ShaderType::FragmentShader => FRAGMENT_SHADER,
28 ShaderType::VertexShader => VERTEX_SHADER,
29 }
30 }
31}
32
33impl TryFrom<u32> for ShaderType {
34 type Error = ();
35
36 fn try_from(value: u32) -> Result<Self, Self::Error> {
37 match value {
38 FRAGMENT_SHADER => Ok(ShaderType::FragmentShader),
39 VERTEX_SHADER => Ok(ShaderType::VertexShader),
40 _ => Err(()),
41 }
42 }
43}
44impl Serialize for ShaderType {
45 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
46 where
47 S: serde::Serializer,
48 {
49 serializer.serialize_u32((*self).into())
50 }
51}
52
53impl<'de> Deserialize<'de> for Checked<ShaderType> {
54 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
55 where
56 D: serde::Deserializer<'de>,
57 {
58 struct Visitor;
59 impl serde::de::Visitor<'_> for Visitor {
60 type Value = Checked<ShaderType>;
61
62 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 write!(f, "any of: {:?}", ShaderType::VALID_SHADER_TYPE)
64 }
65
66 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
67 where
68 E: de::Error,
69 {
70 Ok((value as u32)
71 .try_into()
72 .map(Checked::Valid)
73 .unwrap_or(Checked::Invalid))
74 }
75 }
76 deserializer.deserialize_u32(Visitor)
77 }
78}
79
80#[derive(Clone, Debug, serde_derive::Deserialize, serde_derive::Serialize, Validate, Default)]
81pub struct Shader {
82 pub uri: String,
83 #[serde(rename = "type")]
84 pub type_: Checked<ShaderType>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub name: Option<String>,
87}
88
89impl Shader {
90 pub(crate) fn default_fragment_shader() -> Self {
91 Self {
94 uri: format!(
95 "{}{}",
96 "data:text/plain;base64,",
97 "cHJlY2lzaW9uIGhpZ2hwIGZsb2F0OwoKdW5pZm9ybSBtYXQ0IHVfbW9kZWxWaWV3TWF0cml4Owp1bmlmb3JtIG1hdDQgdV9wcm9qZWN0aW9uTWF0cml4OwoKYXR0cmlidXRlIHZlYzMgYV9wb3NpdGlvbjsKCnZvaWQgbWFpbih2b2lkKQp7CiAgICBnbF9Qb3NpdGlvbiA9IHVfcHJvamVjdGlvbk1hdHJpeCAqIHVfbW9kZWxWaWV3TWF0cml4ICogdmVjNChhX3Bvc2l0aW9uLDEuMCk7Cn0="
98 ),
99 type_: Checked::Valid(ShaderType::FragmentShader),
100 name: None,
101 }
102 }
103 pub(crate) fn default_vertex_shader() -> Self {
104 Self {
105 uri: format!(
106 "{}{}",
107 "data:text/plain;base64,",
108 "cHJlY2lzaW9uIGhpZ2hwIGZsb2F0OwoKdW5pZm9ybSB2ZWM0IHVfZW1pc3Npb247Cgp2b2lkIG1haW4odm9pZCkKewogICAgZ2xfRnJhZ0NvbG9yID0gdV9lbWlzc2lvbjsKfQ=="
109 ),
110 type_: Checked::Valid(ShaderType::VertexShader),
111 name: None,
112 }
113 }
114}
115
116#[derive(Clone, Debug, serde_derive::Deserialize, serde_derive::Serialize, Validate)]
117pub struct Program {
118 #[serde(default)]
119 #[serde(skip_serializing_if = "Vec::is_empty")]
120 pub attributes: Vec<String>,
121 #[serde(rename = "fragmentShader")]
122 pub fragment_shader: StringIndex<Shader>,
123 #[serde(rename = "vertexShader")]
124 pub vertex_shader: StringIndex<Shader>,
125 pub name: Option<String>,
126}
127
128impl Program {
129 pub(crate) fn default_program(fragment_shader: String, vertex_shader: String) -> Self {
130 let attributes = vec!["a_position".to_string()];
131
132 Self {
133 attributes,
134 fragment_shader: StringIndex::new(fragment_shader),
135 vertex_shader: StringIndex::new(vertex_shader),
136 name: None,
137 }
138 }
139}
140
141#[test]
142fn test_program_deserialize() {
143 let data = r#"{
144 "attributes": [
145 "a_normal",
146 "a_position"
147 ],
148 "fragmentShader": "fs_id",
149 "name": "user-defined program name",
150 "vertexShader": "vs_id",
151 "extensions" : {
152 "extension_name" : {
153 "extension specific" : "value"
154 }
155 },
156 "extras" : {
157 "Application specific" : "The extra object can contain any properties."
158 }
159 }"#;
160 let program: Result<Program, _> = serde_json::from_str(data);
161 let program_unwrap = program.unwrap();
162 println!("{}", serde_json::to_string(&program_unwrap).unwrap());
163 assert_eq!(
164 Some("user-defined program name".to_string()),
165 program_unwrap.name
166 );
167}
168
169#[test]
170fn test_shader_deserialize() {
171 let data = r#"{
172 "name": "user-defined vertex shader name",
173 "uri" : "vertexshader.glsl",
174 "type": 35633,
175 "extensions" : {
176 "extension_name" : {
177 "extension specific" : "value"
178 }
179 },
180 "extras" : {
181 "Application specific" : "The extra object can contain any properties."
182 }
183 }"#;
184 let shader: Result<Shader, _> = serde_json::from_str(data);
185 let shader_unwrap = shader.unwrap();
186 println!("{}", serde_json::to_string(&shader_unwrap).unwrap());
187 assert_eq!(
188 Some("user-defined vertex shader name".to_string()),
189 shader_unwrap.name
190 );
191}