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}