using System;
using System.Collections;
using System.Linq;
using Chernobyl.Collections.Generic;
using JetBrains.Annotations;
namespace Chernobyl
{
///
/// Instance used to validate parameters or other values.
///
/// The type being validated.
public struct Validater
{
///
/// Constructor.
///
/// The value to validate.
/// The name of the parameter. This is used
/// in the exception message to make the message easier to understand.
public Validater(T value, string name)
{
Value = value;
Name = name;
}
///
/// The value to validate.
///
public T Value { get; }
///
/// The name of the parameter. This is used in the exception message to
/// make the message easier to understand.
///
public string Name { get; }
}
///
/// Validates reference type instances.
///
public static class ReferenceValidater
{
///
/// Throws an if is null.
///
/// The instance containing the value to validate.
/// The this instance.
public static Validater IfNull(this Validater validator)
where T : class
{
if (validator.Value == null)
throw new ArgumentNullException(validator.Name, "Argument cannot be null. Please provide a valid value.");
return validator;
}
///
/// Throws an if is null. Does
/// the same thing as param.Throw(paramName).IfNull().
///
/// The type of the parameter. This type must be a reference type.
/// The instance to check.
/// The name of the parameter that caused the exception, if any.
/// Thrown if is null.
[ContractAnnotation("param:null => halt")]
public static Validater ThrowIfNull([NoEnumeration, CanBeNull]this T param, string paramName)
where T : class => param.Throw(paramName).IfNull();
}
///
/// Validates instances.
///
public static class ComparableValidater
{
///
/// Throws an if is less
/// than .
///
/// The instance containing the value to validate.
/// The value to compare against.
/// The name of the value comparing against or an empty string if it has
/// no name.
/// The this instance.
public static Validater IfLessThan(this Validater validator, T lessThan, string name = "")
where T : IComparable
{
if (validator.Value.CompareTo(lessThan) < 0)
{
var otherName = name.IsEmptyOrNull() ? lessThan.ToString() : $"{name} (${lessThan})";
throw new ArgumentOutOfRangeException(validator.Name, validator.Value, $"{validator.Name} cannot be less than {otherName}.");
}
return validator;
}
///
/// Throws an if is less
/// than or equal to .
///
/// The instance containing the value to validate.
/// The value to compare against.
/// The name of the value comparing against or an empty string if it has
/// no name.
/// The this instance.
public static Validater IfLessThanOrEqualTo(this Validater validator, T lessThan, string name = "")
where T : IComparable
{
if (validator.Value.CompareTo(lessThan) <= 0)
{
var otherName = name.IsEmptyOrNull() ? lessThan.ToString() : $"{name} (${lessThan})";
throw new ArgumentOutOfRangeException(validator.Name, validator.Value, $"{validator.Name} cannot be less than or equal to {otherName}.");
}
return validator;
}
///
/// Throws an if is greater
/// than .
///
/// The instance containing the value to validate.
/// The value to compare against.
/// The name of the value comparing against or an empty string if it has
/// no name.
/// The this instance.
public static Validater IfGreaterThan(this Validater validator, T greaterThan, string name = "")
where T : IComparable
{
if (validator.Value.CompareTo(greaterThan) > 0)
{
var otherName = name.IsEmptyOrNull() ? greaterThan.ToString() : $"{name} (${greaterThan})";
throw new ArgumentOutOfRangeException(validator.Name, validator.Value, $"{validator.Name} cannot be greater than {otherName}.");
}
return validator;
}
///
/// Throws an if is greater
/// than or equal to .
///
/// The instance containing the value to validate.
/// The value to compare against.
/// The name of the value comparing against or an empty string if it has
/// no name.
/// The this instance.
public static Validater IfGreaterThanOrEqualTo(this Validater validator, T other, string name = "")
where T : IComparable
{
if (validator.Value.CompareTo(other) >= 0)
{
var otherName = name.IsEmptyOrNull() ? other.ToString() : $"{name} (${other})";
throw new ArgumentOutOfRangeException(validator.Name, validator.Value, $"{validator.Name} cannot be greater than or equal to {otherName}.");
}
return validator;
}
///
/// Throws an if
/// is not equal to or between and .
///
/// The instance containing the value to validate.
/// The inclusive lower limit.
/// The inclusive upper limit.
/// The this instance.
public static Validater IfNotBetween(this Validater validator, T lessThan, T greaterThan)
where T : IComparable => validator.IfLessThan(lessThan).IfGreaterThan(greaterThan);
}
///
/// Validates instances.
///
public static class EnumerableValidater
{
///
/// Throws an exception if the provided contains nothing.
///
public static Validater IfEmpty(this Validater validator) where T : IEnumerable
{
// ReSharper disable PossibleMultipleEnumeration
if (!validator.Value.Cast