Skip to main content

luct_core/tiling/
data_tile.rs

1use crate::tiling::index_to_url;
2use std::num::NonZeroU8;
3
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct DataTileId {
6    index: u64,
7    partial: Option<NonZeroU8>,
8}
9
10impl DataTileId {
11    /// Returns the [`DataTileId`] of the tile, which contains the `index`.
12    ///
13    /// The `tree_height` is used to calculate, wether the tile in question should be partial or not.
14    pub fn from_index(index: u64, tree_height: u64) -> Option<Self> {
15        let tile_width = 256;
16
17        // Compute the index of the tile, that should contain the node
18        let index = index / tile_width;
19
20        // Check if we need to fetch a partial tile, and if so, compute it's size
21        let tile_end = (index + 1) * tile_width;
22        let partial = if tile_end < tree_height {
23            None
24        } else {
25            let partial: u8 = (tree_height % tile_width).try_into().unwrap();
26            Some(NonZeroU8::new(partial).unwrap())
27        };
28
29        Some(Self { index, partial })
30    }
31
32    pub fn as_url(&self) -> String {
33        let index_url = index_to_url(self.index);
34
35        match self.partial {
36            Some(partial) => format!("tile/data/{}.p/{}", index_url, partial),
37            None => format!("tile/data/{}", index_url),
38        }
39    }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct DataTile {
44    id: DataTileId,
45    data: Vec<u8>,
46}
47
48#[cfg(test)]
49mod test {
50    use super::*;
51
52    #[test]
53    fn as_url() {
54        assert_eq!(&data_tile_id(1, None).as_url(), "tile/data/001");
55        assert_eq!(
56            &data_tile_id(10987654321, None).as_url(),
57            "tile/data/x010/x987/x654/321"
58        );
59        assert_eq!(
60            &data_tile_id(1234, Some(128)).as_url(),
61            "tile/data/x001/234.p/128"
62        );
63    }
64
65    #[test]
66    fn into_data_tile_id() {
67        assert_eq!(
68            DataTileId::from_index(4, 70000).unwrap(),
69            data_tile_id(0, None)
70        );
71        assert_eq!(
72            DataTileId::from_index(270, 70000).unwrap(),
73            data_tile_id(1, None)
74        );
75        assert_eq!(
76            DataTileId::from_index(69950, 70000).unwrap(),
77            data_tile_id(273, Some(112))
78        );
79    }
80
81    fn data_tile_id(index: u64, partial: Option<u8>) -> DataTileId {
82        DataTileId {
83            index,
84            partial: partial.map(|partial| NonZeroU8::new(partial).unwrap()),
85        }
86    }
87}