mca/
chunk.rs

1use crate::{compression::CompressionType, McaError, REGION_SIZE};
2
3/// A raw compressed chunk, holds the compression type used.  
4/// And the specific chunk byte slice from the region data
5///
6/// This is used when getting chunk data **from** a region file.  
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
8pub struct RawChunk<'a> {
9    pub raw_data: &'a [u8],
10    compression_type: CompressionType,
11}
12
13impl<'a> RawChunk<'a> {
14    /// Decompresses the raw chunk data depending on it's compression type
15    ///
16    /// ## Example
17    /// ```ignore
18    /// // ...
19    ///
20    /// let chunk = region.get_chunk(0, 0)?.unwrap();
21    ///
22    /// let data = chunk.decompress()?;
23    /// ```
24    pub fn decompress(&self) -> Result<Vec<u8>, McaError> {
25        self.compression_type.decompress(&self.raw_data)
26    }
27
28    /// Get the chunks [`CompressionType`]
29    pub fn get_compression_type(&self) -> CompressionType {
30        self.compression_type.clone()
31    }
32
33    /// Creates a new raw chunk from it's bytes and compression type
34    pub fn new(data: &'a [u8], compression: CompressionType) -> RawChunk<'a> {
35        RawChunk {
36            raw_data: data,
37            compression_type: compression,
38        }
39    }
40}
41
42/// A `pending` chunk, holds all metadata used in region chunk payloads.  
43///
44/// This is used when **writing** region files.  
45#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
46pub struct PendingChunk {
47    pub compressed_data: Vec<u8>,
48    pub compression: CompressionType,
49    pub timestamp: u32,
50    pub coordinate: (u8, u8),
51}
52
53impl PendingChunk {
54    /// Create a new pending chunk
55    ///
56    /// ## Example
57    /// ```ignore
58    /// use mca::{PendingChunk, CompressionType};
59    ///
60    /// let data: &[u8] = // ...
61    ///
62    /// let chunk = PendingChunk::new(&data, CompressionType::LZ4, 1724372177, (4, 6));
63    /// ```
64    pub fn new<B>(
65        raw_data: &[u8],
66        compression: CompressionType,
67        timestamp: u32,
68        coordinate: (B, B),
69    ) -> Result<PendingChunk, McaError>
70    where
71        B: Into<u8>,
72    {
73        let coordinate = (coordinate.0.into(), coordinate.1.into());
74        assert!(coordinate.0 < REGION_SIZE as u8);
75        assert!(coordinate.1 < REGION_SIZE as u8);
76
77        let compressed_data = compression.compress(&raw_data)?;
78
79        Ok(PendingChunk {
80            compressed_data,
81            compression,
82            timestamp,
83            coordinate,
84        })
85    }
86
87    /// Create a new pending chunk with already compressed data
88    ///
89    /// ## Example
90    /// ```ignore
91    /// use mca::{PendingChunk, CompressionType};
92    ///
93    /// let data: Vec<u8> = // ...
94    ///
95    /// let chunk = PendingChunk::new_compressed(&data, CompressionType::LZ4, 1724372177, (4, 6));
96    /// ```
97    pub fn new_compressed<B>(
98        compressed_data: Vec<u8>,
99        compression: CompressionType,
100        timestamp: u32,
101        coordinate: (B, B),
102    ) -> Result<PendingChunk, McaError>
103    where
104        B: Into<u8>,
105    {
106        let coordinate = (coordinate.0.into(), coordinate.1.into());
107        assert!(coordinate.0 < REGION_SIZE as u8);
108        assert!(coordinate.1 < REGION_SIZE as u8);
109
110        Ok(PendingChunk {
111            compressed_data,
112            compression,
113            timestamp,
114            coordinate,
115        })
116    }
117}