chrome_remote_interface_model_tools/
lib.rs1use std::convert::TryFrom;
2use std::fs::File;
3use std::io::Write;
4use std::path::Path;
5
6use anyhow::Context as _;
7pub use check_features::check_features;
8use serde::Deserialize;
9
10mod check_features;
11mod render;
12
13#[derive(Debug, Deserialize)]
14#[serde(deny_unknown_fields)]
15struct Property {
16 name: String,
17 #[serde(flatten)]
18 annotation: Annotation,
19 #[serde(flatten)]
20 r#type: Type,
21}
22
23impl Typed for Property {
24 fn r#type(&self) -> &Type {
25 &self.r#type
26 }
27}
28
29impl Annotatable for Property {
30 fn annotation(&self) -> &Annotation {
31 &self.annotation
32 }
33}
34
35#[derive(Debug, Deserialize)]
36struct RawType {
37 r#type: Option<String>,
38 #[serde(rename = "$ref")]
39 r#ref: Option<String>,
40 r#enum: Option<Vec<String>>,
41 properties: Option<Vec<Property>>,
42 items: Option<Type>,
43 optional: Option<bool>,
44}
45
46#[derive(Debug, Deserialize)]
47#[serde(try_from = "RawType")]
48enum Type {
49 String,
50
51 Integer,
52
53 Number,
54
55 Boolean,
56
57 Binary,
58
59 Any,
60
61 EnumString(Vec<String>),
62
63 Object(Vec<Property>),
64
65 Array(Box<Type>),
66
67 Ref(String),
68
69 Option(Box<Type>),
70}
71
72impl TryFrom<RawType> for Type {
73 type Error = anyhow::Error;
74
75 fn try_from(value: RawType) -> Result<Self, Self::Error> {
76 let RawType {
77 r#type,
78 r#ref,
79 r#enum,
80 properties,
81 items,
82 optional,
83 } = value;
84 let result = match (r#type.as_deref(), r#ref, r#enum, properties, items) {
85 (None, Some(r), None, None, None) => Type::Ref(r),
86 (Some("string"), None, Some(v), None, None) => Type::EnumString(v),
87 (Some("string"), None, None, None, None) => Type::String,
88 (Some("integer"), None, None, None, None) => Type::Integer,
89 (Some("number"), None, None, None, None) => Type::Number,
90 (Some("boolean"), None, None, None, None) => Type::Boolean,
91 (Some("binary"), None, None, None, None) => Type::Binary,
92 (Some("any"), None, None, None, None) => Type::Any,
93 (Some("object"), None, None, properties, None) => {
94 Type::Object(properties.unwrap_or_default())
95 }
96 (Some("array"), None, None, None, Some(items)) => Type::Array(Box::new(items)),
97 other => anyhow::bail!("{:?}", other),
98 };
99 if optional.unwrap_or_default() {
100 Ok(Self::Option(Box::new(result)))
101 } else {
102 Ok(result)
103 }
104 }
105}
106
107trait Typed {
108 fn r#type(&self) -> &Type;
109}
110
111trait Annotatable {
112 fn annotation(&self) -> &Annotation;
113
114 fn deps(&self) -> Option<Vec<String>> {
115 None
116 }
117}
118
119#[derive(Debug, Deserialize, Default)]
120struct Annotation {
121 description: Option<String>,
122 #[serde(default)]
123 experimental: bool,
124 #[serde(default)]
125 deprecated: bool,
126}
127
128#[derive(Debug, Deserialize)]
129#[serde(deny_unknown_fields)]
130struct DomainType {
131 id: String,
132 #[serde(flatten)]
133 annotation: Annotation,
134 #[serde(flatten)]
135 r#type: Type,
136}
137
138impl Typed for DomainType {
139 fn r#type(&self) -> &Type {
140 &self.r#type
141 }
142}
143
144impl Annotatable for DomainType {
145 fn annotation(&self) -> &Annotation {
146 &self.annotation
147 }
148}
149
150#[derive(Debug, Deserialize)]
151#[serde(deny_unknown_fields)]
152struct Parameter {
153 name: String,
154 #[serde(flatten)]
155 annotation: Annotation,
156 #[serde(flatten)]
157 r#type: Type,
158}
159
160impl Typed for Parameter {
161 fn r#type(&self) -> &Type {
162 &self.r#type
163 }
164}
165
166impl Annotatable for Parameter {
167 fn annotation(&self) -> &Annotation {
168 &self.annotation
169 }
170}
171
172#[derive(Debug, Deserialize)]
173#[serde(deny_unknown_fields)]
174struct Return {
175 name: String,
176 #[serde(flatten)]
177 annotation: Annotation,
178 #[serde(flatten)]
179 r#type: Type,
180}
181
182impl Typed for Return {
183 fn r#type(&self) -> &Type {
184 &self.r#type
185 }
186}
187
188impl Annotatable for Return {
189 fn annotation(&self) -> &Annotation {
190 &self.annotation
191 }
192}
193
194#[derive(Debug, Deserialize)]
195#[serde(deny_unknown_fields)]
196struct Command {
197 name: String,
198 redirect: Option<String>,
199 #[serde(flatten)]
200 annotation: Annotation,
201 #[serde(default)]
202 parameters: Vec<Parameter>,
203 #[serde(default)]
204 returns: Vec<Return>,
205}
206
207impl Annotatable for Command {
208 fn annotation(&self) -> &Annotation {
209 &self.annotation
210 }
211}
212
213#[derive(Debug, Deserialize)]
214#[serde(deny_unknown_fields)]
215struct Event {
216 name: String,
217 #[serde(flatten)]
218 annotation: Annotation,
219 #[serde(default)]
220 parameters: Vec<Parameter>,
221}
222
223impl Annotatable for Event {
224 fn annotation(&self) -> &Annotation {
225 &self.annotation
226 }
227}
228
229#[derive(Debug, Deserialize)]
230#[serde(deny_unknown_fields)]
231struct Domain {
232 domain: String,
233 #[serde(flatten)]
234 annotation: Annotation,
235 #[serde(default)]
236 dependencies: Vec<String>,
237 #[serde(default)]
238 types: Vec<DomainType>,
239 #[serde(default)]
240 commands: Vec<Command>,
241 #[serde(default)]
242 events: Vec<Event>,
243}
244
245impl Annotatable for Domain {
246 fn annotation(&self) -> &Annotation {
247 &self.annotation
248 }
249
250 fn deps(&self) -> Option<Vec<String>> {
251 Some(
252 vec![self.domain.clone()]
253 .into_iter()
254 .chain(self.dependencies.clone().into_iter())
255 .collect(),
256 )
257 }
258}
259
260#[derive(Debug, Deserialize)]
261#[serde(deny_unknown_fields)]
262struct ProtocolVersion {
263 major: String,
264 minor: String,
265}
266
267#[derive(Debug, Deserialize)]
268#[serde(deny_unknown_fields)]
269struct Protocol {
270 domains: Vec<Domain>,
271 version: ProtocolVersion,
272}
273
274pub fn run<P: AsRef<Path>, W: Write>(path: P, output: &mut W) -> anyhow::Result<()> {
275 let mut f = File::open(path)?;
276 let protocol = serde_json::from_reader(&mut f).context("failed to parse protocol json.")?;
277 let program = render::render(&protocol);
278 write!(output, "{}", program)?;
279 Ok(())
280}