1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
//! Read and write PCD file format.
//!
//! This crate provides data serializer and deserializer for PCD
//! (Point Cloud Data) file format. The [DynReader] and [DynWriter]
//! can read and write PCD files with any valid schemas. It also
//! supports deserializing to static types if the `derive` feature is
//! enabled.
//!
//! # Supported Format Versions
//!
//! - 0.7
//! - Older versions are not supported yet.
//!
//!
//! # Any Schema Example
//!
//! In the case of any schema, the points are represented by an array
//! or a slice of [DynRecord]s, where is record wraps a sequence of
//! data [Field]s.
//!
//! ## Reader
//!
//! The reader is created by [DynReader::open()], returning an
//! iterator, which generates a sequence of
//! [Result\<DynRecord\>](DynRecord).
//!
//! ```rust
//! # use anyhow::Result;
//! # fn main() -> Result<()>  {
//! use pcd_rs::DynReader;
//!
//! // Declare the reader
//! let reader = DynReader::open("test_files/binary.pcd")?;
//!
//! // The reader itself is an iterator of records
//! let points: Result<Vec<_>> = reader.collect();
//! println!("There are {} points found.", points?.len());
//! # Ok(())
//! # }
//! ```
//!
//! ## Writer
//!
//! The writer is first configured by [WriterInit], and then call
//! [WriterInit::create()] to construct the [DynWriter]. The
//! [.push()](DynWriter::push) is used to append the data to the
//! writer. The writer must be finished by
//! [.finish()](DynWriter::finish) in the end.
//!
//! ```rust
//! # use anyhow::Result;
//! # fn main() -> Result<()>  {
//! use pcd_rs::{DataKind, DynRecord, DynWriter, Field, Schema, ValueKind, WriterInit};
//!
//! // Declare point data
//! let points = [
//!     DynRecord(vec![
//!         Field::F32(vec![3.14159]),
//!         Field::U8(vec![2, 1, 7]),
//!         Field::I32(vec![-5]),
//!     ]),
//!     DynRecord(vec![
//!         Field::F32(vec![-0.0]),
//!         Field::U8(vec![254, 6, 98]),
//!         Field::I32(vec![7]),
//!     ]),
//!     DynRecord(vec![
//!         Field::F32(vec![5.6]),
//!         Field::U8(vec![4, 0, 111]),
//!         Field::I32(vec![-100000]),
//!     ]),
//! ];
//!
//! // Declare the schema
//! let schema = vec![
//!     ("x", ValueKind::F32, 1),
//!     ("y", ValueKind::U8, 3),
//!     ("z", ValueKind::I32, 1),
//! ];
//!
//! // Build a writer
//! let mut writer: DynWriter<_> = WriterInit {
//!     width: 300,
//!     height: 1,
//!     viewpoint: Default::default(),
//!     data_kind: DataKind::Ascii,
//!     schema: Some(Schema::from_iter(schema)),
//! }
//! .create("test_files/dump_ascii_untyped.pcd")?;
//!
//! // Send the points to the writer
//! for point in points {
//!     writer.push(&point)?;
//! }
//!
//! // Finalize the writer
//! writer.finish()?;
//! # Ok(())
//! # }
//! ```
#![cfg_attr(
    feature = "derive",
    doc = r##"
# Static Schema Example

The serde-like derives [PcdSerialize] and [PcdDeserialize] allows the
[Reader] and [Writer] to read from to write to the annotated
types. Both are available if the `derive` feature is enabled. The type
must be a `struct` with named fields, where each field type is either
a primitive type, an array or a `Vec`.

## Reader

The reader is constructed by [Reader::open()], which itself is an
iterator. The [.push()](Writer::push) is used to append the data to
the writer. The writer must be finished by [.finish()](Writer::finish)
in the end.

```rust
# use anyhow::Result;
# pub fn main() -> Result<()> {
use pcd_rs::{PcdDeserialize, Reader};

#[derive(PcdDeserialize)]
pub struct Point {
    pub x: f32,
    pub y: f32,
    pub z: f32,
    pub rgb: f32,
}

let reader = Reader::open("test_files/ascii.pcd")?;
let points: Result<Vec<Point>> = reader.collect();
println!("{} points found", points?.len());
# Ok(())
# }
```

## Writer

The writer is configured by [WriterInit] and then created by
[WriterInit::create()].

```rust
# use anyhow::Result;
# pub fn main() -> Result<()> {
use pcd_rs::{DataKind, PcdDeserialize, PcdSerialize, WriterInit};

#[derive(PcdSerialize)]
pub struct Point {
    #[pcd(rename = "new_x")]
    x: f32,
    y: [u8; 3],
    z: i32,
}

// point data
let points = [
    Point {
        x: 3.14159,
        y: [2, 1, 7],
        z: -5,
    },
    Point {
        x: -0.0,
        y: [254, 6, 98],
        z: 7,
    },
    Point {
        x: 5.6,
        y: [4, 0, 111],
        z: -100000,
    },
];

// serialize points
let mut writer = WriterInit {
    width: 300,
    height: 1,
    viewpoint: Default::default(),
    data_kind: DataKind::Ascii,
    schema: None,
}
.create("test_files/dump_ascii_static.pcd")?;

for point in points {
    writer.push(&point)?;
}

writer.finish()?;
# Ok(())
# }
```

# Derives

Both [PcdSerialize] and [PcdDeserialize] supports the following field
attributes.

- `#[pcd(rename = "NEW_NAME")]` sets the field name on the written PCD data.
- `#[pcd(ignore)]` instructs the de/serializer to ignore the field.
"##
)]

#[doc(hidden)]
pub use anyhow;
#[doc(hidden)]
pub use byteorder;

pub mod error;
pub mod metas;
pub mod prelude;
pub mod reader;
pub mod record;
pub mod traits;
mod utils;
pub mod writer;

pub use error::Error;
pub use metas::{DataKind, FieldDef, PcdMeta, Schema, TypeKind, ValueKind, ViewPoint};
#[cfg(feature = "derive")]
pub use pcd_rs_derive::{PcdDeserialize, PcdSerialize};
pub use reader::{DynReader, Reader};
pub use record::{DynRecord, Field, PcdDeserialize, PcdSerialize};
pub use traits::Value;
pub use writer::{DynWriter, Writer, WriterInit};