use std::collections::HashMap;
use serde::Serialize;
use std::marker::PhantomData;
pub fn build_map<'key, 'value, const N: usize>(
array: [(&'key str, Option<&'value str>); N],
) -> HashMap<&'key str, &'value str> {
let mut map = HashMap::with_capacity(N);
for (key, value) in array {
if let Some(value) = value {
map.insert(key, value);
}
}
map
}
pub struct JsonBuilder<Len> {
map: serde_json::Map<String, serde_json::Value>,
len: PhantomData<fn() -> Len>,
}
impl<Len: Natural> JsonBuilder<Len> {
fn from_map(map: serde_json::Map<String, serde_json::Value>) -> Self {
Self {
map,
len: PhantomData,
}
}
pub fn new() -> Self {
Self::from_map(serde_json::Map::with_capacity(Len::VALUE))
}
}
impl<Len: Natural> JsonBuilder<Successor<Len>> {
pub fn required(mut self, name: &str, value: impl Serialize) -> JsonBuilder<Len> {
self.map
.insert(name.to_owned(), serde_json::to_value(value).unwrap());
JsonBuilder::from_map(self.map)
}
pub fn optional(self, name: &str, value: Option<impl Serialize>) -> JsonBuilder<Len> {
if let Some(value) = value {
self.required(name, value)
} else {
JsonBuilder::from_map(self.map)
}
}
}
impl JsonBuilder<Zero> {
pub fn build(self) -> serde_json::Value {
serde_json::Value::Object(self.map)
}
}
pub struct Zero;
pub struct Successor<T>(T);
pub trait Natural {
const VALUE: usize;
}
impl Natural for Zero {
const VALUE: usize = 0;
}
impl<T: Natural> Natural for Successor<T> {
const VALUE: usize = T::VALUE + 1;
}