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 | use bstr::BString; | 7 | use bstr::BString; |
| 8 | use quick_error::quick_error; | 8 | use quick_error::quick_error; |
| 9 | use std::convert::TryInto; | ||
| 9 | 10 | ||
| 10 | quick_error! { | 11 | quick_error! { |
| 11 | #[derive(Debug)] | 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 | pub fn streaming(data: &[u8]) -> Result<Stream, Error> { | 80 | pub fn streaming(data: &[u8]) -> Result<Stream, Error> { |
| 43 | let data_len = data.len(); | 81 | let data_len = data.len(); |
| 44 | if data_len < U16_HEX_BYTES { | 82 | if data_len < U16_HEX_BYTES { |
| @@ -46,23 +84,15 @@ pub fn streaming(data: &[u8]) -> Result<Stream, Error> { · 1 unmodified line | |||
| 46 | bytes_needed: U16_HEX_BYTES - data_len, | 84 | bytes_needed: U16_HEX_BYTES - data_len, |
| 47 | }); | 85 | }); |
| 48 | } | 86 | } |
| 49 | let hex_bytes = &data[..U16_HEX_BYTES]; | 87 | let wanted_bytes = match hex_prefix(data[..U16_HEX_BYTES].try_into().expect("sizes to match"))? { |
| 50 | for (line_bytes, line_type) in &[ | 88 | PacketLineOrWantedSize::Wanted(s) => s as usize, |
| 51 | (FLUSH_LINE, PacketLine::Flush), | 89 | PacketLineOrWantedSize::Line(line) => { |
| 52 | (DELIMITER_LINE, PacketLine::Delimiter), | ||
| 53 | (RESPONSE_END_LINE, PacketLine::ResponseEnd), | ||
| 54 | ] { | ||
| 55 | if hex_bytes == *line_bytes { | ||
| 56 | return Ok(Stream::Complete { | 90 | return Ok(Stream::Complete { |
| 57 | line: *line_type, | 91 | line, |
| 58 | bytes_consumed: 4, | 92 | bytes_consumed: 4, |
| 59 | }); | 93 | }) |
| 60 | } | 94 | } |
| 61 | } | 95 | }; |
| 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; | ||
| 66 | if wanted_bytes > MAX_LINE_LEN { | 96 | if wanted_bytes > MAX_LINE_LEN { |
| 67 | return Err(Error::DataLengthLimitExceeded(wanted_bytes)); | 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 | Ok(Stream::Complete { | 105 | Ok(Stream::Complete { |
| 85 | line: PacketLine::Data(data), | 106 | line: to_data_line(&data[U16_HEX_BYTES..wanted_bytes])?, |
| 86 | bytes_consumed: wanted_bytes, | 107 | bytes_consumed: wanted_bytes, |
| 87 | }) | 108 | }) |
| 88 | } | 109 | } |
| @@ -52,9 +52,9 @@ mod read { · 51 unmodified lines | |||
| 52 | ) -> io::Result<Result<Borrowed<'a>, decode::Error>> { | 52 | ) -> io::Result<Result<Borrowed<'a>, decode::Error>> { |
| 53 | let mut buf_end = 4; | 53 | let mut buf_end = 4; |
| 54 | reader.read_exact(&mut buf[..buf_end])?; | 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 | Err(err) => Ok(Err(err)), | 58 | Err(err) => Ok(Err(err)), |
| 59 | Ok(stream) => match stream { | 59 | Ok(stream) => match stream { |
| 60 | decode::Stream::Complete { | 60 | decode::Stream::Complete { |
| @@ -62,14 +62,16 @@ mod read { · 1 unmodified line | |||
| 62 | bytes_consumed: _, | 62 | bytes_consumed: _, |
| 63 | } => Ok(Ok(line)), | 63 | } => Ok(Ok(line)), |
| 64 | decode::Stream::Incomplete { bytes_needed } => { | 64 | decode::Stream::Incomplete { bytes_needed } => { |
| 65 | reader.read_exact(rest)?; | 65 | reader.read_exact(potential_data)?; |
| 66 | buf_end += bytes_needed; | 66 | buf_end += bytes_needed; |
| 67 | Ok(decode::streaming(&rest[..buf_end]).map(|stream| match stream { | 67 | Ok( |
| 68 | decode::Stream::Complete { line, .. } => line, | 68 | decode::streaming(&potential_data[..buf_end]).map(|stream| match stream { |
| 69 | decode::Stream::Incomplete { .. } => { | 69 | decode::Stream::Complete { line, .. } => line, |
| 70 | unreachable!("we know that our streamer is happy once the missing bytes are provided") | 70 | decode::Stream::Incomplete { .. } => unreachable!( |
| 71 | } | 71 | "we know that our streamer is happy once the missing bytes are provided" |
| 72 | })) | 72 | ), |
| 73 | }), | ||
| 74 | ) | ||
| 73 | } | 75 | } |
| 74 | }, | 76 | }, |
| 75 | } | 77 | } |