feat: EvalState.new_value_attrs
(cherry picked from commit 5b3f4d97f968b518c901c2de3759640b91fd37c2)
This commit is contained in:
parent
dc01d3731f
commit
28deb20a2b
1 changed files with 122 additions and 0 deletions
|
|
@ -492,6 +492,60 @@ impl EvalState {
|
|||
};
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn new_value_attrs<I>(&mut self, attrs: I) -> Result<Value>
|
||||
where
|
||||
I: IntoIterator<Item = (String, Value)>,
|
||||
I::IntoIter: ExactSizeIterator,
|
||||
{
|
||||
let iter = attrs.into_iter();
|
||||
let size = iter.len();
|
||||
let bindings_builder = BindingsBuilder::new(self, size)?;
|
||||
for (name, value) in iter {
|
||||
let name =
|
||||
CString::new(name).with_context(|| "new_value_attrs: name contains null byte")?;
|
||||
unsafe {
|
||||
check_call!(raw::bindings_builder_insert(
|
||||
&mut self.context,
|
||||
bindings_builder.ptr,
|
||||
name.as_ptr(),
|
||||
value.raw_ptr()
|
||||
))?;
|
||||
}
|
||||
}
|
||||
let value = self.new_value_uninitialized()?;
|
||||
unsafe {
|
||||
check_call!(raw::make_attrs(
|
||||
&mut self.context,
|
||||
value.raw_ptr(),
|
||||
bindings_builder.ptr
|
||||
))?;
|
||||
}
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
struct BindingsBuilder {
|
||||
ptr: *mut raw::BindingsBuilder,
|
||||
}
|
||||
impl Drop for BindingsBuilder {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
raw::bindings_builder_free(self.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
impl BindingsBuilder {
|
||||
fn new(eval_state: &mut EvalState, capacity: usize) -> Result<Self> {
|
||||
let ptr = unsafe {
|
||||
check_call!(raw::make_bindings_builder(
|
||||
&mut eval_state.context,
|
||||
eval_state.eval_state.as_ptr(),
|
||||
capacity
|
||||
))
|
||||
}?;
|
||||
Ok(BindingsBuilder { ptr })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gc_now() {
|
||||
|
|
@ -1636,4 +1690,72 @@ mod tests {
|
|||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn eval_state_new_value_attrs_from_slice_empty() {
|
||||
gc_registering_current_thread(|| {
|
||||
let store = Store::open("auto", []).unwrap();
|
||||
let mut es = EvalState::new(store, []).unwrap();
|
||||
let attrs = es.new_value_attrs([]).unwrap();
|
||||
let t = es.value_type(&attrs).unwrap();
|
||||
assert!(t == ValueType::AttrSet);
|
||||
let names = es.require_attrs_names(&attrs).unwrap();
|
||||
assert!(names.is_empty());
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn eval_state_new_value_attrs_from_vec() {
|
||||
gc_registering_current_thread(|| {
|
||||
let store = Store::open("auto", []).unwrap();
|
||||
let mut es = EvalState::new(store, []).unwrap();
|
||||
let attrs = {
|
||||
let a = es.new_value_int(1).unwrap();
|
||||
let b = es.new_value_int(2).unwrap();
|
||||
es.new_value_attrs(vec![("a".to_string(), a), ("b".to_string(), b)])
|
||||
.unwrap()
|
||||
};
|
||||
let t = es.value_type(&attrs).unwrap();
|
||||
assert!(t == ValueType::AttrSet);
|
||||
let names = es.require_attrs_names(&attrs).unwrap();
|
||||
assert_eq!(names.len(), 2);
|
||||
assert_eq!(names[0], "a");
|
||||
assert_eq!(names[1], "b");
|
||||
let a = es.require_attrs_select(&attrs, "a").unwrap();
|
||||
let b = es.require_attrs_select(&attrs, "b").unwrap();
|
||||
let i = es.require_int(&a).unwrap();
|
||||
assert_eq!(i, 1);
|
||||
let i = es.require_int(&b).unwrap();
|
||||
assert_eq!(i, 2);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn eval_state_new_value_attrs_from_hashmap() {
|
||||
gc_registering_current_thread(|| {
|
||||
let store = Store::open("auto", []).unwrap();
|
||||
let mut es = EvalState::new(store, []).unwrap();
|
||||
let attrs = {
|
||||
let a = es.new_value_int(1).unwrap();
|
||||
let b = es.new_value_int(2).unwrap();
|
||||
es.new_value_attrs(HashMap::from([("a".to_string(), a), ("b".to_string(), b)]))
|
||||
.unwrap()
|
||||
};
|
||||
let t = es.value_type(&attrs).unwrap();
|
||||
assert!(t == ValueType::AttrSet);
|
||||
let names = es.require_attrs_names(&attrs).unwrap();
|
||||
assert_eq!(names.len(), 2);
|
||||
assert_eq!(names[0], "a");
|
||||
assert_eq!(names[1], "b");
|
||||
let a = es.require_attrs_select(&attrs, "a").unwrap();
|
||||
let b = es.require_attrs_select(&attrs, "b").unwrap();
|
||||
let i = es.require_int(&a).unwrap();
|
||||
assert_eq!(i, 1);
|
||||
let i = es.require_int(&b).unwrap();
|
||||
assert_eq!(i, 2);
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue