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}