feat: error handling

This commit is contained in:
2025-08-08 19:35:51 +08:00
parent a9cfddbf5c
commit fd182b6233
12 changed files with 187 additions and 311 deletions

View File

@@ -6,7 +6,7 @@ use std::rc::Rc;
use derive_more::Constructor;
use hashbrown::hash_map::Entry;
use hashbrown::{HashMap, HashSet};
use hashbrown::HashMap;
use itertools::Itertools;
use nixjit_error::{Error, Result};
@@ -66,12 +66,7 @@ impl AttrSet {
self.data.insert(sym, val);
}
/// Inserts an attribute.
///
/// # Panics
///
/// This method currently uses `todo!()` and will panic if the attribute
/// already exists, indicating that duplicate attribute handling is not yet implemented.
/// Inserts an attribute, returns an error if the attribute is already defined.
pub fn push_attr(&mut self, sym: String, val: Value) -> Result<()> {
match self.data.entry(sym) {
Entry::Occupied(occupied) => Err(Error::EvalError(format!(
@@ -114,17 +109,22 @@ impl AttrSet {
/// Checks if an attribute path exists within the set.
pub fn has_attr(
&self,
mut path: impl DoubleEndedIterator<Item = Result<String>>,
) -> Result<bool> {
mut path: impl DoubleEndedIterator<Item = Result<Value>>,
) -> Result<Value> {
let mut data = &self.data;
let last = path.nth_back(0).unwrap();
for item in path {
let Some(Value::AttrSet(attrs)) = data.get(&item?) else {
return Ok(false);
let Some(Value::AttrSet(attrs)) =
data.get(item.unwrap().coerce_to_string()?.as_ref().unwrap_string())
else {
return Ok(Value::Bool(false));
};
data = attrs.as_inner();
}
Ok(data.get(&last?).is_some())
Ok(Value::Bool(
data.get(last.unwrap().coerce_to_string()?.as_ref().unwrap_string())
.is_some(),
))
}
/// Merges another `AttrSet` into this one, with attributes from `other`
@@ -169,11 +169,11 @@ impl AttrSet {
}
/// Converts the `AttrSet` to its public-facing representation.
pub fn to_public(&self, seen: &mut HashSet<Value>) -> p::Value {
pub fn to_public(self) -> p::Value {
p::Value::AttrSet(p::AttrSet::new(
self.data
.iter()
.map(|(sym, value)| (sym.as_str().into(), value.to_public(seen)))
.into_iter()
.map(|(sym, value)| (sym.into(), value.to_public()))
.collect(),
))
}