Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change panic to Result<> parameter #97

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ Cargo.lock
tests/docs_cache
/*.pdf
/*.txt
.DS_Store
/tests/docs/*.pdf
64 changes: 35 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,32 +88,32 @@ fn get_info(doc: &Document) -> Option<&Dictionary> {
None
}

fn get_catalog(doc: &Document) -> &Dictionary {
fn get_catalog(doc: &Document) -> Result<&Dictionary, OutputError> {
match doc.trailer.get(b"Root").unwrap() {
&Object::Reference(ref id) => {
match doc.get_object(*id) {
Ok(&Object::Dictionary(ref catalog)) => { return catalog; }
Ok(&Object::Dictionary(ref catalog)) => { return Ok(catalog); }
_ => {}
}
}
_ => {}
}
panic!();
Err(OutputError::PdfError(Error::Invalid(format!("catalog not found")))) //panic!();
}

fn get_pages(doc: &Document) -> &Dictionary {
let catalog = get_catalog(doc);
match catalog.get(b"Pages").unwrap() {
fn get_pages(doc: &Document) -> Result<&Dictionary, OutputError> {
let catalog = get_catalog(doc)?;
match catalog.get(b"Pages")? {
&Object::Reference(ref id) => {
match doc.get_object(*id) {
Ok(&Object::Dictionary(ref pages)) => { return pages; }
Ok(&Object::Dictionary(ref pages)) => { return Ok(pages); }
other => {dlog!("pages: {:?}", other)}
}
}
other => { dlog!("pages: {:?}", other)}
}
dlog!("catalog {:?}", catalog);
panic!();
Err(OutputError::PdfError(Error::Invalid(format!("pages not found")))) //panic!();
}

#[allow(non_upper_case_globals)]
Expand Down Expand Up @@ -490,7 +490,7 @@ impl<'a> PdfSimpleFont<'a> {
}
code += 1;
}
_ => { panic!("wrong type {:?}", o); }
_ => { () } //panic!("wrong type {:?}", o); }
}
}
}
Expand Down Expand Up @@ -670,7 +670,7 @@ impl<'a> PdfType3Font<'a> {
}
code += 1;
}
_ => { panic!("wrong type"); }
_ => { () } //panic!("wrong type"); }
}
}
}
Expand Down Expand Up @@ -887,14 +887,16 @@ fn get_unicode_map<'a>(doc: &'a Document, font: &'a Dictionary) -> Option<HashMa

dlog!("map: {:?}", unicode_map);
}
None => { }
Some(&Object::Name(ref name)) => {
let name = pdf_to_utf8(name);
if name != "Identity-H" {
todo!("unsupported ToUnicode name: {:?}", name);
}
}
_ => { panic!("unsupported cmap {:?}", to_unicode)}
None => { }
_ => {
println!("unsupported cmap {:?}", to_unicode);
} //{ panic!("unsupported cmap {:?}", to_unicode)}
}
unicode_map
}
Expand Down Expand Up @@ -1095,18 +1097,18 @@ enum Function {
}

impl Function {
fn new(doc: &Document, obj: &Object) -> Function {
fn new(doc: &Document, obj: &Object) -> Result<Self, OutputError> {
let dict = match obj {
&Object::Dictionary(ref dict) => dict,
&Object::Stream(ref stream) => &stream.dict,
_ => panic!()
_ => return Err(OutputError::PdfError(Error::Invalid(format!("unexpected dictionary object {:?}", obj)))), //panic!()
};
let function_type: i64 = get(doc, dict, b"FunctionType");
let f = match function_type {
0 => {
let stream = match obj {
&Object::Stream(ref stream) => stream,
_ => panic!()
_ => return Err(OutputError::PdfError(Error::Invalid(format!("unexpected stream object {:?}", obj)))), //panic!()
};
let range: Vec<f64> = get(doc, dict, b"Range");
let domain: Vec<f64> = get(doc, dict, b"Domain");
Expand Down Expand Up @@ -1136,7 +1138,7 @@ impl Function {
}
_ => { panic!("unhandled function type {}", function_type) }
};
f
Ok(f)
}
}

Expand Down Expand Up @@ -1355,8 +1357,8 @@ pub enum ColorSpace {
ICCBased(Vec<u8>)
}

fn make_colorspace<'a>(doc: &'a Document, name: &[u8], resources: &'a Dictionary) -> ColorSpace {
match name {
fn make_colorspace<'a>(doc: &'a Document, name: &[u8], resources: &'a Dictionary) -> Result<ColorSpace, OutputError> {
let cs = match name {
b"DeviceGray" => ColorSpace::DeviceGray,
b"DeviceRGB" => ColorSpace::DeviceRGB,
b"DeviceCMYK" => ColorSpace::DeviceCMYK,
Expand Down Expand Up @@ -1417,7 +1419,7 @@ fn make_colorspace<'a>(doc: &'a Document, name: &[u8], resources: &'a Dictionary
}
_ => panic!("Alternate space should be name or array {:?}", cs[2])
};
let tint_transform = Box::new(Function::new(doc, maybe_deref(doc, &cs[3])));
let tint_transform = Box::new(Function::new(doc, maybe_deref(doc, &cs[3]))?);

dlog!("{:?} {:?} {:?}", name, alternate_space, tint_transform);
ColorSpace::Separation(Separation{ name, alternate_space, tint_transform})
Expand Down Expand Up @@ -1473,7 +1475,8 @@ fn make_colorspace<'a>(doc: &'a Document, name: &[u8], resources: &'a Dictionary
panic!();
}
}
}
};
Ok(cs)
}

struct Processor<'a> {
Expand All @@ -1486,7 +1489,7 @@ impl<'a> Processor<'a> {
}

fn process_stream(&mut self, doc: &'a Document, content: Vec<u8>, resources: &'a Dictionary, media_box: &MediaBox, output: &mut dyn OutputDev, page_num: u32) -> Result<(), OutputError> {
let content = Content::decode(&content).unwrap();
let content = Content::decode(&content)?; //.unwrap();
let mut font_table = HashMap::new();
let mut gs: GraphicsState = GraphicsState {
ts: TextState {
Expand Down Expand Up @@ -1539,12 +1542,12 @@ impl<'a> Processor<'a> {
dlog!("matrix {:?}", gs.ctm);
}
"CS" => {
let name = operation.operands[0].as_name().unwrap();
gs.stroke_colorspace = make_colorspace(doc, name, resources);
let name = operation.operands[0].as_name()?; //.unwrap();
gs.stroke_colorspace = make_colorspace(doc, name, resources)?;
}
"cs" => {
let name = operation.operands[0].as_name().unwrap();
gs.fill_colorspace = make_colorspace(doc, name, resources);
gs.fill_colorspace = make_colorspace(doc, name, resources)?;
}
"SC" | "SCN" => {
gs.stroke_color = match gs.stroke_colorspace {
Expand Down Expand Up @@ -1599,7 +1602,10 @@ impl<'a> Processor<'a> {
Object::String(ref s, _) => {
show_text(&mut gs, s, &tlm, &flip_ctm, output)?;
}
_ => { panic!("unexpected Tj operand {:?}", operation) }
_ => {
//dbg!("unexpected Tj operand {:?}", operation);
return Err(OutputError::PdfError(Error::Invalid(format!("unexpected Tj operand {:?}", operation))));
}
}
}
"Tc" => {
Expand All @@ -1616,7 +1622,7 @@ impl<'a> Processor<'a> {
}
"Tf" => {
let fonts: &Dictionary = get(&doc, resources, b"Font");
let name = operation.operands[0].as_name().unwrap();
let name = operation.operands[0].as_name()?; //.unwrap();
let font = font_table.entry(name.to_owned()).or_insert_with(|| make_font(doc, get::<&Dictionary>(doc, fonts, name))).clone();
{
/*let file = font.get_descriptor().and_then(|desc| desc.get_file());
Expand Down Expand Up @@ -1769,7 +1775,7 @@ impl<'a> Processor<'a> {
// `Do` process an entire subdocument, so we do a recursive call to `process_stream`
// with the subdocument content and resources
let xobject: &Dictionary = get(&doc, resources, b"XObject");
let name = operation.operands[0].as_name().unwrap();
let name = operation.operands[0].as_name()?; //.unwrap();
let xf: &Stream = get(&doc, xobject, name);
let resources = maybe_get_obj(&doc, &xf.dict, b"Resources").and_then(|n| n.as_dict().ok()).unwrap_or(resources);
let contents = get_contents(xf);
Expand Down Expand Up @@ -2118,9 +2124,9 @@ pub fn print_metadata(doc: &Document) {
}
}
}
dlog!("Page count: {}", get::<i64>(&doc, &get_pages(&doc), b"Count"));
dlog!("Page count: {}", get::<i64>(&doc, &get_pages(&doc).unwrap(), b"Count"));
dlog!("Pages: {:?}", get_pages(&doc));
dlog!("Type: {:?}", get_pages(&doc).get(b"Type").and_then(|x| x.as_name()).unwrap());
dlog!("Type: {:?}", get_pages(&doc).unwrap().get(b"Type").and_then(|x| x.as_name()).unwrap());
}

/// Extract the text from a pdf at `path` and return a `String` with the results
Expand Down
9 changes: 5 additions & 4 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@ fn extract_expected_text() {

#[test]
// iterate over all docs in the `tests/docs` directory, don't crash
fn extract_all_docs() {
let docs = std::fs::read_dir("tests/docs").unwrap();
fn extract_all_docs() -> Result<(), std::io::Error> {
let docs = std::fs::read_dir("tests/docs")?;
for doc in docs {
let doc = doc.unwrap();
let doc = doc?;
let path = doc.path();
let filename = path.file_name().unwrap().to_string_lossy();
let filename = path.file_name().unwrap_or_else(|| std::ffi::OsStr::new("")).to_string_lossy();
expected!(&filename, "").test();
}
Ok(())
}

// data structure to make it easy to check if certain files are correctly parsed
Expand Down
Loading