Revised validation interface.

This commit is contained in:
2020-07-14 17:53:34 +01:00
parent 9e1318576a
commit b33ba8f2d3
5 changed files with 53 additions and 92 deletions

View File

@@ -15,13 +15,14 @@
//#![allow(clippy::missing_docs_in_private_items)] // A lot of our private items are simple digimon types, so they don't need documentation
// Modules
mod util;
pub mod bytes;
pub mod card;
pub mod deck;
mod util;
pub mod validation;
// Exports
pub use bytes::Bytes;
pub use card::{Digimon, Digivolve, Item, Table as CardTable};
pub use deck::{Deck, Table as DeckTable};
pub use validation::{Validatable, Validation};

View File

@@ -1,11 +1,5 @@
//! Interface for converting various structures to and from bytes
// Modules
pub mod validation;
// Exports
pub use validation::Validation;
// Std
use std::{error::Error, fmt::Debug};

View File

@@ -1,83 +0,0 @@
//! Error and warning validation for [`Bytes`](crate::Bytes) structures
// Std
use std::borrow::Cow;
/// Validation for (`Bytes::validate`)[`crate::Bytes::validate`]
#[derive(Debug, PartialEq, Clone)]
pub struct Validation<'a> {
/// If the validation was successful.
///
/// If this is `false`, it is strongly encouraged for `warnings` or
/// `errors` to have something to explain why it wasn't successful.
success: bool,
/// All warnings emitted.
///
/// Warnings must not be fatal. `self.to_bytes()` must succeed if only
/// warnings are emitted.
warnings: Vec<Cow<'a, str>>,
/// All errors emitted.
///
/// Errors are fatal by default, `self.to_bytes()` should fail if any errors
/// are emitted.
errors: Vec<Cow<'a, str>>,
}
impl<'a> Default for Validation<'a> {
fn default() -> Self {
Self::new()
}
}
// Constructors
impl<'a> Validation<'a> {
/// Create an empty successful validation, with no warnings or errors
#[must_use]
pub const fn new() -> Self {
Self {
success: true,
warnings: vec![],
errors: vec![],
}
}
}
// Adders
impl<'a> Validation<'a> {
/// Adds a new warning to this validation.
pub fn add_warning(&mut self, warning: impl Into<Cow<'a, str>>) {
self.warnings.push(warning.into());
}
/// Adds a new error to this validation.
///
/// This also turns the validation unsuccessful.
pub fn add_error(&mut self, error: impl Into<Cow<'a, str>>) {
self.errors.push(error.into());
self.success = false;
}
}
// Getters
impl<'a> Validation<'a> {
/// Returns if this validation was successful
#[must_use]
pub const fn successful(&self) -> bool {
self.success
}
/// Returns all warnings
#[must_use]
pub fn warnings(&self) -> &[impl AsRef<str> + 'a] {
&self.warnings
}
/// Returns all errors
#[must_use]
pub fn errors(&self) -> &[impl AsRef<str> + 'a] {
&self.errors
}
}

49
src/game/validation.rs Normal file
View File

@@ -0,0 +1,49 @@
//! Error and warning validation for structures
/// Structures that are validatable to be written to bytes.
///
/// This works in tandem with the [`Bytes`](crate::Bytes) interface to allow
/// applications which take user input to validate input before serializing it.
///
/// Although this information exists by calling [`Bytes::to_bytes`](crate::Bytes::to_bytes),
/// this interface provides two main advantages:
///
/// 1. It is faster than serializing the data, as it doesn't need to write the raw bytes and
/// can focus on simply parsing possible errors.
/// 2. It provides warnings alongside the errors. These are also provided via `log::warn`, but
/// these cannot be sent to the user easily.
pub trait Validatable {
/// Validation type
type Output: Validation;
/// Validates this structure
fn validate(&self) -> Self::Output;
}
/// A validation type.
///
/// This is the output of structures which may be validated.
/// It is a trait to offer more flexibility to each structure to report
/// errors and warnings in it's preferred manner.
pub trait Validation: Clone {
/// Warnings type
type Warnings;
/// Errors type
type Errors;
/// If this validation was successful.
///
/// A successful validation is one that, although may emit warnings, did not emit
/// any errors. Conversely, this also indicates that calling [`to_bytes`] will _not_
/// produce a `Err` value.
fn successful(&self) -> bool {
self.errors().is_none()
}
/// Returns any warnings
fn warnings(&self) -> Option<Self::Warnings>;
/// Returns any errors
fn errors(&self) -> Option<Self::Errors>;
}

View File

@@ -102,5 +102,5 @@ pub mod game;
pub mod io;
// Exports
pub use game::{Bytes, CardTable, Deck, DeckTable, Digimon, Digivolve, Item};
pub use game::{Bytes, CardTable, Deck, DeckTable, Digimon, Digivolve, Item, Validatable, Validation};
pub use io::GameFile;