Skip to main content

draco_io/
traits.rs

1//! Common traits for readers and writers.
2//!
3//! These traits define consistent interfaces for all format implementations.
4//!
5//! # Usage
6//!
7//! Import the trait to access its methods:
8//!
9//! ```ignore
10//! use draco_io::{Writer, ObjWriter};
11//!
12//! let mut writer = ObjWriter::new();
13//! writer.add_mesh(&mesh, Some("Name"))?;  // Calls trait method
14//! writer.write("output.obj")?;
15//! ```
16//!
17//! This enables generic functions:
18//!
19//! ```ignore
20//! fn save<W: Writer>(mut w: W, mesh: &Mesh) -> io::Result<()> {
21//!     w.add_mesh(mesh, Some("Model"))?;
22//!     w.write("output.ext")
23//! }
24//! ```
25
26use std::io::{self, Write};
27use std::path::Path;
28
29use draco_core::mesh::Mesh;
30
31/// Common interface for mesh writers.
32///
33/// All format writers implement this trait, providing a consistent API:
34///
35/// ```ignore
36/// use draco_io::{Writer, ObjWriter};
37///
38/// fn write_mesh<W: Writer>(mut writer: W, mesh: &Mesh) -> io::Result<()> {
39///     writer.add_mesh(mesh, Some("MyMesh"))?;
40///     writer.write("output.ext")
41/// }
42/// ```
43pub trait Writer: Sized {
44    /// Create a new writer instance.
45    fn new() -> Self;
46
47    /// Add a mesh to be written.
48    ///
49    /// # Arguments
50    /// * `mesh` - The mesh to add
51    /// * `name` - Optional name for the mesh (if format supports naming)
52    ///
53    /// # Returns
54    /// * `Ok(())` on success
55    /// * `Err` if the format cannot handle this mesh (e.g., compression failure)
56    fn add_mesh(&mut self, mesh: &Mesh, name: Option<&str>) -> io::Result<()>;
57
58    /// Write all added meshes to a file.
59    ///
60    /// # Arguments
61    /// * `path` - Output file path
62    fn write<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
63
64    /// Get the number of meshes/vertices added.
65    fn vertex_count(&self) -> usize;
66
67    /// Get the number of faces added (if applicable).
68    fn face_count(&self) -> usize {
69        0
70    }
71}
72
73/// Common interface for mesh readers.
74///
75/// All format readers implement this trait, providing a consistent API:
76///
77/// ```ignore
78/// use draco_io::{Reader, ObjReader};
79///
80/// fn load_mesh<R: Reader>(path: &str) -> io::Result<Mesh> {
81///     let mut reader = R::open(path)?;
82///     reader.read_mesh()
83/// }
84/// ```
85pub trait Reader: Sized {
86    /// Open a file for reading.
87    ///
88    /// # Arguments
89    /// * `path` - Input file path
90    fn open<P: AsRef<Path>>(path: P) -> io::Result<Self>;
91
92    /// Read multiple meshes (a scene) from the file.
93    ///
94    /// Formats that represent scenes or multiple mesh primitives should implement
95    /// this method and return all meshes in the file or scene.
96    fn read_meshes(&mut self) -> io::Result<Vec<Mesh>>;
97
98    /// Read a single mesh from the file.
99    ///
100    /// Default implementation returns the first mesh from `read_meshes()`.
101    fn read_mesh(&mut self) -> io::Result<Mesh> {
102        let meshes = self.read_meshes()?;
103        if let Some(m) = meshes.into_iter().next() {
104            Ok(m)
105        } else {
106            Err(io::Error::new(io::ErrorKind::InvalidData, "No mesh found"))
107        }
108    }
109}
110
111/// Common interface for readers that can be constructed from in-memory bytes.
112///
113/// This complements [`Reader::open`] for callers that already have file bytes
114/// loaded, or that are working in browser/embedded environments without direct
115/// filesystem access.
116pub trait ReadFromBytes: Sized {
117    /// Create a reader from a complete file payload.
118    fn from_bytes(bytes: &[u8]) -> io::Result<Self>;
119}
120
121/// Common interface for writers that can emit a complete file payload.
122///
123/// This complements [`Writer::write`] for callers that need to send bytes over
124/// the network, store them in an archive, or run roundtrips without temporary
125/// files.
126pub trait WriteToBytes: Writer {
127    /// Write all added data into a byte vector.
128    fn write_to_vec(&self) -> io::Result<Vec<u8>>;
129
130    /// Write all added data into an arbitrary byte sink.
131    fn write_to<W: Write>(&self, writer: &mut W) -> io::Result<()> {
132        writer.write_all(&self.write_to_vec()?)
133    }
134}
135
136/// Extended writer trait for point cloud support.
137///
138/// Writers that can output point clouds (without faces) implement this trait.
139pub trait PointCloudWriter: Writer {
140    /// Add raw point positions.
141    fn add_points(&mut self, points: &[[f32; 3]]);
142
143    /// Add a single point.
144    fn add_point(&mut self, point: [f32; 3]) {
145        self.add_points(&[point]);
146    }
147}
148
149/// Extended reader trait for point cloud support.
150///
151/// Readers that can read point clouds implement this trait.
152pub trait PointCloudReader: Reader {
153    /// Read point positions only (no faces or topology).
154    fn read_points(&mut self) -> io::Result<Vec<[f32; 3]>>;
155}