1#![deny(missing_docs)]
7
8use std::path::Path;
9
10use thiserror::Error;
11
12#[cfg(feature = "geometry")]
13mod accessor;
14#[cfg(feature = "draco-encode")]
15mod compression;
16pub mod document;
18#[cfg(feature = "geometry")]
19pub use accessor::{AccessorData, DocumentAccessorSource};
20#[cfg(feature = "draco-encode")]
21pub use compression::{CompressionMode, CompressionOptions, CompressionReport};
22mod json;
23pub use document::{
24 Accessor, AccessorIndex, Animation, AnimationIndex, BoundingVolume, Buffer, BufferIndex,
25 BufferView, BufferViewIndex, Camera, CameraIndex, ComponentType, Document, ExternalAsset,
26 ExternalAssetIndex, File, FileIndex, Image, ImageIndex, Material, MaterialIndex, Mesh,
27 MeshIndex, Node, NodeIndex, PrimitiveIndex, PrimitiveRef, Sampler, SamplerIndex, Scene,
28 SceneIndex, Shape, ShapeIndex, Skin, SkinIndex, Texture, TextureIndex, ValidationProfile,
29};
30#[cfg(feature = "geometry")]
31mod packed;
32#[cfg(feature = "geometry")]
33pub use packed::{GeometryError, PackedAttribute, PackedGeometry, PackedIndices, PrimitiveMode};
34#[cfg(feature = "write")]
35mod writer;
36pub use json::Value as JsonValue;
38#[cfg(feature = "write")]
39pub use writer::{GeometryEncoding, GeometryWriteOptions, GeometryWriteReport, PreserveReason};
40pub mod extensions;
42pub use extensions::{
43 BinaryFreeExtension, DracoExtension, ExtensionHandler, ExtensionRegistry,
44 ExtensionValidationContext, MeshGpuInstancingExtension, ResourceStore,
45 StructuralMetadataExtension, BINARY_FREE_EXTENSIONS, EXT_MESHOPT_COMPRESSION,
46 EXT_MESH_GPU_INSTANCING, EXT_STRUCTURAL_METADATA, KHR_DRACO_MESH_COMPRESSION,
47 KHR_MESHOPT_COMPRESSION,
48};
49mod import;
50#[cfg(not(target_arch = "wasm32"))]
51pub use import::open;
52pub use import::{
53 parse, parse_with_options, GltfOutput, GltfResource, Import, DEFAULT_EXTERNAL_ASSET_DEPTH,
54};
55
56pub use draco_io::{
57 ExternalFilePolicy, FileResourceResolver, GlbRangeReader, GltfContainerFormat, GltfError,
58 ResourceLimits, ResourceResolver,
59};
60
61#[derive(Clone, Copy, Debug, PartialEq, Eq)]
63pub enum OutputFormat {
64 SameAsInput,
66 GltfJson,
68 GlbV2,
70 GlbV3,
72}
73
74#[derive(Debug, Error)]
76pub enum Error {
77 #[error("IO error: {0}")]
79 Io(#[from] std::io::Error),
80 #[error("JSON error: {0}")]
82 Json(String),
83 #[error("Draco decode error: {0}")]
85 Decode(#[from] draco_core::DracoError),
86 #[error("draco-io error: {0}")]
88 DracoIo(#[from] GltfError),
89 #[cfg(feature = "geometry")]
91 #[error("geometry error: {0}")]
92 Geometry(#[from] GeometryError),
93 #[error("extension error: {0}")]
95 Extension(String),
96 #[error("glTF validation failed: {0:?}")]
98 Validation(Vec<String>),
99 #[error("resource quota exceeded: {0}")]
101 ResourceLimit(String),
102}
103pub type Result<T> = std::result::Result<T, Error>;
105
106pub struct ImportOptions<'a> {
108 pub base_path: Option<&'a Path>,
110 pub external_file_policy: ExternalFilePolicy,
112 pub resolver: Option<&'a dyn ResourceResolver>,
114 pub limits: ResourceLimits,
116 pub profile: ValidationProfile,
118 pub extensions: ExtensionRegistry,
120}
121impl Default for ImportOptions<'_> {
122 fn default() -> Self {
123 Self {
124 base_path: None,
125 external_file_policy: ExternalFilePolicy::Deny,
126 resolver: None,
127 limits: ResourceLimits::default(),
128 profile: ValidationProfile::Gltf21Draft,
129 extensions: ExtensionRegistry::default(),
130 }
131 }
132}
133
134#[cfg(not(target_arch = "wasm32"))]
135pub fn import(path: impl AsRef<Path>) -> Result<Import> {
137 open(path, ValidationProfile::Gltf21Draft)
138}
139
140pub fn import_slice(bytes: &[u8], base: Option<&Path>) -> Result<Import> {
150 let options = ImportOptions {
151 base_path: base,
152 external_file_policy: if base.is_some() {
153 ExternalFilePolicy::Allow
154 } else {
155 ExternalFilePolicy::Deny
156 },
157 ..ImportOptions::default()
158 };
159 import_slice_with_options(bytes, &options)
160}
161
162pub fn import_slice_with_options(bytes: &[u8], options: &ImportOptions<'_>) -> Result<Import> {
164 let file_resolver = options
165 .base_path
166 .map(|base| FileResourceResolver::new(base, options.external_file_policy));
167 let resolver = options.resolver.or_else(|| {
168 file_resolver
169 .as_ref()
170 .map(|value| value as &dyn ResourceResolver)
171 });
172 parse_with_options(
173 bytes,
174 options.base_path,
175 resolver,
176 &options.limits,
177 options.profile,
178 &options.extensions,
179 )
180}
181
182pub fn validate(document: &Document) -> Result<()> {
186 document.validate(ValidationProfile::Gltf21Draft)
187}
188
189#[cfg(test)]
190mod document_tests;