1use consts::{END_INFO, FILE, FILE_COMMENT, MOD_COMMENT, OUTPUT_COMMENT_FILE};
16use std::ffi::OsStr;
17use std::fs;
18use std::io;
19use std::io::prelude::*;
20use std::path::Path;
21use types::TypeStruct;
22
23use crate::Type;
24
25pub fn loop_over_files<S>(
26 path: &Path,
27 func: &mut dyn FnMut(&Path, &str),
28 files_to_ignore: &[S],
29 verbose: bool,
30) where
31 S: AsRef<Path>,
32{
33 do_loop_over_files(path, path, func, files_to_ignore, verbose)
34}
35
36pub fn do_loop_over_files<S>(
37 work_dir: &Path,
38 path: &Path,
39 func: &mut dyn FnMut(&Path, &str),
40 files_to_ignore: &[S],
41 verbose: bool,
42) where
43 S: AsRef<Path>,
44{
45 match fs::read_dir(path) {
46 Ok(it) => {
47 let mut entries = vec![];
48
49 for entry in it {
50 entries.push(entry.unwrap().path().to_owned());
51 }
52 entries.sort();
53 for entry in entries {
54 check_path_type(work_dir, &entry, func, files_to_ignore, verbose);
55 }
56 }
57 Err(e) => {
58 println!(
59 "Error while trying to iterate over {}: {}",
60 path.display(),
61 e
62 );
63 }
64 }
65}
66
67fn check_path_type<S>(
68 work_dir: &Path,
69 path: &Path,
70 func: &mut dyn FnMut(&Path, &str),
71 files_to_ignore: &[S],
72 verbose: bool,
73) where
74 S: AsRef<Path>,
75{
76 match fs::metadata(path) {
77 Ok(m) => {
78 if m.is_dir() {
79 if path == Path::new("..") || path == Path::new(".") {
80 return;
81 }
82 do_loop_over_files(work_dir, path, func, files_to_ignore, verbose);
83 } else {
84 let path_suffix = strip_prefix(path, work_dir).unwrap();
85 let ignore = path == Path::new(&format!("./{}", OUTPUT_COMMENT_FILE))
86 || path.extension() != Some(OsStr::new("rs"))
87 || files_to_ignore.iter().any(|s| s.as_ref() == path_suffix);
88 if ignore {
89 if verbose {
90 println!("-> {}: ignored", path.display());
91 }
92 return;
93 }
94 if verbose {
95 println!("-> {}", path.display());
96 }
97 func(work_dir, path_suffix.to_str().unwrap());
98 }
99 }
100 Err(e) => {
101 println!("An error occurred on '{}': {}", path.display(), e);
102 }
103 }
104}
105
106pub fn join(s: &[String], join_part: &str) -> String {
107 let mut ret = String::new();
108 let mut it = 0;
109
110 while it < s.len() {
111 ret.push_str(&s[it]);
112 it += 1;
113 if it < s.len() {
114 ret.push_str(join_part);
115 }
116 }
117 ret
118}
119
120fn strip_prefix<'a>(self_: &'a Path, base: &'a Path) -> Result<&'a Path, ()> {
123 iter_after(self_.components(), base.components())
124 .map(|c| c.as_path())
125 .ok_or(())
126}
127
128fn iter_after<A, I, J>(mut iter: I, mut prefix: J) -> Option<I>
129where
130 I: Iterator<Item = A> + Clone,
131 J: Iterator<Item = A>,
132 A: PartialEq,
133{
134 loop {
135 let mut iter_next = iter.clone();
136 match (iter_next.next(), prefix.next()) {
137 (Some(x), Some(y)) => {
138 if x != y {
139 return None;
140 }
141 }
142 (Some(_), None) => return Some(iter),
143 (None, None) => return Some(iter),
144 (None, Some(_)) => return None,
145 }
146 iter = iter_next;
147 }
148}
149
150pub fn write_comment(id: &TypeStruct, comment: &str, ignore_macro: bool) -> String {
151 if ignore_macro {
152 format!("{}{}{}\n{}", MOD_COMMENT, id, END_INFO, comment)
153 } else {
154 format!("{}{:?}{}\n{}", MOD_COMMENT, id, END_INFO, comment)
155 }
156}
157pub fn write_item_doc<F>(w: &mut dyn Write, id: &TypeStruct, f: F) -> io::Result<()>
158where
159 F: FnOnce(&mut dyn Write) -> io::Result<()>,
160{
161 writeln!(w, "{}{}{}", MOD_COMMENT, id, END_INFO)?;
162 f(w)
163}
164
165pub fn write_file_comment(comment: &str, id: &Option<TypeStruct>, ignore_macro: bool) -> String {
166 if let Some(ref t) = *id {
167 if ignore_macro {
168 format!("{} {}{}\n{}", FILE_COMMENT, t, END_INFO, comment)
169 } else {
170 format!("{} {:?}{}\n{}", FILE_COMMENT, t, END_INFO, comment)
171 }
172 } else {
173 format!("{}{}\n{}", FILE_COMMENT, END_INFO, comment)
174 }
175}
176
177pub fn write_file(file: &str) -> String {
178 format!("{}{}{}", FILE, file, END_INFO)
179}
180
181pub fn write_file_name(w: &mut dyn Write, name: Option<&str>) -> io::Result<()> {
182 writeln!(w, "{}{}{}", FILE, name.unwrap_or("*"), END_INFO)
183}
184
185pub fn remove_macro_parent(tys: &mut TypeStruct) {
196 if let Some(parent) = &mut tys.parent {
197 if parent.ty == Type::Macro {
198 tys.parent = None;
199 } else {
200 remove_macro_parent(parent)
201 }
202 }
203}