That way it's possible to continue parsing past the quoted string.
Showing the changes to git-quote/src (1 of 2 files). Show all
Unified · Split
| @@ -28,23 +28,25 @@ use std::{borrow::Cow, io::Read}; · 27 unmodified lines | ||
| 28 | 28 | |
| 29 | 29 | use bstr::{BStr, BString, ByteSlice}; |
| 30 | 30 | |
| 31 | −/// Unquote the given ansi-c quoted `input` string. | |
| 31 | +/// Unquote the given ansi-c quoted `input` string, returning it and all of the consumed bytes. | |
| 32 | 32 | /// |
| 33 | 33 | /// The `input` is returned unaltered if it doesn't start with a `"` character to indicate |
| 34 | −/// quotation, otherwise a new unqoted string will always be allocated. | |
| 34 | +/// quotation, otherwise a new unquoted string will always be allocated. | |
| 35 | +/// The amount of consumed bytes allow to pass strings that start with a quote, and skip all quoted text for additional processing | |
| 35 | 36 | /// |
| 36 | 37 | /// See [the tests][tests] for quotation examples. |
| 37 | 38 | /// |
| 38 | 39 | /// [tests]: https://github.com/Byron/gitoxide/blob/e355b4ad133075152312816816af5ce72cf79cff/git-odb/src/alternate/unquote.rs#L110-L118 |
| 39 | −pub fn undo(input: &BStr) -> Result<Cow<'_, BStr>, undo::Error> { | |
| 40 | +pub fn undo(input: &BStr) -> Result<(Cow<'_, BStr>, usize), undo::Error> { | |
| 40 | 41 | if !input.starts_with(b"\"") { |
| 41 | − return Ok(input.into()); | |
| 42 | + return Ok((input.into(), input.len())); | |
| 42 | 43 | } |
| 43 | 44 | if input.len() < 2 { |
| 44 | 45 | return Err(undo::Error::new("Input must be surrounded by double quotes", input)); |
| 45 | 46 | } |
| 46 | 47 | let original = input.as_bstr(); |
| 47 | 48 | let mut input = &input[1..]; |
| 49 | + let mut consumed = 1; | |
| 48 | 50 | let mut out = BString::default(); |
| 49 | 51 | fn consume_one_past(input: &mut &BStr, position: usize) -> Result<u8, undo::Error> { |
| 50 | 52 | *input = input |
| @@ -59,10 +61,12 @@ pub fn undo(input: &BStr) -> Result<Cow<'_, BStr>, undo::Error> { · 8 unmodified lines | ||
| 59 | 61 | match input.find_byteset(b"\"\\") { |
| 60 | 62 | Some(position) => { |
| 61 | 63 | out.extend_from_slice(&input[..position]); |
| 64 | + consumed += position + 1; | |
| 62 | 65 | match input[position] { |
| 63 | 66 | b'"' => break, |
| 64 | 67 | b'\\' => { |
| 65 | 68 | let next = consume_one_past(&mut input, position)?; |
| 69 | + consumed += 1; | |
| 66 | 70 | match next { |
| 67 | 71 | b'n' => out.push(b'\n'), |
| 68 | 72 | b'r' => out.push(b'\r'), |
| @@ -88,6 +92,7 @@ pub fn undo(input: &BStr) -> Result<Cow<'_, BStr>, undo::Error> { · 19 unmodified lines | ||
| 88 | 92 | let byte = btoi::btou_radix(&buf, 8).map_err(|e| undo::Error::new(e, original))?; |
| 89 | 93 | out.push(byte); |
| 90 | 94 | input = &input[2..]; |
| 95 | + consumed += 2; | |
| 91 | 96 | } |
| 92 | 97 | _ => { |
| 93 | 98 | return Err(undo::Error::UnsupportedEscapeByte { |
| @@ -102,9 +107,10 @@ pub fn undo(input: &BStr) -> Result<Cow<'_, BStr>, undo::Error> { · 8 unmodified lines | ||
| 102 | 107 | } |
| 103 | 108 | None => { |
| 104 | 109 | out.extend_from_slice(input); |
| 110 | + consumed += input.len(); | |
| 105 | 111 | break; |
| 106 | 112 | } |
| 107 | 113 | } |
| 108 | 114 | } |
| 109 | − Ok(out.into()) | |
| 115 | + Ok((out.into(), consumed)) | |
| 110 | 116 | } |