File: StrMatch.pm

package info (click to toggle)
libtype-tiny-perl 2.002001-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 3,948 kB
  • sloc: perl: 14,610; makefile: 2; sh: 1
file content (131 lines) | stat: -rw-r--r-- 3,105 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# INTERNAL MODULE: guts for StrMatch type from Types::Standard.

package Types::Standard::StrMatch;

use 5.008001;
use strict;
use warnings;

BEGIN {
	$Types::Standard::StrMatch::AUTHORITY = 'cpan:TOBYINK';
	$Types::Standard::StrMatch::VERSION   = '2.002001';
}

$Types::Standard::StrMatch::VERSION =~ tr/_//d;

use Type::Tiny      ();
use Types::Standard ();
use Types::TypeTiny ();

sub _croak ($;@) { require Error::TypeTiny; goto \&Error::TypeTiny::croak }

no warnings;

our %expressions;
my $has_regexp_util;
my $serialize_regexp = sub {
	$has_regexp_util = eval {
		require Regexp::Util;
		Regexp::Util->VERSION( '0.003' );
		1;
	} || 0 unless defined $has_regexp_util;
	
	my $re = shift;
	my $serialized;
	if ( $has_regexp_util ) {
		$serialized = eval { Regexp::Util::serialize_regexp( $re ) };
	}
	
	unless ( defined $serialized ) {
		my $key = sprintf( '%s|%s', ref( $re ), $re );
		$expressions{$key} = $re;
		$serialized = sprintf(
			'$Types::Standard::StrMatch::expressions{%s}',
			B::perlstring( $key )
		);
	}
	
	return $serialized;
};

sub __constraint_generator {
	return Types::Standard->meta->get_type( 'StrMatch' ) unless @_;
	
	my ( $regexp, $checker ) = @_;
	
	Types::Standard::is_RegexpRef( $regexp )
		or _croak(
		"First parameter to StrMatch[`a] expected to be a Regexp; got $regexp" );
		
	if ( @_ > 1 ) {
		$checker = Types::TypeTiny::to_TypeTiny( $checker );
		Types::TypeTiny::is_TypeTiny( $checker )
			or _croak(
			"Second parameter to StrMatch[`a] expected to be a type constraint; got $checker"
			);
	}
	
	$checker
		? sub {
		my $value = shift;
		return if ref( $value );
		my @m = ( $value =~ $regexp );
		$checker->check( \@m );
		}
		: sub {
		my $value = shift;
		!ref( $value ) and !!( $value =~ $regexp );
		};
} #/ sub __constraint_generator

sub __inline_generator {
	require B;
	my ( $regexp, $checker ) = @_;
	my $serialized_re = $regexp->$serialize_regexp or return;
	
	if ( $checker ) {
		return unless $checker->can_be_inlined;
		
		return sub {
			my $v = $_[1];
			if ( $Type::Tiny::AvoidCallbacks
				and $serialized_re =~ /Types::Standard::StrMatch::expressions/ )
			{
				require Carp;
				Carp::carp(
					"Cannot serialize regexp without callbacks; serializing using callbacks" );
			}
			sprintf
				"!ref($v) and do { my \$m = [$v =~ %s]; %s }",
				$serialized_re,
				$checker->inline_check( '$m' ),
				;
		};
	} #/ if ( $checker )
	else {
		my $regexp_string = "$regexp";
		if ( $regexp_string =~ /\A\(\?\^u?:\\A(\.+)\)\z/ ) {
			my $length = length $1;
			return sub { "!ref($_) and length($_)>=$length" };
		}
		
		if ( $regexp_string =~ /\A\(\?\^u?:\\A(\.+)\\z\)\z/ ) {
			my $length = length $1;
			return sub { "!ref($_) and length($_)==$length" };
		}
		
		return sub {
			my $v = $_[1];
			if ( $Type::Tiny::AvoidCallbacks
				and $serialized_re =~ /Types::Standard::StrMatch::expressions/ )
			{
				require Carp;
				Carp::carp(
					"Cannot serialize regexp without callbacks; serializing using callbacks" );
			}
			"!ref($v) and !!( $v =~ $serialized_re )";
		};
	} #/ else [ if ( $checker ) ]
} #/ sub __inline_generator

1;