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
/*#![allow(dead_code)]
#![feature(core, exit_status, old_io, old_path)]
extern crate cbor;
extern crate docopt;
extern crate "rustc-serialize" as rustc_serialize;
extern crate suffix;
use std::borrow::ToOwned;
use std::env;
use std::error;
use std::fmt;
use std::old_io as io;
use docopt::Docopt;
use rustc_serialize::Decodable;
use db::DB;
macro_rules! cerr { ($tt:tt) => (return Err(Error::Other(format!($tt)))); }
macro_rules! lg {
($($arg:tt)*) => ({
let _ = ::std::old_io::stderr().write_str(&*format!($($arg)*));
let _ = ::std::old_io::stderr().write_str("\n");
});
}
mod db;
static USAGE: &'static str = "
Usage:
suffix index [ -f <index-file> ] <file> ...
suffix search [ -f <index-file> ] <query>
Options:
-f, --index <index-file> A file path for the index to create/search.
";
#[derive(RustcDecodable)]
struct Args {
cmd_index: bool,
cmd_search: bool,
arg_file: Vec<String>,
arg_query: String,
flag_index: Option<String>,
}
fn cmd_index(idx: Path, files: Vec<Path>) -> CliResult<()> {
let mut enc = cbor::Encoder::from_writer(try!(io::File::create(&idx)));
lg!("Reading documents into memory.");
let mut documents = Vec::with_capacity(files.len());
for file in files {
documents.push((
file.as_str().unwrap().to_owned(),
try!(io::File::open(&file).read_to_string()),
));
}
lg!("Creating database.");
let db = DB::create(documents);
lg!("Writing database to disk.");
Ok(try!(enc.encode(&[db])))
}
fn cmd_search(idx: Path, query: &str) -> CliResult<()> {
lg!("Creating decoder");
let mut dec = cbor::DirectDecoder::from_reader(try!(io::File::open(&idx)));
lg!("Decoding index");
// let db: DB = match dec.decode().next() {
// None => cerr!("Empty index."),
// Some(res) => try!(res),
// };
let db: DB = try!(Decodable::decode(&mut dec));
lg!("Starting search");
let mut results = db.search(query);
results.sort();
for r in results {
println!("{}", r);
}
Ok(())
}
impl Args {
fn run(&self) -> CliResult<()> {
let idx = Path::new(&self.index());
if self.cmd_index {
cmd_index(idx, self.arg_file.iter().map(Path::new).collect())
} else if self.cmd_search {
cmd_search(idx, &self.arg_query)
} else {
// This case should be prevented by Docopt.
unreachable!()
}
}
fn index(&self) -> String {
self.flag_index.clone().unwrap_or("suffix.db".to_string())
}
}
type CliResult<T> = Result<T, Error>;
enum Error {
Io(io::IoError),
Cbor(cbor::CborError),
Other(String),
}
impl error::FromError<io::IoError> for Error {
fn from_error(err: io::IoError) -> Error { Error::Io(err) }
}
impl error::FromError<cbor::CborError> for Error {
fn from_error(err: cbor::CborError) -> Error { Error::Cbor(err) }
}
impl error::FromError<String> for Error {
fn from_error(err: String) -> Error { Error::Other(err) }
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Io(ref err) => err.fmt(f),
Error::Cbor(ref err) => err.fmt(f),
Error::Other(ref s) => write!(f, "{}", s),
}
}
}
fn main() {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode())
.unwrap_or_else(|e| e.exit());
if let Err(err) = args.run() {
io::stderr().write_str(&format!("{}", err)).unwrap();
env::set_exit_status(1);
}
}*/