diff --git a/.vscode/settings.json b/.vscode/settings.json index 307f2aa..26ebec9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,70 @@ { "rust-analyzer.showUnlinkedFileNotification": false, - "editor.tabSize": 2 + "editor.tabSize": 2, + "files.associations": { + "string": "cpp", + "istream": "cpp", + "locale": "cpp", + "tuple": "cpp", + "vector": "cpp", + "__bit_reference": "cpp", + "__config": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__node_handle": "cpp", + "__split_buffer": "cpp", + "__threading_support": "cpp", + "__tree": "cpp", + "__verbose_abort": "cpp", + "any": "cpp", + "array": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "execution": "cpp", + "forward_list": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "limits": "cpp", + "list": "cpp", + "map": "cpp", + "mutex": "cpp", + "new": "cpp", + "optional": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "regex": "cpp", + "set": "cpp", + "span": "cpp", + "sstream": "cpp", + "stack": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string_view": "cpp", + "typeinfo": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "valarray": "cpp", + "variant": "cpp", + "algorithm": "cpp" + } } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e278992..1693866 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,6 +143,12 @@ dependencies = [ "scoped-tls", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.6.0" @@ -252,12 +258,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.5" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -514,6 +521,16 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "flatbuffers" +version = "24.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8add37afff2d4ffa83bc748a70b4b1370984f6980768554182424ef71447c35f" +dependencies = [ + "bitflags 1.3.2", + "rustc_version 0.4.1", +] + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -753,7 +770,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10bc10261f46b8df263b80e7779d1748b1880488cd951fbb9e096430cead10e6" dependencies = [ "ahash 0.8.11", - "bitflags", + "bitflags 2.6.0", "const-str", "cssparser 0.33.0", "cssparser-color", @@ -893,7 +910,7 @@ version = "2.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1bd081bbaef43600fd2c5dd4c525b8ecea7dfdacf40ebc674e87851dce6559e" dependencies = [ - "bitflags", + "bitflags 2.6.0", "ctor", "napi-derive", "napi-sys", @@ -1038,7 +1055,7 @@ version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce9c47a67c66fee4a5a42756f9784d92941bd0ab2b653539a9e90521a44b66f0" dependencies = [ - "bitflags", + "bitflags 2.6.0", "cssparser 0.33.0", "fxhash", "log", @@ -1092,6 +1109,7 @@ version = "0.1.0" dependencies = [ "cssparser 0.33.0", "ego-tree", + "flatbuffers", "html5ever", "indexmap", "lightningcss", @@ -1372,7 +1390,7 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags", + "bitflags 2.6.0", ] [[package]] @@ -1484,13 +1502,22 @@ dependencies = [ "semver 0.9.0", ] +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.23", +] + [[package]] name = "rustix" version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1539,7 +1566,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4eb30575f3638fc8f6815f448d50cb1a2e255b0897985c8c59f4d37b72a07b06" dependencies = [ - "bitflags", + "bitflags 2.6.0", "cssparser 0.31.2", "derive_more", "fxhash", @@ -1647,6 +1674,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "simd-abstraction" version = "0.7.1" @@ -1703,7 +1736,7 @@ dependencies = [ "debugid", "if_chain", "rustc-hash", - "rustc_version", + "rustc_version 0.2.3", "serde", "serde_json", "unicode-id-start", @@ -1943,7 +1976,7 @@ version = "0.112.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d1d5c33c22ad50e8e34b3080a6fb133316d2eaa7d00400fc5018151f5ca44c5a" dependencies = [ - "bitflags", + "bitflags 2.6.0", "bytecheck", "is-macro", "num-bigint", @@ -2029,7 +2062,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "660badfe2eed8b6213ec9dcd71aa0786f8fb46ffa012e0313bcba1fe4a9a5c73" dependencies = [ "better_scoped_tls", - "bitflags", + "bitflags 2.6.0", "indexmap", "once_cell", "phf 0.11.2", diff --git a/Cargo.toml b/Cargo.toml index 06cba6c..cf7c728 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ style = "0.1.0" pcre2 = "0.2.6" regex = "1.10.3" swc_core = { version = "0.90.24", features = ["__common", "ecma_transforms_typescript", "ecma_ast", "ecma_plugin_transform", "ecma_utils", "ecma_parser", "ecma_visit", "ecma_codegen", "__testing_transform"]} +flatbuffers = "24.3.25" [build-dependencies] napi-build = "2.0.1" diff --git a/flatbuffers/stylesheet.fbs b/flatbuffers/stylesheet.fbs new file mode 100644 index 0000000..ee5efd4 --- /dev/null +++ b/flatbuffers/stylesheet.fbs @@ -0,0 +1,50 @@ +namespace Styles; + +table String { + value:string; +} + +table Integer { + value:uint32; +} + +union Value { + String, + Integer, + Object +} + +table KeyValue { + key:string; + value:Value; +} + +table Object { + fields:[KeyValue]; +} + +table DeclarationTuple { + property_id:uint8; + value:Value; +} + +table Selector { + string_value:string; + integer_value:uint32; + is_string:bool; +} + +table Style { + declarations:[DeclarationTuple]; + media:uint32; + selector:[Selector]; +} + +table StyleSheet { + fonts:[string]; + keyframes:[string]; + medias:[string]; + styles:[Style]; +} + +root_type StyleSheet; diff --git a/src/lib.rs b/src/lib.rs index 6755f38..cc9ba26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ #![deny(clippy::all)] use serde::Deserialize; +use napi::bindgen_prelude::Buffer; use json_writer::JsonWriter; use style_parser::StyleParser; @@ -9,6 +10,7 @@ use style_propetries::unit::Platform; #[macro_use] extern crate napi_derive; +mod stylesheet_generated; mod constants; mod json_writer; mod parse_style_properties; @@ -16,19 +18,30 @@ mod style_parser; mod style_propetries; mod utils; mod visitor; +// mod ffi; + +// use ffi::process_stylesheet; // styles: css的code string // platform_string: "ReactNative" | "Harmony" +#[napi(object)] +#[derive(Deserialize)] +pub struct OutputOptions { + pub is_bin: Option +} + #[napi(object)] #[derive(Deserialize)] pub struct ParseOptions { pub platform_string: String, + pub output: Option, } #[napi(object)] pub struct ParseResult { - pub code: String, + pub code: Option, + pub buffer: Option, } #[napi] @@ -38,6 +51,10 @@ pub fn parse(styles: Vec, options: ParseOptions) -> ParseResult { "Harmony" => Platform::Harmony, _ => Platform::Harmony, }; + let output = options.output.unwrap_or(OutputOptions { + is_bin: Some(false) + }); + let is_bin = output.is_bin.unwrap_or(false); // 解析样式文件 let css = styles.join("\n"); @@ -55,7 +72,80 @@ pub fn parse(styles: Vec, options: ParseOptions) -> ParseResult { style_data.all_fonts.borrow().clone(), ); + let style_json = style_map.to_json(); + if is_bin { + // 输出到文件 + let convert_result = utils::convert_json_to_flatbuffer(&style_json); + if let Ok(buffer) = convert_result { + return ParseResult { + code: None, + buffer: Some(Buffer::from(buffer)), + }; + } + return ParseResult { + code: Some(style_json), + buffer: None + }; + } + ParseResult { - code: style_map.to_json(), + code: Some(style_json), + buffer: None + } +} + +#[cfg(test)] +mod tests { + use crate::utils::convert_json_to_flatbuffer; + use serde_json::json; + use crate::stylesheet_generated::styles; + + #[test] + fn test_valid_input() { + let json_input = json!({"fonts":[],"keyframes":[],"medias":[],"styles":[{"declarations":[[22,293],[42,4278753764u32]],"media":0,"selector":["app"]},{"declarations":[[41,4294901760u32]],"media":0,"selector":["tit"]},{"declarations":[[29,24],[41,4291979550u32]],"media":0,"selector":["tit",2,"app"]},{"declarations":[[22,100],[25,100]],"media":0,"selector":["img"]}]}).to_string(); + + let result = convert_json_to_flatbuffer(&json_input); + assert!(result.is_ok()); + + let buffer = result.unwrap(); + let style_sheet = styles::root_as_style_sheet(&buffer).unwrap(); + + // 验证 fonts + assert_eq!(style_sheet.fonts().unwrap().len(), 0); + + // 验证 keyframes + assert_eq!(style_sheet.keyframes().unwrap().len(), 0); + + // 验证 medias + assert_eq!(style_sheet.medias().unwrap().len(), 0); + + // 验证 styles + let styles = style_sheet.styles().unwrap(); + assert_eq!(styles.len(), 4); // 根据实际情况调整 + let first_style = styles.get(0); + assert_eq!(first_style.declarations().unwrap().len(), 2); + + let first_declaration = first_style.declarations().unwrap().get(0); + assert_eq!(first_declaration.property_id(), 22); + assert!(first_declaration.value_as_integer().is_some()); + assert_eq!(first_declaration.value_as_integer().unwrap().value(), 293); + + let second_declaration = first_style.declarations().unwrap().get(1); + assert_eq!(second_declaration.property_id(), 42); + assert!(second_declaration.value_as_integer().is_some()); + assert_eq!(second_declaration.value_as_integer().unwrap().value(), 4278753764); + + let first_selector = first_style.selector().unwrap().get(0); + assert_eq!(first_selector.string_value().unwrap(), "app"); + + let thrird_style = styles.get(2); + assert_eq!(thrird_style.declarations().unwrap().len(), 2); + let selector = thrird_style.selector().unwrap(); + assert_eq!(selector.len(), 3); + let first_selector = selector.get(0); + assert_eq!(first_selector.string_value().unwrap(), "tit"); + let second_selector = selector.get(1); + assert_eq!(second_selector.integer_value(), 2); + } } diff --git a/src/main.rs b/src/main.rs index cd7d75b..a6bef36 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use json_writer::JsonWriter; use style_parser::StyleParser; use style_propetries::unit::Platform; +mod stylesheet_generated; mod constants; mod json_writer; mod parse_style_properties; @@ -32,5 +33,11 @@ pub fn main() { style_data.all_fonts.borrow().clone(), ); - print!("{}", style_map.to_json()); + let style_json = style_map.to_json(); + print!("{}", style_json); + let convert_result = utils::convert_json_to_flatbuffer(&style_json); + if let Ok(buffer) = convert_result { + // 写文件 + std::fs::write("__test__/fixure/style.bin", buffer).unwrap(); + } } diff --git a/src/style_propetries/text_shadow.rs b/src/style_propetries/text_shadow.rs index b99fc6a..e652575 100644 --- a/src/style_propetries/text_shadow.rs +++ b/src/style_propetries/text_shadow.rs @@ -59,7 +59,7 @@ impl ToExpr for TextShadow { PropOrSpread::Prop(Box::new(Prop::KeyValue(KeyValueProp { key: generate_prop_name!("radius"), value: Box::new(generate_expr_by_length!( - self.offset_x.as_ref().unwrap(), + self.blur_radius.as_ref().unwrap(), Platform::Harmony )), }))), diff --git a/src/stylesheet_generated.rs b/src/stylesheet_generated.rs new file mode 100644 index 0000000..2040ef7 --- /dev/null +++ b/src/stylesheet_generated.rs @@ -0,0 +1,1305 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +// @generated + +use core::mem; +use core::cmp::Ordering; + +extern crate flatbuffers; +use self::flatbuffers::{EndianScalar, Follow}; + +#[allow(unused_imports, dead_code)] +pub mod styles { + + use core::mem; + use core::cmp::Ordering; + + extern crate flatbuffers; + use self::flatbuffers::{EndianScalar, Follow}; + +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_VALUE: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_VALUE: u8 = 3; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_VALUE: [Value; 4] = [ + Value::NONE, + Value::String, + Value::Integer, + Value::Object, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct Value(pub u8); +#[allow(non_upper_case_globals)] +impl Value { + pub const NONE: Self = Self(0); + pub const String: Self = Self(1); + pub const Integer: Self = Self(2); + pub const Object: Self = Self(3); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 3; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::String, + Self::Integer, + Self::Object, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::String => Some("String"), + Self::Integer => Some("Integer"), + Self::Object => Some("Object"), + _ => None, + } + } +} +impl core::fmt::Debug for Value { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> flatbuffers::Follow<'a> for Value { + type Inner = Self; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = flatbuffers::read_scalar_at::(buf, loc); + Self(b) + } +} + +impl flatbuffers::Push for Value { + type Output = Value; + #[inline] + unsafe fn push(&self, dst: &mut [u8], _written_len: usize) { + flatbuffers::emplace_scalar::(dst, self.0); + } +} + +impl flatbuffers::EndianScalar for Value { + type Scalar = u8; + #[inline] + fn to_little_endian(self) -> u8 { + self.0.to_le() + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(v: u8) -> Self { + let b = u8::from_le(v); + Self(b) + } +} + +impl<'a> flatbuffers::Verifiable for Value { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + u8::run_verifier(v, pos) + } +} + +impl flatbuffers::SimpleToVerifyInSlice for Value {} +pub struct ValueUnionTableOffset {} + +pub enum StringOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct String<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for String<'a> { + type Inner = String<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> String<'a> { + pub const VT_VALUE: flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + String { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args StringArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = StringBuilder::new(_fbb); + if let Some(x) = args.value { builder.add_value(x); } + builder.finish() + } + + + #[inline] + pub fn value(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(String::VT_VALUE, None)} + } +} + +impl flatbuffers::Verifiable for String<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>("value", Self::VT_VALUE, false)? + .finish(); + Ok(()) + } +} +pub struct StringArgs<'a> { + pub value: Option>, +} +impl<'a> Default for StringArgs<'a> { + #[inline] + fn default() -> Self { + StringArgs { + value: None, + } + } +} + +pub struct StringBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> StringBuilder<'a, 'b, A> { + #[inline] + pub fn add_value(&mut self, value: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(String::VT_VALUE, value); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> StringBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + StringBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for String<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("String"); + ds.field("value", &self.value()); + ds.finish() + } +} +pub enum IntegerOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Integer<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Integer<'a> { + type Inner = Integer<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> Integer<'a> { + pub const VT_VALUE: flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Integer { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args IntegerArgs + ) -> flatbuffers::WIPOffset> { + let mut builder = IntegerBuilder::new(_fbb); + builder.add_value(args.value); + builder.finish() + } + + + #[inline] + pub fn value(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Integer::VT_VALUE, Some(0)).unwrap()} + } +} + +impl flatbuffers::Verifiable for Integer<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::("value", Self::VT_VALUE, false)? + .finish(); + Ok(()) + } +} +pub struct IntegerArgs { + pub value: u32, +} +impl<'a> Default for IntegerArgs { + #[inline] + fn default() -> Self { + IntegerArgs { + value: 0, + } + } +} + +pub struct IntegerBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> IntegerBuilder<'a, 'b, A> { + #[inline] + pub fn add_value(&mut self, value: u32) { + self.fbb_.push_slot::(Integer::VT_VALUE, value, 0); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> IntegerBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + IntegerBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Integer<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Integer"); + ds.field("value", &self.value()); + ds.finish() + } +} +pub enum KeyValueOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct KeyValue<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for KeyValue<'a> { + type Inner = KeyValue<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> KeyValue<'a> { + pub const VT_KEY: flatbuffers::VOffsetT = 4; + pub const VT_VALUE_TYPE: flatbuffers::VOffsetT = 6; + pub const VT_VALUE: flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + KeyValue { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args KeyValueArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = KeyValueBuilder::new(_fbb); + if let Some(x) = args.value { builder.add_value(x); } + if let Some(x) = args.key { builder.add_key(x); } + builder.add_value_type(args.value_type); + builder.finish() + } + + + #[inline] + pub fn key(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(KeyValue::VT_KEY, None)} + } + #[inline] + pub fn value_type(&self) -> Value { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(KeyValue::VT_VALUE_TYPE, Some(Value::NONE)).unwrap()} + } + #[inline] + pub fn value(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(KeyValue::VT_VALUE, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn value_as_string(&self) -> Option> { + if self.value_type() == Value::String { + self.value().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { String::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn value_as_integer(&self) -> Option> { + if self.value_type() == Value::Integer { + self.value().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Integer::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn value_as_object(&self) -> Option> { + if self.value_type() == Value::Object { + self.value().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Object::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl flatbuffers::Verifiable for KeyValue<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>("key", Self::VT_KEY, false)? + .visit_union::("value_type", Self::VT_VALUE_TYPE, "value", Self::VT_VALUE, false, |key, v, pos| { + match key { + Value::String => v.verify_union_variant::>("Value::String", pos), + Value::Integer => v.verify_union_variant::>("Value::Integer", pos), + Value::Object => v.verify_union_variant::>("Value::Object", pos), + _ => Ok(()), + } + })? + .finish(); + Ok(()) + } +} +pub struct KeyValueArgs<'a> { + pub key: Option>, + pub value_type: Value, + pub value: Option>, +} +impl<'a> Default for KeyValueArgs<'a> { + #[inline] + fn default() -> Self { + KeyValueArgs { + key: None, + value_type: Value::NONE, + value: None, + } + } +} + +pub struct KeyValueBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> KeyValueBuilder<'a, 'b, A> { + #[inline] + pub fn add_key(&mut self, key: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(KeyValue::VT_KEY, key); + } + #[inline] + pub fn add_value_type(&mut self, value_type: Value) { + self.fbb_.push_slot::(KeyValue::VT_VALUE_TYPE, value_type, Value::NONE); + } + #[inline] + pub fn add_value(&mut self, value: flatbuffers::WIPOffset) { + self.fbb_.push_slot_always::>(KeyValue::VT_VALUE, value); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> KeyValueBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + KeyValueBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for KeyValue<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("KeyValue"); + ds.field("key", &self.key()); + ds.field("value_type", &self.value_type()); + match self.value_type() { + Value::String => { + if let Some(x) = self.value_as_string() { + ds.field("value", &x) + } else { + ds.field("value", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Value::Integer => { + if let Some(x) = self.value_as_integer() { + ds.field("value", &x) + } else { + ds.field("value", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Value::Object => { + if let Some(x) = self.value_as_object() { + ds.field("value", &x) + } else { + ds.field("value", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("value", &x) + }, + }; + ds.finish() + } +} +pub enum ObjectOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Object<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Object<'a> { + type Inner = Object<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> Object<'a> { + pub const VT_FIELDS: flatbuffers::VOffsetT = 4; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Object { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args ObjectArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = ObjectBuilder::new(_fbb); + if let Some(x) = args.fields { builder.add_fields(x); } + builder.finish() + } + + + #[inline] + pub fn fields(&self) -> Option>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Object::VT_FIELDS, None)} + } +} + +impl flatbuffers::Verifiable for Object<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>>>("fields", Self::VT_FIELDS, false)? + .finish(); + Ok(()) + } +} +pub struct ObjectArgs<'a> { + pub fields: Option>>>>, +} +impl<'a> Default for ObjectArgs<'a> { + #[inline] + fn default() -> Self { + ObjectArgs { + fields: None, + } + } +} + +pub struct ObjectBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> ObjectBuilder<'a, 'b, A> { + #[inline] + pub fn add_fields(&mut self, fields: flatbuffers::WIPOffset>>>) { + self.fbb_.push_slot_always::>(Object::VT_FIELDS, fields); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> ObjectBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + ObjectBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Object<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Object"); + ds.field("fields", &self.fields()); + ds.finish() + } +} +pub enum DeclarationTupleOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct DeclarationTuple<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for DeclarationTuple<'a> { + type Inner = DeclarationTuple<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> DeclarationTuple<'a> { + pub const VT_PROPERTY_ID: flatbuffers::VOffsetT = 4; + pub const VT_VALUE_TYPE: flatbuffers::VOffsetT = 6; + pub const VT_VALUE: flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + DeclarationTuple { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args DeclarationTupleArgs + ) -> flatbuffers::WIPOffset> { + let mut builder = DeclarationTupleBuilder::new(_fbb); + if let Some(x) = args.value { builder.add_value(x); } + builder.add_value_type(args.value_type); + builder.add_property_id(args.property_id); + builder.finish() + } + + + #[inline] + pub fn property_id(&self) -> u8 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(DeclarationTuple::VT_PROPERTY_ID, Some(0)).unwrap()} + } + #[inline] + pub fn value_type(&self) -> Value { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(DeclarationTuple::VT_VALUE_TYPE, Some(Value::NONE)).unwrap()} + } + #[inline] + pub fn value(&self) -> Option> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>(DeclarationTuple::VT_VALUE, None)} + } + #[inline] + #[allow(non_snake_case)] + pub fn value_as_string(&self) -> Option> { + if self.value_type() == Value::String { + self.value().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { String::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn value_as_integer(&self) -> Option> { + if self.value_type() == Value::Integer { + self.value().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Integer::init_from_table(t) } + }) + } else { + None + } + } + + #[inline] + #[allow(non_snake_case)] + pub fn value_as_object(&self) -> Option> { + if self.value_type() == Value::Object { + self.value().map(|t| { + // Safety: + // Created from a valid Table for this object + // Which contains a valid union in this slot + unsafe { Object::init_from_table(t) } + }) + } else { + None + } + } + +} + +impl flatbuffers::Verifiable for DeclarationTuple<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::("property_id", Self::VT_PROPERTY_ID, false)? + .visit_union::("value_type", Self::VT_VALUE_TYPE, "value", Self::VT_VALUE, false, |key, v, pos| { + match key { + Value::String => v.verify_union_variant::>("Value::String", pos), + Value::Integer => v.verify_union_variant::>("Value::Integer", pos), + Value::Object => v.verify_union_variant::>("Value::Object", pos), + _ => Ok(()), + } + })? + .finish(); + Ok(()) + } +} +pub struct DeclarationTupleArgs { + pub property_id: u8, + pub value_type: Value, + pub value: Option>, +} +impl<'a> Default for DeclarationTupleArgs { + #[inline] + fn default() -> Self { + DeclarationTupleArgs { + property_id: 0, + value_type: Value::NONE, + value: None, + } + } +} + +pub struct DeclarationTupleBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> DeclarationTupleBuilder<'a, 'b, A> { + #[inline] + pub fn add_property_id(&mut self, property_id: u8) { + self.fbb_.push_slot::(DeclarationTuple::VT_PROPERTY_ID, property_id, 0); + } + #[inline] + pub fn add_value_type(&mut self, value_type: Value) { + self.fbb_.push_slot::(DeclarationTuple::VT_VALUE_TYPE, value_type, Value::NONE); + } + #[inline] + pub fn add_value(&mut self, value: flatbuffers::WIPOffset) { + self.fbb_.push_slot_always::>(DeclarationTuple::VT_VALUE, value); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> DeclarationTupleBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + DeclarationTupleBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for DeclarationTuple<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("DeclarationTuple"); + ds.field("property_id", &self.property_id()); + ds.field("value_type", &self.value_type()); + match self.value_type() { + Value::String => { + if let Some(x) = self.value_as_string() { + ds.field("value", &x) + } else { + ds.field("value", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Value::Integer => { + if let Some(x) = self.value_as_integer() { + ds.field("value", &x) + } else { + ds.field("value", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + Value::Object => { + if let Some(x) = self.value_as_object() { + ds.field("value", &x) + } else { + ds.field("value", &"InvalidFlatbuffer: Union discriminant does not match value.") + } + }, + _ => { + let x: Option<()> = None; + ds.field("value", &x) + }, + }; + ds.finish() + } +} +pub enum SelectorOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Selector<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Selector<'a> { + type Inner = Selector<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> Selector<'a> { + pub const VT_STRING_VALUE: flatbuffers::VOffsetT = 4; + pub const VT_INTEGER_VALUE: flatbuffers::VOffsetT = 6; + pub const VT_IS_STRING: flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Selector { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args SelectorArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = SelectorBuilder::new(_fbb); + builder.add_integer_value(args.integer_value); + if let Some(x) = args.string_value { builder.add_string_value(x); } + builder.add_is_string(args.is_string); + builder.finish() + } + + + #[inline] + pub fn string_value(&self) -> Option<&'a str> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>(Selector::VT_STRING_VALUE, None)} + } + #[inline] + pub fn integer_value(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Selector::VT_INTEGER_VALUE, Some(0)).unwrap()} + } + #[inline] + pub fn is_string(&self) -> bool { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Selector::VT_IS_STRING, Some(false)).unwrap()} + } +} + +impl flatbuffers::Verifiable for Selector<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>("string_value", Self::VT_STRING_VALUE, false)? + .visit_field::("integer_value", Self::VT_INTEGER_VALUE, false)? + .visit_field::("is_string", Self::VT_IS_STRING, false)? + .finish(); + Ok(()) + } +} +pub struct SelectorArgs<'a> { + pub string_value: Option>, + pub integer_value: u32, + pub is_string: bool, +} +impl<'a> Default for SelectorArgs<'a> { + #[inline] + fn default() -> Self { + SelectorArgs { + string_value: None, + integer_value: 0, + is_string: false, + } + } +} + +pub struct SelectorBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> SelectorBuilder<'a, 'b, A> { + #[inline] + pub fn add_string_value(&mut self, string_value: flatbuffers::WIPOffset<&'b str>) { + self.fbb_.push_slot_always::>(Selector::VT_STRING_VALUE, string_value); + } + #[inline] + pub fn add_integer_value(&mut self, integer_value: u32) { + self.fbb_.push_slot::(Selector::VT_INTEGER_VALUE, integer_value, 0); + } + #[inline] + pub fn add_is_string(&mut self, is_string: bool) { + self.fbb_.push_slot::(Selector::VT_IS_STRING, is_string, false); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> SelectorBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + SelectorBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Selector<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Selector"); + ds.field("string_value", &self.string_value()); + ds.field("integer_value", &self.integer_value()); + ds.field("is_string", &self.is_string()); + ds.finish() + } +} +pub enum StyleOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct Style<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for Style<'a> { + type Inner = Style<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> Style<'a> { + pub const VT_DECLARATIONS: flatbuffers::VOffsetT = 4; + pub const VT_MEDIA: flatbuffers::VOffsetT = 6; + pub const VT_SELECTOR: flatbuffers::VOffsetT = 8; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + Style { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args StyleArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = StyleBuilder::new(_fbb); + if let Some(x) = args.selector { builder.add_selector(x); } + builder.add_media(args.media); + if let Some(x) = args.declarations { builder.add_declarations(x); } + builder.finish() + } + + + #[inline] + pub fn declarations(&self) -> Option>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Style::VT_DECLARATIONS, None)} + } + #[inline] + pub fn media(&self) -> u32 { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::(Style::VT_MEDIA, Some(0)).unwrap()} + } + #[inline] + pub fn selector(&self) -> Option>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(Style::VT_SELECTOR, None)} + } +} + +impl flatbuffers::Verifiable for Style<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>>>("declarations", Self::VT_DECLARATIONS, false)? + .visit_field::("media", Self::VT_MEDIA, false)? + .visit_field::>>>("selector", Self::VT_SELECTOR, false)? + .finish(); + Ok(()) + } +} +pub struct StyleArgs<'a> { + pub declarations: Option>>>>, + pub media: u32, + pub selector: Option>>>>, +} +impl<'a> Default for StyleArgs<'a> { + #[inline] + fn default() -> Self { + StyleArgs { + declarations: None, + media: 0, + selector: None, + } + } +} + +pub struct StyleBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> StyleBuilder<'a, 'b, A> { + #[inline] + pub fn add_declarations(&mut self, declarations: flatbuffers::WIPOffset>>>) { + self.fbb_.push_slot_always::>(Style::VT_DECLARATIONS, declarations); + } + #[inline] + pub fn add_media(&mut self, media: u32) { + self.fbb_.push_slot::(Style::VT_MEDIA, media, 0); + } + #[inline] + pub fn add_selector(&mut self, selector: flatbuffers::WIPOffset>>>) { + self.fbb_.push_slot_always::>(Style::VT_SELECTOR, selector); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> StyleBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + StyleBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for Style<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("Style"); + ds.field("declarations", &self.declarations()); + ds.field("media", &self.media()); + ds.field("selector", &self.selector()); + ds.finish() + } +} +pub enum StyleSheetOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct StyleSheet<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for StyleSheet<'a> { + type Inner = StyleSheet<'a>; + #[inline] + unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table::new(buf, loc) } + } +} + +impl<'a> StyleSheet<'a> { + pub const VT_FONTS: flatbuffers::VOffsetT = 4; + pub const VT_KEYFRAMES: flatbuffers::VOffsetT = 6; + pub const VT_MEDIAS: flatbuffers::VOffsetT = 8; + pub const VT_STYLES: flatbuffers::VOffsetT = 10; + + #[inline] + pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + StyleSheet { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr, A: flatbuffers::Allocator + 'bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr, A>, + args: &'args StyleSheetArgs<'args> + ) -> flatbuffers::WIPOffset> { + let mut builder = StyleSheetBuilder::new(_fbb); + if let Some(x) = args.styles { builder.add_styles(x); } + if let Some(x) = args.medias { builder.add_medias(x); } + if let Some(x) = args.keyframes { builder.add_keyframes(x); } + if let Some(x) = args.fonts { builder.add_fonts(x); } + builder.finish() + } + + + #[inline] + pub fn fonts(&self) -> Option>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(StyleSheet::VT_FONTS, None)} + } + #[inline] + pub fn keyframes(&self) -> Option>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(StyleSheet::VT_KEYFRAMES, None)} + } + #[inline] + pub fn medias(&self) -> Option>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(StyleSheet::VT_MEDIAS, None)} + } + #[inline] + pub fn styles(&self) -> Option>>> { + // Safety: + // Created from valid Table for this object + // which contains a valid value in this slot + unsafe { self._tab.get::>>>(StyleSheet::VT_STYLES, None)} + } +} + +impl flatbuffers::Verifiable for StyleSheet<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::>>>("fonts", Self::VT_FONTS, false)? + .visit_field::>>>("keyframes", Self::VT_KEYFRAMES, false)? + .visit_field::>>>("medias", Self::VT_MEDIAS, false)? + .visit_field::>>>("styles", Self::VT_STYLES, false)? + .finish(); + Ok(()) + } +} +pub struct StyleSheetArgs<'a> { + pub fonts: Option>>>, + pub keyframes: Option>>>, + pub medias: Option>>>, + pub styles: Option>>>>, +} +impl<'a> Default for StyleSheetArgs<'a> { + #[inline] + fn default() -> Self { + StyleSheetArgs { + fonts: None, + keyframes: None, + medias: None, + styles: None, + } + } +} + +pub struct StyleSheetBuilder<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b, A: flatbuffers::Allocator + 'a> StyleSheetBuilder<'a, 'b, A> { + #[inline] + pub fn add_fonts(&mut self, fonts: flatbuffers::WIPOffset>>) { + self.fbb_.push_slot_always::>(StyleSheet::VT_FONTS, fonts); + } + #[inline] + pub fn add_keyframes(&mut self, keyframes: flatbuffers::WIPOffset>>) { + self.fbb_.push_slot_always::>(StyleSheet::VT_KEYFRAMES, keyframes); + } + #[inline] + pub fn add_medias(&mut self, medias: flatbuffers::WIPOffset>>) { + self.fbb_.push_slot_always::>(StyleSheet::VT_MEDIAS, medias); + } + #[inline] + pub fn add_styles(&mut self, styles: flatbuffers::WIPOffset>>>) { + self.fbb_.push_slot_always::>(StyleSheet::VT_STYLES, styles); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>) -> StyleSheetBuilder<'a, 'b, A> { + let start = _fbb.start_table(); + StyleSheetBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl core::fmt::Debug for StyleSheet<'_> { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let mut ds = f.debug_struct("StyleSheet"); + ds.field("fonts", &self.fonts()); + ds.field("keyframes", &self.keyframes()); + ds.field("medias", &self.medias()); + ds.field("styles", &self.styles()); + ds.finish() + } +} +#[inline] +/// Verifies that a buffer of bytes contains a `StyleSheet` +/// and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_style_sheet_unchecked`. +pub fn root_as_style_sheet(buf: &[u8]) -> Result { + flatbuffers::root::(buf) +} +#[inline] +/// Verifies that a buffer of bytes contains a size prefixed +/// `StyleSheet` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `size_prefixed_root_as_style_sheet_unchecked`. +pub fn size_prefixed_root_as_style_sheet(buf: &[u8]) -> Result { + flatbuffers::size_prefixed_root::(buf) +} +#[inline] +/// Verifies, with the given options, that a buffer of bytes +/// contains a `StyleSheet` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_style_sheet_unchecked`. +pub fn root_as_style_sheet_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::root_with_opts::>(opts, buf) +} +#[inline] +/// Verifies, with the given verifier options, that a buffer of +/// bytes contains a size prefixed `StyleSheet` and returns +/// it. Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_style_sheet_unchecked`. +pub fn size_prefixed_root_as_style_sheet_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result, flatbuffers::InvalidFlatbuffer> { + flatbuffers::size_prefixed_root_with_opts::>(opts, buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a StyleSheet and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid `StyleSheet`. +pub unsafe fn root_as_style_sheet_unchecked(buf: &[u8]) -> StyleSheet { + flatbuffers::root_unchecked::(buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a size prefixed StyleSheet and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid size prefixed `StyleSheet`. +pub unsafe fn size_prefixed_root_as_style_sheet_unchecked(buf: &[u8]) -> StyleSheet { + flatbuffers::size_prefixed_root_unchecked::(buf) +} +#[inline] +pub fn finish_style_sheet_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>( + fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, + root: flatbuffers::WIPOffset>) { + fbb.finish(root, None); +} + +#[inline] +pub fn finish_size_prefixed_style_sheet_buffer<'a, 'b, A: flatbuffers::Allocator + 'a>(fbb: &'b mut flatbuffers::FlatBufferBuilder<'a, A>, root: flatbuffers::WIPOffset>) { + fbb.finish_size_prefixed(root, None); +} +} // pub mod Styles + diff --git a/src/utils.rs b/src/utils.rs index c9882b5..b8c473b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,8 +10,10 @@ use swc_core::ecma::{ }, visit::{Visit, VisitWith}, }; +use serde_json::Value; +use flatbuffers::{FlatBufferBuilder, WIPOffset, UnionWIPOffset}; -use crate::{constants::SelectorType, style_propetries::unit::Platform}; +use crate::{constants::SelectorType, stylesheet_generated::styles}; pub fn lowercase_first(s: &mut str) { if let Some(c) = s.get_mut(0..1) { @@ -170,3 +172,143 @@ fn split_classes(input: &str) -> TSelector { TSelector::String(input.replace(".", "")) } } + +fn process_flatbuffer_value(builder: &mut FlatBufferBuilder, value: &Value) -> (styles::Value, WIPOffset) { + match value { + Value::String(s) => create_flatbuffer_string_value(builder, s), + Value::Number(n) => create_flatbuffer_integer_value(builder, n), + Value::Object(obj) => create_flatbuffer_object_value(builder, obj), + _ => { + println!("{:?}", value); + panic!("Invalid value type") + } + } +} + +fn create_flatbuffer_string_value(builder: &mut FlatBufferBuilder, s: &str) -> (styles::Value, WIPOffset) { + let string_offset = builder.create_string(s); + let string = styles::String::create(builder, &styles::StringArgs { + value: Some(string_offset), + }); + (styles::Value::String, string.as_union_value()) +} + +fn create_flatbuffer_integer_value(builder: &mut FlatBufferBuilder, n: &serde_json::Number) -> (styles::Value, WIPOffset) { + let integer = styles::Integer::create(builder, &styles::IntegerArgs { + value: n.as_u64().unwrap() as u32, + }); + (styles::Value::Integer, integer.as_union_value()) +} + +fn create_flatbuffer_object_value(builder: &mut FlatBufferBuilder, obj: &serde_json::Map) -> (styles::Value, WIPOffset) { + let key_values: Vec<_> = obj.iter() + .map(|(key, value)| { + let key_offset = builder.create_string(key); + let (value_type, value_offset) = process_flatbuffer_value(builder, value); + + styles::KeyValue::create(builder, &styles::KeyValueArgs { + key: Some(key_offset), + value_type, + value: Some(value_offset), + }) + }) + .collect(); + + let fields_offset = builder.create_vector(&key_values); + let object = styles::Object::create(builder, &styles::ObjectArgs { + fields: Some(fields_offset), + }); + + (styles::Value::Object, object.as_union_value()) +} + +pub fn convert_json_to_flatbuffer(json_str: &str) -> Result, serde_json::Error> { + let json: Value = serde_json::from_str(json_str)?; + let mut builder = FlatBufferBuilder::new(); + let fonts: Vec> = json["fonts"] + .as_array() + .unwrap() + .iter() + .map(|f| builder.create_string(f.as_str().unwrap())) + .collect(); + let fonts = builder.create_vector(&fonts); + + let keyframes: Vec> = json["keyframes"] + .as_array() + .unwrap() + .iter() + .map(|k| builder.create_string(k.as_str().unwrap())) + .collect(); + let keyframes = builder.create_vector(&keyframes); + + let medias: Vec> = json["medias"] + .as_array() + .unwrap() + .iter() + .map(|m| builder.create_string(m.as_str().unwrap())) + .collect(); + let medias = builder.create_vector(&medias); + + let styles: Vec> = json["styles"] + .as_array() + .unwrap() + .iter() + .map(|style| { + let declarations: Vec> = style["declarations"] + .as_array() + .unwrap() + .iter() + .map(|decl| { + let decl_array = decl.as_array().unwrap(); + let property_id = decl_array[0].as_u64().unwrap() as u8; + let (value_type, value) = process_flatbuffer_value(&mut builder, &decl_array[1]); + styles::DeclarationTuple::create(&mut builder, &styles::DeclarationTupleArgs { + property_id: property_id, + value_type: value_type, + value: Some(value), + }) + }).collect(); + let declarations = builder.create_vector(&declarations); + + let selector: Vec> = style["selector"] + .as_array() + .unwrap() + .iter() + .map(|sel| { + match sel { + Value::String(s) => { + let string_offset = builder.create_string(s); + styles::Selector::create(&mut builder, &styles::SelectorArgs { + string_value: Some(string_offset), + integer_value: 0, + is_string: true, + }) + }, + Value::Number(n) => styles::Selector::create(&mut builder, &styles::SelectorArgs { + string_value: None, + integer_value: n.as_u64().unwrap() as u32, + is_string: false, + }), + _ => panic!("Invalid selector type"), + } + }).collect(); + let selector = builder.create_vector(&selector); + + styles::Style::create(&mut builder, &styles::StyleArgs { + declarations: Some(declarations), + media: style["media"].as_u64().unwrap() as u32, + selector: Some(selector), + }) + }).collect(); + let styles = builder.create_vector(&styles); + let stylesheet = styles::StyleSheet::create(&mut builder, &styles::StyleSheetArgs { + fonts: Some(fonts), + keyframes: Some(keyframes), + medias: Some(medias), + styles: Some(styles), + }); + + builder.finish(stylesheet, None); + Ok(builder.finished_data().to_vec()) + +}