1use super::super::Tag;
2use super::internal::{at::*, *};
3use super::util::*;
4
5#[derive(Copy, Clone)]
6pub struct Script<'a> {
7 data: Bytes<'a>,
8 gsub: u32,
9 gpos: u32,
10 gsub_offset: u32,
11 gpos_offset: u32,
12 tag: Tag,
13}
14
15impl<'a> Script<'a> {
16 pub fn languages(&self) -> Languages<'a> {
17 Languages::new(
18 self.data,
19 self.gsub,
20 self.gpos,
21 self.gsub_offset,
22 self.gpos_offset,
23 )
24 }
25}
26
27#[derive(Copy, Clone)]
28pub struct Scripts<'a> {
29 data: Bytes<'a>,
30 gsub: u32,
31 gpos: u32,
32 in_gsub: bool,
33 len: u16,
34 cur: u16,
35 done: bool,
36}
37
38impl<'a> Scripts<'a> {
39 pub fn new(data: Bytes<'a>, gsub: u32, gpos: u32) -> Self {
40 Self {
41 data,
42 gsub,
43 gpos,
44 in_gsub: true,
45 len: script_count(&data, gsub),
46 cur: 0,
47 done: false,
48 }
49 }
50
51 fn get_next(&mut self) -> Option<Script<'a>> {
52 if self.in_gsub {
53 if self.cur < self.len {
54 let index = self.cur;
55 self.cur += 1;
56 let (tag, offset) = script_at(&self.data, self.gsub, index)?;
57 let gpos_offset = script_by_tag(&self.data, self.gpos, tag).unwrap_or(0);
58 return Some(Script {
59 data: self.data,
60 gsub: self.gsub,
61 gpos: self.gpos,
62 gsub_offset: offset,
63 gpos_offset,
64 tag,
65 });
66 } else {
67 self.in_gsub = false;
68 self.cur = 0;
69 self.len = script_count(&self.data, self.gpos);
70 }
71 } else if self.cur < self.len {
72 let index = self.cur;
73 self.cur += 1;
74 let (tag, offset) = script_at(&self.data, self.gpos, index)?;
75 if script_by_tag(&self.data, self.gsub, tag).is_some() {
76 return None;
77 }
78 return Some(Script {
79 data: self.data,
80 gsub: self.gsub,
81 gpos: self.gpos,
82 gsub_offset: 0,
83 gpos_offset: offset,
84 tag,
85 });
86 } else {
87 self.done = true;
88 }
89 None
90 }
91}
92
93impl<'a> Iterator for Scripts<'a> {
94 type Item = Script<'a>;
95
96 fn next(&mut self) -> Option<Self::Item> {
97 while !self.done {
98 let item = self.get_next();
99 if item.is_some() {
100 return item;
101 }
102 }
103 None
104 }
105}
106
107#[derive(Copy, Clone)]
110pub struct Language<'a> {
111 data: Bytes<'a>,
112 gsub: u32,
113 gpos: u32,
114 gsub_offset: u32,
115 gpos_offset: u32,
116 tag: Tag,
117}
118
119#[derive(Copy, Clone)]
121pub struct Languages<'a> {
122 data: Bytes<'a>,
123 gsub: u32,
124 gpos: u32,
125 gsub_script: u32,
126 gpos_script: u32,
127 in_gsub: bool,
128 len: u16,
129 cur: u16,
130 done: bool,
131}
132
133impl<'a> Languages<'a> {
134 fn new(data: Bytes<'a>, gsub: u32, gpos: u32, gsub_script: u32, gpos_script: u32) -> Self {
135 Self {
136 data,
137 gsub,
138 gpos,
139 gsub_script,
140 gpos_script,
141 in_gsub: true,
142 len: script_language_count(&data, gsub_script),
143 cur: 0,
144 done: false,
145 }
146 }
147
148 fn get_next(&mut self) -> Option<Language<'a>> {
149 if self.in_gsub {
150 if self.cur < self.len {
151 let index = self.cur;
152 self.cur += 1;
153 let (tag, offset) = script_language_at(&self.data, self.gsub_script, index)?;
154 let gsub_default = tag == DFLT;
155 let (gpos_offset, _) = if gsub_default {
156 (
157 script_default_language(&self.data, self.gpos_script).unwrap_or(0),
158 true,
159 )
160 } else {
161 script_language_by_tag(&self.data, self.gpos_script, Some(tag))
162 .unwrap_or((0, false))
163 };
164 return Some(Language {
165 data: self.data,
166 gsub: self.gsub,
167 gpos: self.gpos,
168 gsub_offset: offset,
169 gpos_offset,
170 tag,
171 });
172 } else {
173 self.in_gsub = false;
174 self.cur = 0;
175 self.len = script_language_count(&self.data, self.gpos_script);
176 }
177 } else if self.cur < self.len {
178 let index = self.cur;
179 self.cur += 1;
180 let (tag, offset) = script_language_at(&self.data, self.gpos_script, index)?;
181 if script_language_by_tag(&self.data, self.gsub_script, Some(tag)).is_some() {
182 return None;
183 }
184 return Some(Language {
185 data: self.data,
186 gsub: self.gsub,
187 gpos: self.gpos,
188 gsub_offset: 0,
189 gpos_offset: offset,
190 tag,
191 });
192 } else {
193 self.done = true;
194 }
195 None
196 }
197}
198
199impl<'a> Iterator for Languages<'a> {
200 type Item = Language<'a>;
201
202 fn next(&mut self) -> Option<Self::Item> {
203 while !self.done {
204 let item = self.get_next();
205 if item.is_some() {
206 return item;
207 }
208 }
209 None
210 }
211}
212
213#[derive(Copy, Clone)]
214pub struct WritingSystem<'a> {
215 lang: Language<'a>,
216 script_tag: Tag,
217}
218
219impl<'a> WritingSystem<'a> {
220 pub fn script_tag(&self) -> Tag {
221 self.script_tag
222 }
223
224 pub fn language_tag(&self) -> Tag {
225 self.lang.tag
226 }
227
228 pub fn features(&self) -> Features<'a> {
229 Features::new(&self.lang)
230 }
231}
232
233#[derive(Copy, Clone)]
234pub struct WritingSystems<'a> {
235 scripts: Scripts<'a>,
236 langs: Option<Languages<'a>>,
237 script_tag: Tag,
238}
239
240impl<'a> WritingSystems<'a> {
241 pub fn new(scripts: Scripts<'a>) -> Self {
242 Self {
243 scripts,
244 langs: None,
245 script_tag: 0,
246 }
247 }
248}
249
250impl<'a> Iterator for WritingSystems<'a> {
251 type Item = WritingSystem<'a>;
252
253 fn next(&mut self) -> Option<Self::Item> {
254 loop {
255 if self.langs.is_none() {
256 let script = self.scripts.next()?;
257 self.script_tag = script.tag;
258 self.langs = Some(script.languages());
259 }
260 if let Some(lang) = self.langs.as_mut().unwrap().next() {
261 return Some(WritingSystem {
262 lang,
263 script_tag: self.script_tag,
264 });
265 } else {
266 self.langs = None;
267 }
268 }
269 }
270}
271
272#[derive(Copy, Clone)]
275pub struct Feature {
276 pub stage: u8,
277 pub tag: Tag,
278}
279
280#[derive(Copy, Clone)]
281pub struct Features<'a> {
282 data: Bytes<'a>,
283 gsub: u32,
284 gpos: u32,
285 gsub_language: u32,
286 gpos_language: u32,
287 stage: u8,
288 len: u16,
289 cur: u16,
290 done: bool,
291}
292
293impl<'a> Features<'a> {
294 fn new(language: &Language<'a>) -> Self {
295 Self {
296 data: language.data,
297 gsub: language.gsub,
298 gpos: language.gpos,
299 gsub_language: language.gsub_offset,
300 gpos_language: language.gpos_offset,
301 stage: 0,
302 len: language_feature_count(&language.data, language.gsub_offset),
303 cur: 0,
304 done: false,
305 }
306 }
307
308 fn get_next(&mut self) -> Option<Feature> {
309 let (gsubgpos, language) = match self.stage {
310 0 => (self.gsub, self.gsub_language),
311 _ => (self.gpos, self.gpos_language),
312 };
313 if self.cur < self.len {
314 let index = self.cur;
315 self.cur += 1;
316 let feature = language_feature_at(&self.data, language, index)?;
317 let (tag, _offset) = feature_at(&self.data, gsubgpos, feature)?;
318 return Some(Feature {
319 stage: self.stage,
320 tag,
321 });
322 } else if self.stage == 0 {
323 self.stage = 1;
324 self.len = language_feature_count(&self.data, self.gpos_language);
325 self.cur = 0;
326 } else {
327 self.done = true;
328 }
329 None
330 }
331}
332
333impl<'a> Iterator for Features<'a> {
334 type Item = Feature;
335
336 fn next(&mut self) -> Option<Self::Item> {
337 while !self.done {
338 let item = self.get_next();
339 if item.is_some() {
340 return item;
341 }
342 }
343 None
344 }
345}
346
347#[derive(Copy, Clone)]
348pub struct AllFeatures<'a> {
349 data: Bytes<'a>,
350 seen: SeenFeatures,
351 table: u32,
352 next_table: u32,
353 stage: u8,
354 len: u16,
355 cur: u16,
356}
357
358impl<'a> AllFeatures<'a> {
359 pub fn new(data: Bytes<'a>, gsub: u32, gpos: u32) -> Self {
360 let len = feature_count(&data, gsub);
361 Self {
362 data,
363 seen: SeenFeatures::new(),
364 table: gsub,
365 next_table: gpos,
366 stage: 0,
367 len,
368 cur: 0,
369 }
370 }
371}
372
373impl<'a> Iterator for AllFeatures<'a> {
374 type Item = (u8, Tag);
375
376 fn next(&mut self) -> Option<Self::Item> {
377 loop {
378 if self.cur >= self.len {
379 if self.next_table == 0 {
380 return None;
381 }
382 self.table = self.next_table;
383 self.next_table = 0;
384 self.stage = 1;
385 self.cur = 0;
386 self.len = feature_count(&self.data, self.table);
387 if self.len == 0 {
388 return None;
389 }
390 }
391 let index = self.cur;
392 self.cur += 1;
393 if let Some((tag, _)) = feature_at(&self.data, self.table, index) {
394 match FEATURES.binary_search_by(|pair| pair.0.cmp(&tag)) {
395 Ok(index) => {
396 if self.seen.mark(index) {
397 return Some((self.stage, tag));
398 }
399 }
400 _ => continue,
401 }
402 }
403 }
404 }
405}