The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Venus::Assert - Assert Class

ABSTRACT

Assert Class for Perl 5

SYNOPSIS

package main;

use Venus::Assert;

my $assert = Venus::Assert->new('Float');

# $assert->accept('float');

# $assert->format(sub{sprintf('%.2f', $_)});

# $assert->result(123.456);

# 123.46

DESCRIPTION

This package provides a mechanism for asserting type constraints and coercions on data. Type constraints are handled via Venus::Constraint, and coercions are handled via Venus::Coercion, using Venus::Check to perform data type validations.

ATTRIBUTES

This package has the following attributes:

name

name(string $data) (string)

The name attribute is read-write, accepts (string) values, and is optional.

Since 1.40

name example 1
# given: synopsis

package main;

my $set_name = $assert->name("Example");

# "Example"
name example 2
# given: synopsis

# given: example-1 name

package main;

my $get_name = $assert->name;

# "Example"

INHERITS

This package inherits behaviors from:

Venus::Kind::Utility

INTEGRATES

This package integrates behaviors from:

Venus::Role::Buildable

METHODS

This package provides the following methods:

accept

accept(string $name, any @args) (Venus::Assert)

The accept method registers a condition via "check" based on the arguments provided. The built-in types are defined as methods in Venus::Check.

Since 1.40

accept example 1
# given: synopsis

package main;

$assert = $assert->accept('float');

# bless(..., "Venus::Assert")

# $assert->valid;

# false

# $assert->valid(1.01);

# true
accept example 2
# given: synopsis

package main;

$assert = $assert->accept('number');

# bless(..., "Venus::Assert")

# $assert->valid(1.01);

# false

# $assert->valid(1_01);

# true
accept example 3
# given: synopsis

package Example1;

sub new {
  bless {};
}

package Example2;

sub new {
  bless {};
}

package main;

$assert = $assert->accept('object');

# bless(..., "Venus::Assert")

# $assert->valid;

# false

# $assert->valid(qr//);

# false

# $assert->valid(Example1->new);

# true

# $assert->valid(Example2->new);

# true
accept example 4
# given: synopsis

package Example1;

sub new {
  bless {};
}

package Example2;

sub new {
  bless {};
}

package main;

$assert = $assert->accept('Example1');

# bless(..., "Venus::Assert")

# $assert->valid;

# false

# $assert->valid(qr//);

# false

# $assert->valid(Example1->new);

# true

# $assert->valid(Example2->new);

# false

check

check(Venus::Check $data) (Venus::Check)

The check method gets or sets the Venus::Check object used for performing runtime data type validation.

Since 3.55

check example 1
# given: synopsis

package main;

my $check = $assert->check(Venus::Check->new);

# bless(..., 'Venus::Check')
check example 2
# given: synopsis

package main;

$assert->check(Venus::Check->new);

my $check = $assert->check;

# bless(..., 'Venus::Check')

clear

clear() (Venus::Assert)

The clear method resets the "check", "constraint", and "coercion" attributes and returns the invocant.

Since 1.40

clear example 1
# given: synopsis

package main;

$assert->accept('string');

$assert = $assert->clear;

# bless(..., "Venus::Assert")

coerce

coerce(any $data) (any)

The coerce method dispatches to the "coercion" object and returns the result of the "result" in Venus::Coercion operation.

Since 3.55

coerce example 1
# given: synopsis

package main;

$assert->accept('float');

$assert->format(sub{sprintf('%.2f', $_)});

my $coerce = $assert->coerce(123.456);

# 123.46
coerce example 2
# given: synopsis

package main;

$assert->accept('string');

$assert->format(sub{ucfirst lc $_});

my $coerce = $assert->coerce('heLLo');

# "Hello"

coercion

coercion(Venus::Coercion $data) (Venus::Coercion)

The coercion method gets or sets the Venus::Coercion object used for performing runtime data type coercions.

Since 3.55

coercion example 1
# given: synopsis

package main;

my $coercion = $assert->coercion(Venus::Coercion->new);

# bless(..., 'Venus::Coercion')
coercion example 2
# given: synopsis

package main;

$assert->coercion(Venus::Coercion->new);

my $coercion = $assert->coercion;

# bless(..., 'Venus::Coercion')

conditions

conditions() (Venus::Assert)

The conditions method is an object construction hook that allows subclasses to configure the object on construction setting up constraints and coercions and returning the invocant.

Since 1.40

conditions example 1
# given: synopsis

