1use std::io::Cursor;
4
5use laz::LazVlr;
6
7use crate::byte_source::ByteSource;
8use crate::error::CopcError;
9use crate::hierarchy::HierarchyEntry;
10use crate::types::VoxelKey;
11
12pub struct DecompressedChunk {
14 pub key: VoxelKey,
15 pub data: Vec<u8>,
17 pub point_count: u32,
18 pub point_record_length: u16,
19}
20
21pub async fn fetch_and_decompress(
23 source: &impl ByteSource,
24 entry: &HierarchyEntry,
25 laz_vlr: &LazVlr,
26 point_record_length: u16,
27) -> Result<DecompressedChunk, CopcError> {
28 let compressed = source
29 .read_range(entry.offset, entry.byte_size as u64)
30 .await?;
31
32 let decompressed_size = entry.point_count as usize * point_record_length as usize;
33 let mut decompressed = vec![0u8; decompressed_size];
34
35 laz::decompress_buffer(&compressed, &mut decompressed, laz_vlr.clone())?;
36
37 Ok(DecompressedChunk {
38 key: entry.key,
39 data: decompressed,
40 point_count: entry.point_count as u32,
41 point_record_length,
42 })
43}
44
45pub fn read_points(
47 chunk: &DecompressedChunk,
48 header: &las::Header,
49) -> Result<Vec<las::Point>, CopcError> {
50 let format = header.point_format();
51 let transforms = header.transforms();
52 let mut cursor = Cursor::new(chunk.data.as_slice());
53 let mut points = Vec::with_capacity(chunk.point_count as usize);
54
55 for _ in 0..chunk.point_count {
56 let raw = las::raw::Point::read_from(&mut cursor, format)?;
57 points.push(las::Point::new(raw, transforms));
58 }
59
60 Ok(points)
61}