Skip to content

Commit bdddf94

Browse files
author
Donald Ball
committed
impl read on data
1 parent 4b60bae commit bdddf94

File tree

1 file changed

+62
-9
lines changed

1 file changed

+62
-9
lines changed

rust/lrcp/src/packet.rs

+62-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use regex::bytes::{Captures, Regex};
2+
use std::cmp::{max, min};
3+
use std::collections::VecDeque;
24
use std::fmt::Debug;
5+
use std::io::Read;
36
use std::ops::Range;
47
use std::str::FromStr;
58

@@ -17,7 +20,37 @@ pub struct Data {
1720
session: Session,
1821
position: Position,
1922
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+
}
2154
}
2255

2356
#[derive(Debug, PartialEq, Eq)]
@@ -57,7 +90,7 @@ pub fn parse_message(data: Vec<u8>) -> anyhow::Result<Message> {
5790
let start = cap.start();
5891
let stop = cap.end();
5992
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);
6194
{
6295
let mut offset = 0;
6396
// 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> {
67100
.map(|m| m.start())
68101
.for_each(|m_start| {
69102
if !(m_start == 0 && offset == 0) {
70-
ranges.push(start + offset..start + m_start);
103+
ranges.push_back(start + offset..start + m_start);
71104
}
72105
offset = m_start + 1;
73106
});
74-
if let Some(range) = ranges.last() {
107+
if let Some(range) = ranges.back() {
75108
if range.end < stop {
76-
ranges.push(range.end + 1..stop);
109+
ranges.push_back(range.end + 1..stop);
77110
}
78111
} else {
79-
ranges.push(start..stop);
112+
ranges.push_back(start..stop);
80113
}
81114
}
82115
let data = Data {
83116
session,
84117
position,
85118
source: data,
86119
ranges,
120+
range_cursor: 0,
87121
};
88122
Ok(Message::Data(data))
89123
} else if let Some(caps) = ACK.captures(&data) {
@@ -115,7 +149,8 @@ mod tests {
115149
session: 12345,
116150
position: 23,
117151
source: message.clone(),
118-
ranges: vec![15..21],
152+
ranges: VecDeque::from([15..21]),
153+
range_cursor: 0,
119154
};
120155
assert_eq!(Message::Data(data), parse_message(message).unwrap());
121156
}
@@ -127,7 +162,8 @@ mod tests {
127162
session: 12345,
128163
position: 23,
129164
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,
131167
};
132168
assert_eq!(Message::Data(data), parse_message(message).unwrap());
133169
}
@@ -139,8 +175,25 @@ mod tests {
139175
session: 12345,
140176
position: 23,
141177
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,
143180
};
144181
assert_eq!(Message::Data(data), parse_message(message).unwrap());
145182
}
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+
}
146199
}

0 commit comments

Comments
 (0)