pub(crate) mod sketch;
pub mod template;
use crate::error::Error;
use crate::field::FieldMeaning;
use crate::intent::IntentScore;
use crate::service::ServiceDef;
#[derive(Debug, Clone, Default)]
pub struct BaseContext {
pub intent_index: usize,
pub current_state: Option<String>,
}
pub trait Renderer: Send + Sync {
type Output;
type Context: Default;
fn render(
&self,
service: &ServiceDef,
intents: &[IntentScore],
ctx: &Self::Context,
) -> Result<Self::Output, Error>;
}
pub fn field_display_name(name: &str) -> String {
name.split('_')
.map(|word| {
let mut chars = word.chars();
match chars.next() {
None => String::new(),
Some(c) => {
let upper: String = c.to_uppercase().collect();
upper + &chars.collect::<String>()
}
}
})
.collect::<Vec<_>>()
.join(" ")
}
pub fn is_system_field(meaning: &FieldMeaning) -> bool {
matches!(
meaning,
FieldMeaning::Identifier | FieldMeaning::CreatedAt | FieldMeaning::UpdatedAt
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn base_context_default() {
let ctx = BaseContext::default();
assert_eq!(ctx.intent_index, 0);
assert!(ctx.current_state.is_none());
}
#[test]
fn field_display_name_multi_word() {
assert_eq!(field_display_name("user_name"), "User Name");
}
#[test]
fn field_display_name_single_word() {
assert_eq!(field_display_name("email"), "Email");
}
#[test]
fn field_display_name_timestamp() {
assert_eq!(field_display_name("created_at"), "Created At");
}
#[test]
fn field_display_name_empty() {
assert_eq!(field_display_name(""), "");
}
#[test]
fn is_system_field_identifies_system_meanings() {
assert!(is_system_field(&FieldMeaning::Identifier));
assert!(is_system_field(&FieldMeaning::CreatedAt));
assert!(is_system_field(&FieldMeaning::UpdatedAt));
}
#[test]
fn is_system_field_rejects_domain_meanings() {
assert!(!is_system_field(&FieldMeaning::Money));
assert!(!is_system_field(&FieldMeaning::EntityName));
assert!(!is_system_field(&FieldMeaning::FreeText));
assert!(!is_system_field(&FieldMeaning::Status));
assert!(!is_system_field(&FieldMeaning::Custom("x".into())));
}
}