Add system-query

This commit is contained in:
2023-09-06 13:45:25 +01:00
parent 4df6c19248
commit a0f1031b85
18 changed files with 792 additions and 12 deletions

View File

@ -0,0 +1,180 @@
use itertools::Itertools;
use crate::FlatReqFilter;
pub fn diff_filter(prev: &Vec<FlatReqFilter>, next: &Vec<FlatReqFilter>) -> Vec::<FlatReqFilter> {
let mut added: Vec::<FlatReqFilter> = vec![];
for n in next.iter() {
if !prev.iter().contains(&n) {
added.push(n.clone())
}
}
added
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simple_diff_same() {
let prev = vec![
FlatReqFilter {
id: Some("a".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
}
];
let next = vec![
FlatReqFilter {
id: Some("a".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
}
];
let result = diff_filter(&prev, &next);
assert_eq!(result, vec![])
}
#[test]
fn simple_diff_add() {
let prev = vec![
FlatReqFilter {
id: Some("a".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
}
];
let next = vec![
FlatReqFilter {
id: Some("a".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
},
FlatReqFilter {
id: Some("b".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
},
];
let result = diff_filter(&prev, &next);
assert_eq!(result, vec![
FlatReqFilter {
id: Some("b".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
}
])
}
#[test]
fn simple_diff_replace() {
let prev = vec![
FlatReqFilter {
id: Some("a".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
}
];
let next = vec![
FlatReqFilter {
id: Some("b".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
},
];
let result = diff_filter(&prev, &next);
assert_eq!(result, vec![
FlatReqFilter {
id: Some("b".to_owned()),
author: None,
kind: None,
e_tag: None,
p_tag: None,
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: None,
until: None,
limit: None,
}
])
}
}

View File

@ -0,0 +1,182 @@
use itertools::Itertools;
use crate::{FlatReqFilter, ReqFilter};
#[derive(Clone)]
enum StringOrNumberEntry<'a> {
String((&'static str, &'a String)),
Number((&'static str, &'a i32)),
}
pub fn expand_filter(filter: &ReqFilter) -> Vec<FlatReqFilter> {
let mut ret: Vec<FlatReqFilter> = Vec::new();
let mut inputs: Vec<Vec<StringOrNumberEntry>> = vec![];
if let Some(ids) = &filter.ids {
let t_ids = ids.iter().map(|z| StringOrNumberEntry::String(("id", z))).collect_vec();
inputs.push(t_ids);
}
if let Some(authors) = &filter.authors {
let t_ids = authors.iter().map(|z| StringOrNumberEntry::String(("author", z))).collect_vec();
inputs.push(t_ids);
}
if let Some(kinds) = &filter.kinds {
let t_ids = kinds.iter().map(|z| StringOrNumberEntry::Number(("kind", z))).collect_vec();
inputs.push(t_ids);
}
if let Some(e_tags) = &filter.e_tag {
let t_ids = e_tags.iter().map(|z| StringOrNumberEntry::String(("e_tag", z))).collect_vec();
inputs.push(t_ids);
}
if let Some(p_tags) = &filter.p_tag {
let t_ids = p_tags.iter().map(|z| StringOrNumberEntry::String(("p_tag", z))).collect_vec();
inputs.push(t_ids);
}
if let Some(d_tags) = &filter.d_tag {
let t_ids = d_tags.iter().map(|z| StringOrNumberEntry::String(("d_tag", z))).collect_vec();
inputs.push(t_ids);
}
if let Some(t_tags) = &filter.t_tag {
let t_ids = t_tags.iter().map(|z| StringOrNumberEntry::String(("t_tag", z))).collect_vec();
inputs.push(t_ids);
}
if let Some(r_tags) = &filter.r_tag {
let t_ids = r_tags.iter().map(|z| StringOrNumberEntry::String(("r_tag", z))).collect_vec();
inputs.push(t_ids);
}
if let Some(search) = &filter.search {
let t_ids = search.iter().map(|z| StringOrNumberEntry::String(("search", z))).collect_vec();
inputs.push(t_ids);
}
for p in inputs.iter().multi_cartesian_product() {
ret.push(FlatReqFilter {
id: p.iter().find_map(|q| {
if let StringOrNumberEntry::String((k, v)) = q {
if (*k).eq("id") {
return Some((*v).to_string());
}
}
None
}),
author: p.iter().find_map(|q| {
if let StringOrNumberEntry::String((k, v)) = q {
if (*k).eq("author") {
return Some((*v).to_string());
}
}
None
}),
kind: p.iter().find_map(|q| {
if let StringOrNumberEntry::Number((k, v)) = q {
if (*k).eq("kind") {
return Some((*v).clone());
}
}
None
}),
e_tag: p.iter().find_map(|q| {
if let StringOrNumberEntry::String((k, v)) = q {
if (*k).eq("e_tag") {
return Some((*v).to_string());
}
}
None
}),
p_tag: p.iter().find_map(|q| {
if let StringOrNumberEntry::String((k, v)) = q {
if (*k).eq("p_tag") {
return Some((*v).to_string());
}
}
None
}),
t_tag: p.iter().find_map(|q| {
if let StringOrNumberEntry::String((k, v)) = q {
if (*k).eq("t_tag") {
return Some((*v).to_string());
}
}
None
}),
d_tag: p.iter().find_map(|q| {
if let StringOrNumberEntry::String((k, v)) = q {
if (*k).eq("d_tag") {
return Some((*v).to_string());
}
}
None
}),
r_tag: p.iter().find_map(|q| {
if let StringOrNumberEntry::String((k, v)) = q {
if (*k).eq("r_tag") {
return Some((*v).to_string());
}
}
None
}),
search: p.iter().find_map(|q| {
if let StringOrNumberEntry::String((k, v)) = q {
if (*k).eq("search") {
return Some((*v).to_string());
}
}
None
}),
since: filter.since,
until: filter.until,
limit: filter.limit,
})
}
ret
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ReqFilter;
#[test]
fn test_expand_filter() {
let input = ReqFilter {
authors: Some(vec!["a".to_owned(), "b".to_owned(), "c".to_owned()]),
kinds: Some(vec![1, 2, 3]),
ids: Some(vec!["x".to_owned(), "y".to_owned()]),
p_tag: Some(vec!["a".to_owned()]),
t_tag: None,
d_tag: None,
r_tag: None,
search: None,
since: Some(99),
until: None,
limit: Some(10),
e_tag: None,
};
let output = expand_filter(&input);
output.iter().take(5).for_each(|x| println!("{:?}", x));
let expected = vec![
FlatReqFilter { author: Some("a".to_owned()), kind: Some(1), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("a".to_owned()), kind: Some(1), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("a".to_owned()), kind: Some(2), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("a".to_owned()), kind: Some(2), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("a".to_owned()), kind: Some(3), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("a".to_owned()), kind: Some(3), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("b".to_owned()), kind: Some(1), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("b".to_owned()), kind: Some(1), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("b".to_owned()), kind: Some(2), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("b".to_owned()), kind: Some(2), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("b".to_owned()), kind: Some(3), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("b".to_owned()), kind: Some(3), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("c".to_owned()), kind: Some(1), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("c".to_owned()), kind: Some(1), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("c".to_owned()), kind: Some(2), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("c".to_owned()), kind: Some(2), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("c".to_owned()), kind: Some(3), id: Some("x".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
FlatReqFilter { author: Some("c".to_owned()), kind: Some(3), id: Some("y".to_owned()), p_tag: Some("a".to_owned()), t_tag: None, d_tag: None, r_tag: None, search: None, since: Some(99), until: None, limit: Some(10), e_tag: None },
];
assert_eq!(output.len(), expected.len());
output
.iter()
.for_each(|a| assert!(expected.contains(a)));
}
}

View File

@ -0,0 +1,78 @@
extern crate wasm_bindgen;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;
mod expand;
mod diff;
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct ReqFilter {
#[serde(rename = "ids", skip_serializing_if = "Option::is_none")]
pub ids: Option<Vec<String>>,
#[serde(rename = "authors", skip_serializing_if = "Option::is_none")]
pub authors: Option<Vec<String>>,
#[serde(rename = "kinds", skip_serializing_if = "Option::is_none")]
pub kinds: Option<Vec<i32>>,
#[serde(rename = "#e", skip_serializing_if = "Option::is_none")]
pub e_tag: Option<Vec<String>>,
#[serde(rename = "#p", skip_serializing_if = "Option::is_none")]
pub p_tag: Option<Vec<String>>,
#[serde(rename = "#t", skip_serializing_if = "Option::is_none")]
pub t_tag: Option<Vec<String>>,
#[serde(rename = "#d", skip_serializing_if = "Option::is_none")]
pub d_tag: Option<Vec<String>>,
#[serde(rename = "#r", skip_serializing_if = "Option::is_none")]
pub r_tag: Option<Vec<String>>,
#[serde(rename = "search", skip_serializing_if = "Option::is_none")]
pub search: Option<Vec<String>>,
#[serde(rename = "since", skip_serializing_if = "Option::is_none")]
pub since: Option<i32>,
#[serde(rename = "until", skip_serializing_if = "Option::is_none")]
pub until: Option<i32>,
#[serde(rename = "limit", skip_serializing_if = "Option::is_none")]
pub limit: Option<i32>,
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct FlatReqFilter {
#[serde(rename = "ids", skip_serializing_if = "Option::is_none")]
id: Option<String>,
#[serde(rename = "authors", skip_serializing_if = "Option::is_none")]
author: Option<String>,
#[serde(rename = "kinds", skip_serializing_if = "Option::is_none")]
kind: Option<i32>,
#[serde(rename = "#e", skip_serializing_if = "Option::is_none")]
e_tag: Option<String>,
#[serde(rename = "#p", skip_serializing_if = "Option::is_none")]
p_tag: Option<String>,
#[serde(rename = "#t", skip_serializing_if = "Option::is_none")]
t_tag: Option<String>,
#[serde(rename = "#d", skip_serializing_if = "Option::is_none")]
d_tag: Option<String>,
#[serde(rename = "#r", skip_serializing_if = "Option::is_none")]
r_tag: Option<String>,
#[serde(rename = "search", skip_serializing_if = "Option::is_none")]
search: Option<String>,
#[serde(rename = "since", skip_serializing_if = "Option::is_none")]
since: Option<i32>,
#[serde(rename = "until", skip_serializing_if = "Option::is_none")]
until: Option<i32>,
#[serde(rename = "limit", skip_serializing_if = "Option::is_none")]
limit: Option<i32>,
}
#[wasm_bindgen]
pub fn diff_filters(prev: JsValue, next: JsValue) -> Result<JsValue, JsValue> {
let prev_parsed: Vec<FlatReqFilter> = serde_wasm_bindgen::from_value(prev)?;
let next_parsed: Vec<FlatReqFilter> = serde_wasm_bindgen::from_value(next)?;
let result = diff::diff_filter(&prev_parsed, &next_parsed);
Ok(serde_wasm_bindgen::to_value(&result)?)
}
#[wasm_bindgen]
pub fn expand_filter(val: JsValue) -> Result<JsValue, JsValue> {
let parsed: ReqFilter = serde_wasm_bindgen::from_value(val)?;
let result = expand::expand_filter(&parsed);
Ok(serde_wasm_bindgen::to_value(&result)?)
}

View File