package main;

$assert = $assert->conditions;

# bless(..., 'Venus::Assert')
conditions example 2
package Example::Type::PositveNumber;

use base 'Venus::Assert';

sub conditions {
  my ($self) = @_;

  $self->accept('number', sub {
    $_ >= 0
  });

  return $self;
}

package main;

my $assert = Example::Type::PositveNumber->new;

# $assert->valid(0);

# true

# $assert->valid(1);

# true

# $assert->valid(-1);

# false

constraint

constraint(Venus::Constraint $data) (Venus::Constraint)

The constraint method gets or sets the Venus::Constraint object used for performing runtime data type constraints.

Since 3.55

constraint example 1
# given: synopsis

package main;

my $constraint = $assert->constraint(Venus::Constraint->new);

# bless(..., 'Venus::Constraint')
constraint example 2
# given: synopsis

package main;

$assert->constraint(Venus::Constraint->new);

my $constraint = $assert->constraint;

# bless(..., 'Venus::Constraint')

ensure

ensure(coderef $code) (Venus::Assert)

The ensure method registers a custom (not built-in) constraint condition and returns the invocant.

Since 3.55

ensure example 1
# given: synopsis

package main;

$assert->accept('number');

my $ensure = $assert->ensure(sub {
  $_ >= 0
});

# bless(.., "Venus::Assert")

expression

expression(string $expr) (Venus::Assert)

The expression method parses a string representation of an type assertion, registers the subexpressions using the "accept" method, and returns the invocant.

Since 1.71

expression example 1
# given: synopsis

package main;

$assert = $assert->expression('string');

# bless(..., 'Venus::Assert')

# $assert->valid('hello');

# true

# $assert->valid(['goodbye']);

# false
expression example 2
# given: synopsis

package main;

$assert = $assert->expression('string | coderef');

# bless(..., 'Venus::Assert')

# $assert->valid('hello');

# true

# $assert->valid(sub{'hello'});

# true

# $assert->valid(['goodbye']);

# false
expression example 3
# given: synopsis

package main;

$assert = $assert->expression('string | coderef | Venus::Assert');

# bless(..., 'Venus::Assert')

# $assert->valid('hello');

# true

# $assert->valid(sub{'hello'});

# true

# $assert->valid($assert);

# true

# $assert->valid(['goodbye']);

# false
expression example 4
# given: synopsis

package main;

$assert = $assert->expression('Venus::Assert | within[arrayref, Venus::Assert]');

# bless(..., 'Venus::Assert')

# $assert->valid('hello');

# false

# $assert->valid(sub{'hello'});

# false

# $assert->valid($assert);

# true

# $assert->valid(['goodbye']);

# false

# $assert->valid([$assert]);

# true
expression example 5
# given: synopsis

package main;

