use core::panic;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::fmt::Display;
use std::fmt::Formatter;
use std::hash::Hash;
use std::ops::Deref;
use std::ops::DerefMut;
use crate::Validate;
pub struct Valid<T>
where T: Validate
{
pub(crate) enabled: bool,
inner: T,
}
impl<T: Validate> Valid<T> {
pub fn new(inner: T) -> Self {
Self {
enabled: true,
inner,
}
}
pub fn enable_validation(&mut self, enabled: bool) {
self.enabled = enabled;
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn as_ref(&self) -> Valid<&T> {
Valid {
enabled: self.enabled,
inner: self.deref(),
}
}
pub fn into_inner(self) -> T {
self.inner
}
}
impl<T> Deref for Valid<T>
where T: Validate
{
type Target = T;
fn deref(&self) -> &Self::Target {
#[cfg(debug_assertions)]
if self.enabled
&& let Err(e) = self.inner.validate()
{
panic!("invalid state: {}", e);
}
&self.inner
}
}
impl<T> DerefMut for Valid<T>
where T: Validate
{
fn deref_mut(&mut self) -> &mut Self::Target {
#[cfg(debug_assertions)]
if self.enabled
&& let Err(e) = self.inner.validate()
{
panic!("invalid state: {}", e);
}
&mut self.inner
}
}
impl<T: PartialEq> PartialEq for Valid<T>
where T: Validate
{
fn eq(&self, other: &Self) -> bool {
PartialEq::eq(self.deref(), other.deref())
}
}
impl<T: Eq> Eq for Valid<T> where T: Validate {}
impl<T: PartialOrd> PartialOrd for Valid<T>
where T: Validate
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
PartialOrd::partial_cmp(self.deref(), other.deref())
}
}
impl<T: Ord> Ord for Valid<T>
where T: Validate
{
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(self.deref(), other.deref())
}
}
impl<T: Debug> Debug for Valid<T>
where T: Validate
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}
impl<T: Display> Display for Valid<T>
where T: Validate
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.inner.fmt(f)
}
}
impl<T: Clone> Clone for Valid<T>
where T: Validate
{
fn clone(&self) -> Self {
Self {
enabled: self.enabled,
inner: self.deref().clone(),
}
}
}
impl<T: Copy> Copy for Valid<T> where T: Validate {}
impl<T: Default> Default for Valid<T>
where T: Validate
{
fn default() -> Self {
Self {
enabled: true,
inner: T::default(),
}
}
}
impl<T: Hash> Hash for Valid<T>
where T: Validate
{
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}