use std::cell::RefCell;
pub use serde_json::{Error as JsonError, Value};
use serde_json::{Map, json};
use crate::Event;
pub fn to_data<E: Event>(event: &E) -> Result<Value, JsonError> {
serde_json::to_value(event)
}
pub fn from_data<E: Event>(data: Value) -> Result<E, JsonError> {
serde_json::from_value(data)
}
#[must_use]
pub const fn same_str(left: &str, right: &str) -> bool {
let (left, right) = (left.as_bytes(), right.as_bytes());
if left.len() != right.len() {
return false;
}
let mut index = 0;
while index < left.len() {
if left[index] != right[index] {
return false;
}
index += 1;
}
true
}
thread_local! {
static DERIVING: RefCell<Vec<&'static str>> = const { RefCell::new(Vec::new()) };
}
#[must_use]
pub fn derive(type_name: &'static str, describe: impl FnOnce() -> Value) -> Value {
struct Deriving;
impl Drop for Deriving {
fn drop(&mut self) {
DERIVING.with_borrow_mut(|stack| {
let _ = stack.pop();
});
}
}
let is_recursive = DERIVING.with_borrow_mut(|stack| {
if stack.contains(&type_name) {
return true;
}
stack.push(type_name);
false
});
assert!(
!is_recursive,
"architecturekit: {type_name} is recursive, so its schema can not be derived; implement Schema for it by hand",
);
let _deriving = Deriving;
describe()
}
#[must_use]
pub fn object(type_name: &'static str, fields: Vec<(&'static str, Value, bool)>) -> Value {
let mut properties = Map::new();
let mut required = Vec::new();
for (name, schema, is_optional) in fields {
assert!(
properties.insert(name.to_owned(), schema).is_none(),
"architecturekit: {type_name} writes the field {name} more than once, so its schema can not be derived",
);
if !is_optional {
required.push(Value::from(name));
}
}
let mut schema = json!({
"type": "object",
"properties": properties,
"additionalProperties": false,
});
if !required.is_empty() {
schema["required"] = Value::Array(required);
}
schema
}