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
117
118
119
120
121
122
123
124
125
126
127
128
129
|
use crate::helper::ReadWrite;
use glam::{Vec3, vec3};
use std::io::{Read, Write};
#[derive(Debug, Default, Clone)]
pub struct GraphicsPart(Vec<u8>);
impl ReadWrite for GraphicsPart {
fn write(&self, w: &mut dyn Write) -> anyhow::Result<()> {
w.write_all(&self.0)?;
Ok(())
}
fn read(r: &mut dyn Read) -> anyhow::Result<Self> {
let mut buf = Vec::new();
r.read_to_end(&mut buf)?;
Ok(Self(buf))
}
}
impl<'a> IntoIterator for &'a GraphicsPart {
type Item = GraphicsCommand;
type IntoIter = CommandIter<'a>;
fn into_iter(self) -> Self::IntoIter {
CommandIter(&self.0)
}
}
pub struct CommandIter<'a>(&'a [u8]);
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum GraphicsCommand {
NoFill,
Fill(u8),
NoStroke,
Stroke(u8),
StrokeWidth(f32),
StrokeDash(f32, f32),
Line(Vec3),
Close,
Unknown,
}
impl<'a> Iterator for CommandIter<'a> {
type Item = GraphicsCommand;
fn next(&mut self) -> Option<Self::Item> {
if self.0.len() < 2 {
return None;
}
let step = self.0[0];
let kind = self.0[1];
self.0 = &self.0[2..];
if self.0.len() < step as usize {
return None;
}
let data = &self.0[..step as usize];
self.0 = &self.0[step as usize..];
use GraphicsCommand::*;
Some(match (kind, step) {
(0, 0) => NoFill,
(0, 1) => Fill(data[0]),
(1, 0) => NoStroke,
(1, 1) => Stroke(data[0]),
(2, 4) => StrokeWidth(f32::from_le_bytes([data[0], data[1], data[2], data[3]])),
(3, 8) => StrokeDash(
f32::from_le_bytes([data[0], data[1], data[2], data[3]]),
f32::from_le_bytes([data[4], data[5], data[6], data[7]]),
),
(4, 12) => Line(vec3(
f32::from_le_bytes([data[0], data[1], data[2], data[3]]),
f32::from_le_bytes([data[4], data[5], data[6], data[7]]),
f32::from_le_bytes([data[8], data[9], data[10], data[11]]),
)),
(5, 0) => Close,
_ => Unknown,
})
}
}
impl GraphicsPart {
pub fn push(&mut self, cmd: GraphicsCommand) {
match cmd {
GraphicsCommand::NoFill => self.0.extend([0, 0]),
GraphicsCommand::Fill(n) => self.0.extend([1, 0, n]),
GraphicsCommand::NoStroke => self.0.extend([0, 1]),
GraphicsCommand::Stroke(n) => self.0.extend([1, 1, n]),
GraphicsCommand::StrokeWidth(w) => {
self.0.extend([4, 2]);
self.0.extend(w.to_le_bytes());
}
GraphicsCommand::StrokeDash(a, b) => {
self.0.extend([8, 3]);
self.0.extend(a.to_le_bytes());
self.0.extend(b.to_le_bytes());
}
GraphicsCommand::Line(p) => {
self.0.extend([12, 4]);
self.0.extend(p.x.to_le_bytes());
self.0.extend(p.y.to_le_bytes());
self.0.extend(p.z.to_le_bytes());
}
GraphicsCommand::Close => self.0.extend([0, 5]),
GraphicsCommand::Unknown => self.0.extend([0, 255]),
}
}
}
#[test]
#[cfg(test)]
fn test_ser() {
use GraphicsCommand::*;
let cmds = [
NoFill,
Line(Vec3::NEG_ONE),
Close,
Stroke(4),
StrokeWidth(5.),
StrokeDash(0.5, 1.),
];
let mut p = GraphicsPart::default();
for c in cmds {
p.push(c);
}
for (i, c) in p.into_iter().enumerate() {
assert_eq!(c, cmds[i], "index={i}");
}
}
|