99 lines
2.3 KiB
Rust
99 lines
2.3 KiB
Rust
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<Self>;
|
|
fn child_at_index(&self, idx: usize) -> Option<Self>;
|
|
fn prune_object(&self, _keys: &HashSet<String>) {}
|
|
fn prune_array(&self, _indices: &HashSet<usize>) {}
|
|
}
|
|
|
|
#[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> {
|
|
self.0.get(key).map(ReadOnlyInstance)
|
|
}
|
|
|
|
fn child_at_index(&self, idx: usize) -> Option<Self> {
|
|
self.0.get(idx).map(ReadOnlyInstance)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct MutableInstance {
|
|
ptr: NonNull<Value>,
|
|
}
|
|
|
|
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<Self> {
|
|
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<Self> {
|
|
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<String>) {
|
|
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<usize>) {
|
|
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
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|