1
1
use regex:: bytes:: { Captures , Regex } ;
2
+ use std:: cmp:: { max, min} ;
3
+ use std:: collections:: VecDeque ;
2
4
use std:: fmt:: Debug ;
5
+ use std:: io:: Read ;
3
6
use std:: ops:: Range ;
4
7
use std:: str:: FromStr ;
5
8
@@ -17,7 +20,37 @@ pub struct Data {
17
20
session : Session ,
18
21
position : Position ,
19
22
source : Vec < u8 > ,
20
- ranges : Vec < Range < Position > > ,
23
+ ranges : VecDeque < Range < Position > > ,
24
+ range_cursor : Position ,
25
+ }
26
+
27
+ // TODO if we didn't want to hold onto source for the entire read, we could either
28
+ // nibble off its front ranges as we go. Alternately, if we want to leave source
29
+ // alone, maybe we should box up an array instead, if that's a thing you can do.
30
+ impl Read for Data {
31
+ fn read ( & mut self , buf : & mut [ u8 ] ) -> std:: io:: Result < usize > {
32
+ if buf. len ( ) == 0 {
33
+ return Ok ( 0 ) ;
34
+ }
35
+ let mut buf_offset = 0 ;
36
+ loop {
37
+ let range = self . ranges . front ( ) ;
38
+ if range. is_none ( ) {
39
+ break ;
40
+ }
41
+ let range = range. unwrap ( ) ;
42
+ let possible = range. len ( ) ;
43
+ let wanted = buf. len ( ) - buf_offset;
44
+ let taking = min ( possible, wanted) ;
45
+ let source = & self . source [ range. start ..range. start + taking] ;
46
+ buf[ buf_offset..buf_offset + taking] . copy_from_slice ( source) ;
47
+ buf_offset += taking;
48
+ if taking == range. len ( ) {
49
+ self . ranges . pop_front ( ) ;
50
+ }
51
+ }
52
+ Ok ( buf_offset)
53
+ }
21
54
}
22
55
23
56
#[ derive( Debug , PartialEq , Eq ) ]
@@ -57,7 +90,7 @@ pub fn parse_message(data: Vec<u8>) -> anyhow::Result<Message> {
57
90
let start = cap. start ( ) ;
58
91
let stop = cap. end ( ) ;
59
92
let body = & data. as_slice ( ) [ start..stop] ;
60
- let mut ranges: Vec < Range < Position > > = Vec :: with_capacity ( 1 ) ;
93
+ let mut ranges: VecDeque < Range < Position > > = VecDeque :: with_capacity ( 1 ) ;
61
94
{
62
95
let mut offset = 0 ;
63
96
// TODO could we use regex split instead of doing this manually and still get ranges?
@@ -67,23 +100,24 @@ pub fn parse_message(data: Vec<u8>) -> anyhow::Result<Message> {
67
100
. map ( |m| m. start ( ) )
68
101
. for_each ( |m_start| {
69
102
if !( m_start == 0 && offset == 0 ) {
70
- ranges. push ( start + offset..start + m_start) ;
103
+ ranges. push_back ( start + offset..start + m_start) ;
71
104
}
72
105
offset = m_start + 1 ;
73
106
} ) ;
74
- if let Some ( range) = ranges. last ( ) {
107
+ if let Some ( range) = ranges. back ( ) {
75
108
if range. end < stop {
76
- ranges. push ( range. end + 1 ..stop) ;
109
+ ranges. push_back ( range. end + 1 ..stop) ;
77
110
}
78
111
} else {
79
- ranges. push ( start..stop) ;
112
+ ranges. push_back ( start..stop) ;
80
113
}
81
114
}
82
115
let data = Data {
83
116
session,
84
117
position,
85
118
source : data,
86
119
ranges,
120
+ range_cursor : 0 ,
87
121
} ;
88
122
Ok ( Message :: Data ( data) )
89
123
} else if let Some ( caps) = ACK . captures ( & data) {
@@ -115,7 +149,8 @@ mod tests {
115
149
session : 12345 ,
116
150
position : 23 ,
117
151
source : message. clone ( ) ,
118
- ranges : vec ! [ 15 ..21 ] ,
152
+ ranges : VecDeque :: from ( [ 15 ..21 ] ) ,
153
+ range_cursor : 0 ,
119
154
} ;
120
155
assert_eq ! ( Message :: Data ( data) , parse_message( message) . unwrap( ) ) ;
121
156
}
@@ -127,7 +162,8 @@ mod tests {
127
162
session : 12345 ,
128
163
position : 23 ,
129
164
source : message. clone ( ) ,
130
- ranges : vec ! [ 15 ..18 , 19 ..23 , 24 ..28 ] ,
165
+ ranges : VecDeque :: from ( [ 15 ..18 , 19 ..23 , 24 ..28 ] ) ,
166
+ range_cursor : 0 ,
131
167
} ;
132
168
assert_eq ! ( Message :: Data ( data) , parse_message( message) . unwrap( ) ) ;
133
169
}
@@ -139,8 +175,25 @@ mod tests {
139
175
session : 12345 ,
140
176
position : 23 ,
141
177
source : message. clone ( ) ,
142
- ranges : vec ! [ 16 ..17 , 18 ..19 , 20 ..21 ] ,
178
+ ranges : VecDeque :: from ( [ 16 ..17 , 18 ..19 , 20 ..21 ] ) ,
179
+ range_cursor : 0 ,
143
180
} ;
144
181
assert_eq ! ( Message :: Data ( data) , parse_message( message) . unwrap( ) ) ;
145
182
}
183
+
184
+ #[ test]
185
+ fn test_read_message_data ( ) {
186
+ let message = b"/data/12345/23/foo\\ /bar\\ \\ baz/" . to_vec ( ) ;
187
+ let mut data = Data {
188
+ session : 12345 ,
189
+ position : 23 ,
190
+ source : message. clone ( ) ,
191
+ ranges : VecDeque :: from ( [ 15 ..18 , 19 ..23 , 24 ..28 ] ) ,
192
+ range_cursor : 0 ,
193
+ } ;
194
+ let mut buf: Vec < u8 > = vec ! [ ] ;
195
+ let n = data. read_to_end ( & mut buf) . unwrap ( ) ;
196
+ assert_eq ! ( n, 11 ) ;
197
+ assert_eq ! ( b"foo/bar\\ baz" . to_vec( ) , buf) ;
198
+ }
146
199
}
0 commit comments