html_bindgen/parse/
webidls.rs1use std::path::PathBuf;
2
3use super::{Attribute, AttributeType};
4use crate::Result;
5use convert_case::{Case, Casing};
6use serde::{Deserialize, Serialize};
7use weedle::interface::InterfaceMember;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct ParsedInterface {
12 pub name: String,
13 pub inherits_from: Option<String>,
14 pub attributes: Vec<Attribute>,
15}
16
17pub fn parse_webidls(
18 iter: impl Iterator<Item = Result<(String, PathBuf)>>,
19) -> Result<Vec<ParsedInterface>> {
20 let mut outputs = vec![];
21 for res in iter {
22 let (string, path) = res?;
23 let filename = path.file_name().unwrap().to_str().unwrap();
24 if !filename.starts_with("HTML") {
25 continue;
26 }
27 let string = string.trim();
28 let definitions = weedle::parse(&string).map_err(|err| err.to_string())?;
29 let definitions = definitions.into_iter();
30 for def in definitions {
31 if let weedle::Definition::Interface(interface) = def {
32 outputs.push(ParsedInterface {
33 name: parse_interface_name(&interface),
34 inherits_from: parse_inheritance(&interface),
35 attributes: interface
36 .members
37 .body
38 .iter()
39 .filter_map(parse_attributes)
40 .collect::<Vec<_>>(),
41 });
42 }
43 }
44 }
45 Ok(outputs)
46}
47
48fn parse_interface_name(interface: &weedle::InterfaceDefinition) -> String {
49 interface.identifier.0.to_owned()
50}
51
52fn parse_inheritance(interface: &weedle::InterfaceDefinition) -> Option<String> {
53 interface
54 .inheritance
55 .map(|parent| parent.identifier.0.to_string())
56}
57
58fn parse_attributes(member: &InterfaceMember) -> Option<Attribute> {
59 if let InterfaceMember::Attribute(attr) = member {
60 if attr.readonly.is_some() {
62 return None;
63 }
64
65 let ty = match &attr.type_.type_ {
66 weedle::types::Type::Single(ty) => match ty {
67 weedle::types::SingleType::NonAny(ty) => match ty {
68 weedle::types::NonAnyType::Integer(_) => AttributeType::Integer,
69 weedle::types::NonAnyType::FloatingPoint(_) => AttributeType::Float,
70 weedle::types::NonAnyType::Boolean(_) => AttributeType::Bool,
71 weedle::types::NonAnyType::Object(_) => {
72 return None;
74 }
75 weedle::types::NonAnyType::USVString(_)
76 | weedle::types::NonAnyType::DOMString(_) => AttributeType::String,
77 weedle::types::NonAnyType::Identifier(id) => {
78 AttributeType::Identifier(id.type_.0.to_owned())
79 }
80 ty => unreachable!("{ty:?} is not a recognized type"),
81 },
82 weedle::types::SingleType::Any(_) => return None,
83 },
84 _ => return None,
85 };
86 let field_name = attr.identifier.0.to_string().to_case(Case::Snake);
87 let field_name = super::normalize_field_name(&field_name);
88 Some(Attribute {
89 name: attr.identifier.0.to_string(),
90 field_name,
91 description: String::new(),
92 ty,
93 })
94 } else {
95 None
96 }
97}