refactor(tvix/rm): introduce helper for AttrSet Entry API
There are multiple points where an insertion needs to be done into an attribute set, but copying the key or checking for presence before insertion should be avoided As that is a little bit noisy, it's been factored out into a helper function in this commit. Change-Id: Ibcb054ebeb25a1236c06c812f47c8e74180d4fc9 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6107 Tested-by: BuildkiteCI Reviewed-by: grfn <grfn@gws.fyi>
This commit is contained in:
parent
295d6e1d59
commit
52736a1dbc
1 changed files with 27 additions and 20 deletions
|
@ -234,12 +234,7 @@ impl VM {
|
||||||
//
|
//
|
||||||
let key = self.pop();
|
let key = self.pop();
|
||||||
match key {
|
match key {
|
||||||
Value::String(ks) => {
|
Value::String(ks) => set_attr(&mut attrs, ks, value)?,
|
||||||
// TODO(tazjin): try_insert (rust#82766) or entry API
|
|
||||||
if attrs.insert(ks.clone(), value).is_some() {
|
|
||||||
return Err(Error::DuplicateAttrsKey { key: ks.0 });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Value::AttrPath(mut path) => {
|
Value::AttrPath(mut path) => {
|
||||||
set_nested_attr(
|
set_nested_attr(
|
||||||
|
@ -299,23 +294,15 @@ pub enum NumberPair {
|
||||||
Integer(i64, i64),
|
Integer(i64, i64),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a nested attribute inside of an attribute set, throwing a
|
// Set an attribute on an in-construction attribute set, while
|
||||||
// duplicate key error if a non-hashmap entry already exists on the
|
// checking against duplicate key.s
|
||||||
// path.
|
fn set_attr(
|
||||||
//
|
|
||||||
// There is some optimisation potential for this simple implementation
|
|
||||||
// if it becomes a problem.
|
|
||||||
fn set_nested_attr(
|
|
||||||
attrs: &mut BTreeMap<NixString, Value>,
|
attrs: &mut BTreeMap<NixString, Value>,
|
||||||
key: NixString,
|
key: NixString,
|
||||||
mut path: Vec<NixString>,
|
|
||||||
value: Value,
|
value: Value,
|
||||||
) -> EvalResult<()> {
|
) -> EvalResult<()> {
|
||||||
let entry = attrs.entry(key);
|
let entry = attrs.entry(key);
|
||||||
|
|
||||||
// If there is no next key we are at the point where we
|
|
||||||
// should insert the value itself.
|
|
||||||
if path.is_empty() {
|
|
||||||
match entry {
|
match entry {
|
||||||
std::collections::btree_map::Entry::Occupied(entry) => {
|
std::collections::btree_map::Entry::Occupied(entry) => {
|
||||||
return Err(Error::DuplicateAttrsKey {
|
return Err(Error::DuplicateAttrsKey {
|
||||||
|
@ -330,6 +317,26 @@ fn set_nested_attr(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set a nested attribute inside of an attribute set, throwing a
|
||||||
|
// duplicate key error if a non-hashmap entry already exists on the
|
||||||
|
// path.
|
||||||
|
//
|
||||||
|
// There is some optimisation potential for this simple implementation
|
||||||
|
// if it becomes a problem.
|
||||||
|
fn set_nested_attr(
|
||||||
|
attrs: &mut BTreeMap<NixString, Value>,
|
||||||
|
key: NixString,
|
||||||
|
mut path: Vec<NixString>,
|
||||||
|
value: Value,
|
||||||
|
) -> EvalResult<()> {
|
||||||
|
// If there is no next key we are at the point where we
|
||||||
|
// should insert the value itself.
|
||||||
|
if path.is_empty() {
|
||||||
|
return set_attr(attrs, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
let entry = attrs.entry(key);
|
||||||
|
|
||||||
// If there is not we go one step further down, in which case we
|
// If there is not we go one step further down, in which case we
|
||||||
// need to ensure that there either is no entry, or the existing
|
// need to ensure that there either is no entry, or the existing
|
||||||
// entry is a hashmap into which to insert the next value.
|
// entry is a hashmap into which to insert the next value.
|
||||||
|
|
Loading…
Reference in a new issue