1use onestore::{ExGuid, FileDataReference, ObjectData, PropertySets, RevisionIndex, Store, Value};
2use std::{
3 collections::BTreeSet,
4 env,
5 io::{self, Write},
6};
7
8fn main() -> Result<(), Box<dyn std::error::Error>> {
9 let mut output = io::BufWriter::new(io::stdout().lock());
10 for path in env::args_os().skip(1) {
11 let bytes = onestore::read_file(path)?;
12 let store = Store::parse(&bytes)?;
13 let index = RevisionIndex::parse(&store)?;
14 index.validate_current()?;
15 let mut seen = BTreeSet::new();
16 let mut pending = vec![index.root];
17 while let Some(osid) = pending.pop() {
18 if !seen.insert(osid) {
19 continue;
20 }
21 let rid = index.spaces[&osid].labels[&(ExGuid::default(), 1)];
22 let revision = index.resolve(osid, rid)?;
23 for oid in revision.reachable()? {
24 let object = &revision.objects[&oid];
25 pending.extend(object.references()?.object_spaces);
26 if object.jcid == 0x6000b {
27 let metadata = revision
28 .roots
29 .get(&2)
30 .map(|oid| revision.objects[oid].jcid)
31 .unwrap_or(0);
32 writeln!(output, "page\t{osid}\t{metadata:x}")?;
33 }
34 let mut record = None;
35 if object.jcid == 0x6000e
36 && let ObjectData::Properties(data) = object.data
37 {
38 let properties = PropertySets::parse(data)?;
39 let boiler = properties.sets[0]
40 .iter()
41 .any(|p| matches!(p.id, 0x88001c87 | 0x88001c88 | 0x88001cb5));
42 record = Some(("ascii", &[][..]));
43 let property = properties.sets[0]
44 .iter()
45 .find(|property| property.id == 0x1c001c22)
46 .or_else(|| {
47 properties.sets[0]
48 .iter()
49 .find(|property| property.id == 0x1c003498)
50 });
51 if let Some(property) = property
52 && let Value::Bytes(data) = property.value
53 {
54 record = Some((
55 if property.id == 0x1c001c22 {
56 if boiler { "boiler-unicode" } else { "unicode" }
57 } else {
58 if boiler { "boiler-ascii" } else { "ascii" }
59 },
60 data,
61 ));
62 }
63 }
64 if let Some(FileDataReference::Internal(guid)) = object.file_reference()? {
65 record = Some(("file", store.file_data(guid)?));
66 }
67 if let Some((kind, data)) = record {
68 write!(output, "{kind}\t{osid}\t")?;
69 for byte in data {
70 write!(output, "{byte:02x}")?;
71 }
72 writeln!(output)?;
73 }
74 }
75 }
76 }
77 Ok(())
78}