2018-10-11 21:59:30 +00:00
|
|
|
extern crate actix_web;
|
|
|
|
extern crate serde;
|
|
|
|
#[macro_use]
|
|
|
|
extern crate serde_derive;
|
2018-10-22 18:55:47 +00:00
|
|
|
extern crate grep;
|
|
|
|
extern crate time;
|
2018-10-11 21:59:30 +00:00
|
|
|
|
|
|
|
use actix_web::{fs, http, server, App, HttpResponse, Query};
|
2018-10-22 18:55:47 +00:00
|
|
|
|
|
|
|
use std::error::Error;
|
|
|
|
|
|
|
|
use grep::regex::RegexMatcher;
|
|
|
|
use grep::searcher::sinks::Lossy;
|
|
|
|
use grep::searcher::{BinaryDetection, SearcherBuilder};
|
|
|
|
use std::fs::File;
|
2018-10-11 21:59:30 +00:00
|
|
|
|
|
|
|
fn main() {
|
2018-10-22 18:55:47 +00:00
|
|
|
server::new(|| {
|
|
|
|
App::new()
|
|
|
|
.route("/service/search", http::Method::GET, search)
|
|
|
|
.handler(
|
|
|
|
"/",
|
|
|
|
fs::StaticFiles::new("../ui/dist/")
|
|
|
|
.unwrap()
|
|
|
|
.index_file("index.html"),
|
|
|
|
)
|
|
|
|
.finish()
|
|
|
|
}).bind("127.0.0.1:8080")
|
|
|
|
.unwrap()
|
|
|
|
.run();
|
2018-10-11 21:59:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
struct SearchQuery {
|
2018-10-22 18:55:47 +00:00
|
|
|
q: String,
|
|
|
|
page: Option<usize>,
|
|
|
|
size: Option<usize>,
|
2018-10-11 21:59:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn search(query: Query<SearchQuery>) -> HttpResponse {
|
2018-10-22 18:55:47 +00:00
|
|
|
HttpResponse::Ok()
|
|
|
|
.header("Access-Control-Allow-Origin", "*")
|
|
|
|
.content_type("text/csv")
|
|
|
|
.body(ripgrep(query))
|
2018-10-11 21:59:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn ripgrep(query: Query<SearchQuery>) -> String {
|
2018-10-22 18:55:47 +00:00
|
|
|
let page = query.page.unwrap_or(1);
|
|
|
|
let size = query.size.unwrap_or(10);
|
|
|
|
let offset = size * (page - 1) + 1;
|
|
|
|
let csv_file = File::open("../../torrents.csv");
|
|
|
|
|
|
|
|
println!(
|
|
|
|
"query = {} , page = {}, size = {}, offset = {}",
|
|
|
|
query.q, page, size, offset
|
|
|
|
);
|
|
|
|
|
|
|
|
let results = search_file(csv_file.unwrap(), &query.q).unwrap();
|
|
|
|
|
|
|
|
results[offset - 1..offset + size].join("")
|
|
|
|
}
|
|
|
|
|
|
|
|
fn search_file(file: File, query: &str) -> Result<Vec<String>, Box<Error>> {
|
|
|
|
let pattern = query.replace(" ", ".*");
|
|
|
|
|
|
|
|
let matcher = RegexMatcher::new_line_matcher(&pattern)?;
|
|
|
|
let mut matches: Vec<String> = vec![];
|
|
|
|
|
|
|
|
let mut searcher = SearcherBuilder::new()
|
|
|
|
.binary_detection(BinaryDetection::quit(b'\x00'))
|
|
|
|
// .line_number(false)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
searcher.search_file(
|
|
|
|
&matcher,
|
|
|
|
&file,
|
|
|
|
Lossy(|_lnum, line| {
|
|
|
|
matches.push(line.to_string());
|
|
|
|
Ok(true)
|
|
|
|
}),
|
|
|
|
)?;
|
|
|
|
|
|
|
|
Ok(matches)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use std::fs::File;
|
|
|
|
use time::PreciseTime;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test() {
|
|
|
|
let start = PreciseTime::now();
|
|
|
|
let results =
|
|
|
|
super::search_file(File::open("../../torrents.csv").unwrap(), "sherlock").unwrap();
|
|
|
|
assert!(results.len() > 2);
|
|
|
|
let end = PreciseTime::now();
|
|
|
|
println!("Query took {} seconds.", start.to(end));
|
|
|
|
}
|
2018-10-11 21:59:30 +00:00
|
|
|
}
|