multablemultivalue
This commit is contained in:
parent
559afb01fa
commit
cbb970c293
1 changed files with 159 additions and 58 deletions
195
src/file.rs
195
src/file.rs
|
@ -92,6 +92,13 @@ impl MutableValue<'_, '_, '_> {
|
|||
.ok_or(GitConfigError::KeyDoesNotExist(self.key))
|
||||
}
|
||||
|
||||
/// Update the value to the provided one. This modifies the value such that
|
||||
/// the Value event(s) are replaced with a single new event containing the
|
||||
/// new value.
|
||||
pub fn set_string(&mut self, input: String) {
|
||||
self.set_bytes(input.into_bytes());
|
||||
}
|
||||
|
||||
/// Update the value to the provided one. This modifies the value such that
|
||||
/// the Value event(s) are replaced with a single new event containing the
|
||||
/// new value.
|
||||
|
@ -101,20 +108,116 @@ impl MutableValue<'_, '_, '_> {
|
|||
self.section
|
||||
.insert(self.index, Event::Value(Cow::Owned(input)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Update the value to the provided one. This modifies the value such that
|
||||
/// the Value event(s) are replaced with a single new event containing the
|
||||
/// new value.
|
||||
pub fn set_string(&mut self, input: String) {
|
||||
self.set_bytes(input.into_bytes());
|
||||
pub struct MutableMultiValue<'borrow, 'lookup, 'event> {
|
||||
section: &'borrow mut HashMap<SectionId, Vec<Event<'event>>>,
|
||||
key: &'lookup str,
|
||||
indices_and_sizes: Vec<(SectionId, usize, usize)>,
|
||||
}
|
||||
|
||||
impl<'event> MutableMultiValue<'_, '_, 'event> {
|
||||
/// Returns the actual value. This is computed each time this is called, so
|
||||
/// it's best to reuse this value or own it if an allocation is acceptable.
|
||||
pub fn value(&self) -> Result<Vec<Cow<'_, [u8]>>, GitConfigError> {
|
||||
let mut found_key = false;
|
||||
let mut values = vec![];
|
||||
let mut partial_value = None;
|
||||
// section_id is guaranteed to exist in self.sections, else we have a
|
||||
// violated invariant.
|
||||
for (section_id, index, size) in &self.indices_and_sizes {
|
||||
for event in &self.section.get(section_id).unwrap()[*index..*size] {
|
||||
match event {
|
||||
Event::Key(event_key) if *event_key == self.key => found_key = true,
|
||||
Event::Value(v) if found_key => {
|
||||
found_key = false;
|
||||
values.push(normalize_bytes(v.borrow()));
|
||||
}
|
||||
Event::ValueNotDone(v) if found_key => {
|
||||
partial_value = Some((*v).to_vec());
|
||||
}
|
||||
Event::ValueDone(v) if found_key => {
|
||||
found_key = false;
|
||||
partial_value.as_mut().unwrap().extend(&**v);
|
||||
values.push(normalize_vec(partial_value.take().unwrap()));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pub struct MutableMultiValue<'borrow, 'lookup, 'event> {
|
||||
// section: &'borrow mut Vec<Event<'event>>,
|
||||
// key: &'lookup str,
|
||||
// indices_and_sizes: Vec<(usize, usize)>,
|
||||
// }
|
||||
if values.is_empty() {
|
||||
return Err(GitConfigError::KeyDoesNotExist(self.key));
|
||||
}
|
||||
|
||||
Ok(values)
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.indices_and_sizes.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.indices_and_sizes.is_empty()
|
||||
}
|
||||
|
||||
pub fn set_string(&mut self, index: usize, input: String) {
|
||||
self.set_bytes(index, input.into_bytes())
|
||||
}
|
||||
|
||||
pub fn set_bytes(&mut self, index: usize, input: Vec<u8>) {
|
||||
self.set_value(index, Cow::Owned(input))
|
||||
}
|
||||
|
||||
pub fn set_value(&mut self, index: usize, input: Cow<'event, [u8]>) {
|
||||
let (section_id, index, size) = &mut self.indices_and_sizes[index];
|
||||
self.section
|
||||
.get_mut(section_id)
|
||||
.unwrap()
|
||||
.drain(*index..*index + *size);
|
||||
*size = 1;
|
||||
self.section
|
||||
.get_mut(section_id)
|
||||
.unwrap()
|
||||
.insert(*index, Event::Value(input));
|
||||
}
|
||||
|
||||
pub fn set_values(&mut self, input: impl Iterator<Item = Cow<'event, [u8]>>) {
|
||||
for ((section_id, index, size), value) in self.indices_and_sizes.iter_mut().zip(input) {
|
||||
self.section
|
||||
.get_mut(section_id)
|
||||
.unwrap()
|
||||
.drain(*index..*index + *size);
|
||||
*size = 1;
|
||||
self.section
|
||||
.get_mut(section_id)
|
||||
.unwrap()
|
||||
.insert(*index, Event::Value(value));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_string_all(&mut self, input: String) {
|
||||
self.set_bytes_all(input.into_bytes())
|
||||
}
|
||||
|
||||
pub fn set_bytes_all(&mut self, input: Vec<u8>) {
|
||||
self.set_values_all(Cow::Owned(input))
|
||||
}
|
||||
|
||||
pub fn set_values_all(&mut self, input: Cow<'event, [u8]>) {
|
||||
for (section_id, index, size) in &mut self.indices_and_sizes {
|
||||
self.section
|
||||
.get_mut(section_id)
|
||||
.unwrap()
|
||||
.drain(*index..*index + *size);
|
||||
*size = 1;
|
||||
self.section
|
||||
.get_mut(section_id)
|
||||
.unwrap()
|
||||
.insert(*index, Event::Value(input.clone()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// High level `git-config` reader and writer.
|
||||
///
|
||||
|
@ -317,7 +420,7 @@ impl<'event> GitConfig<'event> {
|
|||
|
||||
// section_id is guaranteed to exist in self.sections, else we have a
|
||||
// violated invariant.
|
||||
for event in self.sections.get(§ion_id).unwrap() {
|
||||
for event in self.sections.get(section_id).unwrap() {
|
||||
match event {
|
||||
Event::Key(event_key) if *event_key == key => found_key = true,
|
||||
Event::Value(v) if found_key => {
|
||||
|
@ -336,10 +439,8 @@ impl<'event> GitConfig<'event> {
|
|||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
match latest_value.or_else(|| partial_value.map(normalize_vec)) {
|
||||
Some(v) => return Ok(v),
|
||||
None => (),
|
||||
if let Some(v) = latest_value.or_else(|| partial_value.map(normalize_vec)) {
|
||||
return Ok(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,7 +470,7 @@ impl<'event> GitConfig<'event> {
|
|||
let mut size = 0;
|
||||
let mut index = 0;
|
||||
let mut found_key = false;
|
||||
for (i, event) in self.sections.get(§ion_id).unwrap().iter().enumerate() {
|
||||
for (i, event) in self.sections.get(section_id).unwrap().iter().enumerate() {
|
||||
match event {
|
||||
Event::Key(event_key) if *event_key == key => found_key = true,
|
||||
Event::Value(_) if found_key => {
|
||||
|
@ -394,7 +495,7 @@ impl<'event> GitConfig<'event> {
|
|||
}
|
||||
|
||||
return Ok(MutableValue {
|
||||
section: self.sections.get_mut(§ion_id).unwrap(),
|
||||
section: self.sections.get_mut(section_id).unwrap(),
|
||||
key,
|
||||
size,
|
||||
index,
|
||||
|
@ -514,9 +615,9 @@ impl<'event> GitConfig<'event> {
|
|||
/// Cow::Borrowed(b"d")
|
||||
/// ]
|
||||
/// );
|
||||
/// for value in git_config.get_raw_multi_value_mut("core", None, "a")? {
|
||||
/// *value = Cow::Borrowed(b"g");
|
||||
///}
|
||||
///
|
||||
/// git_config.get_raw_multi_value_mut("core", None, "a")?.set_string_all("g".to_string());
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// git_config.get_raw_multi_value("core", None, "a")?,
|
||||
/// vec![
|
||||
|
@ -544,42 +645,45 @@ impl<'event> GitConfig<'event> {
|
|||
section_name: &'lookup str,
|
||||
subsection_name: Option<&'lookup str>,
|
||||
key: &'lookup str,
|
||||
) -> Result<Vec<&mut Cow<'event, [u8]>>, GitConfigError<'lookup>> {
|
||||
let key = key;
|
||||
) -> Result<MutableMultiValue<'_, 'lookup, 'event>, GitConfigError<'lookup>> {
|
||||
let section_ids = self
|
||||
.get_section_ids_by_name_and_subname(section_name, subsection_name)?
|
||||
.to_vec();
|
||||
|
||||
let mut indices = vec![];
|
||||
for section_id in section_ids.iter().rev() {
|
||||
let mut size = 0;
|
||||
let mut index = 0;
|
||||
let mut found_key = false;
|
||||
let values: Vec<&mut Cow<'event, [u8]>> = self
|
||||
.sections
|
||||
.iter_mut()
|
||||
.filter_map(|(k, v)| {
|
||||
if section_ids.contains(k) {
|
||||
let mut values = vec![];
|
||||
for event in v {
|
||||
for (i, event) in self.sections.get(section_id).unwrap().iter().enumerate() {
|
||||
match event {
|
||||
Event::Key(event_key) if *event_key == key => found_key = true,
|
||||
Event::Value(v) if found_key => {
|
||||
values.push(v);
|
||||
Event::Value(_) if found_key => {
|
||||
indices.push((*section_id, i, 1));
|
||||
found_key = false;
|
||||
}
|
||||
Event::ValueNotDone(_) if found_key => {
|
||||
size = 1;
|
||||
index = i;
|
||||
}
|
||||
Event::ValueDone(_) if found_key => {
|
||||
found_key = false;
|
||||
size += 1;
|
||||
indices.push((*section_id, index, size));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
Some(values)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
// TODO: return mutable entry instead
|
||||
// TODO: support partial values
|
||||
if values.is_empty() {
|
||||
Err(GitConfigError::KeyDoesNotExist(key))
|
||||
if !indices.is_empty() {
|
||||
Ok(MutableMultiValue {
|
||||
section: &mut self.sections,
|
||||
key,
|
||||
indices_and_sizes: indices,
|
||||
})
|
||||
} else {
|
||||
Ok(values)
|
||||
Err(GitConfigError::KeyDoesNotExist(key))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -717,11 +821,8 @@ impl<'event> GitConfig<'event> {
|
|||
key: &'lookup str,
|
||||
new_values: impl Iterator<Item = Cow<'event, [u8]>>,
|
||||
) -> Result<(), GitConfigError<'lookup>> {
|
||||
let values = self.get_raw_multi_value_mut(section_name, subsection_name, key)?;
|
||||
for (old, new) in values.into_iter().zip(new_values) {
|
||||
*old = new;
|
||||
}
|
||||
Ok(())
|
||||
self.get_raw_multi_value_mut(section_name, subsection_name, key)
|
||||
.map(|mut v| v.set_values(new_values))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue