blend_inspect_rs/
lib.rs

1
2use core::result::Result;
3use std::slice::Iter;
4
5use thiserror::Error;
6
7mod analyse;
8mod parse;
9
10pub use crate::analyse::{Struct, Structure, Type, Mode};
11pub use crate::analyse::analyse;
12pub use crate::parse::{BlendFile, Dna, DnaType, DnaStruct, DnaField, FileBlock, FileHeader, Identifier, PointerSize, Version, Endianness, Address, AddressLike, AddressTable, HasDnaTypeIndex};
13pub use crate::parse::parse;
14
15
16pub type Data<'a> = &'a[u8];
17
18#[derive(Debug)]
19pub struct Blend {
20    blend_file: BlendFile,
21    structure: Structure,
22}
23
24impl Blend {
25
26    pub fn blocks(&self) -> Iter<'_, FileBlock> {
27        self.blend_file.blocks.iter()
28    }
29
30    pub fn structs(&self) -> Iter<'_, Struct> {
31        self.structure.structs()
32    }
33
34    pub fn version(&self) -> &Version {
35        &self.blend_file.header.version
36    }
37
38    pub fn pointer_size(&self) -> usize {
39        match self.blend_file.header.pointer_size {
40            PointerSize::Pointer4Bytes => 4,
41            PointerSize::Pointer8Bytes => 8
42        }
43    }
44
45    pub fn endianness(&self) -> &Endianness {
46        &self.blend_file.header.endianness
47    }
48
49    pub fn find_struct_by_name(&self, name: &str) -> Option<&Struct> {
50        self.structure.find_struct_by_name(name)
51    }
52}
53
54pub trait BlendSource<'a> {
55    fn data(&self) -> Data<'a>;
56}
57
58impl <'a> BlendSource<'a> for &'a[u8] {
59    fn data(&self) -> Data<'a> {
60        self
61    }
62}
63
64impl <'a> BlendSource<'a> for &'a Vec<u8> {
65    fn data(&self) -> Data<'a> {
66        &self[..]
67    }
68}
69
70#[derive(Error, Debug)]
71#[error("Failed to read blender data! {message}")]
72pub struct BlendError {
73
74    message: String,
75
76    #[source]
77    cause: Box<dyn std::error::Error>,
78}
79
80pub fn inspect<'a, A>(source: A) -> Result<Blend, BlendError>
81where A: BlendSource<'a> {
82    let blend_file = parse(source)
83        .map_err(|cause| {
84            BlendError {
85                message: String::from("Could not parse header, blocks and dna!"),
86                cause: Box::new(cause)
87            }
88        })?;
89    let structure = analyse(&blend_file, Mode::All)
90        .map_err(|cause| {
91            BlendError {
92                message: String::from("Could not analyse the structure of the blender data!"),
93                cause: Box::new(cause)
94            }
95        })?;
96    Ok(Blend {
97        blend_file,
98        structure
99    })
100}