difftreelog
fix objectRemoveKey only skips the current stack
in: master
1 file changed
crates/jrsonnet-evaluator/src/obj.rsdiffbeforeafterboth5 fmt::{self, Debug},5 fmt::{self, Debug},6 hash::{Hash, Hasher},6 hash::{Hash, Hasher},7 mem,7 mem,8 num::Saturating,8 ops::ControlFlow,9 ops::ControlFlow,9};10};101148 impl SuperDepth {49 impl SuperDepth {49 pub(super) fn deepen(self) {}50 pub(super) fn deepen(self) {}50 }51 }5152 #[derive(Clone, Copy, Debug)]53 pub struct FieldSortKey(());54 impl FieldSortKey {55 pub const fn new(_: SuperDepth, _: FieldIndex) -> Self {56 Self(())57 }58 }59}52}605361#[cfg(feature = "exp-preserve-order")]54#[cfg(feature = "exp-preserve-order")]89 }82 }90}83}918485#[cfg(feature = "exp-preserve-order")]92use ordering::{FieldIndex, FieldSortKey, SuperDepth};86use ordering::FieldSortKey;87use ordering::{FieldIndex, SuperDepth};938894// 0 - add89// 0 - add95// 12 - visibility90// 12 - visibility177172178pub enum EnumFields {173pub enum EnumFields {179 Normal(Visibility),174 Normal(Visibility),180 Omit,175 Omit(Skip),181}176}182177183#[derive(Trace, Clone)]178#[derive(Trace, Clone)]187 // Continue iterating over cores, add current value to sum stack182 // Continue iterating over cores, add current value to sum stack188 SuperPlus(Val),183 SuperPlus(Val),189 // Ignore the field value, stop at this layer instead184 // Ignore the field value, stop at this layer instead190 Omit,185 Omit(#[trace(skip)] Skip),191 NotFound,186 NotFound,192}187}193188194#[derive(Acyclic, Clone)]189#[derive(Acyclic, Clone)]195pub enum FieldVisibility {190pub enum FieldVisibility {196 Found(Visibility),191 Found(Visibility),197 Omit,192 Omit(Skip),198 NotFound,193 NotFound,199}194}200195201#[derive(Acyclic, Clone)]196#[derive(Acyclic, Clone)]202pub enum HasFieldIncludeHidden {197pub enum HasFieldIncludeHidden {203 Exists,198 Exists,204 NotFound,199 NotFound,205 Omit,200 Omit(Skip),206}201}207202203type Skip = Saturating<usize>;204208pub trait ObjectCore: Trace + Any + Debug {205pub trait ObjectCore: Trace + Any + Debug {209 // If callback returns false, iteration stops, and this call returns false.206 // If callback returns false, iteration stops, and this call returns false.210 fn enum_fields_core(207 fn enum_fields_core(215212216 fn has_field_include_hidden_core(&self, name: IStr) -> HasFieldIncludeHidden;213 fn has_field_include_hidden_core(&self, name: IStr) -> HasFieldIncludeHidden;217214218 fn get_for_core(&self, key: IStr, sup_this: SupThis) -> Result<GetFor>;215 fn get_for_core(&self, key: IStr, sup_this: SupThis, omit_only: bool) -> Result<GetFor>;219 fn field_visibility_core(&self, field: IStr) -> FieldVisibility;216 fn field_visibility_core(&self, field: IStr) -> FieldVisibility;220217221 fn run_assertions_core(&self, sup_this: SupThis) -> Result<()>;218 fn run_assertions_core(&self, sup_this: SupThis) -> Result<()>;323 }320 }324 }321 }325322326 fn get_for_core(&self, key: IStr, _sup_this: SupThis) -> Result<GetFor> {323 fn get_for_core(&self, key: IStr, _sup_this: SupThis, omit_only: bool) -> Result<GetFor> {324 if omit_only {325 return Ok(GetFor::NotFound);326 }327 let v = self.this.get_idx(key, self.sup)?;327 let v = self.this.get_idx(key, self.sup)?;328 Ok(v.map_or(GetFor::NotFound, |v| GetFor::Final(v)))328 Ok(v.map_or(GetFor::NotFound, |v| GetFor::Final(v)))329 }329 }343#[derive(Debug, Acyclic)]343#[derive(Debug, Acyclic)]344struct OmitFieldsCore {344struct OmitFieldsCore {345 omit: FxHashSet<IStr>,345 omit: FxHashSet<IStr>,346 prev_layers: usize,346}347}347impl ObjectCore for OmitFieldsCore {348impl ObjectCore for OmitFieldsCore {348 fn enum_fields_core(349 fn enum_fields_core(352 ) -> bool {353 ) -> bool {353 let mut fi = FieldIndex::default();354 let mut fi = FieldIndex::default();354 for f in &self.omit {355 for f in &self.omit {355 if let ControlFlow::Break(()) = handler(*super_depth, fi, f.clone(), EnumFields::Omit) {356 if let ControlFlow::Break(()) = handler(357 *super_depth,358 fi,359 f.clone(),360 EnumFields::Omit(Saturating(self.prev_layers)),361 ) {356 return false;362 return false;357 }363 }358 fi = fi.next();364 fi = fi.next();362368363 fn has_field_include_hidden_core(&self, name: IStr) -> HasFieldIncludeHidden {369 fn has_field_include_hidden_core(&self, name: IStr) -> HasFieldIncludeHidden {364 if self.omit.contains(&name) {370 if self.omit.contains(&name) {365 return HasFieldIncludeHidden::Omit;371 return HasFieldIncludeHidden::Omit(Saturating(self.prev_layers));366 }372 }367 HasFieldIncludeHidden::NotFound373 HasFieldIncludeHidden::NotFound368 }374 }369375370 fn get_for_core(&self, key: IStr, _sup_this: SupThis) -> Result<GetFor> {376 fn get_for_core(&self, key: IStr, _sup_this: SupThis, _omit_only: bool) -> Result<GetFor> {371 if self.omit.contains(&key) {377 if self.omit.contains(&key) {372 return Ok(GetFor::Omit);378 return Ok(GetFor::Omit(Saturating(self.prev_layers)));373 }379 }374 Ok(GetFor::NotFound)380 Ok(GetFor::NotFound)375 }381 }376382377 fn field_visibility_core(&self, field: IStr) -> FieldVisibility {383 fn field_visibility_core(&self, field: IStr) -> FieldVisibility {378 if self.omit.contains(&field) {384 if self.omit.contains(&field) {379 return FieldVisibility::Omit;385 return FieldVisibility::Omit(Saturating(self.prev_layers));380 }386 }381 FieldVisibility::NotFound387 FieldVisibility::NotFound382 }388 }503 /// If object only contains hidden fields - may return zero.509 /// If object only contains hidden fields - may return zero.504 pub fn len(&self) -> usize {510 pub fn len(&self) -> usize {505 self.fields_visibility()511 self.fields_visibility()506 .iter()512 .values()507 .filter(|(_, (visible, _))| *visible)513 .filter(|d| d.visible())508 .count()514 .count()509 }515 }510 /// For each field, calls callback.516 /// For each field, calls callback.527 handler: &mut EnumFieldsHandler<'_>,533 handler: &mut EnumFieldsHandler<'_>,528 idx: CoreIdx,534 idx: CoreIdx,529 ) -> bool {535 ) -> bool {530 for core in self.0.cores[..idx.idx].iter() {536 for core in self.0.cores[..idx.idx].iter().rev() {531 if !core.0.enum_fields_core(super_depth, handler) {537 if !core.0.enum_fields_core(super_depth, handler) {532 return false;538 return false;533 }539 }545 )551 )546 }552 }547 fn has_field_include_hidden_idx(&self, name: IStr, core: CoreIdx) -> bool {553 fn has_field_include_hidden_idx(&self, name: IStr, core: CoreIdx) -> bool {554 let mut skip = Saturating(0usize);548 for ele in self.0.cores[..core.idx].iter().rev() {555 for ele in self.0.cores[..core.idx].iter().rev() {549 match ele.0.has_field_include_hidden_core(name.clone()) {556 match ele.0.has_field_include_hidden_core(name.clone()) {550 HasFieldIncludeHidden::Exists => return true,557 HasFieldIncludeHidden::Exists => {558 if skip.0 == 0 {559 return true;560 }561 }562 HasFieldIncludeHidden::Omit(new_skip) => {563 // +1 including this core564 skip = skip.max(new_skip + Saturating(1));565 }551 HasFieldIncludeHidden::NotFound => {}566 HasFieldIncludeHidden::NotFound => {}552 HasFieldIncludeHidden::Omit => break,553 }567 }568 skip -= 1;554 }569 }555 false570 false556 }571 }605 fn get_idx_uncached(&self, key: IStr, core: CoreIdx) -> Result<Option<Val>> {620 fn get_idx_uncached(&self, key: IStr, core: CoreIdx) -> Result<Option<Val>> {606 self.run_assertions()?;621 self.run_assertions()?;607 let mut add_stack = Vec::with_capacity(2);622 let mut add_stack = Vec::with_capacity(2);623 let mut skip = Saturating(0);608 for (sup, core) in self.0.cores[..core.idx].iter().enumerate().rev() {624 for (sup, core) in self.0.cores[..core.idx].iter().enumerate().rev() {609 let sup_this = SupThis {625 let sup_this = SupThis {610 sup: CoreIdx { idx: sup },626 sup: CoreIdx { idx: sup },611 this: self.clone(),627 this: self.clone(),612 };628 };613 match core.0.get_for_core(key.clone(), sup_this)? {629 match core.0.get_for_core(key.clone(), sup_this, skip.0 != 0)? {614 GetFor::Final(val) if add_stack.is_empty() => return Ok(Some(val)),630 GetFor::Final(val) if add_stack.is_empty() => {631 if skip.0 == 0 {632 return Ok(Some(val));633 }634 }615 GetFor::Final(val) => {635 GetFor::Final(val) => {616 add_stack.push(val);636 if skip.0 == 0 {637 add_stack.push(val);617 break;638 break;639 }618 }640 }619 GetFor::SuperPlus(val) => {641 GetFor::SuperPlus(val) => {620 add_stack.push(val);642 if skip.0 == 0 {643 add_stack.push(val);644 }621 }645 }622 GetFor::Omit => {646 GetFor::Omit(new_skip) => {623 break;647 // +1 including this core648 skip = skip.max(new_skip + Saturating(1));624 }649 }625 GetFor::NotFound => {650 GetFor::NotFound => {}626 continue;627 }628 }651 }652 skip -= 1;629 }653 }630 if add_stack.is_empty() {654 if add_stack.is_empty() {631 // None of layers had this field655 // None of layers had this field663 }687 }664 fn field_visibility_idx(&self, field: IStr, core: CoreIdx) -> Option<Visibility> {688 fn field_visibility_idx(&self, field: IStr, core: CoreIdx) -> Option<Visibility> {665 let mut exists = false;689 let mut exists = false;690 let mut skip = Saturating(0usize);666 for ele in self.0.cores[..core.idx].iter().rev() {691 for ele in self.0.cores[..core.idx].iter().rev() {667 let vis = ele.0.field_visibility_core(field.clone());692 let vis = ele.0.field_visibility_core(field.clone());668 match vis {693 match vis {669 FieldVisibility::Found(vis @ (Visibility::Unhide | Visibility::Hidden)) => {694 FieldVisibility::Found(vis @ (Visibility::Unhide | Visibility::Hidden)) => {670 return Some(vis)695 if skip.0 == 0 {696 return Some(vis);697 }671 }698 }672 FieldVisibility::Found(Visibility::Normal) => exists = true,699 FieldVisibility::Found(Visibility::Normal) => {700 if skip.0 == 0 {701 exists = true702 }703 }673 FieldVisibility::NotFound => {}704 FieldVisibility::NotFound => {}674 FieldVisibility::Omit => break,705 FieldVisibility::Omit(new_skip) => {706 // +1 including this core707 skip = skip.max(new_skip + Saturating(1));708 }675 }709 }710 skip -= 1;676 }711 }677 exists.then_some(Visibility::Normal)712 exists.then_some(Visibility::Normal)678 }713 }732 pub fn downgrade(self) -> WeakObjValue {767 pub fn downgrade(self) -> WeakObjValue {733 WeakObjValue(self.0.downgrade())768 WeakObjValue(self.0.downgrade())734 }769 }770}771772#[derive(Debug)]773struct FieldVisibilityData {735 fn fields_visibility(&self) -> FxHashMap<IStr, (bool, FieldSortKey)> {774 omitted_until: Saturating<usize>,775 exists_visible: Option<Visibility>,776 #[cfg(feature = "exp-preserve-order")]777 key: FieldSortKey,778}779impl FieldVisibilityData {780 fn visible(&self) -> bool {781 self.exists_visible782 .expect("non-existing fields shall be dropped at the end of fn fields_visibility()")783 .is_visible()784 }785 #[cfg(feature = "exp-preserve-order")]786 fn sort_key(&self) -> FieldSortKey {787 self.key788 }789}790791impl ObjValue {792 fn fields_visibility(&self) -> FxHashMap<IStr, FieldVisibilityData> {736 let mut out = FxHashMap::default();793 let mut out = FxHashMap::default();794737 self.enum_fields(&mut |depth, index, name, visibility| {795 let mut super_depth = SuperDepth::default();796 let mut omit_index = Saturating(0);797 for core in self.0.cores.iter().rev() {798 core.0799 .enum_fields_core(&mut super_depth, &mut |_depth, _index, name, visibility| {738 let new_sort_key = FieldSortKey::new(depth, index);800 let entry = out.entry(name);739 let entry = out.entry(name);801 let data = entry.or_insert(FieldVisibilityData {802 exists_visible: None,803 #[cfg(feature = "exp-preserve-order")]740 if matches!(visibility, EnumFields::Omit) {804 key: FieldSortKey::new(_depth, _index),805 omitted_until: omit_index,806 });807 match visibility {741 if let Entry::Occupied(v) = entry {808 EnumFields::Omit(new_skip) => {742 v.remove();809 // +1 including this core810 data.omitted_until = data743 }811 .omitted_until744 return ControlFlow::Continue(());812 .max(omit_index + new_skip + Saturating(1));745 }813 }746 let (visible, _) = entry.or_insert((true, new_sort_key));814 EnumFields::Normal(Visibility::Normal) => {815 if data.omitted_until <= omit_index {747 match visibility {816 if data.exists_visible.is_none() {748 EnumFields::Omit => unreachable!(),817 data.exists_visible = Some(Visibility::Normal);749 EnumFields::Normal(Visibility::Normal) => {}818 }819 }820 }821 EnumFields::Normal(Visibility::Hidden) => {750 EnumFields::Normal(Visibility::Hidden) => {822 if data.omitted_until <= omit_index {823 data.exists_visible = Some(match data.exists_visible {824 // We're iterating in reverse, later unhide is preserved825 Some(Visibility::Unhide) => Visibility::Unhide,751 *visible = false;826 _ => Visibility::Hidden,827 });752 }828 }753 EnumFields::Normal(Visibility::Unhide) => {829 }830 EnumFields::Normal(Visibility::Unhide) => {754 *visible = true;831 if data.omitted_until <= omit_index {832 data.exists_visible = Some(match data.exists_visible {833 // We're iterating in reverse, later hide is preserved834 Some(Visibility::Hidden) => Visibility::Hidden,835 _ => Visibility::Unhide,836 });755 }837 }756 };838 }839 };757 return ControlFlow::Continue(());840 return ControlFlow::Continue(());758 });841 });842843 super_depth.deepen();844 omit_index += 1;845 }846847 out.retain(|_, v| v.exists_visible.is_some());848759 out849 out760 }850 }768 let (mut fields, mut keys): (Vec<_>, Vec<_>) = self858 let (mut fields, mut keys): (Vec<_>, Vec<_>) = self769 .fields_visibility()859 .fields_visibility()770 .into_iter()860 .into_iter()771 .filter(|(_, (visible, _))| include_hidden || *visible)861 .filter(|(_, d)| include_hidden || d.visible())772 .enumerate()862 .enumerate()773 .map(|(idx, (k, (_, sk)))| (k, (sk, idx)))863 .map(|(idx, (k, d))| (k, (d.sort_key(), idx)))774 .unzip();864 .unzip();775 keys.sort_unstable_by_key(|v| v.0);865 keys.sort_unstable_by_key(|v| v.0);776 // Reorder in-place by resulting indexes866 // Reorder in-place by resulting indexes794 let mut fields: Vec<_> = self884 let mut fields: Vec<_> = self795 .fields_visibility()885 .fields_visibility()796 .into_iter()886 .into_iter()797 .filter(|(_, (visible, _))| include_hidden || *visible)887 .filter(|(_, d)| include_hidden || d.visible())798 .map(|(k, _)| k)888 .map(|(k, _)| k)799 .collect();889 .collect();800 fields.sort_unstable();890 fields.sort_unstable();896 }986 }897 }987 }898988899 fn get_for_core(&self, key: IStr, sup_this: SupThis) -> Result<GetFor> {989 fn get_for_core(&self, key: IStr, sup_this: SupThis, omit_only: bool) -> Result<GetFor> {990 if omit_only {991 return Ok(GetFor::NotFound);992 }900 match self.this_entries.get(&key) {993 match self.this_entries.get(&key) {901 Some(k) => {994 Some(k) => {902 let v = k.invoke.evaluate(sup_this)?;995 let v = k.invoke.evaluate(sup_this)?;100110941002 pub fn with_fields_omitted(&mut self, omit: FxHashSet<IStr>) {1095 pub fn with_fields_omitted(&mut self, omit: FxHashSet<IStr>) {1003 self.commit();1096 self.commit();1004 self.sup.push(CcObjectCore::new(OmitFieldsCore { omit }));1097 self.sup.push(CcObjectCore::new(OmitFieldsCore {1098 omit,1099 prev_layers: self.sup.len(),1100 }));1005 }1101 }100611021007 pub fn build(mut self) -> ObjValue {1103 pub fn build(mut self) -> ObjValue {