difftreelog
refactor object builder
in: master
3 files changed
crates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/evaluate/mod.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate/mod.rs
@@ -2,14 +2,14 @@
error::Error::*,
evaluate::operator::{evaluate_add_op, evaluate_binary_op_special, evaluate_unary_op},
push, throw, with_state, ArrValue, Bindable, Context, ContextCreator, FuncDesc, FuncVal,
- FutureWrapper, LazyBinding, LazyVal, LazyValValue, ObjMember, ObjValue, ObjectAssertion,
+ FutureWrapper, LazyBinding, LazyVal, LazyValValue, ObjValue, ObjValueBuilder, ObjectAssertion,
Result, Val,
};
use jrsonnet_gc::{Gc, Trace};
use jrsonnet_interner::IStr;
use jrsonnet_parser::{
ArgsDesc, AssertStmt, BindSpec, CompSpec, Expr, ExprLocation, FieldMember, ForSpecData,
- IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc, Visibility,
+ IfSpecData, LiteralType, LocExpr, Member, ObjBody, ParamsDesc,
};
use jrsonnet_types::ValType;
use rustc_hash::{FxHashMap, FxHasher};
@@ -254,8 +254,7 @@
new_bindings.fill(bindings);
}
- let mut new_members = FxHashMap::default();
- let mut assertions: Vec<Box<dyn ObjectAssertion>> = Vec::new();
+ let mut builder = ObjValueBuilder::new();
for member in members.iter() {
match member {
Member::Field(FieldMember {
@@ -291,19 +290,16 @@
)?))
}
}
- new_members.insert(
- name.clone(),
- ObjMember {
- add: *plus,
- visibility: *visibility,
- invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjMemberBinding {
- context_creator: context_creator.clone(),
- value: value.clone(),
- name,
- }))),
- location: value.1.clone(),
- },
- );
+ builder
+ .member(name.clone())
+ .with_add(*plus)
+ .with_visibility(*visibility)
+ .with_location(value.1.clone())
+ .bindable(Box::new(ObjMemberBinding {
+ context_creator: context_creator.clone(),
+ value: value.clone(),
+ name,
+ }));
}
Member::Field(FieldMember {
name,
@@ -338,20 +334,16 @@
)))
}
}
- new_members.insert(
- name.clone(),
- ObjMember {
- add: false,
- visibility: Visibility::Hidden,
- invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjMemberBinding {
- context_creator: context_creator.clone(),
- value: value.clone(),
- params: params.clone(),
- name,
- }))),
- location: value.1.clone(),
- },
- );
+ builder
+ .member(name.clone())
+ .hide()
+ .with_location(value.1.clone())
+ .binding(LazyBinding::Bindable(Gc::new(Box::new(ObjMemberBinding {
+ context_creator: context_creator.clone(),
+ value: value.clone(),
+ params: params.clone(),
+ name,
+ }))));
}
Member::BindStmt(_) => {}
Member::AssertStmt(stmt) => {
@@ -371,14 +363,14 @@
evaluate_assert(ctx, &self.assert)
}
}
- assertions.push(Box::new(ObjectAssert {
+ builder.assert(Box::new(ObjectAssert {
context_creator: context_creator.clone(),
assert: stmt.clone(),
}));
}
}
}
- let this = ObjValue::new(None, Gc::new(new_members), Gc::new(assertions));
+ let this = builder.build();
future_this.fill(this.clone());
Ok(this)
}
@@ -388,7 +380,7 @@
ObjBody::MemberList(members) => evaluate_member_list_object(context, members)?,
ObjBody::ObjComp(obj) => {
let future_this = FutureWrapper::new();
- let mut new_members = FxHashMap::default();
+ let mut builder = ObjValueBuilder::new();
evaluate_comp(context.clone(), &obj.compspecs, &mut |ctx| {
let new_bindings = FutureWrapper::new();
let context_creator = ContextCreator(context.clone(), new_bindings.clone());
@@ -435,18 +427,13 @@
)?))
}
}
- new_members.insert(
- n,
- ObjMember {
- add: false,
- visibility: Visibility::Normal,
- invoke: LazyBinding::Bindable(Gc::new(Box::new(ObjCompBinding {
- context: ctx,
- value: obj.value.clone(),
- }))),
- location: obj.value.1.clone(),
- },
- );
+ builder
+ .member(n)
+ .with_location(obj.value.1.clone())
+ .bindable(Box::new(ObjCompBinding {
+ context: ctx,
+ value: obj.value.clone(),
+ }));
}
v => throw!(FieldMustBeStringGot(v.value_type())),
}
@@ -454,7 +441,7 @@
Ok(())
})?;
- let this = ObjValue::new(None, Gc::new(new_members), Gc::new(Vec::new()));
+ let this = builder.build();
future_this.fill(this.clone());
this
}
crates/jrsonnet-evaluator/src/integrations/serde.rsdiffbeforeafterboth1use crate::{1use crate::{2 error::{Error::*, LocError, Result},2 error::{Error::*, LocError, Result},3 throw, LazyBinding, LazyVal, ObjMember, ObjValue, Val,3 throw, ObjValueBuilder, Val,4};4};5use jrsonnet_gc::Gc;6use jrsonnet_parser::Visibility;7use rustc_hash::FxHasher;8use serde_json::{Map, Number, Value};5use serde_json::{Map, Number, Value};9use std::{6use std::convert::{TryFrom, TryInto};10 collections::HashMap,11 convert::{TryFrom, TryInto},12 hash::BuildHasherDefault,13};14715impl TryFrom<&Val> for Value {8impl TryFrom<&Val> for Value {16 type Error = LocError;9 type Error = LocError;54 Value::Number(n) => Self::Num(n.as_f64().expect("as f64")),47 Value::Number(n) => Self::Num(n.as_f64().expect("as f64")),55 Value::String(s) => Self::Str((s as &str).into()),48 Value::String(s) => Self::Str((s as &str).into()),56 Value::Array(a) => {49 Value::Array(a) => {57 let mut out = Vec::with_capacity(a.len());50 let mut out: Vec<Val> = Vec::with_capacity(a.len());58 for v in a {51 for v in a {59 out.push(LazyVal::new_resolved(v.into()));52 out.push(v.into());60 }53 }61 Self::Arr(out.into())54 Self::Arr(out.into())62 }55 }63 Value::Object(o) => {56 Value::Object(o) => {64 let mut entries = HashMap::with_capacity_and_hasher(57 let mut builder = ObjValueBuilder::with_capacity(o.len());65 o.len(),66 BuildHasherDefault::<FxHasher>::default(),67 );68 for (k, v) in o {58 for (k, v) in o {69 entries.insert(59 builder.member((k as &str).into()).value(v.into());70 (k as &str).into(),71 ObjMember {72 add: false,73 visibility: Visibility::Normal,74 invoke: LazyBinding::Bound(LazyVal::new_resolved(v.into())),75 location: None,76 },77 );78 }60 }79 Self::Obj(ObjValue::new(None, Gc::new(entries), Gc::new(Vec::new())))61 Val::Obj(builder.build())80 }62 }81 }63 }82 }64 }crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/obj.rs
+++ b/crates/jrsonnet-evaluator/src/obj.rs
@@ -1,9 +1,10 @@
use crate::operator::evaluate_add_op;
-use crate::{LazyBinding, Result, Val};
+use crate::{Bindable, LazyBinding, LazyVal, Result, Val};
use jrsonnet_gc::{Gc, GcCell, Trace};
use jrsonnet_interner::IStr;
use jrsonnet_parser::{ExprLocation, Visibility};
-use rustc_hash::{FxHashMap, FxHashSet};
+use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
+use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::{fmt::Debug, hash::BuildHasherDefault};
@@ -274,3 +275,98 @@
hasher.write_usize(&*self.0 as *const _ as usize)
}
}
+
+pub struct ObjValueBuilder {
+ super_obj: Option<ObjValue>,
+ map: FxHashMap<IStr, ObjMember>,
+ assertions: Vec<Box<dyn ObjectAssertion>>,
+}
+impl ObjValueBuilder {
+ pub fn new() -> Self {
+ Self::with_capacity(0)
+ }
+ pub fn with_capacity(capacity: usize) -> Self {
+ Self {
+ super_obj: None,
+ map: HashMap::with_capacity_and_hasher(
+ capacity,
+ BuildHasherDefault::<FxHasher>::default(),
+ ),
+ assertions: Vec::new(),
+ }
+ }
+ pub fn reserve_asserts(&mut self, capacity: usize) -> &mut Self {
+ self.assertions.reserve_exact(capacity);
+ self
+ }
+ pub fn with_super(&mut self, super_obj: ObjValue) -> &mut Self {
+ self.super_obj = Some(super_obj);
+ self
+ }
+
+ pub fn assert(&mut self, assertion: Box<dyn ObjectAssertion>) -> &mut Self {
+ self.assertions.push(assertion);
+ self
+ }
+ pub fn member(&mut self, name: IStr) -> ObjMemberBuilder {
+ ObjMemberBuilder {
+ value: self,
+ name,
+ add: false,
+ visibility: Visibility::Normal,
+ location: None,
+ }
+ }
+
+ pub fn build(self) -> ObjValue {
+ ObjValue::new(self.super_obj, Gc::new(self.map), Gc::new(self.assertions))
+ }
+}
+
+#[must_use = "value not added unless binding() was called"]
+pub struct ObjMemberBuilder<'v> {
+ value: &'v mut ObjValueBuilder,
+ name: IStr,
+ add: bool,
+ visibility: Visibility,
+ location: Option<ExprLocation>,
+}
+
+impl<'v> ObjMemberBuilder<'v> {
+ pub fn with_add(mut self, add: bool) -> Self {
+ self.add = add;
+ self
+ }
+ pub fn add(self) -> Self {
+ self.with_add(true)
+ }
+ pub fn with_visibility(mut self, visibility: Visibility) -> Self {
+ self.visibility = visibility;
+ self
+ }
+ pub fn hide(self) -> Self {
+ self.with_visibility(Visibility::Hidden)
+ }
+ pub fn with_location(mut self, location: Option<ExprLocation>) -> Self {
+ self.location = location;
+ self
+ }
+ pub fn value(self, value: Val) -> &'v mut ObjValueBuilder {
+ self.binding(LazyBinding::Bound(LazyVal::new_resolved(value)))
+ }
+ pub fn bindable(self, bindable: Box<dyn Bindable>) -> &'v mut ObjValueBuilder {
+ self.binding(LazyBinding::Bindable(Gc::new(bindable)))
+ }
+ pub fn binding(self, binding: LazyBinding) -> &'v mut ObjValueBuilder {
+ self.value.map.insert(
+ self.name,
+ ObjMember {
+ add: self.add,
+ visibility: self.visibility,
+ invoke: binding,
+ location: self.location,
+ },
+ );
+ self.value
+ }
+}