Skip to main content

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(crate) 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.
129#[derive(Debug, Clone)]
130pub struct SerializeOptions {
131    format: PlyFormat,
132    comments: Vec<String>,
133    obj_info: Vec<String>,
134}
135
136impl SerializeOptions {
137    /// Create a new [`SerializeOptions`] with the given format.
138    pub fn new(format: PlyFormat) -> Self {
139        Self {
140            format,
141            comments: Vec::new(),
142            obj_info: Vec::new(),
143        }
144    }
145
146    /// Default [`SerializeOptions`] for ASCII format.
147    pub fn ascii() -> Self {
148        Self::new(PlyFormat::Ascii)
149    }
150
151    /// Default [`SerializeOptions`] for binary (little-endian) format.
152    pub fn binary_le() -> Self {
153        Self::new(PlyFormat::BinaryLittleEndian)
154    }
155
156    /// Default [`SerializeOptions`] for binary (big-endian) format.
157    pub fn binary_be() -> Self {
158        Self::new(PlyFormat::BinaryBigEndian)
159    }
160
161    /// Add comments to the PLY header.
162    ///
163    /// Comments appear in the header section and are often used for metadata.
164    pub fn with_comments(mut self, comments: Vec<String>) -> Self {
165        self.comments.extend(comments);
166        self
167    }
168
169    /// Add obj_info lines to the PLY header.
170    ///
171    /// Similar to comments but may be treated differently by some PLY readers.
172    /// Often used for application-specific metadata.
173    pub fn with_obj_info(mut self, obj_info: Vec<String>) -> Self {
174        self.obj_info.extend(obj_info);
175        self
176    }
177}