1use yog_mirror::{Cell, Kind};
5
6use crate::{BlockPos, Point};
7
8const XZ_BITS: u32 = 26;
11const Y_BITS: u32 = 12;
12const X_SHIFT: u32 = Y_BITS + XZ_BITS;
13const Z_SHIFT: u32 = Y_BITS;
14
15const fn mask(bits: u32) -> i64 {
16 (1 << bits) - 1
17}
18
19const fn field(p: i64, shift: u32, bits: u32) -> i32 {
22 ((p << (i64::BITS - shift - bits)) >> (i64::BITS - bits)) as i32
23}
24
25impl BlockPos {
26 pub const fn packed(self) -> u64 {
28 (((self.x as i64 & mask(XZ_BITS)) << X_SHIFT)
29 | ((self.z as i64 & mask(XZ_BITS)) << Z_SHIFT)
30 | (self.y as i64 & mask(Y_BITS))) as u64
31 }
32
33 pub const fn unpacked(packed: u64) -> BlockPos {
35 let p = packed as i64;
36 BlockPos::new(
37 field(p, X_SHIFT, XZ_BITS),
38 field(p, 0, Y_BITS),
39 field(p, Z_SHIFT, XZ_BITS),
40 )
41 }
42}
43
44impl Cell for Point {
45 const KIND: Kind = Kind::F64;
46 const COUNT: u32 = 3;
47
48 #[inline]
49 fn put(&self, out: &mut [u8]) {
50 [self.x, self.y, self.z].put(out);
51 }
52
53 #[inline]
54 fn take(bytes: &[u8]) -> Self {
55 let [x, y, z] = <[f64; 3]>::take(bytes);
56 Point { x, y, z }
57 }
58}
59
60impl Cell for BlockPos {
61 const KIND: Kind = Kind::I32;
62 const COUNT: u32 = 3;
63
64 #[inline]
65 fn put(&self, out: &mut [u8]) {
66 <[i32; 3]>::from(*self).put(out);
67 }
68
69 #[inline]
70 fn take(bytes: &[u8]) -> Self {
71 <[i32; 3]>::take(bytes).into()
72 }
73}
74
75#[cfg(test)]
76mod tests;