gltf_v1/
gltf.rs

1use std::path::Path;
2use std::{fs, io, ops};
3
4use crate::binary;
5use crate::document::Document;
6use crate::error::Result;
7
8/// glTF JSON wrapper plus binary payload.
9#[derive(Clone, Debug)]
10pub struct Gltf {
11    /// The glTF JSON wrapper.
12    pub document: Document,
13
14    /// The glTF binary payload in the case of binary glTF.
15    pub blob: Option<Vec<u8>>,
16}
17
18impl Gltf {
19    /// Convenience function that loads glTF from the file system.
20    pub fn open<P>(path: P) -> Result<Self>
21    where
22        P: AsRef<Path>,
23    {
24        let file = fs::File::open(path)?;
25        let reader = io::BufReader::new(file);
26        let gltf = Self::from_reader(reader)?;
27        Ok(gltf)
28    }
29    /// Loads glTF from a reader without performing validation checks.
30    pub fn from_reader_without_validation<R>(mut reader: R) -> Result<Self>
31    where
32        R: io::Read + io::Seek,
33    {
34        let mut magic = [0u8; 4];
35        reader.read_exact(&mut magic)?;
36        reader.seek(io::SeekFrom::Current(-4))?;
37        let (json, blob): (json::Root, Option<Vec<u8>>);
38        if magic.starts_with(b"glTF") {
39            let mut glb = binary::Glb::from_reader(reader)?;
40            // TODO: use `json::from_reader` instead of `json::from_slice`
41            json = json::deserialize::from_slice(&glb.content)?;
42            blob = glb.body.take().map(|x| x.into_owned());
43        } else {
44            json = json::deserialize::from_reader(reader)?;
45            blob = None;
46        };
47        let document = Document::from_json_without_validation(json);
48        Ok(Gltf { document, blob })
49    }
50    /// Loads glTF from a reader.
51    pub fn from_reader<R>(reader: R) -> Result<Self>
52    where
53        R: io::Read + io::Seek,
54    {
55        let gltf = Self::from_reader_without_validation(reader)?;
56        gltf.document.validate()?;
57        Ok(gltf)
58    }
59
60    pub fn from_slice_without_validation(slice: &[u8]) -> Result<Self> {
61        let (json, blob): (json::Root, Option<Vec<u8>>);
62        if slice.starts_with(b"glTF") {
63            let mut glb = binary::Glb::from_slice(slice)?;
64            json = json::deserialize::from_slice(&glb.content)?;
65            blob = glb.body.take().map(|x| x.into_owned());
66        } else {
67            json = json::deserialize::from_slice(slice)?;
68            blob = None;
69        };
70        let document = Document::from_json_without_validation(json);
71        Ok(Gltf { document, blob })
72    }
73
74    pub fn from_slice(slice: &[u8]) -> Result<Self> {
75        let gltf = Self::from_slice_without_validation(slice)?;
76        gltf.document.validate()?;
77        Ok(gltf)
78    }
79}
80
81impl ops::Deref for Gltf {
82    type Target = Document;
83    fn deref(&self) -> &Self::Target {
84        &self.document
85    }
86}
87
88impl ops::DerefMut for Gltf {
89    fn deref_mut(&mut self) -> &mut Self::Target {
90        &mut self.document
91    }
92}