normalize get_raw_value
This commit is contained in:
parent
c01b61cb11
commit
493729cc3c
2 changed files with 63 additions and 24 deletions
16
src/file.rs
16
src/file.rs
|
@ -1,4 +1,7 @@
|
||||||
use crate::parser::{parse_from_bytes, Error, Event, ParsedSectionHeader, Parser};
|
use crate::{
|
||||||
|
parser::{parse_from_bytes, Error, Event, ParsedSectionHeader, Parser},
|
||||||
|
values::normalize_vec,
|
||||||
|
};
|
||||||
use std::collections::{HashMap, VecDeque};
|
use std::collections::{HashMap, VecDeque};
|
||||||
use std::{borrow::Borrow, convert::TryFrom};
|
use std::{borrow::Borrow, convert::TryFrom};
|
||||||
use std::{borrow::Cow, fmt::Display};
|
use std::{borrow::Cow, fmt::Display};
|
||||||
|
@ -51,6 +54,15 @@ enum LookupTreeNode<'a> {
|
||||||
NonTerminal(HashMap<Cow<'a, str>, Vec<SectionId>>),
|
NonTerminal(HashMap<Cow<'a, str>, Vec<SectionId>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct MutableValue<'a> {
|
||||||
|
section: &'a mut Vec<Event<'a>>,
|
||||||
|
value: Cow<'a, [u8]>,
|
||||||
|
index: usize,
|
||||||
|
size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MutableValue<'_> {}
|
||||||
|
|
||||||
/// High level `git-config` reader and writer.
|
/// High level `git-config` reader and writer.
|
||||||
///
|
///
|
||||||
/// Internally, this uses various acceleration data structures to improve
|
/// Internally, this uses various acceleration data structures to improve
|
||||||
|
@ -270,7 +282,7 @@ impl<'a> GitConfig<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
latest_value
|
latest_value
|
||||||
.or_else(|| partial_value.map(Cow::Owned))
|
.or_else(|| partial_value.map(|v| normalize_vec(v)))
|
||||||
.ok_or(GitConfigError::KeyDoesNotExist(key))
|
.ok_or(GitConfigError::KeyDoesNotExist(key))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,53 +21,62 @@ use std::str::FromStr;
|
||||||
/// need to call this yourself. However, if you're directly handling events
|
/// need to call this yourself. However, if you're directly handling events
|
||||||
/// from the parser, you may want to use this to help with value interpretation.
|
/// from the parser, you may want to use this to help with value interpretation.
|
||||||
///
|
///
|
||||||
|
/// Generally speaking, you'll want to use one of the variants of this function,
|
||||||
|
/// such as [`normalize_str`] or [`normalize_vec`].
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Values don't need modification are returned borrowed, without allocation.
|
/// Values don't need modification are returned borrowed, without allocation.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # use git_config::values::normalize;
|
/// # use git_config::values::normalize_str;
|
||||||
/// assert_eq!(normalize(b"hello world"), Cow::Borrowed(b"hello world".into()));
|
/// assert_eq!(normalize_str("hello world"), Cow::Borrowed(b"hello world".into()));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Fully quoted values are optimized to not need allocations.
|
/// Fully quoted values are optimized to not need allocations.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # use git_config::values::normalize;
|
/// # use git_config::values::normalize_str;
|
||||||
/// assert_eq!(normalize(b"\"hello world\""), Cow::Borrowed(b"hello world".into()));
|
/// assert_eq!(normalize_str("\"hello world\""), Cow::Borrowed(b"hello world".into()));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Quoted values are unwrapped as an owned variant.
|
/// Quoted values are unwrapped as an owned variant.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # use git_config::values::normalize;
|
/// # use git_config::values::normalize_str;
|
||||||
/// assert_eq!(normalize(b"hello \"world\""), Cow::<[u8]>::Owned(b"hello world".to_vec()));
|
/// assert_eq!(normalize_str("hello \"world\""), Cow::<[u8]>::Owned(b"hello world".to_vec()));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Escaped quotes are unescaped.
|
/// Escaped quotes are unescaped.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::borrow::Cow;
|
/// # use std::borrow::Cow;
|
||||||
/// # use git_config::values::normalize;
|
/// # use git_config::values::normalize_str;
|
||||||
/// assert_eq!(normalize(br#"hello "world\"""#), Cow::<[u8]>::Owned(br#"hello world""#.to_vec()));
|
/// assert_eq!(normalize_str(r#"hello "world\"""#), Cow::<[u8]>::Owned(br#"hello world""#.to_vec()));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`parser`]: crate::parser::Parser
|
/// [`parser`]: crate::parser::Parser
|
||||||
pub fn normalize(input: &[u8]) -> Cow<'_, [u8]> {
|
pub fn normalize_cow(input: Cow<'_, [u8]>) -> Cow<'_, [u8]> {
|
||||||
let mut first_index = 0;
|
let mut first_index = 0;
|
||||||
let mut last_index = 0;
|
let mut last_index = 0;
|
||||||
|
|
||||||
let size = input.len();
|
let size = input.len();
|
||||||
|
if &*input == b"\"\"" {
|
||||||
if input == b"\"\"" {
|
|
||||||
return Cow::Borrowed(&[]);
|
return Cow::Borrowed(&[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if size >= 3 && input[0] == b'=' && input[size - 1] == b'=' && input[size - 2] != b'\\' {
|
if size >= 3 && input[0] == b'=' && input[size - 1] == b'=' && input[size - 2] != b'\\' {
|
||||||
return normalize(&input[1..size]);
|
match input {
|
||||||
|
Cow::Borrowed(input) => return normalize_bytes(&input[1..size]),
|
||||||
|
Cow::Owned(mut input) => {
|
||||||
|
input.pop();
|
||||||
|
input.remove(0);
|
||||||
|
return normalize_vec(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut owned = vec![];
|
let mut owned = vec![];
|
||||||
|
@ -104,12 +113,27 @@ pub fn normalize(input: &[u8]) -> Cow<'_, [u8]> {
|
||||||
|
|
||||||
owned.extend(dbg!(&input[last_index..]));
|
owned.extend(dbg!(&input[last_index..]));
|
||||||
if owned.is_empty() {
|
if owned.is_empty() {
|
||||||
Cow::Borrowed(input)
|
input
|
||||||
} else {
|
} else {
|
||||||
Cow::Owned(owned)
|
Cow::Owned(owned)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn normalize_bytes(input: &[u8]) -> Cow<'_, [u8]> {
|
||||||
|
normalize_cow(Cow::Borrowed(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn normalize_vec(input: Vec<u8>) -> Cow<'static, [u8]> {
|
||||||
|
normalize_cow(Cow::Owned(input))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn normalize_str(input: &str) -> Cow<'_, [u8]> {
|
||||||
|
normalize_bytes(input.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
/// Fully enumerated valid types that a `git-config` value can be.
|
/// Fully enumerated valid types that a `git-config` value can be.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
||||||
|
@ -944,31 +968,34 @@ impl TryFrom<&[u8]> for ColorAttribute {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod normalize {
|
mod normalize {
|
||||||
use super::normalize;
|
use super::normalize_str;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn not_modified_is_borrowed() {
|
fn not_modified_is_borrowed() {
|
||||||
assert_eq!(normalize(b"hello world"), Cow::Borrowed(b"hello world"));
|
assert_eq!(normalize_str("hello world"), Cow::Borrowed(b"hello world"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn modified_is_owned() {
|
fn modified_is_owned() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
normalize(b"hello \"world\""),
|
normalize_str("hello \"world\""),
|
||||||
Cow::<[u8]>::Owned(b"hello world".to_vec())
|
Cow::<[u8]>::Owned(b"hello world".to_vec())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn all_quoted_is_optimized() {
|
fn all_quoted_is_optimized() {
|
||||||
assert_eq!(normalize(b"\"hello world\""), Cow::Borrowed(b"hello world"));
|
assert_eq!(
|
||||||
|
normalize_str("\"hello world\""),
|
||||||
|
Cow::Borrowed(b"hello world")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn all_quote_optimization_is_correct() {
|
fn all_quote_optimization_is_correct() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
normalize(br#""hello" world\""#),
|
normalize_str(r#""hello" world\""#),
|
||||||
Cow::Borrowed(b"hello world\"")
|
Cow::Borrowed(b"hello world\"")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -976,7 +1003,7 @@ mod normalize {
|
||||||
#[test]
|
#[test]
|
||||||
fn quotes_right_next_to_each_other() {
|
fn quotes_right_next_to_each_other() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
normalize(b"\"hello\"\" world\""),
|
normalize_str("\"hello\"\" world\""),
|
||||||
Cow::<[u8]>::Owned(b"hello world".to_vec())
|
Cow::<[u8]>::Owned(b"hello world".to_vec())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -984,19 +1011,19 @@ mod normalize {
|
||||||
#[test]
|
#[test]
|
||||||
fn escaped_quotes_are_kept() {
|
fn escaped_quotes_are_kept() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
normalize(br#""hello \"\" world""#),
|
normalize_str(r#""hello \"\" world""#),
|
||||||
Cow::<[u8]>::Owned(b"hello \"\" world".to_vec())
|
Cow::<[u8]>::Owned(b"hello \"\" world".to_vec())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_string() {
|
fn empty_string() {
|
||||||
assert_eq!(normalize(b""), Cow::Borrowed(b""));
|
assert_eq!(normalize_str(""), Cow::Borrowed(b""));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_normalized_string_is_optimized() {
|
fn empty_normalized_string_is_optimized() {
|
||||||
assert_eq!(normalize(b"\"\""), Cow::Borrowed(b""));
|
assert_eq!(normalize_str("\"\""), Cow::Borrowed(b""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue