epoint_io/epoint/
write.rs1use crate::Error::{InvalidFileExtension, NoFileName};
2use crate::epoint::write_impl::write_epoint_format;
3use crate::epoint::{FILE_EXTENSION_EPOINT_FORMAT, FILE_EXTENSION_EPOINT_TAR_FORMAT};
4use crate::error::Error;
5use chrono::{DateTime, Utc};
6use epoint_core::PointCloud;
7use std::fs::{File, OpenOptions};
8use std::io::Write;
9use std::path::Path;
10
11pub const DEFAULT_COMPRESSION_LEVEL: i32 = 10;
12
13#[derive(Debug, Clone)]
16pub struct EpointWriter<W: Write> {
17 writer: W,
18 compression_level: Option<i32>,
19 time: Option<DateTime<Utc>>,
20}
21
22impl<W: Write> EpointWriter<W> {
23 pub fn new(writer: W) -> Self {
24 Self {
25 writer,
26 compression_level: Some(DEFAULT_COMPRESSION_LEVEL),
27 time: None,
28 }
29 }
30
31 pub fn with_compressed(mut self, compressed: bool) -> Self {
32 if compressed {
33 self.compression_level = Some(DEFAULT_COMPRESSION_LEVEL);
34 } else {
35 self.compression_level = None;
36 }
37 self
38 }
39
40 pub fn with_time(mut self, time: Option<DateTime<Utc>>) -> Self {
41 self.time = time;
42 self
43 }
44
45 pub fn finish(self, point_cloud: PointCloud) -> Result<(), Error> {
46 write_epoint_format(self.writer, point_cloud, self.compression_level, self.time)?;
47
48 Ok(())
49 }
50}
51
52impl EpointWriter<File> {
53 pub fn from_path(path: impl AsRef<Path>) -> Result<Self, Error> {
54 let file_name_str = path
55 .as_ref()
56 .file_name()
57 .ok_or(NoFileName())?
58 .to_string_lossy()
59 .to_lowercase();
60 if !file_name_str.ends_with(FILE_EXTENSION_EPOINT_TAR_FORMAT)
61 && !file_name_str.ends_with(FILE_EXTENSION_EPOINT_FORMAT)
62 {
63 return Err(InvalidFileExtension(file_name_str.to_string()));
64 }
65
66 let file = OpenOptions::new()
67 .create(true)
68 .write(true)
69 .truncate(true)
70 .open(path)?;
71 Ok(Self::new(file))
72 }
73}