use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StoredQuery {
pub name: String,
pub expression: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
#[derive(Debug, Default)]
pub struct QueryStore {
queries: HashMap<String, StoredQuery>,
}
impl QueryStore {
pub fn new() -> Self {
Self::default()
}
pub fn define(&mut self, query: StoredQuery) -> Option<StoredQuery> {
self.queries.insert(query.name.clone(), query)
}
pub fn get(&self, name: &str) -> Option<&StoredQuery> {
self.queries.get(name)
}
pub fn delete(&mut self, name: &str) -> Option<StoredQuery> {
self.queries.remove(name)
}
pub fn list(&self) -> Vec<&StoredQuery> {
let mut queries: Vec<_> = self.queries.values().collect();
queries.sort_by(|a, b| a.name.cmp(&b.name));
queries
}
pub fn len(&self) -> usize {
self.queries.len()
}
pub fn is_empty(&self) -> bool {
self.queries.is_empty()
}
pub fn clear(&mut self) {
self.queries.clear();
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_define_and_get() {
let mut store = QueryStore::new();
let query = StoredQuery {
name: "count".to_string(),
expression: "length(@)".to_string(),
description: Some("Count items".to_string()),
};
assert!(store.define(query.clone()).is_none());
assert_eq!(store.len(), 1);
let retrieved = store.get("count").unwrap();
assert_eq!(retrieved.name, "count");
assert_eq!(retrieved.expression, "length(@)");
assert_eq!(retrieved.description, Some("Count items".to_string()));
}
#[test]
fn test_define_overwrites() {
let mut store = QueryStore::new();
let query1 = StoredQuery {
name: "test".to_string(),
expression: "length(@)".to_string(),
description: None,
};
let query2 = StoredQuery {
name: "test".to_string(),
expression: "keys(@)".to_string(),
description: Some("Updated".to_string()),
};
assert!(store.define(query1).is_none());
let old = store.define(query2).unwrap();
assert_eq!(old.expression, "length(@)");
let current = store.get("test").unwrap();
assert_eq!(current.expression, "keys(@)");
}
#[test]
fn test_delete() {
let mut store = QueryStore::new();
let query = StoredQuery {
name: "to_delete".to_string(),
expression: "`null`".to_string(),
description: None,
};
store.define(query);
assert_eq!(store.len(), 1);
let deleted = store.delete("to_delete").unwrap();
assert_eq!(deleted.name, "to_delete");
assert_eq!(store.len(), 0);
assert!(store.delete("nonexistent").is_none());
}
#[test]
fn test_list() {
let mut store = QueryStore::new();
store.define(StoredQuery {
name: "zebra".to_string(),
expression: "`1`".to_string(),
description: None,
});
store.define(StoredQuery {
name: "alpha".to_string(),
expression: "`2`".to_string(),
description: None,
});
store.define(StoredQuery {
name: "beta".to_string(),
expression: "`3`".to_string(),
description: None,
});
let list = store.list();
assert_eq!(list.len(), 3);
assert_eq!(list[0].name, "alpha");
assert_eq!(list[1].name, "beta");
assert_eq!(list[2].name, "zebra");
}
#[test]
fn test_clear() {
let mut store = QueryStore::new();
store.define(StoredQuery {
name: "a".to_string(),
expression: "`1`".to_string(),
description: None,
});
store.define(StoredQuery {
name: "b".to_string(),
expression: "`2`".to_string(),
description: None,
});
assert_eq!(store.len(), 2);
store.clear();
assert!(store.is_empty());
}
#[test]
fn test_get_nonexistent() {
let store = QueryStore::new();
assert!(store.get("never_defined").is_none());
}
#[test]
fn test_empty_name() {
let mut store = QueryStore::new();
store.define(StoredQuery {
name: "".to_string(),
expression: "length(@)".to_string(),
description: Some("Empty name query".to_string()),
});
assert_eq!(store.len(), 1);
let retrieved = store.get("").unwrap();
assert_eq!(retrieved.name, "");
assert_eq!(retrieved.expression, "length(@)");
assert_eq!(retrieved.description, Some("Empty name query".to_string()));
}
#[test]
fn test_is_empty() {
let mut store = QueryStore::new();
assert!(store.is_empty());
store.define(StoredQuery {
name: "q".to_string(),
expression: "@".to_string(),
description: None,
});
assert!(!store.is_empty());
store.clear();
assert!(store.is_empty());
}
#[test]
fn test_list_ordering_stability() {
let mut store = QueryStore::new();
store.define(StoredQuery {
name: "c".to_string(),
expression: "`3`".to_string(),
description: None,
});
store.define(StoredQuery {
name: "b".to_string(),
expression: "`2`".to_string(),
description: None,
});
store.define(StoredQuery {
name: "a".to_string(),
expression: "`1`".to_string(),
description: None,
});
let list = store.list();
assert_eq!(list.len(), 3);
assert_eq!(list[0].name, "a");
assert_eq!(list[1].name, "b");
assert_eq!(list[2].name, "c");
}
}