Skip to content

Commit

Permalink
impl map_index
Browse files Browse the repository at this point in the history
  • Loading branch information
karatakis committed Nov 29, 2024
1 parent 1917755 commit 6cfb972
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 11 deletions.
60 changes: 49 additions & 11 deletions tailcall-template/src/jq/jq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ where

fn from_map<I: IntoIterator<Item = (Self, Self)>>(iter: I) -> ValR<Self> {
iter.into_iter().fold(ValR::Ok(Self(JsonLike::object(JsonObjectLike::new()))), |acc, (key, value)| {
let key = match JsonLike::as_str(&key.0) {
Some(key) => key,
None => return ValR::Err(jaq_core::Error::str("Key cannot be converted to String")),
let Some(key) = JsonLike::as_str(&key.0) else {
return ValR::Err(jaq_core::Error::str("Key cannot be converted to String"))
};

match acc {
Expand All @@ -58,19 +57,17 @@ where

fn index(self, index: &Self) -> ValR<Self> {
if let Some(obj) = self.0.as_object() {
let key = match index.0.as_str() {
Some(key) => key,
None => return ValR::Err(jaq_core::Error::str("Key cannot be converted to String"))
let Some(key) = index.0.as_str() else {
return ValR::Err(jaq_core::Error::str("Key cannot be converted to String"))
};

match obj.get_key(key) {
Some(item) => ValR::Ok(JsonLikeHelper(item.clone())),
None => ValR::Ok(JsonLikeHelper(JsonLike::null())),
}
} else if let Some(arr) = self.0.as_array() {
let index: u64 = match index.0.as_u64() {
Some(item) => item,
None => return ValR::Err(jaq_core::Error::str("Index cannot be converted to u64"))
let Some(index) = index.0.as_u64() else {
return ValR::Err(jaq_core::Error::str("Index cannot be converted to u64"))
};

match arr.get(index as usize) {
Expand Down Expand Up @@ -134,12 +131,53 @@ where
}

fn map_index<'a, I: Iterator<Item = jaq_core::ValX<'a, Self>>>(
self,
mut self,
index: &Self,
opt: jaq_core::path::Opt,
f: impl Fn(Self) -> I,
) -> jaq_core::ValX<'a, Self> {
todo!()
if let Some(obj) = self.0.as_object_mut() {
let Some(key) = index.0.as_str() else {
return opt.fail(self, |_v| jaq_core::Exn::from(jaq_core::Error::str("Key cannot be converted to String")))
};

match obj.get_key(key) {
Some(e) => {
match f(JsonLikeHelper(e.clone())).next().transpose()? {
Some(value) => obj.insert_key(key, value.0),
None => {obj.remove_key(key);},
}
},
None => {
if let Some(value) = f(JsonLikeHelper(JsonLike::null())).next().transpose()? {
obj.insert_key(key, value.0);
}
},
}
Ok(self)
} else if let Some(arr) = self.0.as_array_mut() {
let Some(index) = index.0.as_u64() else {
return opt.fail(self, |_v| jaq_core::Exn::from(jaq_core::Error::str("Index cannot be converted to u64")))
};
let abs_or = |i| {
abs_index(i, arr.len()).ok_or(jaq_core::Error::str(format!("index {i} out of bounds")))
};
// TODO: perform error handling
let index = match abs_or(index.try_into().unwrap()) {
Ok(index) => index,
Err(e) => return opt.fail(self, |_v| jaq_core::Exn::from(e)),
};

let item = arr[index].clone();
if let Some(value) = f(JsonLikeHelper(item)).next().transpose()? {
arr[index] = value.0;
} else {
arr.remove(index);
}
Ok(self)
} else {
return opt.fail(self, |_v| jaq_core::Exn::from(jaq_core::Error::str("Value is not object or array")))
}
}

fn map_range<'a, I: Iterator<Item = jaq_core::ValX<'a, Self>>>(
Expand Down
5 changes: 5 additions & 0 deletions tailcall-template/src/jsonlike/borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ impl<'ctx> JsonObjectLike<'ctx> for ObjectAsVec<'ctx> {
fn insert_key(&mut self, key: &'ctx str, value: Self::Value) {
self.insert(key, value);
}

fn remove_key(&mut self, _key: &'ctx str) -> Option<Self::Value> {
// TODO: implement it
unimplemented!()
}
}

impl<'ctx> JsonLike<'ctx> for Value<'ctx> {
Expand Down
4 changes: 4 additions & 0 deletions tailcall-template/src/jsonlike/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ impl<'obj, Value: JsonLike<'obj> + Clone> JsonObjectLike<'obj> for IndexMap<Name
fn insert_key(&mut self, key: &'obj str, value: Self::Value) {
self.insert(Name::new(key), value);
}

fn remove_key(&mut self, key: &'obj str) -> Option<Self::Value> {
self.swap_remove(key)
}
}

impl<'json> JsonLike<'json> for ConstValue {
Expand Down
1 change: 1 addition & 0 deletions tailcall-template/src/jsonlike/json_like.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub trait JsonObjectLike<'obj>: Sized {
fn with_capacity(n: usize) -> Self;
fn get_key(&self, key: &str) -> Option<&Self::Value>;
fn insert_key(&mut self, key: &'obj str, value: Self::Value);
fn remove_key(&mut self, key: &'obj str) -> Option<Self::Value>;
}

#[cfg(test)]
Expand Down
4 changes: 4 additions & 0 deletions tailcall-template/src/jsonlike/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ impl<'obj> JsonObjectLike<'obj> for serde_json::Map<String, serde_json::Value> {
fn insert_key(&mut self, key: &'obj str, value: Self::Value) {
self.insert(key.to_owned(), value);
}

fn remove_key(&mut self, key: &'obj str) -> Option<Self::Value> {
self.remove(key)
}
}

impl<'json> JsonLike<'json> for serde_json::Value {
Expand Down

0 comments on commit 6cfb972

Please sign in to comment.