Skip to content

Commit 7ea25c5

Browse files
committed
the first succeeding tests for streaming decoding :D
1 parent 843c6fb commit 7ea25c5

File tree

4 files changed

+46
-19
lines changed

4 files changed

+46
-19
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,10 @@ Please see _'Development Status'_ for a listing of all crates and their capabili
9595
start out with a sync implementation, and later add an async one that reuses all the protocol code.
9696
* [ ] [PKT-Line](https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt#L52:L52)
9797
* [ ] encode
98-
* [ ] decode
98+
* [ ] decode (zero-copy)
9999
* [ ] [error line](https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt#L28:L28)
100+
* [ ] [V2 additions](https://github.com/git/git/blob/master/Documentation/technical/protocol-v2.txt#L35:L36)
101+
* [ ]
100102
* [ ] `Iterator` for multi-plexed pack lines from `Read`
101103
* [ ] parse and serialize [capabilities](https://github.com/git/git/blob/master/Documentation/technical/protocol-capabilities.txt#L1:L1)
102104
* [ ] **Version 1**

git-protocol/src/packet_line/decode.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::packet_line::Borrowed::Flush;
21
use crate::packet_line::{self, FLUSH_LINE, MAX_DATA_LEN, MAX_LINE_LEN, U16_HEX_BYTES};
32
use bstr::BString;
43
use quick_error::quick_error;
@@ -23,41 +22,46 @@ quick_error! {
2322
}
2423
}
2524

26-
pub enum ParseResult<'a> {
25+
pub enum Stream<'a> {
2726
Complete {
28-
result: Result<packet_line::Borrowed<'a>, Error>,
27+
line: packet_line::Borrowed<'a>,
2928
bytes_consumed: usize,
3029
},
3130
Incomplete {
3231
bytes_needed: usize,
3332
},
3433
}
3534

36-
pub fn streaming(data: &[u8]) -> ParseResult {
35+
pub fn streaming(data: &[u8]) -> Result<Stream, Error> {
3736
let data_len = data.len();
3837
if data_len < U16_HEX_BYTES {
39-
return ParseResult::Incomplete {
38+
return Ok(Stream::Incomplete {
4039
bytes_needed: U16_HEX_BYTES - data_len,
41-
};
40+
});
4241
}
4342
let hex_bytes = &data[..U16_HEX_BYTES];
4443
if hex_bytes == FLUSH_LINE {
45-
return ParseResult::Complete {
46-
result: Ok(packet_line::Borrowed::Flush),
44+
return Ok(Stream::Complete {
45+
line: packet_line::Borrowed::Flush,
4746
bytes_consumed: 4,
48-
};
47+
});
4948
}
5049

5150
let mut buf = [0u8; U16_HEX_BYTES / 2];
5251
hex::decode_to_slice(hex_bytes, &mut buf)?;
5352
let wanted_bytes = u16::from_be_bytes(buf) as usize;
5453
if data_len < wanted_bytes {
55-
return ParseResult::Incomplete {
54+
return Ok(Stream::Incomplete {
5655
bytes_needed: wanted_bytes,
57-
};
56+
});
5857
}
5958
if wanted_bytes > MAX_LINE_LEN {
6059
return Err(Error::DataLengthLimitExceeded(wanted_bytes));
6160
}
62-
ParseResult::Complete { result }
61+
62+
// todo: error line
63+
Ok(Stream::Complete {
64+
line: packet_line::Borrowed::Data(&data[U16_HEX_BYTES..wanted_bytes]),
65+
bytes_consumed: wanted_bytes,
66+
})
6367
}

git-protocol/src/packet_line/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ impl<'a> Borrowed<'a> {
1919
Borrowed::Data(d) => encode::data_to_write(d, out),
2020
}
2121
}
22+
23+
pub fn as_slice(&self) -> &[u8] {
24+
match self {
25+
Borrowed::Data(d) => d,
26+
Borrowed::Flush => &[],
27+
}
28+
}
2229
}
2330

2431
pub mod decode;
Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
mod streaming {
22
use git_protocol::{
3-
packet_line::decode::{streaming, ParseResult},
3+
packet_line::decode::{self, streaming, Stream},
44
PacketLine,
55
};
66

7-
fn assert_complete(res: ParseResult, expected_consumed: usize, expected_value: PacketLine) -> crate::Result {
8-
match res {
9-
ParseResult::Complete { result, bytes_consumed } => {
7+
fn assert_complete(
8+
res: Result<Stream, decode::Error>,
9+
expected_consumed: usize,
10+
expected_value: PacketLine,
11+
) -> crate::Result {
12+
match res? {
13+
Stream::Complete { line, bytes_consumed } => {
1014
assert_eq!(bytes_consumed, expected_consumed);
11-
assert_eq!(result?, expected_value);
15+
assert_eq!(line, expected_value);
1216
}
13-
ParseResult::Incomplete { .. } => panic!("expected parsing to be complete, not partial"),
17+
Stream::Incomplete { .. } => panic!("expected parsing to be complete, not partial"),
1418
}
1519
Ok(())
1620
}
@@ -19,4 +23,14 @@ mod streaming {
1923
fn flush() -> crate::Result {
2024
assert_complete(streaming(b"0000someotherstuff"), 4, PacketLine::Flush)
2125
}
26+
27+
#[test]
28+
fn round_trips() -> crate::Result {
29+
for (line, bytes) in &[(PacketLine::Flush, 4), (PacketLine::Data(b"hello there"), 15)] {
30+
let mut out = Vec::new();
31+
line.to_write(&mut out)?;
32+
assert_complete(streaming(&out), *bytes, *line)?;
33+
}
34+
Ok(())
35+
}
2236
}

0 commit comments

Comments
 (0)