use std::fmt::Debug;
use crate::{message::Message, result::Violation};
use serde::{Deserialize, Serialize};
use self::{
body_empty::BodyEmpty, body_max_length::BodyMaxLength, description_empty::DescriptionEmpty,
description_format::DescriptionFormat, description_max_length::DescriptionMaxLength,
footers_empty::FootersEmpty, r#type::Type, scope::Scope, scope_empty::ScopeEmpty,
scope_format::ScopeFormat, scope_max_length::ScopeMaxLength, subject_empty::SubjectEmpty,
type_empty::TypeEmpty, type_format::TypeFormat, type_max_length::TypeMaxLength,
};
pub mod body_empty;
pub mod body_max_length;
pub mod description_empty;
pub mod description_format;
pub mod description_max_length;
pub mod footers_empty;
pub mod scope;
pub mod scope_empty;
pub mod scope_format;
pub mod scope_max_length;
pub mod subject_empty;
pub mod r#type;
pub mod type_empty;
pub mod type_format;
pub mod type_max_length;
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct Rules {
#[serde(rename = "body-empty")]
#[serde(skip_serializing_if = "Option::is_none")]
pub body_empty: Option<BodyEmpty>,
#[serde(rename = "body-max-length")]
#[serde(skip_serializing_if = "Option::is_none")]
pub body_max_length: Option<BodyMaxLength>,
#[serde(rename = "description-empty")]
#[serde(skip_serializing_if = "Option::is_none")]
pub description_empty: Option<DescriptionEmpty>,
#[serde(rename = "description-format")]
#[serde(skip_serializing_if = "Option::is_none")]
pub description_format: Option<DescriptionFormat>,
#[serde(rename = "description-max-length")]
#[serde(skip_serializing_if = "Option::is_none")]
pub description_max_length: Option<DescriptionMaxLength>,
#[serde(rename = "footers-empty")]
#[serde(skip_serializing_if = "Option::is_none")]
pub footers_empty: Option<FootersEmpty>,
#[serde(rename = "scope")]
#[serde(skip_serializing_if = "Option::is_none")]
pub scope: Option<Scope>,
#[serde(rename = "scope-empty")]
#[serde(skip_serializing_if = "Option::is_none")]
pub scope_empty: Option<ScopeEmpty>,
#[serde(rename = "scope-format")]
#[serde(skip_serializing_if = "Option::is_none")]
pub scope_format: Option<ScopeFormat>,
#[serde(rename = "scope-max-length")]
#[serde(skip_serializing_if = "Option::is_none")]
pub scope_max_length: Option<ScopeMaxLength>,
#[serde(rename = "subject-empty")]
#[serde(skip_serializing_if = "Option::is_none")]
pub subject_empty: Option<SubjectEmpty>,
#[serde(rename = "type")]
#[serde(skip_serializing_if = "Option::is_none")]
pub r#type: Option<Type>,
#[serde(rename = "type-empty")]
#[serde(skip_serializing_if = "Option::is_none")]
pub type_empty: Option<TypeEmpty>,
#[serde(rename = "type-format")]
#[serde(skip_serializing_if = "Option::is_none")]
pub type_format: Option<TypeFormat>,
#[serde(rename = "type-max-length")]
#[serde(skip_serializing_if = "Option::is_none")]
pub type_max_length: Option<TypeMaxLength>,
}
impl Rules {
pub fn validate(&self, message: &Message) -> Vec<Violation> {
let mut results = Vec::new();
if let Some(rule) = &self.body_empty {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.body_max_length {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.description_empty {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.description_format {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.description_max_length {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.scope {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.scope_empty {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.scope_format {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.scope_max_length {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.subject_empty {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.r#type {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.type_empty {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.type_format {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
if let Some(rule) = &self.type_max_length {
if let Some(validation) = rule.validate(message) {
results.push(validation);
}
}
results
}
}
impl Default for Rules {
fn default() -> Self {
Self {
body_empty: None,
body_max_length: None,
description_empty: DescriptionEmpty::default().into(),
description_format: None,
description_max_length: None,
footers_empty: None,
scope: None,
scope_empty: None,
scope_format: None,
scope_max_length: None,
subject_empty: SubjectEmpty::default().into(),
r#type: None,
type_empty: TypeEmpty::default().into(),
type_format: None,
type_max_length: None,
}
}
}
pub trait Rule: Default {
const NAME: &'static str;
fn message(&self, message: &Message) -> String;
const LEVEL: Level;
fn validate(&self, message: &Message) -> Option<Violation>;
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub enum Level {
#[serde(rename = "error")]
Error,
#[serde(rename = "ignore")]
Ignore,
#[serde(rename = "warning")]
Warning,
}