The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Data::Sah::Type::BaseType - Specification for base type

VERSION

version 0.03

DESCRIPTION

This is the specification for the 'BaseType' role. All Sah types directly or indirectly consume this role.

Unless mentioned explicitly, priority is 50 (default).

CLAUSES

default

Supply a default value.

Priority: 1 (very high). This is processed before all other clauses.

Example: Given schema [int => {req=>1}] an undef data is invalid, but given schema [int => {req=>1, default=>3}] an undef data is valid because it will be given default value first.

SANITY

This is a "hidden" clause that cannot be specified in schemas (due to uppercase spelling), but compilers use them to add checks.

Priority: 50 (default), but due to its spelling, by sorting, it will be processed before all other normal clauses.

PREPROCESS

This is a "hidden" clause that cannot be specified in schemas (due to uppercase spelling), but compilers use them to preprocess data before further checking (for example, Perl compiler for the datetime type can convert string data to DateTime object).

Priority: 5 (very high), executed after default and req/forbidden.

req

If set to 1, require that data be defined. Otherwise, allow data to be undef (the default behaviour).

Priority: 3 (very high), executed after default.

By default, undef will pass even elaborate schema, e.g. [int => {min=>0, max=>10, div_by=>3}] will still pass an undef. However, undef will not pass [int=>{req=>1}].

This behaviour is much like NULLs in SQL: we *can't* (in)validate something that is unknown/unset.

See also: forbidden

forbidden

This is the opposite of req, requiring that data be not defined (i.e. undef).

Priority: 3 (very high), executed after default.

Given schema [int=>{forbidden=>1}], a non-undef value will fail. Another example: the schema [int=>{req=>1, forbidden=>1}] will always fail due to conflicting clauses.

See also: req

prefilters => [EXPR, ...]

NOT YET IMPLEMENTED.

Run expression(s), usually to preprocess data before further checking. Data is referred to in expression by variable $_. Prefiltered value will persist until the end of all other clauses, and after that will be restored by the POSTPROCESS clause.

Priority: 10 (high). Run after default and req/forbidden (and PREPROCESS).

Specific attributes: permanent. If set to true, then prefiltered value will persist and won't be restored by POSTPROCESS.

postfilters => [EXPR, ...]

NOT YET IMPLEMENTED.

Run expression(s), usually to postprocess data. Data is referred to in expression by variable $_. From here on, the data will be permanently set to the postfiltered value.

Priority: 90 (very low). Run after all other clauses, before POSTPROCESS.

POSTPROCESS

This is a "hidden" clause that cannot be specified in schemas (due to uppercase spelling), compilers use them to restore value temporarily changed by prefilters (unless the prefilter is set to be permanent, or between schemas in deps, see the deps clause).

Priority: 95 (very low). Run after all the other clauses.

lang => LOCALECODE

NOT YET IMPLEMENTED.

Set language for this schema.

Priority: 2 (very high)

default_lang => LOCALECODE (defaut: en_US)

NOT YET IMPLEMENTED.

Set default language for this schema. Language-dependant attribute values (e.g. summary, description) will be assumed to be in the default language.

Priority: 2 (very high)

name => STR

A short short (usually single-word, without any formatting) to name the schema, useful for identifying the schema when used as a type for human compiler.

To store translations, you can use the alt.lang.* clause attributes.

Example:

 [int => {
     'name:alt.lang.en_US' => 'pos_int',
     'name:alt.lang.id_ID' => 'bil_pos',
     min=>0,
 }]

See also: summary, description, comment, tags.

summary => STR

A one-line text (about 70-80 character max, without any formatting) to describe the schema. This is useful, e.g. for manually describe a schema instead of using the human compiler. It can also be used in form field labels.

To store translations, you can use the alt.lang.* clause attributes.

Example:

 # definition for 'single_dice_throw' schema/type
 [int => {
     req => 1,
     'summary:alt.lang.en_US' =>
         'A number representing result of single dice throw (1-6)',
     'summary:alt.lang.id_ID' =>
         'Bilangan yang menyatakan hasil lempar sebuah dadu (1-6)',
     between => [1, 6],
 }]

Using the human compiler, the above schema will be output as the standard, more boring 'Integer, value between 1 and 6.'

See also: name, description, comment, tags.

description => STR

A longer text (a paragraph or more) to describe the schema, useful e.g. for help/usage text. Text should be in Org format.

To store translations, you can use the alt.lang.* clause attributes.

Example:

 [array => {
     name        => 'http_headers',
     description => <<EOT,
 HTTP headers should be specified as an array of 2-element arrays (pairs). Each
 pair should contain header name in the first element (all lowercase, *-*
 written as *_*) and header value in the second element.

 Example:

 : [[content_type => 'text/html'], [accept => 'text/html'], [accept => '*/*']]

 EOT
     req => 1,
     of  => 'http_header',
  },
  {
      def => {
          http_header => ['array*', len=>2],
      },
 }]

See also: name, summary, comment, tags.

comment => STR

Can contain any kind of text (format unspecified), will be ignored during validation. Meant to store internal comment (for schema authors/developers).

See also: name, summary, description, tags.

tags => ARRAY OF STR

A list of tags, can be used to categorize schemas.

See also: name, summary, description, comment.

noop => ANY

Will do nothing. This clause is just a convenience if you want to do nothing (or perhaps just use the attributes of this clause to do things).

fail => BOOL

If set to 1, validation of this clause always fails. This is just a convenience to force failure.

cset => HASH

Evaluate a clause set.

if => [CLAUSE1=>VAL, CLAUSE2=>VAL] or [CLAUSE_SET(S)1, CLAUSE_SET(S)2]

NOT YET IMPLEMENTED.

This is similar to deps, but instead of using schemas as arguments, clauses are used. The first form (4-argument) states that if CLAUSE1 succeeds, then CLAUSE2 must also succeed. The second form (2-argument) operates on a clause set (hash) or clause sets (array of hashes).

Examples:

 # leap year
 [int => {div_by=>4, if => [div_by => 100, div_by => 400]]

The "if" clause states that if input number is divisible by 100, it must also divisible by 400. Otherwise, the clause fails.

 [str => {min_len=>1, max_len=>10,
          if => [ {min_len=>4, max_len=>6}, {is_palindrome=>1} ]}]

The above says that if a string has length between 4 and 6 then it must be a palindrome. Otherwise it doesn't have to be one. But nevertheless, all input must be between 1 and 10 characters long.

 [str => {if => [ [{match=>'a'}, {match=>'b'}],
                  [{match=>'c'}, {match=>'d'}] ]}]

The above says that if a string matches 'a' and 'b', it must also match 'c' and 'd'. As a side note, the above schema can also be written as:

 [str => {if => [ 'match&'=>['a', 'b'], 'match&'=>['c', 'd'] ]}]

check => EXPR

NOT YET IMPLEMENTED.

Evaluate expression, which must evaluate to a true value for this clause to succeed.

AUTHOR

Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Steven Haryanto.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.