pub struct CreateMeta {
pub fields: &'static [CreateField],
pub model_name: &'static str,
}
pub struct CreateField {
pub name: &'static str,
pub required: bool,
}
#[doc(hidden)]
#[diagnostic::on_unimplemented(
message = "`{Self}` does not carry Toasty create-field metadata",
label = "this type cannot be validated as a create target",
note = "Only Toasty model field paths and direct relation create scopes carry create-field metadata."
)]
pub trait ValidateCreate {
const CREATE_META: &'static CreateMeta;
}
pub const fn assert_create_fields(meta: &CreateMeta, provided: &[&str]) {
let mut i = 0;
while i < meta.fields.len() {
let field = &meta.fields[i];
if field.required && !const_contains(provided, field.name) {
panic!(
"missing required field in create! macro — check model definition for required fields"
);
}
i += 1;
}
}
pub const fn const_contains(haystack: &[&str], needle: &str) -> bool {
let mut i = 0;
while i < haystack.len() {
if const_str_eq(haystack[i], needle) {
return true;
}
i += 1;
}
false
}
const fn const_str_eq(a: &str, b: &str) -> bool {
let a = a.as_bytes();
let b = b.as_bytes();
if a.len() != b.len() {
return false;
}
let mut i = 0;
while i < a.len() {
if a[i] != b[i] {
return false;
}
i += 1;
}
true
}