Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
drmorr0 committed Sep 23, 2024
1 parent a6f3ca2 commit 01b860c
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 3 deletions.
5 changes: 5 additions & 0 deletions sk-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod check;
mod completions;
mod crd;
mod delete;
Expand Down Expand Up @@ -27,6 +28,9 @@ struct SkCommandRoot {
#[derive(Subcommand)]
#[allow(clippy::large_enum_variant)]
enum SkSubcommand {
#[command(about = "check trace file for issues")]
CheckTrace(check::Args),

#[command(about = "generate shell completions for skctl")]
Completions(completions::Args),

Expand Down Expand Up @@ -54,6 +58,7 @@ async fn main() -> EmptyResult {
let args = SkCommandRoot::parse();

match &args.subcommand {
SkSubcommand::CheckTrace(args) => check::cmd(args),
SkSubcommand::Completions(args) => completions::cmd(args, SkCommandRoot::command()),
SkSubcommand::Crd => crd::cmd(),
SkSubcommand::Export(args) => export::cmd(args).await,
Expand Down
49 changes: 46 additions & 3 deletions sk-core/src/jsonutils/patch_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ pub fn add(path: &str, key: &str, value: &Value, obj: &mut Value, overwrite: boo
Ok(())
}

// pub fn list(path: &str, key: &str, obj: &Value) -> anyhow::Result<Vec<Value>> {
// let parts: Vec<_> = path.split('*').collect();
// patch_ext_helper(&parts, obj)
// .ok_or(JsonPatchError::invalid_pointer(path))?
// .iter()
// .map(|v| v.as_object().ok_or(JsonPatchError::unexpected_type(path)).map(|o| o.get(key)))
// }

pub fn remove(path: &str, key: &str, obj: &mut Value) -> EmptyResult {
let parts: Vec<_> = path.split('*').collect();
for v in patch_ext_helper(&parts, obj).ok_or(JsonPatchError::invalid_pointer(path))? {
Expand All @@ -74,22 +82,57 @@ pub fn remove(path: &str, key: &str, obj: &mut Value) -> EmptyResult {
Ok(())
}

trait MaybeMutableJsonValue: Sized {
type ArrayType: IntoIterator;

fn ptr(self, pointer: &str) -> Option<Self>;
fn arr(self) -> Option<Self::ArrayType>;
}

impl<'a> MaybeMutableJsonValue for &'a Value {
type ArrayType = &'a Vec<Value>;

fn ptr(self, pointer: &str) -> Option<Self> {
self.pointer(pointer)
}

fn arr(self) -> Option<Self::ArrayType> {
self.as_array()
}
}

impl<'a> MaybeMutableJsonValue for &'a mut Value {
type ArrayType = &'a mut Vec<Value>;

fn ptr(self, pointer: &str) -> Option<Self> {
self.pointer_mut(pointer)
}

fn arr(self) -> Option<Self::ArrayType> {
self.as_array_mut()
}
}


// Given a list of "path parts", i.e., paths split by `*`, recursively walk through all the
// possible "end" values that the path references; return a mutable reference so we can make
// modifications at those points. We assume that this function is never called with an empty
// `parts` array, which is valid in normal use since "some_string".split('*') will return
// ["some_string"].
fn patch_ext_helper<'a>(parts: &[&str], value: &'a mut Value) -> Option<Vec<&'a mut Value>> {
fn patch_ext_helper<'a, T: MaybeMutableJsonValue>(parts: &[&str], value: T) -> Option<Vec<T>>
where
<<T as MaybeMutableJsonValue>::ArrayType as IntoIterator>::Item: MaybeMutableJsonValue,
{
if parts.len() == 1 {
return Some(vec![value.pointer_mut(parts[0])?]);
return Some(vec![value.ptr(parts[0])?]);
}

let mut res = vec![];

// If there was an array value, e.g., /foo/bar/*/baz, our path parts will look like
// /foo/bar/ and /baz; so we need to strip off the trailing '/' in our first part
let len = parts[0].len();
let next_array_val = value.pointer_mut(&parts[0][..len - 1])?.as_array_mut()?;
let next_array_val = value.ptr(&parts[0][..len - 1])?.arr()?;
for v in next_array_val {
let cons = patch_ext_helper(&parts[1..], v)?;
res.extend(cons);
Expand Down

0 comments on commit 01b860c

Please sign in to comment.