Skip to content

Commit 27e39d8

Browse files
committed
Add api/stats/ route and implement pdf parser with poppler-rs.
1 parent 9c5faa9 commit 27e39d8

4 files changed

Lines changed: 123 additions & 16 deletions

File tree

Cargo.lock

Lines changed: 67 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
colored = "3.0.0"
8-
poppler = "0.6.0"
8+
poppler-rs = "0.24.1"
99
rust-stemmers = "1.2.0"
1010
serde = { version = "1.0.219" , features = ["derive"] }
1111
serde_json = "1.0.140"

src/main.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod server;
1212
mod model;
1313

1414
use crate::model::*;
15-
use poppler::PopplerDocument;
15+
use poppler::{Document};
1616

1717
/* Parse all the text (Character Events) from the XML File */
1818
fn parse_xml_file(file_path: &Path) -> Result<String, ()> {
@@ -51,22 +51,32 @@ fn parse_txt_file(file_path: &Path) -> Result<String, ()> {
5151

5252
/* Parse all the text from the PDF File with Poppler */
5353
fn parse_pdf_files(file_path: &Path) -> Result<String, ()> {
54-
let mut content = String::new();
55-
56-
let pdf_file = PopplerDocument::new_from_file(file_path, None).map_err(|err| {
57-
eprintln!("{}: Failed to open pdf file as {}", "ERROR".red().bold(), err.to_string().red());
54+
let mut file_content = Vec::new();
55+
56+
File::open(file_path)
57+
.and_then(|mut file| file.read_to_end(&mut file_content))
58+
.map_err(|err| {
59+
eprintln!("{}: Failed to get contents of PDF file {path} as {err}", "ERROR".red().bold(), path = file_path.to_string_lossy().bright_blue(), err = err.to_string().red());
60+
})?;
61+
62+
63+
let pdf_file = Document::from_data(&file_content, None).map_err(|err| {
64+
eprintln!("{}: Failed to make poppler document out of PDF file {path} as {err}", "ERROR".red().bold(), path = file_path.to_string_lossy().bright_blue(), err = err.to_string().red());
5865
})?;
5966

60-
if !pdf_file.is_empty() {
61-
for (n, page) in pdf_file.pages().enumerate() {
62-
if let Some(text) = page.get_text() {
63-
content.push_str(text);
67+
68+
let mut content = String::new();
69+
if pdf_file.n_pages() > 0 {
70+
for i in 0..pdf_file.n_pages() {
71+
if let Some(page) = pdf_file.page(i) {
72+
if let Some(text) = page.text() {
73+
content.push_str(&text.as_str());
74+
}
6475
} else {
65-
eprintln!("{}: Could not get text of page {n} of {file_path}.", "ERROR".red().bold(), file_path = file_path.to_string_lossy().bright_blue())
76+
eprintln!("{}: Could not get text of page {i} of {file_path}.", "ERROR".red().bold(), file_path = file_path.to_string_lossy().bright_blue())
6677
}
6778
}
6879
}
69-
println!("{}", content.split_at(1000).0);
7080
Ok(content)
7181
}
7282

src/server.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,36 @@ pub fn serve_api_search(mut request: Request, model: Arc<Mutex<InMemoryModel>>)
8787
return request.respond(response);
8888
}
8989

90+
pub fn serve_api_stats(request: Request, model: Arc<Mutex<InMemoryModel>>) -> io::Result<()> {
91+
use serde::Serialize;
92+
#[derive(Default, Serialize)]
93+
struct Stats {
94+
doc_count: usize,
95+
unique_term_count: usize,
96+
}
97+
98+
let model = model.lock().unwrap();
99+
let stats = Stats {
100+
doc_count: model.docs.len(),
101+
unique_term_count: model.gtf.len()
102+
};
103+
104+
let json = match serde_json::to_string(&stats) {
105+
Ok(json) => json,
106+
Err(err) => {
107+
eprintln!("{}: could not convert search results to JSON as {err}", "ERROR".bold().red(), err = err.to_string().red());
108+
return serve_500(request);
109+
}
110+
};
111+
112+
let content_header = Header::from_bytes("Content-Type", "application/json")
113+
.expect("Header entered is not a garbage value");
114+
115+
let response = Response::from_string(json).with_header(content_header);
116+
117+
return request.respond(response);
118+
}
119+
90120
pub fn serve_request(request: Request, model: Arc<Mutex<InMemoryModel>>) -> io::Result<()> {
91121
println!("{info}: Received request! method: [{req}], url: {url:?}",
92122
info = "INFO".bright_cyan(),
@@ -108,6 +138,10 @@ pub fn serve_request(request: Request, model: Arc<Mutex<InMemoryModel>>) -> io::
108138
serve_api_search(request, model)?
109139
}
110140

141+
(Method::Get, "/api/stats") => {
142+
serve_api_stats(request, model)?
143+
}
144+
111145
_ => {
112146
return serve_404(request);
113147
}

0 commit comments

Comments
 (0)