serde_ply/ser/
mod.rs

1//! PLY file serialization.
2
3use std::io::Write;
4
5use serde::{ser::Error, Serialize};
6
7use crate::{
8    ser::{header_collector::HeaderCollector, ply_file::PlyReaderSerializer},
9    PlyFormat, SerializeError,
10};
11
12mod header_collector;
13mod ply_file;
14mod row;
15
16pub mod val_writer;
17
18/// Serialize PLY data to a writer.
19///
20/// Writes the complete PLY file including header and data in the specified format.
21/// The writer receives the raw PLY bytes.
22///
23/// # Example
24/// ```rust
25/// use serde::Serialize;
26/// use serde_ply::{to_writer, SerializeOptions};
27/// use std::io::Cursor;
28///
29/// #[derive(Serialize)]
30/// struct Vertex { x: f32, y: f32, z: f32 }
31///
32/// #[derive(Serialize)]
33/// struct Mesh { vertex: Vec<Vertex> }
34///
35/// let mesh = Mesh {
36///     vertex: vec![Vertex { x: 0.0, y: 0.0, z: 0.0 }]
37/// };
38///
39/// let mut buffer = Vec::new();
40/// to_writer(&mesh, SerializeOptions::ascii(), &mut buffer)?;
41/// # Ok::<(), Box<dyn std::error::Error>>(())
42/// ```
43pub fn to_writer<T>(
44    val: &T,
45    options: SerializeOptions,
46    mut writer: impl Write,
47) -> Result<(), SerializeError>
48where
49    T: Serialize,
50{
51    let format = options.format;
52    val.serialize(&mut HeaderCollector::new(options, &mut writer))?;
53    val.serialize(&mut PlyReaderSerializer::new(format, &mut writer))?;
54    Ok(())
55}
56
57/// Serialize PLY data to bytes.
58///
59/// Returns the complete PLY file as a byte vector in the specified format.
60/// Works with both ASCII and binary formats.
61///
62/// # Example
63/// ```rust
64/// use serde::Serialize;
65/// use serde_ply::{to_bytes, SerializeOptions};
66///
67/// #[derive(Serialize)]
68/// struct Point { x: f32, y: f32 }
69///
70/// #[derive(Serialize)]
71/// struct Points { vertex: Vec<Point> }
72///
73/// let points = Points {
74///     vertex: vec![Point { x: 1.0, y: 2.0 }]
75/// };
76///
77/// let bytes = to_bytes(&points, SerializeOptions::binary_le())?;
78/// # Ok::<(), Box<dyn std::error::Error>>(())
79/// ```
80pub fn to_bytes<T>(val: &T, options: SerializeOptions) -> Result<Vec<u8>, SerializeError>
81where
82    T: Serialize,
83{
84    let mut buf = vec![];
85    to_writer(val, options, &mut buf)?;
86    Ok(buf)
87}
88
89/// Serialize PLY data to a string.
90///
91/// This only works with ASCII format since binary data cannot be represented as valid UTF-8.
92/// Returns the complete PLY file as a string.
93///
94/// # Example
95/// ```rust
96/// use serde::Serialize;
97/// use serde_ply::{to_string, SerializeOptions};
98///
99/// #[derive(Serialize)]
100/// struct Vertex { x: f32, y: f32, z: f32 }
101///
102/// #[derive(Serialize)]
103/// struct Mesh { vertex: Vec<Vertex> }
104///
105/// let mesh = Mesh {
106///     vertex: vec![Vertex { x: 0.0, y: 0.0, z: 0.0 }]
107/// };
108///
109/// let ply_string = to_string(&mesh, SerializeOptions::ascii())?;
110/// assert!(ply_string.starts_with("ply\n"));
111/// # Ok::<(), Box<dyn std::error::Error>>(())
112/// ```
113pub fn to_string<T>(val: &T, options: SerializeOptions) -> Result<String, SerializeError>
114where
115    T: Serialize,
116{
117    if options.format != PlyFormat::Ascii {
118        return Err(SerializeError::custom(
119            "Cannot serialize binary PLY to string",
120        ));
121    }
122    String::from_utf8(to_bytes(val, options)?).map_err(|e| SerializeError::custom(e.to_string()))
123}
124
125/// Options for PLY file serialization.
126///
127/// Builder struct for configuring PLY output format and metadata like comments.
128/// Use the convenience methods like [`Self::ascii()`] for common configurations.
129pub struct SerializeOptions {
130    format: PlyFormat,
131    comments: Vec<String>,
132    obj_info: Vec<String>,
133}
134
135impl SerializeOptions {
136    /// Create a new [`SerializeOptions`] with the given format.
137    pub fn new(format: PlyFormat) -> Self {
138        Self {
139            format,
140            comments: Vec::new(),
141            obj_info: Vec::new(),
142        }
143    }
144
145    /// Default [`SerializeOptions`] for ASCII format.
146    pub fn ascii() -> Self {
147        Self::new(PlyFormat::Ascii)
148    }
149
150    /// Default [`SerializeOptions`] for binary (little-endian) format.
151    pub fn binary_le() -> Self {
152        Self::new(PlyFormat::BinaryLittleEndian)
153    }
154
155    /// Default [`SerializeOptions`] for binary (big-endian) format.
156    pub fn binary_be() -> Self {
157        Self::new(PlyFormat::BinaryBigEndian)
158    }
159
160    /// Add comments to the PLY header.
161    ///
162    /// Comments appear in the header section and are often used for metadata.
163    pub fn with_comments(mut self, comments: Vec<String>) -> Self {
164        self.comments.extend(comments);
165        self
166    }
167
168    /// Add obj_info lines to the PLY header.
169    ///
170    /// Similar to comments but may be treated differently by some PLY readers.
171    /// Often used for application-specific metadata.
172    pub fn with_obj_info(mut self, obj_info: Vec<String>) -> Self {
173        self.obj_info.extend(obj_info);
174        self
175    }
176}