1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::io::BufReader;
use std::io::BufRead;
use std::io;
use std::collections::HashSet;
extern crate regex;
use regex::Regex;
const LIBRS_FILENAME: &'static str = "src/lib.rs";
#[derive(Debug, Clone)]
pub struct Bundler<'a> {
binrs_filename: &'a Path,
bundle_filename: &'a Path,
librs_filename: &'a Path,
_crate_name: &'a str,
skip_use: HashSet<String>,
}
impl<'a> Bundler<'a> {
pub fn new(binrs_filename: &'a Path, bundle_filename: &'a Path) -> Bundler<'a> {
Bundler {
binrs_filename: binrs_filename,
bundle_filename: bundle_filename,
librs_filename: Path::new(LIBRS_FILENAME),
_crate_name: "",
skip_use: HashSet::new(),
}
}
pub fn crate_name(&mut self, name: &'a str) {
self._crate_name = name;
}
pub fn run(&mut self) {
let mut o = File::create(&self.bundle_filename).expect(&format!(
"error creating {}",
&self.bundle_filename.display()
));
self.binrs(&mut o).expect(&format!(
"error creating bundle {} for {}",
self.bundle_filename.display(),
self.binrs_filename.display()
));
println!("rerun-if-changed={}", self.bundle_filename.display());
}
fn binrs(&mut self, mut o: &mut File) -> Result<(), io::Error> {
let bin_fd = try!(File::open(self.binrs_filename));
let mut bin_reader = BufReader::new(&bin_fd);
let extcrate_re = Regex::new(
format!(r"^extern crate {};$", String::from(self._crate_name)).as_str(),
).unwrap();
let usecrate_re = Regex::new(
format!(r"^use {}::(.*);$", String::from(self._crate_name)).as_str(),
).unwrap();
let mut line = String::new();
while bin_reader.read_line(&mut line).unwrap() > 0 {
line.pop();
if extcrate_re.is_match(&line) {
try!(self.librs(o));
} else if let Some(cap) = usecrate_re.captures(&line) {
let moduse = cap.get(1).unwrap().as_str();
if !self.skip_use.contains(moduse) {
try!(writeln!(&mut o, "use {};", moduse));
}
} else {
try!(writeln!(&mut o, "{}", line.chars().collect::<String>()));
}
line.clear();
}
Ok(())
}
fn librs(&mut self, mut o: &mut File) -> Result<(), io::Error> {
let lib_fd = File::open(self.librs_filename).expect("could not open lib.rs");
let mut lib_reader = BufReader::new(&lib_fd);
let mod_re = Regex::new(r"^\s*pub mod (.+);$").unwrap();
let mut line = String::new();
while lib_reader.read_line(&mut line).unwrap() > 0 {
line.pop();
if let Some(cap) = mod_re.captures(&line) {
let modname = cap.get(1).unwrap().as_str();
try!(self.usemod(o, modname, modname));
} else {
try!(writeln!(&mut o, "{}", line));
}
line.clear();
}
Ok(())
}
fn usemod(&mut self, mut o: &mut File, mod_name: &str, mod_path: &str) -> Result<(), io::Error> {
let mod_filenames0 = vec![
format!("src/{}.rs", mod_name),
format!("src/{}/mod.rs", mod_name),
];
let mod_fd = mod_filenames0.iter().map(|fn0| {
let mod_filename = Path::new(&fn0);
File::open(mod_filename)
}).filter(|fd| fd.is_ok()).next();
assert!(mod_fd.is_some(), format!("could not find file for module {}", mod_name));
let mut mod_reader = BufReader::new(mod_fd.unwrap().unwrap());
let mod_re = Regex::new(r"^\s*pub mod (.+);$").unwrap();
let mut line = String::new();
try!(writeln!(&mut o, "pub mod {} {{", mod_name));
self.skip_use.insert(String::from(mod_path));
while mod_reader.read_line(&mut line).unwrap() > 0 {
line.pop();
if let Some(cap) = mod_re.captures(&line) {
let submodname = cap.get(1).unwrap().as_str();
let submodpath = format!("{}::{}", mod_path, submodname);
try!(self.usemod(o, submodname, submodpath.as_str()));
} else {
try!(writeln!(&mut o, "{}", line));
}
line.clear();
}
try!(writeln!(&mut o, "}}"));
Ok(())
}
}