use derive_builder::Builder;
use serde::Serialize;
use uuid::Uuid;
#[derive(Clone, Serialize)]
pub(crate) struct Query<D>
where
D: Serialize + ?Sized,
{
query: D,
}
impl<D: Serialize + Sized> From<D> for Query<D> {
fn from(value: D) -> Self {
Self { query: value }
}
}
#[derive(Serialize, Clone)]
#[serde(untagged)]
pub enum StrOrUuid {
Str(String),
Uid(Uuid),
}
impl From<&str> for StrOrUuid {
fn from(s: &str) -> Self {
StrOrUuid::Str(s.to_string())
}
}
impl From<String> for StrOrUuid {
fn from(s: String) -> Self {
StrOrUuid::Str(s)
}
}
impl From<Uuid> for StrOrUuid {
fn from(u: Uuid) -> Self {
StrOrUuid::Uid(u)
}
}
#[derive(Clone, Serialize, Builder)]
#[serde(transparent)]
#[builder(pattern = "owned")]
pub struct UuidQuery {
#[builder(default)]
values: Vec<Uuid>,
}
impl From<Uuid> for UuidQuery {
fn from(value: Uuid) -> Self {
Self {
values: vec![value],
}
}
}
impl From<Vec<Uuid>> for UuidQuery {
fn from(values: Vec<Uuid>) -> Self {
Self { values }
}
}
impl<const N: usize> From<[Uuid; N]> for UuidQuery {
fn from(values: [Uuid; N]) -> Self {
Self {
values: values.into(),
}
}
}
impl UuidQueryBuilder {
pub fn insert(mut self, single: Uuid) -> Self {
self.values.get_or_insert_with(Vec::new).push(single);
self
}
pub fn insert_many<I>(mut self, values: I) -> Self
where
I: IntoIterator<Item = Uuid>,
{
self.values.get_or_insert_with(Vec::new).extend(values);
self
}
}
#[derive(Clone, Serialize, Builder)]
#[serde(transparent)]
#[builder(pattern = "owned")]
pub struct SimpleQuery {
#[builder(default)]
values: Vec<StrOrUuid>,
}
impl SimpleQueryBuilder {
pub fn insert<T: Into<StrOrUuid>>(mut self, single: T) -> Self {
self.values.get_or_insert_with(Vec::new).push(single.into());
self
}
pub fn insert_many<I, T>(mut self, values: I) -> Self
where
I: IntoIterator<Item = T>,
T: Into<StrOrUuid>,
{
self.values
.get_or_insert_with(Vec::new)
.extend(values.into_iter().map(Into::into));
self
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use serde_json::json;
use uuid::Uuid;
use super::{Query, UuidQuery};
#[test]
fn uuid_query_serializes_as_query_array() {
let uuid =
Uuid::from_str("751de3e0-42f1-4da0-bf62-40d1f5096e50").unwrap();
let query: Query<UuidQuery> = UuidQuery::from(uuid).into();
assert_eq!(
serde_json::to_value(query).unwrap(),
json!({
"query": ["751de3e0-42f1-4da0-bf62-40d1f5096e50"]
})
);
}
#[test]
fn uuid_query_can_be_built_from_vec() {
let uuid =
Uuid::from_str("751de3e0-42f1-4da0-bf62-40d1f5096e50").unwrap();
let query: Query<UuidQuery> = UuidQuery::from(vec![uuid]).into();
assert_eq!(
serde_json::to_value(query).unwrap(),
json!({
"query": ["751de3e0-42f1-4da0-bf62-40d1f5096e50"]
})
);
}
}