wasm_css/components/
from_css.rs1use super::{effect::Effect, Components};
4use std::collections::BTreeMap;
5
6#[derive(Debug)]
9enum State {
10 FieldKey,
11 EffectKey,
12 FieldValue,
13 EffectKeyInner,
14 EffectValueInner,
15}
16
17impl Components {
18 pub(crate) fn from_css(css: &str) -> Self {
19 let css_bytes = css.as_bytes();
20 let mut fields = BTreeMap::new();
21 let mut effects = vec![];
22
23 let mut state = None;
24 let mut key_buffer = vec![];
25 let mut value_buffer = vec![];
26 let mut effect_buffer = Effect::new("".to_string());
27 let mut previous_byte = None::<u8>;
28 let mut key_inner_buffer = vec![];
29 let mut value_inner_buffer = vec![];
30
31 for (byte_index, byte) in css.as_bytes().iter().enumerate() {
32 match byte {
33 b'\n' => {}
34 b' ' => {
35 macro_rules! handle_space {
36 ($buffer:expr) => {
37 if !$buffer.is_empty() {
38 let previous_byte = previous_byte.unwrap();
39 if previous_byte != b' '
40 && previous_byte != b'('
41 && !previous_byte.is_ascii_digit()
42 && !css_bytes.get(byte_index + 1).is_some_and(|b| b == &b')')
43 {
44 $buffer.push(*byte);
45 }
46 }
47 };
48 }
49
50 match state {
51 Some(State::EffectKey) => {
52 handle_space!(&mut key_buffer);
53 }
54 Some(State::FieldValue) => {
55 handle_space!(&mut value_buffer);
56 }
57 Some(State::EffectValueInner) => {
58 handle_space!(&mut value_inner_buffer);
59 }
60 _ => {}
61 }
62 }
63 b'&' | b'@' => {
64 state = Some(State::EffectKey);
65
66 key_buffer.push(*byte);
67 }
68 b'{' => {
69 state = Some(State::EffectKeyInner);
70 }
71 b':' => match state {
72 Some(State::FieldKey) => {
73 state = Some(State::FieldValue);
74 }
75 Some(State::EffectKey) => {
76 key_buffer.push(*byte);
77 }
78 Some(State::EffectKeyInner) => {
79 state = Some(State::EffectValueInner);
80 }
81 _ => {
82 }
84 },
85 b';' => match state {
86 Some(State::FieldValue) => {
87 let mut key_bytes = vec![b'\t'];
88 key_bytes.append(&mut key_buffer);
89
90 match state {
91 Some(State::FieldValue) => {
92 let mut value_bytes = vec![];
93 value_bytes.append(&mut value_buffer);
94
95 key_bytes.extend_from_slice(b": ");
96 value_bytes.extend_from_slice(b";\n");
97
98 unsafe {
99 fields.insert(
100 String::from_utf8_unchecked(key_bytes),
101 String::from_utf8_unchecked(value_bytes),
102 );
103 }
104 }
105 _ => {
106 }
108 }
109
110 state = None;
111 }
112 Some(State::EffectValueInner) => {
113 let mut effect_key_bytes = vec![b'\t'; 2];
114 effect_key_bytes.append(&mut key_inner_buffer);
115 effect_key_bytes.extend_from_slice(b": ");
116
117 let mut effect_value_bytes = vec![];
118 effect_value_bytes.append(&mut value_inner_buffer);
119 effect_value_bytes.extend_from_slice(b";\n");
120
121 unsafe {
122 effect_buffer.fields.insert(
123 String::from_utf8_unchecked(effect_key_bytes),
124 String::from_utf8_unchecked(effect_value_bytes),
125 );
126 }
127
128 state = Some(State::EffectKeyInner);
129 }
130 _ => {
131 }
133 },
134 b'}' => match state {
135 Some(State::EffectKeyInner) => {
136 let mut key_bytes = vec![b'\t'];
137 key_bytes.append(&mut key_buffer);
138
139 match state {
140 Some(State::EffectKeyInner) => {
141 key_bytes.extend_from_slice(b"{\n");
142
143 let mut effect =
144 Effect::new(unsafe { String::from_utf8_unchecked(key_bytes) });
145 std::mem::swap(&mut effect.fields, &mut effect_buffer.fields);
146
147 effects.push(effect);
148 }
149 _ => {
150 }
152 }
153
154 state = None;
155 }
156 _ => {
157 }
159 },
160 byte => match state {
161 Some(State::FieldKey) | Some(State::EffectKey) => {
162 key_buffer.push(*byte);
163 }
164 Some(State::FieldValue) => {
165 value_buffer.push(*byte);
166 }
167 Some(State::EffectKeyInner) => {
168 key_inner_buffer.push(*byte);
169 }
170 Some(State::EffectValueInner) => {
171 value_inner_buffer.push(*byte);
172 }
173 None => {
174 state = Some(State::FieldKey);
175
176 key_buffer.push(*byte);
177 }
178 },
179 }
180
181 previous_byte = Some(*byte);
182 }
183
184 Self { fields, effects }
185 }
186}