Allow for rejecting nested record cells (#6463)

* add new function to remove data at a cellpath; allow reject to use cellpath

* add tests

* fmt

* fix clippt

* get it working properly with lists of records

* fix clippy, hopefully

* fix clippy, hopefully 2
This commit is contained in:
pwygab
2022-09-03 20:35:36 +08:00
committed by GitHub
parent 4656310a1c
commit e81689f2c0
3 changed files with 179 additions and 138 deletions

View File

@ -926,6 +926,141 @@ impl Value {
Ok(())
}
pub fn remove_data_at_cell_path(&mut self, cell_path: &[PathMember]) -> Result<(), ShellError> {
match cell_path.len() {
0 => Ok(()),
1 => {
let path_member = cell_path.first().expect("there is a first");
match path_member {
PathMember::String {
val: col_name,
span,
} => match self {
Value::List { vals, .. } => {
for val in vals.iter_mut() {
match val {
Value::Record {
cols,
vals,
span: v_span,
} => {
let mut found = false;
for (i, col) in cols.clone().iter().enumerate() {
if col == col_name {
cols.remove(i);
vals.remove(i);
found = true;
}
}
if !found {
return Err(ShellError::CantFindColumn(*span, *v_span));
}
}
v => return Err(ShellError::CantFindColumn(*span, v.span()?)),
}
}
Ok(())
}
Value::Record {
cols,
vals,
span: v_span,
} => {
let mut found = false;
for (i, col) in cols.clone().iter().enumerate() {
if col == col_name {
cols.remove(i);
vals.remove(i);
found = true;
}
}
if !found {
return Err(ShellError::CantFindColumn(*span, *v_span));
}
Ok(())
}
v => Err(ShellError::CantFindColumn(*span, v.span()?)),
},
PathMember::Int { val: row_num, span } => match self {
Value::List { vals, .. } => {
if vals.get_mut(*row_num).is_some() {
vals.remove(*row_num);
Ok(())
} else {
Err(ShellError::AccessBeyondEnd(vals.len(), *span))
}
}
v => Err(ShellError::NotAList(*span, v.span()?)),
},
}
}
_ => {
let path_member = cell_path.first().expect("there is a first");
match path_member {
PathMember::String {
val: col_name,
span,
} => match self {
Value::List { vals, .. } => {
for val in vals.iter_mut() {
match val {
Value::Record {
cols,
vals,
span: v_span,
} => {
let mut found = false;
for col in cols.iter().zip(vals.iter_mut()) {
if col.0 == col_name {
found = true;
col.1.remove_data_at_cell_path(&cell_path[1..])?
}
}
if !found {
return Err(ShellError::CantFindColumn(*span, *v_span));
}
}
v => return Err(ShellError::CantFindColumn(*span, v.span()?)),
}
}
Ok(())
}
Value::Record {
cols,
vals,
span: v_span,
} => {
let mut found = false;
for col in cols.iter().zip(vals.iter_mut()) {
if col.0 == col_name {
found = true;
col.1.remove_data_at_cell_path(&cell_path[1..])?
}
}
if !found {
return Err(ShellError::CantFindColumn(*span, *v_span));
}
Ok(())
}
v => Err(ShellError::CantFindColumn(*span, v.span()?)),
},
PathMember::Int { val: row_num, span } => match self {
Value::List { vals, .. } => {
if let Some(v) = vals.get_mut(*row_num) {
v.remove_data_at_cell_path(&cell_path[1..])
} else {
Err(ShellError::AccessBeyondEnd(vals.len(), *span))
}
}
v => Err(ShellError::NotAList(*span, v.span()?)),
},
}
}
}
}
pub fn insert_data_at_cell_path(
&mut self,
cell_path: &[PathMember],