use serde_json::Value; use HashSet; use std::ptr::NonNull; pub trait ValidationInstance<'a>: Copy + Clone { fn as_value(&self) -> &'a Value; fn child_at_key(&self, key: &str) -> Option; fn child_at_index(&self, idx: usize) -> Option; fn prune_object(&self, _keys: &HashSet) {} fn prune_array(&self, _indices: &HashSet) {} } #[derive(Clone, Copy)] pub struct ReadOnlyInstance<'a>(pub &'a Value); impl<'a> ValidationInstance<'a> for ReadOnlyInstance<'a> { fn as_value(&self) -> &'a Value { self.0 } fn child_at_key(&self, key: &str) -> Option { self.0.get(key).map(ReadOnlyInstance) } fn child_at_index(&self, idx: usize) -> Option { self.0.get(idx).map(ReadOnlyInstance) } } #[derive(Clone, Copy)] pub struct MutableInstance { ptr: NonNull, } impl MutableInstance { pub fn new(val: &mut Value) -> Self { Self { ptr: NonNull::from(val), } } } impl<'a> ValidationInstance<'a> for MutableInstance { fn as_value(&self) -> &'a Value { unsafe { self.ptr.as_ref() } } fn child_at_key(&self, key: &str) -> Option { unsafe { if let Some(obj) = self.ptr.as_ref().as_object() { if obj.contains_key(key) { let parent_mut = &mut *self.ptr.as_ptr(); if let Some(child_val) = parent_mut.get_mut(key) { return Some(MutableInstance::new(child_val)); } } } None } } fn child_at_index(&self, idx: usize) -> Option { unsafe { if let Some(arr) = self.ptr.as_ref().as_array() { if idx < arr.len() { let parent_mut = &mut *self.ptr.as_ptr(); if let Some(child_val) = parent_mut.get_mut(idx) { return Some(MutableInstance::new(child_val)); } } } None } } fn prune_object(&self, keys: &HashSet) { unsafe { let val_mut = &mut *self.ptr.as_ptr(); if let Some(obj) = val_mut.as_object_mut() { obj.retain(|k, _| keys.contains(k)); } } } fn prune_array(&self, indices: &HashSet) { unsafe { let val_mut = &mut *self.ptr.as_ptr(); if let Some(arr) = val_mut.as_array_mut() { let mut i = 0; arr.retain(|_| { let keep = indices.contains(&i); i += 1; keep }); } } } }