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,
16 pub data: Vec<u8>,
18 pub point_count: u32,
20 pub point_record_length: u16,
22}
23
24pub async fn fetch_and_decompress(
26 source: &impl ByteSource,
27 entry: &HierarchyEntry,
28 laz_vlr: &LazVlr,
29 point_record_length: u16,
30) -> Result<DecompressedChunk, CopcError> {
31 let compressed = source
32 .read_range(entry.offset, entry.byte_size as u64)
33 .await?;
34
35 let decompressed_size = entry.point_count as usize * point_record_length as usize;
36 let mut decompressed = vec![0u8; decompressed_size];
37
38 laz::decompress_buffer(&compressed, &mut decompressed, laz_vlr.clone())?;
39
40 Ok(DecompressedChunk {
41 key: entry.key,
42 data: decompressed,
43 point_count: entry.point_count as u32,
44 point_record_length,
45 })
46}
47
48pub fn read_points(
50 chunk: &DecompressedChunk,
51 header: &las::Header,
52) -> Result<Vec<las::Point>, CopcError> {
53 let format = header.point_format();
54 let transforms = header.transforms();
55 let mut cursor = Cursor::new(chunk.data.as_slice());
56 let mut points = Vec::with_capacity(chunk.point_count as usize);
57
58 for _ in 0..chunk.point_count {
59 let raw = las::raw::Point::read_from(&mut cursor, format)?;
60 points.push(las::Point::new(raw, transforms));
61 }
62
63 Ok(points)
64}