use serde::{Deserialize, Serialize};
use std::borrow::Cow;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum FieldType {
Input,
Output,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Field<'a> {
#[serde(borrow)]
pub name: Cow<'a, str>,
#[serde(borrow)]
pub desc: Cow<'a, str>,
#[serde(borrow)]
pub prefix: Cow<'a, str>,
pub field_type: FieldType,
#[serde(borrow)]
pub format: Option<Cow<'a, str>>,
}
impl<'a> Field<'a> {
pub fn new(
name: impl Into<Cow<'a, str>>,
desc: impl Into<Cow<'a, str>>,
field_type: FieldType,
) -> Self {
let name = name.into();
let prefix = Self::infer_prefix(&name);
Self {
name,
desc: desc.into(),
prefix: Cow::Owned(prefix),
field_type,
format: None,
}
}
pub fn with_prefix(mut self, prefix: impl Into<Cow<'a, str>>) -> Self {
self.prefix = prefix.into();
self
}
pub fn with_format(mut self, format: impl Into<Cow<'a, str>>) -> Self {
self.format = Some(format.into());
self
}
pub fn into_owned(self) -> Field<'static> {
Field {
name: Cow::Owned(self.name.into_owned()),
desc: Cow::Owned(self.desc.into_owned()),
prefix: Cow::Owned(self.prefix.into_owned()),
field_type: self.field_type,
format: self.format.map(|f| Cow::Owned(f.into_owned())),
}
}
fn infer_prefix(name: &str) -> String {
let mut result = String::with_capacity(name.len() + 5);
let mut prev_lower = false;
for (i, ch) in name.chars().enumerate() {
if i > 0 && ch.is_uppercase() && prev_lower {
result.push(' ');
}
if i == 0 {
result.push(ch.to_ascii_uppercase());
} else {
result.push(ch);
}
prev_lower = ch.is_lowercase();
}
result
}
}
pub struct InputField;
impl InputField {
pub fn create<'a>(name: impl Into<Cow<'a, str>>, desc: impl Into<Cow<'a, str>>) -> Field<'a> {
Field::new(name, desc, FieldType::Input)
}
}
pub struct OutputField;
impl OutputField {
pub fn create<'a>(name: impl Into<Cow<'a, str>>, desc: impl Into<Cow<'a, str>>) -> Field<'a> {
Field::new(name, desc, FieldType::Output)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_infer_prefix() {
assert_eq!(Field::infer_prefix("question"), "Question");
assert_eq!(Field::infer_prefix("answerText"), "Answer Text");
assert_eq!(Field::infer_prefix("someValue"), "Some Value");
}
#[test]
fn test_field_creation() {
let field = InputField::create("query", "User query");
assert_eq!(field.name, "query");
assert_eq!(field.desc, "User query");
assert_eq!(field.prefix, "Query");
assert_eq!(field.field_type, FieldType::Input);
}
}