$assert = $assert->expression('
  string
  | within[
      arrayref, within[
        hashref, string
      ]
    ]
');

# bless(..., 'Venus::Assert')

# $assert->valid('hello');

# true

# $assert->valid(sub{'hello'});

# false

# $assert->valid($assert);

# false

# $assert->valid([]);

# false

# $assert->valid([{'test' => ['okay']}]);

# false

# $assert->valid([{'test' => 'okay'}]);

# true

format

format(coderef $code) (Venus::Assert)

The format method registers a custom (not built-in) coercion condition and returns the invocant.

Since 3.55

format example 1
# given: synopsis

package main;

$assert->accept('number');

my $format = $assert->format(sub {
  sprintf '%.2f', $_
});

# bless(.., "Venus::Assert")

parse

parse(string $expr) (any)

The parse method accepts a string representation of a type assertion and returns a data structure representing one or more method calls to be used for validating the assertion signature.

Since 2.01

parse example 1
# given: synopsis

package main;

my $parsed = $assert->parse('');

# ['']
parse example 2
# given: synopsis

package main;

my $parsed = $assert->parse('any');

# ['any']
parse example 3
# given: synopsis

package main;

my $parsed = $assert->parse('string | number');

# ['either', 'string', 'number']
parse example 4
# given: synopsis

package main;

my $parsed = $assert->parse('enum[up,down,left,right]');

# [['enum', 'up', 'down', 'left', 'right']]
parse example 5
# given: synopsis

package main;

my $parsed = $assert->parse('number | float | boolean');

# ['either', 'number', 'float', 'boolean']
parse example 6
# given: synopsis

package main;

my $parsed = $assert->parse('Example');

# ['Example']
parse example 7
# given: synopsis

package main;

my $parsed = $assert->parse('coderef | Venus::Code');

# ['either', 'coderef', 'Venus::Code']
parse example 8
# given: synopsis

package main;

my $parsed = $assert->parse('tuple[number, arrayref, coderef]');

# [['tuple', 'number', 'arrayref', 'coderef']]
parse example 9
# given: synopsis

package main;

my $parsed = $assert->parse('tuple[number, within[arrayref, hashref], coderef]');

# [['tuple', 'number', ['within', 'arrayref', 'hashref'], 'coderef']]
parse example 10
# given: synopsis

package main;

my $parsed = $assert->parse(
  'tuple[number, within[arrayref, hashref] | arrayref, coderef]'
);

# [
#   ['tuple', 'number',
#     ['either', ['within', 'arrayref', 'hashref'], 'arrayref'], 'coderef']
# ]
parse example 11
# given: synopsis

package main;

my $parsed = $assert->parse(
  'hashkeys["id", number | float, "upvotes", within[arrayref, boolean]]'
);

# [[
#   'hashkeys',
#   'id',
#     ['either', 'number', 'float'],
#   'upvotes',
#     ['within', 'arrayref', 'boolean']
# ]]

render

render(string $into, string $expression) (string)

The render method builds and returns a type expressions suitable for providing to "expression" based on the data provided.

Since 2.55

render example 1
# given: synopsis

package main;

$assert = $assert->render;

# undef
render example 2
# given: synopsis

package main;

$assert = $assert->render(undef, 'string');

# "string"
render example 3
# given: synopsis

package main;

$assert = $assert->render('routines', ['say', 'say_pretty']);

# 'routines["say", "say_pretty"]'
render example 4
# given: synopsis

package main;

$assert = $assert->render('hashkeys', {id => 'number', name => 'string'});

# 'hashkeys["id", number, "name", string]'
render example 5
# given: synopsis

package main;

$assert = $assert->render('hashkeys', {
  id => 'number',
  profile => {
    level => 'string',
  },
});

# 'hashkeys["id", number, "profile", hashkeys["level", string]]'

result

result(any $data) (any)

The result method validates the value provided against the registered constraints and if valid returns the result of the value having any registered coercions applied. If the value is invalid an exception from Venus::Check will be thrown.

Since 3.55

result example 1
# given: synopsis

package main;

$assert->accept('number')->format(sub{sprintf '%.2f', $_});

my $result = $assert->result(1);

# "1.00"
result example 2
# given: synopsis

package main;

$assert->accept('number')->format(sub{sprintf '%.2f', $_});

my $result = $assert->result('hello');

# Exception! (isa Venus::Check::Error) (see error_on_coded)

valid

valid(any $data) (any)

The valid method dispatches to the "constraint" object and returns the result of the "result" in Venus::Constraint operation.

Since 3.55

valid example 1
# given: synopsis

package main;

$assert->accept('float');

$assert->ensure(sub{$_ >= 1});

my $valid = $assert->valid('1.00');

# true
valid example 2
# given: synopsis

package main;

$assert->accept('float');

$assert->ensure(sub{$_ >= 1});

my $valid = $assert->valid('0.99');

# false

validate

validate(any $data) (any)

The validate method validates the value provided against the registered constraints and if valid returns the value. If the value is invalid an exception from Venus::Check will be thrown.

Since 3.55

validate example 1
# given: synopsis

package main;

$assert->accept('number');

my $validate = $assert->validate(1);

# 1
validate example 2
# given: synopsis

package main;

$assert->accept('number');

my $validate = $assert->validate('hello');

# Exception! (isa Venus::Check::Error) (see error_on_coded)

validator

validator(any @args) (coderef)

The validator method returns a coderef which calls the "validate" method with the invocant when called.

Since 3.55

validator example 1
# given: synopsis

package main;

$assert->accept('string');

my $validator = $assert->validator;

# sub{...}

# my $result = $validator->();

# Exception! (isa Venus::Check::Error) (see error_on_coded)
validator example 2
# given: synopsis

package main;

$assert->accept('string');

my $validator = $assert->validator;

# sub{...}

# my $result = $validator->('hello');

# "hello"

AUTHORS

Awncorp, awncorp@cpan.org

LICENSE

Copyright (C) 2022, Awncorp, awncorp@cpan.org.

This program is free software, you can redistribute it and/or modify it under the terms of the Apache license version 2.0.