@@ -5,16 +5,27 @@ use tokio::{
5
5
sync:: Mutex ,
6
6
} ;
7
7
8
+ #[ derive( Debug ) ]
8
9
pub enum Action {
9
- DrawCubeNormal ,
10
10
Erase ,
11
+ DrawCubeNormal ,
11
12
DrawCubeHollow ,
12
13
DrawCircleNormal ,
13
14
DrawCircleHollow ,
14
15
DrawTriangleNormal ,
15
16
DrawTriangleHollow ,
16
17
}
17
18
19
+ const RESOLUTION : usize = RESOLUTION_WIDTH * RESOLUTION_HEIGHT ;
20
+ const RESOLUTION_HEIGHT : usize = 1000 ;
21
+ const RESOLUTION_WIDTH : usize = 1920 ;
22
+
23
+ // binary format:
24
+ // 0-0: action (3b) + height (5b)
25
+ // 1-3: x (12b) + y (12b)
26
+ // 4-6: color
27
+
28
+ #[ derive( Debug ) ]
18
29
pub struct ClientMessage {
19
30
pub action : Action ,
20
31
@@ -26,14 +37,50 @@ pub struct ClientMessage {
26
37
}
27
38
28
39
impl ClientMessage {
40
+ fn decode_u12 ( data : & [ u8 ] ) -> [ u16 ; 2 ] {
41
+ let mut buf: [ u16 ; 2 ] = [ 0 ; 2 ] ;
42
+
43
+ buf[ 0 ] = ( data[ 0 ] as u16 ) | ( ( data[ 1 ] as u16 & 0xf ) << 8 ) ;
44
+ buf[ 1 ] = ( ( data[ 1 ] as u16 ) >> 4 ) | ( ( data[ 2 ] as u16 ) << 4 ) ;
45
+
46
+ buf
47
+ }
48
+
49
+ fn encode_u12 ( data : [ u16 ; 2 ] ) -> [ u8 ; 3 ] {
50
+ let mut buf = [ 0 ; 3 ] ;
51
+
52
+ buf[ 0 ] = ( data[ 0 ] & 0xff ) as u8 ;
53
+ buf[ 1 ] = ( ( data[ 0 ] >> 8 ) | ( data[ 1 ] << 4 ) ) as u8 ;
54
+ buf[ 2 ] = ( data[ 1 ] >> 4 ) as u8 ;
55
+
56
+ buf
57
+ }
58
+
59
+ fn decode_u3 ( data : u8 ) -> u8 {
60
+ data & 0b111
61
+ }
62
+
63
+ fn encode_u3 ( data : u8 ) -> u8 {
64
+ data & 0b111
65
+ }
66
+
67
+ fn decode_u5 ( data : u8 ) -> u8 {
68
+ data >> 3
69
+ }
70
+
71
+ fn encode_u5 ( data : u8 ) -> u8 {
72
+ data << 3
73
+ }
74
+
29
75
pub fn decode ( data : & [ u8 ] ) -> Option < Self > {
30
- if data. len ( ) != 9 {
76
+ if data. len ( ) != 7 {
31
77
return None ;
32
78
}
33
79
34
- let action = match data[ 0 ] {
35
- 0 => Action :: DrawCubeNormal ,
36
- 1 => Action :: Erase ,
80
+ let action_height = data[ 0 ] ;
81
+ let action = match Self :: decode_u3 ( action_height) {
82
+ 0 => Action :: Erase ,
83
+ 1 => Action :: DrawCubeNormal ,
37
84
2 => Action :: DrawCubeHollow ,
38
85
3 => Action :: DrawCircleNormal ,
39
86
4 => Action :: DrawCircleHollow ,
@@ -42,12 +89,12 @@ impl ClientMessage {
42
89
_ => return None ,
43
90
} ;
44
91
45
- let x = u16 :: from_le_bytes ( [ data [ 1 ] , data [ 2 ] ] ) ;
46
- let y = u16 :: from_le_bytes ( [ data [ 3 ] , data [ 4 ] ] ) ;
47
- let height = data[ 5 ] ;
48
- let color = [ data[ 6 ] , data[ 7 ] , data[ 8 ] ] ;
92
+ let height = Self :: decode_u5 ( action_height ) ;
93
+
94
+ let [ x , y ] = Self :: decode_u12 ( & data[ 1 .. 4 ] ) ;
95
+ let color = [ data[ 4 ] , data[ 5 ] , data[ 6 ] ] ;
49
96
50
- if height == 0 {
97
+ if height == 0 || x >= RESOLUTION_WIDTH as u16 || y >= RESOLUTION_HEIGHT as u16 {
51
98
return None ;
52
99
}
53
100
@@ -60,77 +107,120 @@ impl ClientMessage {
60
107
} )
61
108
}
62
109
63
- pub fn encode ( & self ) -> [ u8 ; 9 ] {
64
- let mut buf = [ 0 ; 9 ] ;
110
+ pub fn encode ( & self ) -> [ u8 ; 7 ] {
111
+ let mut buf = [ 0 ; 7 ] ;
65
112
66
- buf[ 0 ] = match self . action {
67
- Action :: DrawCubeNormal => 0 ,
68
- Action :: Erase => 1 ,
113
+ buf[ 0 ] = Self :: encode_u3 ( match self . action {
114
+ Action :: Erase => 0 ,
115
+ Action :: DrawCubeNormal => 1 ,
69
116
Action :: DrawCubeHollow => 2 ,
70
117
Action :: DrawCircleNormal => 3 ,
71
118
Action :: DrawCircleHollow => 4 ,
72
119
Action :: DrawTriangleNormal => 5 ,
73
120
Action :: DrawTriangleHollow => 6 ,
74
- } ;
121
+ } ) | Self :: encode_u5 ( self . height ) ;
122
+ buf[ 1 ..4 ] . copy_from_slice ( & Self :: encode_u12 ( [ self . x , self . y ] ) ) ;
123
+ buf[ 4 ..7 ] . copy_from_slice ( & self . color ) ;
75
124
76
- buf[ 1 ..3 ] . copy_from_slice ( & self . x . to_le_bytes ( ) ) ;
77
- buf[ 3 ..5 ] . copy_from_slice ( & self . y . to_le_bytes ( ) ) ;
78
- buf[ 5 ] = self . height ;
79
- buf[ 6 ..9 ] . copy_from_slice ( & self . color ) ;
125
+ if std:: env:: var ( "DEBUG" ) . is_ok ( ) {
126
+ println ! ( "encoded: {:?}" , & self ) ;
127
+ }
80
128
81
129
buf
82
130
}
131
+
132
+ pub fn encode_internal ( & self ) -> u32 {
133
+ let mut buf = [ 0 ; 4 ] ;
134
+
135
+ buf[ 0 ] = Self :: encode_u3 ( match self . action {
136
+ Action :: Erase => 0 ,
137
+ Action :: DrawCubeNormal => 1 ,
138
+ Action :: DrawCubeHollow => 2 ,
139
+ Action :: DrawCircleNormal => 3 ,
140
+ Action :: DrawCircleHollow => 4 ,
141
+ Action :: DrawTriangleNormal => 5 ,
142
+ Action :: DrawTriangleHollow => 6 ,
143
+ } ) | Self :: encode_u5 ( self . height ) ;
144
+ buf[ 1 ..4 ] . copy_from_slice ( & self . color ) ;
145
+
146
+ u32:: from_le_bytes ( buf)
147
+ }
83
148
}
84
149
85
150
pub struct Data {
86
- pub file : Option < File > ,
87
- pub data : Option < Arc < Mutex < Vec < u8 > > > > ,
88
-
151
+ pub data : Arc < Mutex < Vec < u32 > > > ,
89
152
pub listeners : Vec < tokio:: sync:: mpsc:: Sender < Vec < u8 > > > ,
90
- save : bool ,
91
153
}
92
154
93
155
impl Data {
94
156
pub async fn new ( path : Option < & str > , save : bool ) -> Self {
95
- let file = match path {
157
+ let mut file = match path {
96
158
Some ( path) => Some ( if save {
97
159
OpenOptions :: new ( )
98
160
. read ( true )
99
- . append ( true )
161
+ . write ( true )
100
162
. create ( true )
101
163
. open ( path)
102
164
. await
103
165
. unwrap ( )
104
166
} else {
105
167
File :: open ( path) . await . unwrap ( )
106
168
} ) ,
107
- None => {
108
- return Self {
109
- file : None ,
110
- data : Some ( Arc :: new ( Mutex :: new ( Vec :: new ( ) ) ) ) ,
111
- listeners : Vec :: new ( ) ,
112
- save,
113
- }
114
- }
169
+ None => None ,
115
170
} ;
116
171
117
- if !save {
118
- let mut data = Vec :: new ( ) ;
119
- file. unwrap ( ) . read_to_end ( & mut data) . await . unwrap ( ) ;
172
+ let mut data: Vec < u32 > ;
173
+ if file. is_some ( ) {
174
+ let mut file_data: Vec < u8 > = Vec :: with_capacity ( RESOLUTION * 4 ) ;
175
+ file. as_mut ( )
176
+ . unwrap ( )
177
+ . read_to_end ( & mut file_data)
178
+ . await
179
+ . unwrap ( ) ;
180
+
181
+ data = file_data
182
+ . chunks_exact ( 4 )
183
+ . map ( |chunk| {
184
+ let mut buf = [ 0 ; 4 ] ;
185
+ buf. copy_from_slice ( chunk) ;
186
+
187
+ u32:: from_le_bytes ( buf)
188
+ } )
189
+ . collect :: < Vec < u32 > > ( ) ;
190
+ data. resize ( RESOLUTION , 0 ) ;
191
+ } else {
192
+ data = Vec :: with_capacity ( RESOLUTION ) ;
193
+ data. resize ( RESOLUTION , 0 ) ;
120
194
121
- return Self {
122
- file : None ,
123
- data : Some ( Arc :: new ( Mutex :: new ( data) ) ) ,
124
- listeners : Vec :: new ( ) ,
125
- save,
126
- } ;
195
+ println ! ( "data: {:?}" , & data. len( ) ) ;
196
+ }
197
+
198
+ let data = Arc :: new ( Mutex :: new ( data) ) ;
199
+ let task_data = Arc :: clone ( & data) ;
200
+ if file. is_some ( ) && save {
201
+ tokio:: spawn ( async move {
202
+ let mut file = file. unwrap ( ) ;
203
+
204
+ loop {
205
+ tokio:: time:: sleep ( tokio:: time:: Duration :: from_secs ( 5 ) ) . await ;
206
+
207
+ println ! ( "saving data..." ) ;
208
+
209
+ let data = task_data. lock ( ) . await ;
210
+ for chunk in data. iter ( ) {
211
+ file. write_all ( & chunk. to_le_bytes ( ) ) . await . unwrap ( ) ;
212
+ }
213
+
214
+ println ! ( "saving data... done" ) ;
215
+
216
+ file. sync_all ( ) . await . unwrap ( ) ;
217
+ }
218
+ } ) ;
127
219
}
128
220
129
221
Self {
130
- file,
131
- data : None ,
222
+ data,
132
223
listeners : Vec :: new ( ) ,
133
- save,
134
224
}
135
225
}
136
226
@@ -142,20 +232,18 @@ impl Data {
142
232
self . listeners . retain ( |listener| !listener. is_closed ( ) ) ;
143
233
}
144
234
145
- pub async fn write ( & mut self , data : & ClientMessage ) {
146
- let encoded = data. encode ( ) ;
147
-
148
- if let Some ( file) = & mut self . file {
149
- if !self . save {
150
- return ;
151
- }
235
+ pub async fn write ( & mut self , data : & [ ClientMessage ] ) {
236
+ let self_data = Arc :: clone ( & self . data ) ;
237
+ let mut self_data = self_data. lock ( ) . await ;
152
238
153
- file. write_all ( & encoded) . await . unwrap ( ) ;
154
- } else {
155
- let self_data = self . data . as_mut ( ) . unwrap ( ) ;
239
+ for message in data {
240
+ let index = ( message. y as usize * RESOLUTION_WIDTH ) + message. x as usize ;
241
+ self_data[ index] = message. encode_internal ( ) ;
242
+ }
156
243
157
- let mut self_data = self_data. lock ( ) . await ;
158
- self_data. extend_from_slice ( & encoded) ;
244
+ let mut encoded = Vec :: with_capacity ( 7 * data. len ( ) ) ;
245
+ for message in data {
246
+ encoded. extend_from_slice ( & message. encode ( ) ) ;
159
247
}
160
248
161
249
for listener in & self . listeners {
0 commit comments