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}