1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
use crate::{split::split, Block, Pixel, Ref, View, P2};
use std::io::{Read, Result, Write};
impl Pixel {
#[inline]
pub fn write(&self, w: &mut impl Write) -> Result<()> {
w.write_all(&[
self.r.clamp(0, 255) as u8,
self.g.clamp(0, 255) as u8,
self.b.clamp(0, 255) as u8,
])
}
#[inline]
pub fn read(r: &mut impl Read) -> Result<Pixel> {
Ok(Self {
r: read_byte(r)? as i16,
g: read_byte(r)? as i16,
b: read_byte(r)? as i16,
})
}
}
impl Pixel {
#[inline]
pub fn write_full(&self, w: &mut impl Write) -> Result<()> {
write_word(w, self.r)?;
write_word(w, self.g)?;
write_word(w, self.b)?;
Ok(())
}
#[inline]
pub fn read_full(r: &mut impl Read) -> Result<Pixel> {
Ok(Self {
r: read_word(r)?,
g: read_word(r)?,
b: read_word(r)?,
})
}
}
impl P2 {
#[inline]
pub fn write(&self, w: &mut impl Write) -> Result<()> {
write_word(w, self.x as i16)?;
write_word(w, self.y as i16)?;
Ok(())
}
#[inline]
pub fn read(r: &mut impl Read) -> Result<P2> {
Ok(Self {
x: read_word(r)? as i32,
y: read_word(r)? as i32,
})
}
}
impl Block {
pub fn write(&self, w: &mut impl Write) -> Result<()> {
match self {
Block::Split(a, b) => {
w.write_all(&[0])?;
a.write(w)?;
b.write(w)?;
}
Block::Lit(pixels) => {
w.write_all(&[1])?;
for p in pixels {
p.write(w)?;
}
}
Block::Ref(k) => {
w.write_all(&[2])?;
k.pos_off.write(w)?;
k.color_off.write_full(w)?;
}
}
Ok(())
}
pub fn read(r: &mut impl Read, view: View) -> Result<Block> {
match read_byte(r)? {
0 => {
let [av, bv] = split(view);
Ok(Block::Split(
Box::new(Block::read(r, av)?),
Box::new(Block::read(r, bv)?),
))
}
1 => {
let mut px = vec![];
for _ in 0..view.size().area() {
px.push(Pixel::read(r)?)
}
Ok(Block::Lit(px))
}
2 => Ok(Block::Ref(Ref {
pos_off: P2::read(r)?,
color_off: Pixel::read_full(r)?,
})),
_ => Err(std::io::Error::other("unknown block variant")),
}
}
}
#[inline]
fn read_byte(r: &mut impl Read) -> Result<u8> {
let mut buf = [0u8];
r.read_exact(&mut buf)?;
Ok(buf[0])
}
#[inline]
fn write_word(w: &mut impl Write, v: i16) -> Result<()> {
w.write_all(&[(v & 0xff) as u8, (v >> 8) as u8])
}
#[inline]
fn read_word(r: &mut impl Read) -> Result<i16> {
Ok((read_byte(r)? as u16 | ((read_byte(r)? as u16) << 8)) as i16)
}
|