use std::fmt;
use crate::{Directive, EnumValue, StringValue};
#[derive(Debug, PartialEq, Clone)]
pub struct EnumDefinition {
name: String,
description: Option<StringValue>,
values: Vec<EnumValue>,
directives: Vec<Directive>,
extend: bool,
}
impl EnumDefinition {
pub fn new(name: String) -> Self {
Self {
name,
description: None,
values: Vec::new(),
directives: Vec::new(),
extend: false,
}
}
pub fn extend(&mut self) {
self.extend = true;
}
pub fn description(&mut self, description: String) {
self.description = Some(StringValue::Top {
source: description,
});
}
pub fn value(&mut self, value: EnumValue) {
self.values.push(value)
}
pub fn directive(&mut self, directive: Directive) {
self.directives.push(directive)
}
}
impl fmt::Display for EnumDefinition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.extend {
write!(f, "extend ")?;
} else if let Some(description) = &self.description {
writeln!(f, "{description}")?;
}
write!(f, "enum {}", self.name)?;
for directive in &self.directives {
write!(f, " {directive}")?;
}
write!(f, " {{")?;
for value in &self.values {
write!(f, "\n{value}")?;
}
writeln!(f, "\n}}")
}
}
#[cfg(test)]
mod tests {
use crate::{Argument, Value};
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn it_encodes_a_simple_enum() {
let enum_ty_1 = EnumValue::new("CAT_TREE".to_string());
let enum_ty_2 = EnumValue::new("BED".to_string());
let enum_ty_3 = EnumValue::new("CARDBOARD_BOX".to_string());
let mut enum_ = EnumDefinition::new("NapSpots".to_string());
enum_.value(enum_ty_1);
enum_.value(enum_ty_2);
enum_.value(enum_ty_3);
assert_eq!(
enum_.to_string(),
r#"enum NapSpots {
CAT_TREE
BED
CARDBOARD_BOX
}
"#
);
}
#[test]
fn it_encodes_enum_with_descriptions() {
let mut enum_ty_1 = EnumValue::new("CAT_TREE".to_string());
enum_ty_1.description("Top bunk of a cat tree.".to_string());
let enum_ty_2 = EnumValue::new("BED".to_string());
let mut enum_ty_3 = EnumValue::new("CARDBOARD_BOX".to_string());
let mut deprecated_directive = Directive::new(String::from("deprecated"));
deprecated_directive.arg(Argument::new(
String::from("reason"),
Value::String(String::from("Box was recycled.")),
));
enum_ty_3.directive(deprecated_directive);
let mut directive = Directive::new(String::from("testDirective"));
directive.arg(Argument::new(
String::from("first"),
Value::String("one".to_string()),
));
let mut enum_ = EnumDefinition::new("NapSpots".to_string());
enum_.description("Favourite cat nap spots.".to_string());
enum_.value(enum_ty_1);
enum_.value(enum_ty_2);
enum_.value(enum_ty_3);
enum_.directive(directive);
assert_eq!(
enum_.to_string(),
r#""Favourite cat nap spots."
enum NapSpots @testDirective(first: "one") {
"Top bunk of a cat tree."
CAT_TREE
BED
CARDBOARD_BOX @deprecated(reason: "Box was recycled.")
}
"#
);
}
#[test]
fn it_encodes_enum_extension() {
let mut enum_ty_1 = EnumValue::new("CAT_TREE".to_string());
enum_ty_1.description("Top bunk of a cat tree.".to_string());
let enum_ty_2 = EnumValue::new("BED".to_string());
let mut enum_ty_3 = EnumValue::new("CARDBOARD_BOX".to_string());
let mut deprecated_directive = Directive::new(String::from("deprecated"));
deprecated_directive.arg(Argument::new(
String::from("reason"),
Value::String(String::from("Box was recycled.")),
));
enum_ty_3.directive(deprecated_directive);
let mut directive = Directive::new(String::from("testDirective"));
directive.arg(Argument::new(
String::from("first"),
Value::String("one".to_string()),
));
let mut enum_ = EnumDefinition::new("NapSpots".to_string());
enum_.description("Favourite cat nap spots.".to_string());
enum_.value(enum_ty_1);
enum_.value(enum_ty_2);
enum_.value(enum_ty_3);
enum_.directive(directive);
enum_.extend();
assert_eq!(
enum_.to_string(),
r#"extend enum NapSpots @testDirective(first: "one") {
"Top bunk of a cat tree."
CAT_TREE
BED
CARDBOARD_BOX @deprecated(reason: "Box was recycled.")
}
"#
);
}
}