Skip to main content

parse_document_bytes

Function parse_document_bytes 

Source
pub fn parse_document_bytes(bytes: &[u8]) -> Result<OoxmlPackage, String>
Expand description

Parses either a DOCX (OOXML zip) or a legacy Word 97-2003 binary .doc file, detected by magic bytes, into the same in-memory package shape.

Examples found in repository?
examples/dump_doc_text.rs (line 5)
1fn main() {
2    let path = std::env::args().nth(1).expect("path");
3    let bytes = std::fs::read(&path).expect("read");
4    let pkg = if path.ends_with(".doc") {
5        rust_docx::parse_document_bytes(&bytes).expect("parse")
6    } else {
7        rust_docx::parse_docx(&bytes).expect("parse_docx")
8    };
9    let model = rust_docx::build_doc_model(&pkg);
10    print!("{}", text(&model));
11}
More examples
Hide additional examples
examples/dump_doc_meta.rs (line 5)
1fn main() {
2    let path = std::env::args().nth(1).expect("path");
3    let bytes = std::fs::read(&path).expect("read");
4    let pkg = if path.ends_with(".doc") {
5        rust_docx::parse_document_bytes(&bytes).expect("parse")
6    } else {
7        rust_docx::parse_docx(&bytes).expect("parse_docx")
8    };
9    let model = rust_docx::build_doc_model(&pkg);
10    println!("parts: {}", pkg.parts.len());
11    println!("binary assets: {:?}", pkg.binary_assets.keys().collect::<Vec<_>>());
12    println!("headers: {}", model.metadata.header_sections.len());
13    println!("footers: {}", model.metadata.footer_sections.len());
14    println!("numbering: {}", model.metadata.numbering_definitions.is_some());
15    println!("footnotes: {:?}", model.metadata.footnotes.as_ref().map(|n| n.len()));
16    for h in &model.metadata.header_sections {
17        println!("  header {} type={:?} nodes={}", h.part_name, h.reference_type, h.nodes.len());
18    }
19    println!("warnings: {:?}", &model.metadata.warnings);
20}
examples/dump_doc_structure.rs (line 5)
1fn main() {
2    let path = std::env::args().nth(1).expect("path");
3    let bytes = std::fs::read(&path).expect("read");
4    let pkg = if path.ends_with(".doc") {
5        rust_docx::parse_document_bytes(&bytes).expect("parse")
6    } else {
7        rust_docx::parse_docx(&bytes).expect("parse_docx")
8    };
9    let model = rust_docx::build_doc_model(&pkg);
10    for (i, node) in model.nodes.iter().enumerate() {
11        match node {
12            rust_docx::DocNode::Paragraph(p) => {
13                let text: String = p.children.iter().filter_map(|c| match c {
14                    rust_docx::ParagraphChildNode::Text(r) => Some(r.text.clone()),
15                    _ => None,
16                }).collect();
17                println!("{i:3} P {:?}", &text.chars().take(60).collect::<String>());
18            }
19            rust_docx::DocNode::Table(t) => {
20                println!("{i:3} T rows={} cols(first)={}", t.rows.len(),
21                    t.rows.first().map(|r| r.cells.len()).unwrap_or(0));
22            }
23        }
24    }
25}
examples/sweep_doc_corpus.rs (line 25)
3fn main() {
4    let dir = std::env::args().nth(1).expect("dir");
5    let mut ok = 0usize;
6    let mut failed: Vec<(String, String)> = Vec::new();
7    let mut empty: Vec<String> = Vec::new();
8    let mut entries: Vec<_> = fs::read_dir(&dir)
9        .expect("read dir")
10        .filter_map(Result::ok)
11        .map(|entry| entry.path())
12        .filter(|path| path.extension().map(|ext| ext == "doc").unwrap_or(false))
13        .collect();
14    entries.sort();
15    for path in entries {
16        let name = path.file_name().unwrap().to_string_lossy().to_string();
17        let bytes = match fs::read(&path) {
18            Ok(bytes) => bytes,
19            Err(error) => {
20                failed.push((name, format!("io: {error}")));
21                continue;
22            }
23        };
24        let result = std::panic::catch_unwind(|| {
25            let pkg = rust_docx::parse_document_bytes(&bytes)?;
26            let model = rust_docx::build_doc_model(&pkg);
27            let mut text_len = 0usize;
28            let mut tables = 0usize;
29            for node in &model.nodes {
30                match node {
31                    rust_docx::DocNode::Table(_) => tables += 1,
32                    rust_docx::DocNode::Paragraph(p) => {
33                        for c in &p.children {
34                            if let rust_docx::ParagraphChildNode::Text(r) = c {
35                                text_len += r.text.len();
36                            }
37                        }
38                    }
39                }
40            }
41            Ok::<(usize, usize, usize), String>((model.nodes.len(), text_len, tables))
42        });
43        match result {
44            Ok(Ok((nodes, text_len, tables))) => {
45                ok += 1;
46                if text_len == 0 && tables == 0 {
47                    empty.push(name.clone());
48                }
49                println!("OK {name}: nodes={nodes} text={text_len} tables={tables}");
50            }
51            Ok(Err(error)) => failed.push((name, error)),
52            Err(_) => failed.push((name, "PANIC".to_string())),
53        }
54    }
55    println!("\n=== {ok} ok, {} failed, {} empty ===", failed.len(), empty.len());
56    for (name, error) in &failed {
57        println!("FAIL {name}: {error}");
58    }
59    for name in &empty {
60        println!("EMPTY {name}");
61    }
62}