← Index
NYTProf Performance Profile   « line view »
For split.pl
  Run on Thu Apr 20 02:05:47 2023
Reported on Thu Apr 20 18:31:09 2023

Filename/home/hejohns/perl5/lib/perl5/Types/Serialiser.pm
StatementsExecuted 14 statements in 460µs
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1118µs31µsTypes::Serialiser::BooleanBase::::BEGIN@126Types::Serialiser::BooleanBase::BEGIN@126
1118µs17µsTypes::Serialiser::::BEGIN@20 Types::Serialiser::BEGIN@20
1115µs5µsTypes::Serialiser::::BEGIN@112 Types::Serialiser::BEGIN@112
1115µs19µsTypes::Serialiser::Error::::BEGIN@157 Types::Serialiser::Error::BEGIN@157
0000s0sTypes::Serialiser::BooleanBase::::__ANON__[:126]Types::Serialiser::BooleanBase::__ANON__[:126]
0000s0sTypes::Serialiser::BooleanBase::::__ANON__[:127]Types::Serialiser::BooleanBase::__ANON__[:127]
0000s0sTypes::Serialiser::BooleanBase::::__ANON__[:128]Types::Serialiser::BooleanBase::__ANON__[:128]
0000s0sTypes::Serialiser::Error::::error Types::Serialiser::Error::error
0000s0sTypes::Serialiser::::as_bool Types::Serialiser::as_bool
0000s0sTypes::Serialiser::::error Types::Serialiser::error
0000s0sTypes::Serialiser::::false Types::Serialiser::false
0000s0sTypes::Serialiser::::is_bool Types::Serialiser::is_bool
0000s0sTypes::Serialiser::::is_error Types::Serialiser::is_error
0000s0sTypes::Serialiser::::is_false Types::Serialiser::is_false
0000s0sTypes::Serialiser::::is_true Types::Serialiser::is_true
0000s0sTypes::Serialiser::::true Types::Serialiser::true
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1=head1 NAME
2
3Types::Serialiser - simple data types for common serialisation formats
4
5=encoding utf-8
6
7=head1 SYNOPSIS
8
9=head1 DESCRIPTION
10
11This module provides some extra datatypes that are used by common
12serialisation formats such as JSON or CBOR. The idea is to have a
13repository of simple/small constants and containers that can be shared by
14different implementations so they become interoperable between each other.
15
16=cut
17
18package Types::Serialiser;
19
20270µs227µs
# spent 17µs (8+10) within Types::Serialiser::BEGIN@20 which was called: # once (8µs+10µs) by JSON::XS::BEGIN@100 at line 20
use common::sense; # required to suppress annoying warnings
# spent 17µs making 1 call to Types::Serialiser::BEGIN@20 # spent 10µs making 1 call to common::sense::import
21
221300nsour $VERSION = '1.01';
23
24=head1 SIMPLE SCALAR CONSTANTS
25
26Simple scalar constants are values that are overloaded to act like simple
27Perl values, but have (class) type to differentiate them from normal Perl
28scalars. This is necessary because these have different representations in
29the serialisation formats.
30
31In the following, functions with zero or one arguments have a prototype of
32C<()> and C<($)>, respectively, so act as constants and unary operators.
33
34=head2 BOOLEANS (Types::Serialiser::Boolean class)
35
36This type has only two instances, true and false. A natural representation
37for these in Perl is C<1> and C<0>, but serialisation formats need to be
38able to differentiate between them and mere numbers.
39
40=over 4
41
42=item $Types::Serialiser::true, Types::Serialiser::true
43
44This value represents the "true" value. In most contexts is acts like
45the number C<1>. It is up to you whether you use the variable form
46(C<$Types::Serialiser::true>) or the constant form (C<Types::Serialiser::true>).
47
48The constant is represented as a reference to a scalar containing C<1> -
49implementations are allowed to directly test for this.
50
51=item $Types::Serialiser::false, Types::Serialiser::false
52
53This value represents the "false" value. In most contexts is acts like
54the number C<0>. It is up to you whether you use the variable form
55(C<$Types::Serialiser::false>) or the constant form (C<Types::Serialiser::false>).
56
57The constant is represented as a reference to a scalar containing C<0> -
58implementations are allowed to directly test for this.
59
60=item Types::Serialiser::as_bool $value
61
62Converts a Perl scalar into a boolean, which is useful syntactic
63sugar. Strictly equivalent to:
64
65 $value ? $Types::Serialiser::true : $Types::Serialiser::false
66
67=item $is_bool = Types::Serialiser::is_bool $value
68
69Returns true iff the C<$value> is either C<$Types::Serialiser::true> or
70C<$Types::Serialiser::false>.
71
72For example, you could differentiate between a perl true value and a
73C<Types::Serialiser::true> by using this:
74
75 $value && Types::Serialiser::is_bool $value
76
77=item $is_true = Types::Serialiser::is_true $value
78
79Returns true iff C<$value> is C<$Types::Serialiser::true>.
80
81=item $is_false = Types::Serialiser::is_false $value
82
83Returns false iff C<$value> is C<$Types::Serialiser::false>.
84
85=back
86
87=head2 ERROR (Types::Serialiser::Error class)
88
89This class has only a single instance, C<error>. It is used to signal
90an encoding or decoding error. In CBOR for example, and object that
91couldn't be encoded will be represented by a CBOR undefined value, which
92is represented by the error value in Perl.
93
94=over 4
95
96=item $Types::Serialiser::error, Types::Serialiser::error
97
98This value represents the "error" value. Accessing values of this type
99will throw an exception.
100
101The constant is represented as a reference to a scalar containing C<undef>
102- implementations are allowed to directly test for this.
103
104=item $is_error = Types::Serialiser::is_error $value
105
106Returns false iff C<$value> is C<$Types::Serialiser::error>.
107
108=back
109
110=cut
111
112
# spent 5µs within Types::Serialiser::BEGIN@112 which was called: # once (5µs+0s) by JSON::XS::BEGIN@100 at line 118
BEGIN {
113 # for historical reasons, and to avoid extra dependencies in JSON::PP,
114 # we alias *Types::Serialiser::Boolean with JSON::PP::Boolean.
115 package JSON::PP::Boolean;
116
11715µs *Types::Serialiser::Boolean:: = *JSON::PP::Boolean::;
118191µs15µs}
# spent 5µs making 1 call to Types::Serialiser::BEGIN@112
119
120{
121 # this must done before blessing to work around bugs
122 # in perl < 5.18 (it seems to be fixed in 5.18).
1231200ns package Types::Serialiser::BooleanBase;
124
125 use overload
126
# spent 31µs (8+24) within Types::Serialiser::BooleanBase::BEGIN@126 which was called: # once (8µs+24µs) by JSON::XS::BEGIN@100 at line 129
"0+" => sub { ${$_[0]} },
127 "++" => sub { $_[0] = ${$_[0]} + 1 },
128 "--" => sub { $_[0] = ${$_[0]} - 1 },
1292216µs255µs fallback => 1;
# spent 31µs making 1 call to Types::Serialiser::BooleanBase::BEGIN@126 # spent 24µs making 1 call to overload::import
130
13116µs @Types::Serialiser::Boolean::ISA = Types::Serialiser::BooleanBase::;
132}
133
13411µsour $true = do { bless \(my $dummy = 1), Types::Serialiser::Boolean:: };
1351200nsour $false = do { bless \(my $dummy = 0), Types::Serialiser::Boolean:: };
1361300nsour $error = do { bless \(my $dummy ), Types::Serialiser::Error:: };
137
138sub true () { $true }
139sub false () { $false }
140sub error () { $error }
141
142sub as_bool($) { $_[0] ? $true : $false }
143
144sub is_bool ($) { UNIVERSAL::isa $_[0], Types::Serialiser::Boolean:: }
145sub is_true ($) { $_[0] && UNIVERSAL::isa $_[0], Types::Serialiser::Boolean:: }
146sub is_false ($) { !$_[0] && UNIVERSAL::isa $_[0], Types::Serialiser::Boolean:: }
147sub is_error ($) { UNIVERSAL::isa $_[0], Types::Serialiser::Error:: }
148
149package Types::Serialiser::Error;
150
151sub error {
152 require Carp;
153 Carp::croak ("caught attempt to use the Types::Serialiser::error value");
154};
155
156use overload
15712µs114µs
# spent 19µs (5+15) within Types::Serialiser::Error::BEGIN@157 which was called: # once (5µs+15µs) by JSON::XS::BEGIN@100 at line 160
"0+" => \&error,
# spent 14µs making 1 call to overload::import
158 "++" => \&error,
159 "--" => \&error,
160163µs119µs fallback => 1;
# spent 19µs making 1 call to Types::Serialiser::Error::BEGIN@157
161
162=head1 NOTES FOR XS USERS
163
164The recommended way to detect whether a scalar is one of these objects
165is to check whether the stash is the C<Types::Serialiser::Boolean> or
166C<Types::Serialiser::Error> stash, and then follow the scalar reference to
167see if it's C<1> (true), C<0> (false) or C<undef> (error).
168
169While it is possible to use an isa test, directly comparing stash pointers
170is faster and guaranteed to work.
171
172For historical reasons, the C<Types::Serialiser::Boolean> stash is
173just an alias for C<JSON::PP::Boolean>. When printed, the classname
174with usually be C<JSON::PP::Boolean>, but isa tests and stash pointer
175comparison will normally work correctly (i.e. Types::Serialiser::true ISA
176JSON::PP::Boolean, but also ISA Types::Serialiser::Boolean).
177
178=head1 A GENERIC OBJECT SERIALIATION PROTOCOL
179
180This section explains the object serialisation protocol used by
181L<CBOR::XS>. It is meant to be generic enough to support any kind of
182generic object serialiser.
183
184This protocol is called "the Types::Serialiser object serialisation
185protocol".
186
187=head2 ENCODING
188
189When the encoder encounters an object that it cannot otherwise encode (for
190example, L<CBOR::XS> can encode a few special types itself, and will first
191attempt to use the special C<TO_CBOR> serialisation protocol), it will
192look up the C<FREEZE> method on the object.
193
194Note that the C<FREEZE> method will normally be called I<during> encoding,
195and I<MUST NOT> change the data structure that is being encoded in any
196way, or it might cause memory corruption or worse.
197
198If it exists, it will call it with two arguments: the object to serialise,
199and a constant string that indicates the name of the data model. For
200example L<CBOR::XS> uses C<CBOR>, and the L<JSON> and L<JSON::XS> modules
201(or any other JSON serialiser), would use C<JSON> as second argument.
202
203The C<FREEZE> method can then return zero or more values to identify the
204object instance. The serialiser is then supposed to encode the class name
205and all of these return values (which must be encodable in the format)
206using the relevant form for Perl objects. In CBOR for example, there is a
207registered tag number for encoded perl objects.
208
209The values that C<FREEZE> returns must be serialisable with the serialiser
210that calls it. Therefore, it is recommended to use simple types such as
211strings and numbers, and maybe array references and hashes (basically, the
212JSON data model). You can always use a more complex format for a specific
213data model by checking the second argument, the data model.
214
215The "data model" is not the same as the "data format" - the data model
216indicates what types and kinds of return values can be returned from
217C<FREEZE>. For example, in C<CBOR> it is permissible to return tagged CBOR
218values, while JSON does not support these at all, so C<JSON> would be a
219valid (but too limited) data model name for C<CBOR::XS>. similarly, a
220serialising format that supports more or less the same data model as JSON
221could use C<JSON> as data model without losing anything.
222
223=head2 DECODING
224
225When the decoder then encounters such an encoded perl object, it should
226look up the C<THAW> method on the stored classname, and invoke it with the
227classname, the constant string to identify the data model/data format, and
228all the return values returned by C<FREEZE>.
229
230=head2 EXAMPLES
231
232See the C<OBJECT SERIALISATION> section in the L<CBOR::XS> manpage for
233more details, an example implementation, and code examples.
234
235Here is an example C<FREEZE>/C<THAW> method pair:
236
237 sub My::Object::FREEZE {
238 my ($self, $model) = @_;
239
240 ($self->{type}, $self->{id}, $self->{variant})
241 }
242
243 sub My::Object::THAW {
244 my ($class, $model, $type, $id, $variant) = @_;
245
246 $class->new (type => $type, id => $id, variant => $variant)
247 }
248
249=head1 BUGS
250
251The use of L<overload> makes this module much heavier than it should be
252(on my system, this module: 4kB RSS, overload: 260kB RSS).
253
254=head1 SEE ALSO
255
256Currently, L<JSON::XS> and L<CBOR::XS> use these types.
257
258=head1 AUTHOR
259
260 Marc Lehmann <schmorp@schmorp.de>
261 http://home.schmorp.de/
262
263=cut
264
26514µs1
266