Showing the changes to git-protocol/src (2 of 2 files). Show all
Unified · Split
| @@ -6,6 +6,7 @@ use crate::{ · 5 unmodified lines | ||
| 6 | 6 | }; |
| 7 | 7 | use bstr::BString; |
| 8 | 8 | use quick_error::quick_error; |
| 9 | +use std::convert::TryInto; | |
| 9 | 10 | |
| 10 | 11 | quick_error! { |
| 11 | 12 | #[derive(Debug)] |
| @@ -39,6 +40,43 @@ pub enum Stream<'a> { · 27 unmodified lines | ||
| 39 | 40 | }, |
| 40 | 41 | } |
| 41 | 42 | |
| 43 | +pub enum PacketLineOrWantedSize<'a> { | |
| 44 | + Line(PacketLine<'a>), | |
| 45 | + Wanted(u16), | |
| 46 | +} | |
| 47 | + | |
| 48 | +pub fn hex_prefix(data: &[u8; 4]) -> Result<PacketLineOrWantedSize, Error> { | |
| 49 | + for (line_bytes, line_type) in &[ | |
| 50 | + (FLUSH_LINE, PacketLine::Flush), | |
| 51 | + (DELIMITER_LINE, PacketLine::Delimiter), | |
| 52 | + (RESPONSE_END_LINE, PacketLine::ResponseEnd), | |
| 53 | + ] { | |
| 54 | + if data == *line_bytes { | |
| 55 | + return Ok(PacketLineOrWantedSize::Line(*line_type)); | |
| 56 | + } | |
| 57 | + } | |
| 58 | + | |
| 59 | + let mut buf = [0u8; U16_HEX_BYTES / 2]; | |
| 60 | + hex::decode_to_slice(data, &mut buf)?; | |
| 61 | + let wanted_bytes = u16::from_be_bytes(buf); | |
| 62 | + if wanted_bytes == 4 { | |
| 63 | + return Err(Error::DataIsEmpty); | |
| 64 | + } | |
| 65 | + Ok(PacketLineOrWantedSize::Wanted(wanted_bytes)) | |
| 66 | +} | |
| 67 | + | |
| 68 | +pub fn to_data_line(data: &[u8]) -> Result<PacketLine, Error> { | |
| 69 | + if data.len() > MAX_LINE_LEN { | |
| 70 | + return Err(Error::DataLengthLimitExceeded(data.len())); | |
| 71 | + } | |
| 72 | + | |
| 73 | + if data.len() >= ERR_PREFIX.len() && &data[..ERR_PREFIX.len()] == ERR_PREFIX { | |
| 74 | + return Err(Error::Line(data[ERR_PREFIX.len()..].into(), data.len())); | |
| 75 | + } | |
| 76 | + Ok(PacketLine::Data(data)) | |
| 77 | +} | |
| 78 | + | |
| 79 | +// TODO: verify this one is actually needed in the end | |
| 42 | 80 | pub fn streaming(data: &[u8]) -> Result<Stream, Error> { |
| 43 | 81 | let data_len = data.len(); |
| 44 | 82 | if data_len < U16_HEX_BYTES { |
| @@ -46,23 +84,15 @@ pub fn streaming(data: &[u8]) -> Result<Stream, Error> { · 1 unmodified line | ||
| 46 | 84 | bytes_needed: U16_HEX_BYTES - data_len, |
| 47 | 85 | }); |
| 48 | 86 | } |
| 49 | − let hex_bytes = &data[..U16_HEX_BYTES]; | |
| 50 | − for (line_bytes, line_type) in &[ | |
| 51 | − (FLUSH_LINE, PacketLine::Flush), | |
| 52 | − (DELIMITER_LINE, PacketLine::Delimiter), | |
| 53 | − (RESPONSE_END_LINE, PacketLine::ResponseEnd), | |
| 54 | − ] { | |
| 55 | − if hex_bytes == *line_bytes { | |
| 87 | + let wanted_bytes = match hex_prefix(data[..U16_HEX_BYTES].try_into().expect("sizes to match"))? { | |
| 88 | + PacketLineOrWantedSize::Wanted(s) => s as usize, | |
| 89 | + PacketLineOrWantedSize::Line(line) => { | |
| 56 | 90 | return Ok(Stream::Complete { |
| 57 | − line: *line_type, | |
| 91 | + line, | |
| 58 | 92 | bytes_consumed: 4, |
| 59 | − }); | |
| 93 | + }) | |
| 60 | 94 | } |
| 61 | − } | |
| 62 | − | |
| 63 | − let mut buf = [0u8; U16_HEX_BYTES / 2]; | |
| 64 | − hex::decode_to_slice(hex_bytes, &mut buf)?; | |
| 65 | − let wanted_bytes = u16::from_be_bytes(buf) as usize; | |
| 95 | + }; | |
| 66 | 96 | if wanted_bytes > MAX_LINE_LEN { |
| 67 | 97 | return Err(Error::DataLengthLimitExceeded(wanted_bytes)); |
| 68 | 98 | } |
| @@ -72,17 +102,8 @@ pub fn streaming(data: &[u8]) -> Result<Stream, Error> { · 3 unmodified lines | ||
| 72 | 102 | }); |
| 73 | 103 | } |
| 74 | 104 | |
| 75 | − if wanted_bytes == 4 { | |
| 76 | − return Err(Error::DataIsEmpty); | |
| 77 | − } | |
| 78 | − | |
| 79 | − let data = &data[U16_HEX_BYTES..wanted_bytes]; | |
| 80 | − if data.len() >= ERR_PREFIX.len() && &data[..ERR_PREFIX.len()] == ERR_PREFIX { | |
| 81 | − return Err(Error::Line(data[ERR_PREFIX.len()..].into(), wanted_bytes)); | |
| 82 | − } | |
| 83 | − | |
| 84 | 105 | Ok(Stream::Complete { |
| 85 | − line: PacketLine::Data(data), | |
| 106 | + line: to_data_line(&data[U16_HEX_BYTES..wanted_bytes])?, | |
| 86 | 107 | bytes_consumed: wanted_bytes, |
| 87 | 108 | }) |
| 88 | 109 | } |
| @@ -52,9 +52,9 @@ mod read { · 51 unmodified lines | ||
| 52 | 52 | ) -> io::Result<Result<Borrowed<'a>, decode::Error>> { |
| 53 | 53 | let mut buf_end = 4; |
| 54 | 54 | reader.read_exact(&mut buf[..buf_end])?; |
| 55 | − let (from, rest) = buf.split_at_mut(buf_end); | |
| 55 | + let (hex_bytes, potential_data) = buf.split_at_mut(buf_end); | |
| 56 | 56 | |
| 57 | − match decode::streaming(from) { | |
| 57 | + match decode::streaming(hex_bytes) { | |
| 58 | 58 | Err(err) => Ok(Err(err)), |
| 59 | 59 | Ok(stream) => match stream { |
| 60 | 60 | decode::Stream::Complete { |
| @@ -62,14 +62,16 @@ mod read { · 1 unmodified line | ||
| 62 | 62 | bytes_consumed: _, |
| 63 | 63 | } => Ok(Ok(line)), |
| 64 | 64 | decode::Stream::Incomplete { bytes_needed } => { |
| 65 | − reader.read_exact(rest)?; | |
| 65 | + reader.read_exact(potential_data)?; | |
| 66 | 66 | buf_end += bytes_needed; |
| 67 | − Ok(decode::streaming(&rest[..buf_end]).map(|stream| match stream { | |
| 68 | − decode::Stream::Complete { line, .. } => line, | |
| 69 | − decode::Stream::Incomplete { .. } => { | |
| 70 | − unreachable!("we know that our streamer is happy once the missing bytes are provided") | |
| 71 | − } | |
| 72 | − })) | |
| 67 | + Ok( | |
| 68 | + decode::streaming(&potential_data[..buf_end]).map(|stream| match stream { | |
| 69 | + decode::Stream::Complete { line, .. } => line, | |
| 70 | + decode::Stream::Incomplete { .. } => unreachable!( | |
| 71 | + "we know that our streamer is happy once the missing bytes are provided" | |
| 72 | + ), | |
| 73 | + }), | |
| 74 | + ) | |
| 73 | 75 | } |
| 74 | 76 | }, |
| 75 | 77 | } |