1use crate::{dummy_debug, evaluate_binary_op, BoxedBinding, Val};2use jsonnet_parser::{BinaryOpType, Visibility};3use std::{4 collections::{BTreeMap, BTreeSet},5 rc::Rc,6};78#[derive(Debug)]9pub struct ObjMember {10 pub add: bool,11 pub visibility: Visibility,12 pub invoke: BoxedBinding,13}1415#[derive(Debug)]16pub struct ObjValueInternals {17 super_obj: Option<ObjValue>,18 this_entries: Rc<BTreeMap<String, ObjMember>>,19}20pub struct ObjValue(Rc<ObjValueInternals>);21dummy_debug!(ObjValue);22impl ObjValue {23 pub fn new(24 super_obj: Option<ObjValue>,25 this_entries: Rc<BTreeMap<String, ObjMember>>,26 ) -> ObjValue {27 ObjValue(Rc::new(ObjValueInternals {28 super_obj,29 this_entries,30 }))31 }32 pub fn with_super(&self, super_obj: ObjValue) -> ObjValue {33 match &self.0.super_obj {34 None => ObjValue::new(Some(super_obj), self.0.this_entries.clone()),35 Some(v) => ObjValue::new(Some(v.with_super(super_obj)), self.0.this_entries.clone()),36 }37 }38 pub fn fields(&self) -> BTreeSet<String> {39 let mut fields = BTreeSet::new();40 self.0.this_entries.keys().for_each(|k| {41 fields.insert(k.clone());42 });43 if self.0.super_obj.is_some() {44 for field in self.0.super_obj.clone().unwrap().fields() {45 fields.insert(field);46 }47 }48 fields49 }50 pub fn get_raw(&self, key: &str, real_this: Option<ObjValue>) -> Option<Val> {51 match (self.0.this_entries.get(key), &self.0.super_obj) {52 (Some(k), None) => Some(k.invoke.evaluate(53 real_this.or_else(|| Some(self.clone())),54 self.0.super_obj.clone().map(|e| e.clone()),55 )),56 (Some(k), Some(s)) => {57 let our = k58 .invoke59 .evaluate(Some(self.clone()), self.0.super_obj.clone());60 if k.add {61 s.get_raw(key, Some(self.clone()))62 .map_or(Some(our.clone()), |v| {63 Some(evaluate_binary_op(&v, BinaryOpType::Add, &our))64 })65 } else {66 Some(our)67 }68 }69 (None, Some(s)) => s.get_raw(key, Some(self.clone())),70 (None, None) => None,71 }72 }73}74impl Clone for ObjValue {75 fn clone(&self) -> Self {76 ObjValue(self.0.clone())77 }78}79impl PartialEq for ObjValue {80 fn eq(&self, other: &Self) -> bool {81 Rc::ptr_eq(&self.0, &other.0)82 }83}