public final class VerifiableArray<E, X extends Throwable>
           extends AbstractVerifiableObject<E[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableArray(FailedValidationExecutor<X> failedValidationExecutor,
                           E[] subject,
                           Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    @Override
    public E[] isEqualTo(E[] other) throws X {
        E[] subject = getSubject();
        if (null == subject || !Arrays.deepEquals(subject, other)) {
            fail("t -> Arrays.deepEquals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    @Override
    public E[] isNotEqualTo(E[] other) throws X {
        E[] subject = getSubject();
        if (null == subject || Arrays.deepEquals(subject, other)) {
            fail("t -> !Arrays.deepEquals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public E[] isEmpty() throws X {
        E[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public E[] isNotEmpty() throws X {
        E[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public E[] hasLengthOf(int n) throws X {
        E[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public E[] hasLengthOfAtLeast(int n) throws X {
        E[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public E[] hasLengthOfAtMost(int n) throws X {
        E[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }
} public final class VerifiableBooleanArray<X extends Throwable>
           extends AbstractVerifiableObject<boolean[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableBooleanArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableBooleanArray(FailedValidationExecutor<X> failedValidationExecutor,
                                  boolean[] subject,
                                  Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public boolean[] isEqualTo(boolean[] other) throws X {
        boolean[] subject = getSubject();
        if (null == subject || !Arrays.equals(subject, other)) {
            fail("t -> Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public boolean[] isNotEqualTo(boolean[] other) throws X {
        boolean[] subject = getSubject();
        if (null == subject || Arrays.equals(subject, other)) {
            fail("t -> !Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public boolean[] isEmpty() throws X {
        boolean[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public boolean[] isNotEmpty() throws X {
        boolean[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public boolean[] hasLengthOf(int n) throws X {
        boolean[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public boolean[] hasLengthOfAtLeast(int n) throws X {
        boolean[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public boolean[] hasLengthOfAtMost(int n) throws X {
        boolean[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it contains the value.
     *
     * @throws X if the subject is null or does not contain the value.
     */
    public boolean[] contains(boolean value) throws X {
        boolean[] subject = getSubject();
        if (null == subject || !containsHelper(subject, value)) {
            fail("t -> t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it does not contain the value.
     *
     * @throws X if the subject is null or does contain the value.
     */
    public boolean[] doesNotContain(boolean value) throws X {
        boolean[] subject = getSubject();
        if (null == subject || containsHelper(subject, value)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static boolean containsHelper(boolean[] array, boolean value) {
        for (boolean next : Objects.requireNonNull(array, ValidityUtils.nullArgumentMessage("array"))) {
            if (next == value) {
                return true;
            }
        }
        return false;
    }
} public final class VerifiableByteArray<X extends Throwable>
           extends AbstractVerifiableObject<byte[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableByteArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableByteArray(FailedValidationExecutor<X> failedValidationExecutor,
                               byte[] subject,
                               Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public byte[] isEqualTo(byte[] other) throws X {
        byte[] subject = getSubject();
        if (null == subject || !Arrays.equals(subject, other)) {
            fail("t -> Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public byte[] isNotEqualTo(byte[] other) throws X {
        byte[] subject = getSubject();
        if (null == subject || Arrays.equals(subject, other)) {
            fail("t -> !Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public byte[] isEmpty() throws X {
        byte[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public byte[] isNotEmpty() throws X {
        byte[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public byte[] hasLengthOf(int n) throws X {
        byte[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public byte[] hasLengthOfAtLeast(int n) throws X {
        byte[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public byte[] hasLengthOfAtMost(int n) throws X {
        byte[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it contains the value.
     *
     * @throws X if the subject is null or does not contain the value.
     */
    public byte[] contains(byte value) throws X {
        byte[] subject = getSubject();
        if (null == subject || !containsHelper(subject, value)) {
            fail("t -> t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it does not contain the value.
     *
     * @throws X if the subject is null or does contain the value.
     */
    public byte[] doesNotContain(byte value) throws X {
        byte[] subject = getSubject();
        if (null == subject || containsHelper(subject, value)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static boolean containsHelper(byte[] array, byte value) {
        for (byte next : Objects.requireNonNull(array, ValidityUtils.nullArgumentMessage("array"))) {
            if (next == value) {
                return true;
            }
        }
        return false;
    }
} public final class VerifiableCharArray<X extends Throwable>
           extends AbstractVerifiableObject<char[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableCharArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableCharArray(FailedValidationExecutor<X> failedValidationExecutor,
                               char[] subject,
                               Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public char[] isEqualTo(char[] other) throws X {
        char[] subject = getSubject();
        if (null == subject || !Arrays.equals(subject, other)) {
            fail("t -> Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public char[] isNotEqualTo(char[] other) throws X {
        char[] subject = getSubject();
        if (null == subject || Arrays.equals(subject, other)) {
            fail("t -> !Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public char[] isEmpty() throws X {
        char[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public char[] isNotEmpty() throws X {
        char[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public char[] hasLengthOf(int n) throws X {
        char[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public char[] hasLengthOfAtLeast(int n) throws X {
        char[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public char[] hasLengthOfAtMost(int n) throws X {
        char[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it contains the value.
     *
     * @throws X if the subject is null or does not contain the value.
     */
    public char[] contains(char value) throws X {
        char[] subject = getSubject();
        if (null == subject || !containsHelper(subject, value)) {
            fail("t -> t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it does not contain the value.
     *
     * @throws X if the subject is null or does contain the value.
     */
    public char[] doesNotContain(char value) throws X {
        char[] subject = getSubject();
        if (null == subject || containsHelper(subject, value)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static boolean containsHelper(char[] array, char value) {
        for (char next : Objects.requireNonNull(array, ValidityUtils.nullArgumentMessage("array"))) {
            if (next == value) {
                return true;
            }
        }
        return false;
    }
} public final class VerifiableDoubleArray<X extends Throwable>
           extends AbstractVerifiableObject<double[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableDoubleArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableDoubleArray(FailedValidationExecutor<X> failedValidationExecutor,
                                 double[] subject,
                                 Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public double[] isEqualTo(double[] other) throws X {
        double[] subject = getSubject();
        if (null == subject || !Arrays.equals(subject, other)) {
            fail("t -> Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public double[] isNotEqualTo(double[] other) throws X {
        double[] subject = getSubject();
        if (null == subject || Arrays.equals(subject, other)) {
            fail("t -> !Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public double[] isEmpty() throws X {
        double[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public double[] isNotEmpty() throws X {
        double[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public double[] hasLengthOf(int n) throws X {
        double[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public double[] hasLengthOfAtLeast(int n) throws X {
        double[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public double[] hasLengthOfAtMost(int n) throws X {
        double[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it contains the value.
     *
     * @throws X if the subject is null or does not contain the value.
     */
    public double[] contains(double value) throws X {
        double[] subject = getSubject();
        if (null == subject || !containsHelper(subject, value)) {
            fail("t -> t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it does not contain the value.
     *
     * @throws X if the subject is null or does contain the value.
     */
    public double[] doesNotContain(double value) throws X {
        double[] subject = getSubject();
        if (null == subject || containsHelper(subject, value)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static boolean containsHelper(double[] array, double value) {
        for (double next : Objects.requireNonNull(array, ValidityUtils.nullArgumentMessage("array"))) {
            if (Double.compare(next, value) == 0) {
                return true;
            }
        }
        return false;
    }
} public final class VerifiableFloatArray<X extends Throwable>
           extends AbstractVerifiableObject<float[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableFloatArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableFloatArray(FailedValidationExecutor<X> failedValidationExecutor,
                                float[] subject,
                                Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public float[] isEqualTo(float[] other) throws X {
        float[] subject = getSubject();
        if (null == subject || !Arrays.equals(subject, other)) {
            fail("t -> Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public float[] isNotEqualTo(float[] other) throws X {
        float[] subject = getSubject();
        if (null == subject || Arrays.equals(subject, other)) {
            fail("t -> !Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public float[] isEmpty() throws X {
        float[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public float[] isNotEmpty() throws X {
        float[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public float[] hasLengthOf(int n) throws X {
        float[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public float[] hasLengthOfAtLeast(int n) throws X {
        float[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public float[] hasLengthOfAtMost(int n) throws X {
        float[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it contains the value.
     *
     * @throws X if the subject is null or does not contain the value.
     */
    public float[] contains(float value) throws X {
        float[] subject = getSubject();
        if (null == subject || !containsHelper(subject, value)) {
            fail("t -> t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it does not contain the value.
     *
     * @throws X if the subject is null or does contain the value.
     */
    public float[] doesNotContain(float value) throws X {
        float[] subject = getSubject();
        if (null == subject || containsHelper(subject, value)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static boolean containsHelper(float[] array, float value) {
        for (float next : Objects.requireNonNull(array, ValidityUtils.nullArgumentMessage("array"))) {
            if (Float.compare(next, value) == 0) {
                return true;
            }
        }
        return false;
    }
} public final class VerifiableIntArray<X extends Throwable>
           extends AbstractVerifiableObject<int[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableIntArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableIntArray(FailedValidationExecutor<X> failedValidationExecutor,
                              int[] subject,
                              Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public int[] isEqualTo(int[] other) throws X {
        int[] subject = getSubject();
        if (null == subject || !Arrays.equals(subject, other)) {
            fail("t -> Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public int[] isNotEqualTo(int[] other) throws X {
        int[] subject = getSubject();
        if (null == subject || Arrays.equals(subject, other)) {
            fail("t -> !Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public int[] isEmpty() throws X {
        int[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public int[] isNotEmpty() throws X {
        int[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public int[] hasLengthOf(int n) throws X {
        int[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public int[] hasLengthOfAtLeast(int n) throws X {
        int[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public int[] hasLengthOfAtMost(int n) throws X {
        int[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it contains the value.
     *
     * @throws X if the subject is null or does not contain the value.
     */
    public int[] contains(int value) throws X {
        int[] subject = getSubject();
        if (null == subject || !containsHelper(subject, value)) {
            fail("t -> t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it does not contain the value.
     *
     * @throws X if the subject is null or does contain the value.
     */
    public int[] doesNotContain(int value) throws X {
        int[] subject = getSubject();
        if (null == subject || containsHelper(subject, value)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static boolean containsHelper(int[] array, int value) {
        for (int next : Objects.requireNonNull(array, ValidityUtils.nullArgumentMessage("array"))) {
            if (next == value) {
                return true;
            }
        }
        return false;
    }
} public final class VerifiableLongArray<X extends Throwable>
           extends AbstractVerifiableObject<long[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableLongArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableLongArray(FailedValidationExecutor<X> failedValidationExecutor,
                               long[] subject,
                               Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public long[] isEqualTo(long[] other) throws X {
        long[] subject = getSubject();
        if (null == subject || !Arrays.equals(subject, other)) {
            fail("t -> Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public long[] isNotEqualTo(long[] other) throws X {
        long[] subject = getSubject();
        if (null == subject || Arrays.equals(subject, other)) {
            fail("t -> !Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public long[] isEmpty() throws X {
        long[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public long[] isNotEmpty() throws X {
        long[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public long[] hasLengthOf(int n) throws X {
        long[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public long[] hasLengthOfAtLeast(int n) throws X {
        long[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public long[] hasLengthOfAtMost(int n) throws X {
        long[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it contains the value.
     *
     * @throws X if the subject is null or does not contain the value.
     */
    public long[] contains(long value) throws X {
        long[] subject = getSubject();
        if (null == subject || !containsHelper(subject, value)) {
            fail("t -> t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it does not contain the value.
     *
     * @throws X if the subject is null or does contain the value.
     */
    public long[] doesNotContain(long value) throws X {
        long[] subject = getSubject();
        if (null == subject || containsHelper(subject, value)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static boolean containsHelper(long[] array, long value) {
        for (long next : Objects.requireNonNull(array, ValidityUtils.nullArgumentMessage("array"))) {
            if (next == value) {
                return true;
            }
        }
        return false;
    }
} public final class VerifiableShortArray<X extends Throwable>
           extends AbstractVerifiableObject<short[], X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableShortArray} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableShortArray(FailedValidationExecutor<X> failedValidationExecutor,
                                short[] subject,
                                Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public short[] isEqualTo(short[] other) throws X {
        short[] subject = getSubject();
        if (null == subject || !Arrays.equals(subject, other)) {
            fail("t -> Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public short[] isNotEqualTo(short[] other) throws X {
        short[] subject = getSubject();
        if (null == subject || Arrays.equals(subject, other)) {
            fail("t -> !Arrays.equals(t, " + ValidityUtils.describe(other) + ")");
        }
        return subject;
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public short[] isEmpty() throws X {
        short[] subject = getSubject();
        if (null == subject || subject.length != 0) {
            fail("t -> t.length == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public short[] isNotEmpty() throws X {
        short[] subject = getSubject();
        if (null == subject || subject.length == 0) {
            fail("t -> t.length != 0");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length equals "n".
     *
     * @throws X if the subject is null or if it's length isn't "n".
     */
    public short[] hasLengthOf(int n) throws X {
        short[] subject = getSubject();
        if (null == subject || subject.length != n) {
            fail("t -> t.length == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is greater than or equal to "n".
     *
     * @throws X if the subject is null or has length less than "n".
     */
    public short[] hasLengthOfAtLeast(int n) throws X {
        short[] subject = getSubject();
        if (null == subject || subject.length < n) {
            fail("t -> t.length >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject length.
     *
     * @return the subject if its length is less than or equal to "n".
     *
     * @throws X if the subject is null or has length greater than "n".
     */
    public short[] hasLengthOfAtMost(int n) throws X {
        short[] subject = getSubject();
        if (null == subject || subject.length > n) {
            fail("t -> t.length <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it contains the value.
     *
     * @throws X if the subject is null or does not contain the value.
     */
    public short[] contains(short value) throws X {
        short[] subject = getSubject();
        if (null == subject || !containsHelper(subject, value)) {
            fail("t -> t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    /**
     * @param value the value to look for in the array.
     *
     * @return the subject if it does not contain the value.
     *
     * @throws X if the subject is null or does contain the value.
     */
    public short[] doesNotContain(short value) throws X {
        short[] subject = getSubject();
        if (null == subject || containsHelper(subject, value)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(value) + ")");
        }
        return subject;
    }

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static boolean containsHelper(short[] array, short value) {
        for (short next : Objects.requireNonNull(array, ValidityUtils.nullArgumentMessage("array"))) {
            if (next == value) {
                return true;
            }
        }
        return false;
    }
} public final class VerifiableBoolean<X extends Throwable>
           extends AbstractVerifiableObject<Boolean, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableBoolean} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableBoolean(FailedValidationExecutor<X> failedValidationExecutor,
                             Boolean subject,
                             Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @return the Boolean true if the subject is true.
     *
     * @throws X if the subject is null or false.
     */
    public Boolean isTrue() throws X {
        Boolean subject = getSubject();
        if (null == subject || !subject) {
            fail("t -> t");
        }
        return subject;
    }

    /**
     * @return the Boolean false if the subject is false.
     *
     * @throws X if the subject is null or true.
     */
    public Boolean isFalse() throws X {
        Boolean subject = getSubject();
        if (null == subject || subject) {
            fail("t -> !t");
        }
        return subject;
    }
} public final class VerifiableByte<X extends Throwable>
           extends AbstractVerifiableComparableNumber<Byte, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Constants
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static final Byte ZERO = 0;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableByte} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableByte(FailedValidationExecutor<X> failedValidationExecutor,
                          Byte subject,
                          Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    @Override
    protected Byte getZero() {
        return ZERO;
    }
} public final class VerifiableCharacter<X extends Throwable>
           extends AbstractVerifiableComparable<Character, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableCharacter} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableCharacter(FailedValidationExecutor<X> failedValidationExecutor,
                               Character subject,
                               Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @return the subject if it is upper case.
     *
     * @throws X if the subject is null or not upper case.
     */
    public Character isUpperCase() throws X {
        Character subject = getSubject();
        if (null == subject || !Character.isUpperCase(subject)) {
            fail("t -> Character.isUpperCase(t)");
        }
        return subject;
    }

    /**
     * @return the subject if it is lower case.
     *
     * @throws X if the subject is null or not lower case.
     */
    public Character isLowerCase() throws X {
        Character subject = getSubject();
        if (null == subject || !Character.isLowerCase(subject)) {
            fail("t -> Character.isLowerCase(t)");
        }
        return subject;
    }

    /**
     * @return the subject if it is a letter or digit case.
     *
     * @throws X if the subject is null is not a letter or digit.
     */
    public Character isLetterOrDigit() throws X {
        Character subject = getSubject();
        if (null == subject || !Character.isLetterOrDigit(subject)) {
            fail("t -> Character.isLetterOrDigit(t)");
        }
        return subject;
    }

    /**
     * @return the subject if it is alphabetic.
     *
     * @throws X if the subject is null or is not alphabetic.
     */
    public Character isAlphabetic() throws X {
        Character subject = getSubject();
        if (null == subject || !Character.isAlphabetic(subject)) {
            fail("t -> Character.isAlphabetic(t)");
        }
        return subject;
    }

    /**
     * @return the subject if it is a digit.
     *
     * @throws X if the subject is null or is not a digit.
     */
    public Character isDigit() throws X {
        Character subject = getSubject();
        if (null == subject || !Character.isDigit(subject)) {
            fail("t -> Character.isDigit(t)");
        }
        return subject;
    }
} public final class VerifiableClass<T, X extends Throwable>
           extends AbstractVerifiableObject<Class<T>, X> {

    /**
     * Create a new {@link VerifiableClass} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableClass(FailedValidationExecutor<X> failedValidationExecutor,
                           Class<T> subject,
                           Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @param clazz the class to check if the subject is assignable from.
     *
     * @return the subject if it is assignable from clazz.
     *
     * @throws X if the subject is null or is not assignable from clazz.
     */
    public Class<T> isAssignableFrom(Class<?> clazz) throws X {
        Class<T> subject = getSubject();
        if (null == subject || !subject.isAssignableFrom(clazz)) {
            fail("t -> t.isAssignableFrom(" + ValidityUtils.describe(clazz) + ")");
        }
        return subject;
    }

    /**
     * @param clazz the annotation to check for on the subject.
     *
     * @return the subject if it has the clazz annotation.
     *
     * @throws X if the subject is null or does not have the clazz annotation.
     */
    public Class<T> hasAnnotation(Class<? extends Annotation> clazz) throws X {
        Class<T> subject = getSubject();
        if (null == subject || null == subject.getAnnotation(clazz)) {
            fail("t -> null != t.getAnnotation(" + ValidityUtils.describe(clazz) + ")");
        }
        return subject;
    }
} public final class VerifiableCollection<E, T extends Collection<E>, X extends Throwable>
           extends AbstractVerifiableObject<T, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableCollection} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableCollection(FailedValidationExecutor<X> failedValidationExecutor,
                                T subject,
                                Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or is not empty.
     */
    public T isEmpty() throws X {
        T subject = getSubject();
        if (null == subject || !subject.isEmpty()) {
            fail("t -> t.isEmpty()");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or is empty.
     */
    public T isNotEmpty() throws X {
        T subject = getSubject();
        if (null == subject || subject.isEmpty()) {
            fail("t -> !t.isEmpty()");
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject size.
     *
     * @return the subject if its size equals "n".
     *
     * @throws X if the subject is null or if it's size isn't "n".
     */
    public T hasSizeOf(int n) throws X {
        T subject = getSubject();
        if (null == subject || subject.size() != n) {
            fail("t -> t.size() == " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject size.
     *
     * @return the subject if its size is greater than or equal to "n".
     *
     * @throws X if the subject is null or has size less than "n".
     */
    public T hasSizeOfAtLeast(int n) throws X {
        T subject = getSubject();
        if (null == subject || subject.size() < n) {
            fail("t -> t.size() >= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param n the value to check against the subject size.
     *
     * @return the subject if its size is less than or equal to "n".
     *
     * @throws X if the subject is null or has size greater than "n".
     */
    public T hasSizeOfAtMost(int n) throws X {
        T subject = getSubject();
        if (null == subject || subject.size() > n) {
            fail("t -> t.size() <= " + ValidityUtils.describe(n));
        }
        return subject;
    }

    /**
     * @param e the object to check if the subject contains.
     *
     * @return the subject if it contains "e".
     *
     * @throws X if the subject is null or does not contain "e".
     */
    public T contains(E e) throws X {
        T subject = getSubject();
        if (null == subject || !subject.contains(e)) {
            fail("t -> t.contains(" + ValidityUtils.describe(e) + ")");
        }
        return subject;
    }

    /**
     * @param e the object to check if the subject contains.
     *
     * @return the subject if it does not contain "e".
     *
     * @throws X if the subject is null or does contain "e".
     */
    public T doesNotContain(E e) throws X {
        T subject = getSubject();
        if (null == subject || subject.contains(e)) {
            fail("t -> !t.contains(" + ValidityUtils.describe(e) + ")");
        }
        return subject;
    }
} public final class VerifiableDouble<X extends Throwable>
           extends AbstractVerifiableComparableNumber<Double, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Constants
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static final Double ZERO = 0.0;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableDouble} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableDouble(FailedValidationExecutor<X> failedValidationExecutor,
                            Double subject,
                            Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    @Override
    protected Double getZero() {
        return ZERO;
    }
} public final class VerifiableDuration<X extends Throwable>
           extends AbstractVerifiableComparable<Duration, X> {

    /**
     * Create a new {@link AbstractVerifiableObject} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     * @throws NullPointerException if failedValidationExecutor is null.
     */
    public VerifiableDuration(FailedValidationExecutor<X> failedValidationExecutor,
                              Duration subject,
                              Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @return the subject if it is zero.
     *
     * @throws X if the subject is null or is not zero.
     */
    public Duration isZero() throws X {
        Duration subject = getSubject();
        if (null == subject || !subject.isZero()) {
            fail("t -> t.isZero()");
        }
        return subject;
    }

    /**
     * @return the subject if it is not zero.
     *
     * @throws X if the subject is null or is zero.
     */
    public Duration isNotZero() throws X {
        Duration subject = getSubject();
        if (null == subject || subject.isZero()) {
            fail("t -> !t.isZero()");
        }
        return subject;
    }

    /**
     * @return the subject if it is zero or non-negative.
     *
     * @throws X if the subject is null or negative.
     */
    public Duration isGreaterThanOrEqualToZero() throws X {
        Duration subject = getSubject();
        if (null == subject || subject.isNegative()) {
            fail("t -> !t.isNegative()");
        }
        return subject;
    }

    /**
     * @return the subject if is it negative or zero.
     *
     * @throws X if the subject is null, or neither negative or zero.
     */
    public Duration isLessThanOrEqualToZero() throws X {
        Duration subject = getSubject();
        if (null == subject || !(subject.isZero() || subject.isNegative())) {
            fail("t -> !(t.isZero() || t.isNegative())");
        }
        return subject;
    }

    /**
     * @return the subject if it is not zero and not negative.
     *
     * @throws X if the subject is null, is zero, or is positive.
     */
    public Duration isStrictlyNegative() throws X {
        Duration subject = getSubject();
        if (null == subject || !subject.isNegative()) {
            fail("t -> t.isNegative()");
        }
        return subject;
    }

    /**
     * @return the subject if it is not zero and not positive.
     *
     * @throws X if the subject is null, is zero, or is negative.
     */
    public Duration isStrictlyPositive() throws X {
        Duration subject = getSubject();
        if (null == subject || subject.isZero() || subject.isNegative()) {
            fail("t -> !t.isZero() && !t.isNegative()");
        }
        return subject;
    }
} public final class VerifiableFloat<X extends Throwable>
           extends AbstractVerifiableComparableNumber<Float, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Constants
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static final Float ZERO = 0F;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableFloat} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableFloat(FailedValidationExecutor<X> failedValidationExecutor,
                           Float subject,
                           Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    @Override
    protected Float getZero() {
        return ZERO;
    }
} public final class VerifiableInstant<X extends Throwable>
           extends AbstractVerifiableComparable<Instant, X> {

    /**
     * Create a new {@link AbstractVerifiableComparable} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableInstant(FailedValidationExecutor<X> failedValidationExecutor,
                             Instant subject,
                             Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }
} public final class VerifiableInteger<X extends Throwable>
           extends AbstractVerifiableComparableNumber<Integer, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Constants
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static final Integer ZERO = 0;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableInteger} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableInteger(FailedValidationExecutor<X> failedValidationExecutor,
                             Integer subject,
                             Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    @Override
    protected Integer getZero() {
        return ZERO;
    }
} public final class VerifiableLong<X extends Throwable>
           extends AbstractVerifiableComparableNumber<Long, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Constants
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static final Long ZERO = 0L;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableLong} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableLong(FailedValidationExecutor<X> failedValidationExecutor,
                          Long subject,
                          Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    @Override
    protected Long getZero() {
        return ZERO;
    }
} public final class VerifiableObject<T, X extends Throwable>
           extends AbstractVerifiableObject<T, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableObject} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableObject(FailedValidationExecutor<X> failedValidationExecutor,
                            T subject,
                            Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }
} public final class VerifiableShort<X extends Throwable>
           extends AbstractVerifiableComparableNumber<Short, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Constants
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private static final Short ZERO = 0;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableShort} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableShort(FailedValidationExecutor<X> failedValidationExecutor,
                           Short subject,
                           Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    @Override
    protected Short getZero() {
        return ZERO;
    }
} public final class VerifiableString<X extends Throwable>
           extends AbstractVerifiableComparable<String, X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiableString} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     *                                 May be null.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiableString(FailedValidationExecutor<X> failedValidationExecutor,
                            String subject,
                            Supplier<String> messageSupplier) {
        super(failedValidationExecutor, subject, messageSupplier);
    }

    /**
     * @return the subject if it is empty.
     *
     * @throws X if the subject is null or not empty.
     */
    public String isEmpty() throws X {
        String subject = getSubject();
        if (null == subject || !subject.isEmpty()) {
            fail("t -> t.isEmpty()");
        }
        return subject;
    }

    /**
     * @return the subject if it is not empty.
     *
     * @throws X if the subject is null or empty.
     */
    public String isNotEmpty() throws X {
        String subject = getSubject();
        if (null == subject || subject.isEmpty()) {
            fail("t -> !t.isEmpty()");
        }
        return subject;
    }

    /**
     * @param prefix the String prefix the subject should start with.
     *
     * @return the subject if it starts with the prefix.
     *
     * @throws X if the subject is null or does not start with the prefix.
     */
    public String startsWith(String prefix) throws X {
        String subject = getSubject();
        if (null == subject || !subject.startsWith(prefix)) {
            fail("t -> t.startsWith(" + ValidityUtils.describe(prefix) + ")");
        }
        return subject;
    }

    /**
     * @param prefix the String prefix the subject should not start with.
     *
     * @return the subject if it does not start with the prefix.
     *
     * @throws X if the subject is null or does start with the prefix.
     */
    public String doesNotStartWith(String prefix) throws X {
        String subject = getSubject();
        if (null == subject || subject.startsWith(prefix)) {
            fail("t -> !t.startsWith(" + ValidityUtils.describe(prefix) + ")");
        }
        return subject;
    }

    /**
     * @param suffix the String suffix the subject should end with.
     *
     * @return the subject if it ends with the suffix.
     *
     * @throws X if the subject is null or does not end with the suffix.
     */
    public String endsWith(String suffix) throws X {
        String subject = getSubject();
        if (null == subject || !subject.endsWith(suffix)) {
            fail("t -> t.endsWith(" + ValidityUtils.describe(suffix) + ")");
        }
        return subject;
    }

    /**
     * @param suffix the String suffix the subject should not end with.
     *
     * @return the subject if it does not end with the suffix.
     *
     * @throws X if the subject is null or does end with the suffix.
     */
    public String doesNotEndWith(String suffix) throws X {
        String subject = getSubject();
        if (null == subject || subject.endsWith(suffix)) {
            fail("t -> !t.endsWith(" + ValidityUtils.describe(suffix) + ")");
        }
        return subject;
    }

    /**
     * @param regex the String regex the subject should match.
     *
     * @return the subject if it does match the regex.
     *
     * @throws X if the subject is null or does not match the regex.
     */
    public String matches(String regex) throws X {
        String subject = getSubject();
        if (null == subject || !subject.matches(regex)) {
            fail("t -> t.matches(" + ValidityUtils.describe(regex) + ")");
        }
        return subject;
    }

    /**
     * @param regex the String regex the subject should not match.
     *
     * @return the subject if it does not match the regex.
     *
     * @throws X if the subject is null or does match the regex.
     */
    public String doesNotMatch(String regex) throws X {
        String subject = getSubject();
        if (null == subject || subject.matches(regex)) {
            fail("t -> !t.matches(" + ValidityUtils.describe(regex) + ")");
        }
        return subject;
    }
} public final class VerifiablePrimitiveBoolean<X extends Throwable>
           extends AbstractVerifiablePrimitive<X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Fields
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private final boolean subject;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiablePrimitiveBoolean} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiablePrimitiveBoolean(FailedValidationExecutor<X> failedValidationExecutor,
                                      boolean subject,
                                      Supplier<String> messageSupplier) {
        super(failedValidationExecutor, messageSupplier);
        this.subject = subject;
    }

    /**
     * @return the Boolean true if the subject is true.
     *
     * @throws X if the subject is null or false.
     */
    public boolean isTrue() throws X {
        if (!subject) {
            fail("t -> t");
        }
        return subject;
    }

    /**
     * @return the Boolean false if the subject is false.
     *
     * @throws X if the subject is null or true.
     */
    public boolean isFalse() throws X {
        if (subject) {
            fail("t -> !t");
        }
        return subject;
    }

    /**
     * @param expected the String description of the expected value.
     *
     * @throws NullPointerException if expected is null.
     * @throws X                    always, unless expected is null.
     */
    protected void fail(String expected) throws X {
        getFailedValidationExecutor().fail(expected, subject, getMessageSupplier());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": <" + ValidityUtils.describe(subject) + ">";
    }
} public final class VerifiablePrimitiveByte<X extends Throwable>
           extends AbstractVerifiablePrimitive<X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Fields
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private final byte subject;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiablePrimitiveByte} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiablePrimitiveByte(FailedValidationExecutor<X> failedValidationExecutor,
                                   byte subject,
                                   Supplier<String> messageSupplier) {
        super(failedValidationExecutor, messageSupplier);
        this.subject = subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public byte isEqualTo(byte other) throws X {
        if (subject != other) {
            fail("t -> t == " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public byte isNotEqualTo(byte other) throws X {
        if (subject == other) {
            fail("t -> t != " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @return the subject if it is comparable to zero.
     *
     * @throws X if the subject is not zero.
     */
    public byte isZero() throws X {
        if (subject != 0) {
            fail("t -> t == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not comparable to zero.
     *
     * @throws X if the subject is zero.
     */
    public byte isNotZero() throws X {
        if (subject == 0) {
            fail("t -> t != 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is greater than zero.
     *
     * @throws X if the subject is less than or equal to zero.
     */
    public byte isStrictlyPositive() throws X {
        return isGreaterThan((byte) 0);
    }

    /**
     * @return the subject if it is less than zero.
     *
     * @throws X if the subject is greater than or equal to zero.
     */
    public byte isStrictlyNegative() throws X {
        return isLessThan((byte) 0);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than other.
     *
     * @throws X if the subject is null or not greater than other.
     */
    public byte isGreaterThan(byte other) throws X {
        if (subject <= other) {
            fail("t -> t > " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public byte isGreaterThanOrEqualTo(byte other) throws X {
        if (subject < other) {
            fail("t -> t >= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public byte isAtLeast(byte other) throws X {
        return isGreaterThanOrEqualTo(other);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than other.
     *
     * @throws X if the subject is null or is not less than other.
     */
    public byte isLessThan(byte other) throws X {
        if (subject >= other) {
            fail("t -> t < " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to to other.
     */
    public byte isLessThanOrEqualTo(byte other) throws X {
        if (subject > other) {
            fail("t -> t <= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to other.
     */
    public byte isAtMost(byte other) throws X {
        return isLessThanOrEqualTo(other);
    }

    /**
     * Tests the subject with the given predicate. Note that any {@link Throwable} thrown
     * during the testing of the predicate is not handled and will be thrown instead
     * of the usual throwable for this verifiable instance.
     *
     * @param expected the {@link IntPredicate} to use to test the subject.
     *                 May not be null.
     *
     * @return the subject if it satisfies the predicate.
     *
     * @throws X                    if the subject does not satisfy the predicate.
     * @throws NullPointerException if expected is null.
     */
    public byte satisfies(IntPredicate expected) throws X {
        if (null == expected) {
            throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected"));
        }
        if (!expected.test(subject)) {
            fail(ValidityUtils.describe(expected));
        }
        return subject;
    }

    /**
     * @param expected the String description of the expected value.
     *
     * @throws NullPointerException if expected is null.
     * @throws X                    always, unless expected is null.
     */
    protected void fail(String expected) throws X {
        getFailedValidationExecutor().fail(expected, subject, getMessageSupplier());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": <" + ValidityUtils.describe(subject) + ">";
    }
} public final class VerifiablePrimitiveChar<X extends Throwable>
           extends AbstractVerifiablePrimitive<X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Fields
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private final char subject;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiablePrimitiveChar} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiablePrimitiveChar(FailedValidationExecutor<X> failedValidationExecutor,
                                   char subject,
                                   Supplier<String> messageSupplier) {
        super(failedValidationExecutor, messageSupplier);
        this.subject = subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public char isEqualTo(char other) throws X {
        if (subject != other) {
            fail("t -> t == " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public char isNotEqualTo(char other) throws X {
        if (subject == other) {
            fail("t -> t != " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than other.
     *
     * @throws X if the subject is null or not greater than other.
     */
    public char isGreaterThan(char other) throws X {
        if (subject <= other) {
            fail("t -> t > " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public char isGreaterThanOrEqualTo(char other) throws X {
        if (subject < other) {
            fail("t -> t >= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public char isAtLeast(char other) throws X {
        return isGreaterThanOrEqualTo(other);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than other.
     *
     * @throws X if the subject is null or is not less than other.
     */
    public char isLessThan(char other) throws X {
        if (subject >= other) {
            fail("t -> t < " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to to other.
     */
    public char isLessThanOrEqualTo(char other) throws X {
        if (subject > other) {
            fail("t -> t <= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to other.
     */
    public char isAtMost(char other) throws X {
        return isLessThanOrEqualTo(other);
    }

    /**
     * @return the subject if it is upper case.
     *
     * @throws X if the subject is null or not upper case.
     */
    public Character isUpperCase() throws X {
        if (!Character.isUpperCase(subject)) {
            fail("t -> Character.isUpperCase(t)");
        }
        return subject;
    }

    /**
     * @return the subject if it is lower case.
     *
     * @throws X if the subject is null or not lower case.
     */
    public char isLowerCase() throws X {
        if (!Character.isLowerCase(subject)) {
            fail("t -> Character.isLowerCase(t)");
        }
        return subject;
    }

    /**
     * @return the subject if it is a letter or digit case.
     *
     * @throws X if the subject is null is not a letter or digit.
     */
    public char isLetterOrDigit() throws X {
        if (!Character.isLetterOrDigit(subject)) {
            fail("t -> Character.isLetterOrDigit(t)");
        }
        return subject;
    }

    /**
     * @return the subject if it is alphabetic.
     *
     * @throws X if the subject is null or is not alphabetic.
     */
    public char isAlphabetic() throws X {
        if (!Character.isAlphabetic(subject)) {
            fail("t -> Character.isAlphabetic(t)");
        }
        return subject;
    }

    /**
     * @return the subject if it is a digit.
     *
     * @throws X if the subject is null or is not a digit.
     */
    public char isDigit() throws X {
        if (!Character.isDigit(subject)) {
            fail("t -> Character.isDigit(t)");
        }
        return subject;
    }

    /**
     * Tests the subject with the given predicate. Note that any {@link Throwable} thrown
     * during the testing of the predicate is not handled and will be thrown instead
     * of the usual throwable for this verifiable instance.
     *
     * @param expected the {@link IntPredicate} to use to test the subject.
     *                 May not be null.
     *
     * @return the subject if it satisfies the predicate.
     *
     * @throws X                    if the subject does not satisfy the predicate.
     * @throws NullPointerException if expected is null.
     */
    public char satisfies(IntPredicate expected) throws X {
        if (null == expected) {
            throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected"));
        }
        if (!expected.test(subject)) {
            fail(ValidityUtils.describe(expected));
        }
        return subject;
    }

    /**
     * @param expected the String description of the expected value.
     *
     * @throws NullPointerException if expected is null.
     * @throws X                    always, unless expected is null.
     */
    protected void fail(String expected) throws X {
        getFailedValidationExecutor().fail(expected, subject, getMessageSupplier());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": <" + ValidityUtils.describe(subject) + ">";
    }
} public final class VerifiablePrimitiveDouble<X extends Throwable>
           extends AbstractVerifiablePrimitive<X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Fields
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private final double subject;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiablePrimitiveDouble} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiablePrimitiveDouble(FailedValidationExecutor<X> failedValidationExecutor,
                                     double subject,
                                     Supplier<String> messageSupplier) {
        super(failedValidationExecutor, messageSupplier);
        this.subject = subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public double isEqualTo(double other) throws X {
        if (subject != other) {
            fail("t -> t == " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public double isNotEqualTo(double other) throws X {
        if (subject == other) {
            fail("t -> t != " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @return the subject if it is comparable to zero.
     *
     * @throws X if the subject is not zero.
     */
    public double isZero() throws X {
        if (subject != 0) {
            fail("t -> t == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not comparable to zero.
     *
     * @throws X if the subject is zero.
     */
    public double isNotZero() throws X {
        if (subject == 0) {
            fail("t -> t != 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is greater than zero.
     *
     * @throws X if the subject is less than or equal to zero.
     */
    public double isStrictlyPositive() throws X {
        return isGreaterThan((double) 0);
    }

    /**
     * @return the subject if it is less than zero.
     *
     * @throws X if the subject is greater than or equal to zero.
     */
    public double isStrictlyNegative() throws X {
        return isLessThan((double) 0);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than other.
     *
     * @throws X if the subject is null or not greater than other.
     */
    public double isGreaterThan(double other) throws X {
        if (subject <= other) {
            fail("t -> t > " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public double isGreaterThanOrEqualTo(double other) throws X {
        if (subject < other) {
            fail("t -> t >= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public double isAtLeast(double other) throws X {
        return isGreaterThanOrEqualTo(other);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than other.
     *
     * @throws X if the subject is null or is not less than other.
     */
    public double isLessThan(double other) throws X {
        if (subject >= other) {
            fail("t -> t < " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to to other.
     */
    public double isLessThanOrEqualTo(double other) throws X {
        if (subject > other) {
            fail("t -> t <= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to other.
     */
    public double isAtMost(double other) throws X {
        return isLessThanOrEqualTo(other);
    }

    /**
     * Tests the subject with the given predicate. Note that any {@link Throwable} thrown
     * during the testing of the predicate is not handled and will be thrown instead
     * of the usual throwable for this verifiable instance.
     *
     * @param expected the {@link DoublePredicate} to use to test the subject.
     *                 May not be null.
     *
     * @return the subject if it satisfies the predicate.
     *
     * @throws X                    if the subject does not satisfy the predicate.
     * @throws NullPointerException if expected is null.
     */
    public double satisfies(DoublePredicate expected) throws X {
        if (null == expected) {
            throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected"));
        }
        if (!expected.test(subject)) {
            fail(ValidityUtils.describe(expected));
        }
        return subject;
    }

    /**
     * @param expected the String description of the expected value.
     *
     * @throws NullPointerException if expected is null.
     * @throws X                    always, unless expected is null.
     */
    protected void fail(String expected) throws X {
        getFailedValidationExecutor().fail(expected, subject, getMessageSupplier());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": <" + ValidityUtils.describe(subject) + ">";
    }
} public final class VerifiablePrimitiveFloat<X extends Throwable>
           extends AbstractVerifiablePrimitive<X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Fields
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private final float subject;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiablePrimitiveFloat} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiablePrimitiveFloat(FailedValidationExecutor<X> failedValidationExecutor,
                                    float subject,
                                    Supplier<String> messageSupplier) {
        super(failedValidationExecutor, messageSupplier);
        this.subject = subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public float isEqualTo(float other) throws X {
        if (subject != other) {
            fail("t -> t == " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public float isNotEqualTo(float other) throws X {
        if (subject == other) {
            fail("t -> t != " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @return the subject if it is comparable to zero.
     *
     * @throws X if the subject is not zero.
     */
    public float isZero() throws X {
        if (subject != 0) {
            fail("t -> t == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not comparable to zero.
     *
     * @throws X if the subject is zero.
     */
    public float isNotZero() throws X {
        if (subject == 0) {
            fail("t -> t != 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is greater than zero.
     *
     * @throws X if the subject is less than or equal to zero.
     */
    public float isStrictlyPositive() throws X {
        return isGreaterThan((float) 0);
    }

    /**
     * @return the subject if it is less than zero.
     *
     * @throws X if the subject is greater than or equal to zero.
     */
    public float isStrictlyNegative() throws X {
        return isLessThan((float) 0);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than other.
     *
     * @throws X if the subject is null or not greater than other.
     */
    public float isGreaterThan(float other) throws X {
        if (subject <= other) {
            fail("t -> t > " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public float isGreaterThanOrEqualTo(float other) throws X {
        if (subject < other) {
            fail("t -> t >= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public float isAtLeast(float other) throws X {
        return isGreaterThanOrEqualTo(other);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than other.
     *
     * @throws X if the subject is null or is not less than other.
     */
    public float isLessThan(float other) throws X {
        if (subject >= other) {
            fail("t -> t < " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to to other.
     */
    public float isLessThanOrEqualTo(float other) throws X {
        if (subject > other) {
            fail("t -> t <= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to other.
     */
    public float isAtMost(float other) throws X {
        return isLessThanOrEqualTo(other);
    }

    /**
     * Tests the subject with the given predicate. Note that any {@link Throwable} thrown
     * during the testing of the predicate is not handled and will be thrown instead
     * of the usual throwable for this verifiable instance.
     *
     * @param expected the {@link DoublePredicate} to use to test the subject.
     *                 May not be null.
     *
     * @return the subject if it satisfies the predicate.
     *
     * @throws X                    if the subject does not satisfy the predicate.
     * @throws NullPointerException if expected is null.
     */
    public float satisfies(DoublePredicate expected) throws X {
        if (null == expected) {
            throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected"));
        }
        if (!expected.test(subject)) {
            fail(ValidityUtils.describe(expected));
        }
        return subject;
    }

    /**
     * @param expected the String description of the expected value.
     *
     * @throws NullPointerException if expected is null.
     * @throws X                    always, unless expected is null.
     */
    protected void fail(String expected) throws X {
        getFailedValidationExecutor().fail(expected, subject, getMessageSupplier());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": <" + ValidityUtils.describe(subject) + ">";
    }
} public final class VerifiablePrimitiveInt<X extends Throwable>
           extends AbstractVerifiablePrimitive<X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Fields
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private final int subject;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiablePrimitiveInt} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiablePrimitiveInt(FailedValidationExecutor<X> failedValidationExecutor,
                                  int subject,
                                  Supplier<String> messageSupplier) {
        super(failedValidationExecutor, messageSupplier);
        this.subject = subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is equal to other.
     *
     * @throws X if the subject is null or if it is not equal to other.
     */
    public int isEqualTo(int other) throws X {
        if (subject != other) {
            fail("t -> t == " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     *
     * @return the subject if it is not equal to other.
     *
     * @throws X if the subject is null or if it is equal to other.
     */
    public int isNotEqualTo(int other) throws X {
        if (subject == other) {
            fail("t -> t != " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @return the subject if it is comparable to zero.
     *
     * @throws X if the subject is not zero.
     */
    public int isZero() throws X {
        if (subject != 0) {
            fail("t -> t == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not comparable to zero.
     *
     * @throws X if the subject is zero.
     */
    public int isNotZero() throws X {
        if (subject == 0) {
            fail("t -> t != 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is greater than zero.
     *
     * @throws X if the subject is less than or equal to zero.
     */
    public int isStrictlyPositive() throws X {
        return isGreaterThan(0);
    }

    /**
     * @return the subject if it is less than zero.
     *
     * @throws X if the subject is greater than or equal to zero.
     */
    public int isStrictlyNegative() throws X {
        return isLessThan(0);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than other.
     *
     * @throws X if the subject is null or not greater than other.
     */
    public int isGreaterThan(int other) throws X {
        if (subject <= other) {
            fail("t -> t > " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public int isGreaterThanOrEqualTo(int other) throws X {
        if (subject < other) {
            fail("t -> t >= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is greater than or equal to other.
     *
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public int isAtLeast(int other) throws X {
        return isGreaterThanOrEqualTo(other);
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than other.
     *
     * @throws X if the subject is null or is not less than other.
     */
    public int isLessThan(int other) throws X {
        if (subject >= other) {
            fail("t -> t < " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to to other.
     */
    public int isLessThanOrEqualTo(int other) throws X {
        if (subject > other) {
            fail("t -> t <= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     *
     * @return the subject if it is less than or equal to other.
     *
     * @throws X if the subject is null or is not less than or equal to other.
     */
    public int isAtMost(int other) throws X {
        return isLessThanOrEqualTo(other);
    }

    /**
     * Tests the subject with the given predicate. Note that any {@link Throwable} thrown
     * during the testing of the predicate is not handled and will be thrown instead
     * of the usual throwable for this verifiable instance.
     *
     * @param expected the {@link IntPredicate} to use to test the subject.
     *                 May not be null.
     *
     * @return the subject if it satisfies the predicate.
     *
     * @throws X                    if the subject does not satisfy the predicate.
     * @throws NullPointerException if expected is null.
     */
    public int satisfies(IntPredicate expected) throws X {
        if (null == expected) {
            throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected"));
        }
        if (!expected.test(subject)) {
            fail(ValidityUtils.describe(expected));
        }
        return subject;
    }

    /**
     * @param expected the String description of the expected value.
     *
     * @throws NullPointerException if expected is null.
     * @throws X                    always, unless expected is null.
     */
    protected void fail(String expected) throws X {
        getFailedValidationExecutor().fail(expected, subject, getMessageSupplier());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": <" + ValidityUtils.describe(subject) + ">";
    }
} public final class VerifiablePrimitiveLong<X extends Throwable>
           extends AbstractVerifiablePrimitive<X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Fields
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private final long subject;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiablePrimitiveLong} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiablePrimitiveLong(FailedValidationExecutor<X> failedValidationExecutor,
                                   long subject,
                                   Supplier<String> messageSupplier) {
        super(failedValidationExecutor, messageSupplier);
        this.subject = subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     * @return the subject if it is equal to other.
     * @throws X if the subject is null or if it is not equal to other.
     */
    public long isEqualTo(long other) throws X {
        if (subject != other) {
            fail("t -> t == " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     * @return the subject if it is not equal to other.
     * @throws X if the subject is null or if it is equal to other.
     */
    public long isNotEqualTo(long other) throws X {
        if (subject == other) {
            fail("t -> t != " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @return the subject if it is comparable to zero.
     * @throws X if the subject is not zero.
     */
    public long isZero() throws X {
        if (subject != 0) {
            fail("t -> t == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not comparable to zero.
     * @throws X if the subject is zero.
     */
    public long isNotZero() throws X {
        if (subject == 0) {
            fail("t -> t != 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is greater than zero.
     * @throws X if the subject is less than or equal to zero.
     */
    public long isStrictlyPositive() throws X {
        return isGreaterThan((long) 0);
    }

    /**
     * @return the subject if it is less than zero.
     * @throws X if the subject is greater than or equal to zero.
     */
    public long isStrictlyNegative() throws X {
        return isLessThan((long) 0);
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is greater than other.
     * @throws X if the subject is null or not greater than other.
     */
    public long isGreaterThan(long other) throws X {
        if (subject <= other) {
            fail("t -> t > " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is greater than or equal to other.
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public long isGreaterThanOrEqualTo(long other) throws X {
        if (subject < other) {
            fail("t -> t >= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is greater than or equal to other.
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public long isAtLeast(long other) throws X {
        return isGreaterThanOrEqualTo(other);
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is less than other.
     * @throws X if the subject is null or is not less than other.
     */
    public long isLessThan(long other) throws X {
        if (subject >= other) {
            fail("t -> t < " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is less than or equal to other.
     * @throws X if the subject is null or is not less than or equal to to other.
     */
    public long isLessThanOrEqualTo(long other) throws X {
        if (subject > other) {
            fail("t -> t <= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is less than or equal to other.
     * @throws X if the subject is null or is not less than or equal to other.
     */
    public long isAtMost(long other) throws X {
        return isLessThanOrEqualTo(other);
    }

    /**
     * Tests the subject with the given predicate. Note that any {@link Throwable} thrown
     * during the testing of the predicate is not handled and will be thrown instead
     * of the usual throwable for this verifiable instance.
     *
     * @param expected the {@link LongPredicate} to use to test the subject.
     *                 May not be null.
     * @return the subject if it satisfies the predicate.
     * @throws X                    if the subject does not satisfy the predicate.
     * @throws NullPointerException if expected is null.
     */
    public long satisfies(LongPredicate expected) throws X {
        if (null == expected) {
            throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected"));
        }
        if (!expected.test(subject)) {
            fail(ValidityUtils.describe(expected));
        }
        return subject;
    }

    /**
     * @param expected the String description of the expected value.
     * @throws NullPointerException if expected is null.
     * @throws X                    always, unless expected is null.
     */
    protected void fail(String expected) throws X {
        getFailedValidationExecutor().fail(expected, subject, getMessageSupplier());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": <" + ValidityUtils.describe(subject) + ">";
    }
} public final class VerifiablePrimitiveShort<X extends Throwable>
           extends AbstractVerifiablePrimitive<X> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Fields
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    private final short subject;

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Instance Methods
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /**
     * Create a new {@link VerifiablePrimitiveShort} instance with the given values.
     *
     * @param failedValidationExecutor the {@link FailedValidationExecutor} to be called
     *                                 on validation failure.
     *                                 May not be null.
     * @param subject                  the subject to be validated.
     * @param messageSupplier          the {@link Supplier} of the String custom message to pre-pend a failure with.
     *                                 May not be null.
     *
     * @throws NullPointerException if failedValidationExecutor or messageSupplier are null.
     */
    public VerifiablePrimitiveShort(FailedValidationExecutor<X> failedValidationExecutor,
                                    short subject,
                                    Supplier<String> messageSupplier) {
        super(failedValidationExecutor, messageSupplier);
        this.subject = subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     * @return the subject if it is equal to other.
     * @throws X if the subject is null or if it is not equal to other.
     */
    public short isEqualTo(short other) throws X {
        if (subject != other) {
            fail("t -> t == " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to check for equality with against the subject.
     * @return the subject if it is not equal to other.
     * @throws X if the subject is null or if it is equal to other.
     */
    public short isNotEqualTo(short other) throws X {
        if (subject == other) {
            fail("t -> t != " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @return the subject if it is comparable to zero.
     * @throws X if the subject is not zero.
     */
    public short isZero() throws X {
        if (subject != 0) {
            fail("t -> t == 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is not comparable to zero.
     * @throws X if the subject is zero.
     */
    public short isNotZero() throws X {
        if (subject == 0) {
            fail("t -> t != 0");
        }
        return subject;
    }

    /**
     * @return the subject if it is greater than zero.
     * @throws X if the subject is less than or equal to zero.
     */
    public short isStrictlyPositive() throws X {
        return isGreaterThan((short) 0);
    }

    /**
     * @return the subject if it is less than zero.
     * @throws X if the subject is greater than or equal to zero.
     */
    public short isStrictlyNegative() throws X {
        return isLessThan((short) 0);
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is greater than other.
     * @throws X if the subject is null or not greater than other.
     */
    public short isGreaterThan(short other) throws X {
        if (subject <= other) {
            fail("t -> t > " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is greater than or equal to other.
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public short isGreaterThanOrEqualTo(short other) throws X {
        if (subject < other) {
            fail("t -> t >= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is greater than or equal to other.
     * @throws X if the subject is null or is not greater than or equal to other.
     */
    public short isAtLeast(short other) throws X {
        return isGreaterThanOrEqualTo(other);
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is less than other.
     * @throws X if the subject is null or is not less than other.
     */
    public short isLessThan(short other) throws X {
        if (subject >= other) {
            fail("t -> t < " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is less than or equal to other.
     * @throws X if the subject is null or is not less than or equal to to other.
     */
    public short isLessThanOrEqualTo(short other) throws X {
        if (subject > other) {
            fail("t -> t <= " + ValidityUtils.describe(other));
        }
        return subject;
    }

    /**
     * @param other the object to compare the subject against.
     * @return the subject if it is less than or equal to other.
     * @throws X if the subject is null or is not less than or equal to other.
     */
    public short isAtMost(short other) throws X {
        return isLessThanOrEqualTo(other);
    }

    /**
     * Tests the subject with the given predicate. Note that any {@link Throwable} thrown
     * during the testing of the predicate is not handled and will be thrown instead
     * of the usual throwable for this verifiable instance.
     *
     * @param expected the {@link IntPredicate} to use to test the subject.
     *                 May not be null.
     * @return the subject if it satisfies the predicate.
     * @throws X                    if the subject does not satisfy the predicate.
     * @throws NullPointerException if expected is null.
     */
    public short satisfies(IntPredicate expected) throws X {
        if (null == expected) {
            throw new NullPointerException(ValidityUtils.nullArgumentMessage("expected"));
        }
        if (!expected.test(subject)) {
            fail(ValidityUtils.describe(expected));
        }
        return subject;
    }

    /**
     * @param expected the String description of the expected value.
     * @throws NullPointerException if expected is null.
     * @throws X                    always, unless expected is null.
     */
    protected void fail(String expected) throws X {
        getFailedValidationExecutor().fail(expected, subject, getMessageSupplier());
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + ": <" + ValidityUtils.describe(subject) + ">";
    }
}
import com.redfin.validity.verifiers.arrays.VerifiableArray;
import com.redfin.validity.verifiers.arrays.VerifiableBooleanArray;
import com.redfin.validity.verifiers.arrays.VerifiableByteArray;
import com.redfin.validity.verifiers.arrays.VerifiableCharArray;
import com.redfin.validity.verifiers.arrays.VerifiableDoubleArray;
import com.redfin.validity.verifiers.arrays.VerifiableFloatArray;
import com.redfin.validity.verifiers.arrays.VerifiableIntArray;
import com.redfin.validity.verifiers.arrays.VerifiableLongArray;
import com.redfin.validity.verifiers.arrays.VerifiableShortArray;
import com.redfin.validity.verifiers.objects.VerifiableBoolean;
import com.redfin.validity.verifiers.objects.VerifiableByte;
import com.redfin.validity.verifiers.objects.VerifiableCharacter;
import com.redfin.validity.verifiers.objects.VerifiableClass;
import com.redfin.validity.verifiers.objects.VerifiableCollection;
import com.redfin.validity.verifiers.objects.VerifiableDouble;
import com.redfin.validity.verifiers.objects.VerifiableDuration;
import com.redfin.validity.verifiers.objects.VerifiableFloat;
import com.redfin.validity.verifiers.objects.VerifiableInstant;
import com.redfin.validity.verifiers.objects.VerifiableInteger;
import com.redfin.validity.verifiers.objects.VerifiableLong;
import com.redfin.validity.verifiers.objects.VerifiableObject;
import com.redfin.validity.verifiers.objects.VerifiableShort;
import com.redfin.validity.verifiers.objects.VerifiableString;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveBoolean;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveByte;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveChar;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveDouble;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveFloat;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveInt;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveLong;
import com.redfin.validity.verifiers.primitives.VerifiablePrimitiveShort;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
/*
 * Copyright: (c) 2016 Redfin
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.redfin.validity;


@SuppressWarnings("ConstantConditions")
interface AbstractVerifiableFactoryContract<X extends Throwable,
                                            F extends AbstractVerifiableFactory<X, F>>
  extends NotValueTypeContract<AbstractVerifiableFactory<X, F>> {

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Test cases
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    @Test
    default void testWithMessageReturnsDifferentInstance() {
        String message = "hello";
        Assertions.assertTrue(getNotValueTypeInstance().withMessage(message) != getNotValueTypeInstance().withMessage(message),
                              "AbstractVerifiableFactory should return a new instance for withMessage(String)");
    }

    @Test
    default void testWithMessageFactoryReturnsGivenMessage() {
        String message = "world";
        Assertions.assertEquals(message,
                                getNotValueTypeInstance().withMessage(message).getMessageSupplier().get(),
                                "AbstractVerifiableFactory should return given message.");
    }

    @Test
    default void testAbstractVerifiableFactoryWithMessageReturnsFactoryWithGivenExecutor() {
        AbstractVerifiableFactory<X, F> factory = getNotValueTypeInstance();
        FailedValidationExecutor<X> executor = factory.getFailedValidationExecutor();
        Assertions.assertTrue(executor == factory.withMessage("hello").getFailedValidationExecutor(),
                              "AbstractVerifiableFactory withMessage(String) should return factory with same validation executor.");
    }

    // --------------------------------------------------------------
    // Factory method tests
    // --------------------------------------------------------------

    /*
     * The following tests have some redundancy built-in to them. That is on purpose
     * to quickly catch any ambiguity issues with the method overloading done in the
     * AbstractVerifiableFactory class.
     */

    // - - - - - - - - - - - - - - - - - - - - - -
    // Arrays
    // - - - - - - - - - - - - - - - - - - - - - -

    @Test
    default void testReturnsExpectedVerifiableArray() {
        Integer[] subject = new Integer[0];
        Assertions.assertTrue(getNotValueTypeInstance().that(subject) instanceof VerifiableArray<?, ?>,
                              "AbstractVerifiableFactory should have returned a non-null object of the expected type.");
    }

    @Test
    default void testReturnsExpectedVerifiableArrayForNullSubject() {
        Integer[] subject = null;
        Assertions.assertTrue(getNotValueTypeInstance().that(subject) instanceof VerifiableArray<?, ?>,
                              "AbstractVerifiableFactory should have returned a non-null object of the expected type.");
    }

    @Test
    default void testReturnsExpectedVerifiableBooleanArray() {
        boolean[] subject = new boolean[0];
        Assertions.assertTrue(getNotValueTypeInstance().that(subject) instanceof VerifiableBooleanArray<?>,
                              "AbstractVerifiableFactory should have returned a non-null object of the expected type.");
    }

    @Test
    default void testReturnsExpectedVerifiableBooleanArrayForNullSubject() {
        boolean[] subject = null;
        Assertions.assertTrue(getNotValueTypeInstance().that(subject) instanceof VerifiableBooleanArray<?>,
                              "AbstractVerifiableFactory should have returned a non-null object of the expected type.");
    }

    @Test
    default void testReturnsExpectedVerifiableByteArray() {
        byte[] subject = new byte[0];
        Assertions.assertTrue(getNotValueTypeInstance().that(subject) instanceof VerifiableByteArray<?>,
                              "AbstractVerifiableFactory should have returned a non-null object of the expected type.");
    }

    @Test
    default void testReturnsExpectedVerifiableByteArrayForNullSubject() {
        byte[] subject = null;
        Assertions.assertTrue(getNotValueTypeInstance().that(subject) instanceof VerifiableByteArray<?>,
                              "AbstractVerifiableFactory should have returned a non-null object of the expected type.");
    }

    @Test
    default void testReturnsExpectedVerifiableCharArray() {
        char[] subject = new char[0];
        Assertions.assertTrue(getNotValueTypeInstance().that(subject) instanceof VerifiableCharArray<?>,