1use crate::font;
2use failure::Error;
3use std::convert::TryFrom;
4use std::fs::{self, DirEntry};
5use std::io;
6use std::iter::Iterator;
7use std::path::{Path, PathBuf};
8
9#[derive(Debug)]
11pub struct FontIterator {
12 path: PathBuf,
13 cursor: usize,
14 entries: Vec<DirEntry>,
15}
16
17impl FontIterator {
18 pub fn open(dir: &Path) -> Result<Self, Error> {
20 let mut entries = vec![];
21 visit_dirs(dir, &mut entries)?;
22 Ok(Self {
23 entries,
24 path: dir.to_path_buf(),
25 cursor: 0,
26 })
27 }
28}
29
30impl Iterator for FontIterator {
31 type Item = Result<font::Font, Error>;
32
33 #[inline]
34 fn next(&mut self) -> Option<Self::Item> {
35 let entry = match self.entries.get(self.cursor) {
36 Some(entry) => entry,
37 None => return None,
38 };
39
40 let entry = font::Font::try_from(entry);
41 self.cursor += 1;
42 Some(entry)
43 }
44}
45
46fn visit_dirs(dir: &Path, entries: &mut Vec<DirEntry>) -> io::Result<()> {
47 for entry in fs::read_dir(dir)? {
48 let entry = entry?;
49 let path = entry.path();
50 if path.is_dir() {
51 visit_dirs(&path, entries)?;
52 } else if is_font(&path) {
53 entries.push(entry);
54 }
55 }
56 Ok(())
57}
58
59#[inline]
61fn is_font(file: &Path) -> bool {
62 let ext = match file.extension() {
63 Some(str) => str,
64 None => return false,
65 };
66
67 let ext = match ext.to_str() {
68 Some(str) => str,
69 None => return false,
70 };
71
72 match ext {
73 "ttf" => true,
74 "otf" => true,
75 _ => false,
76 }
77}