File Coverage

blib/lib/TOML/Tiny.pm
Criterion Covered Total %
statement 35 43 81.4
branch 5 8 62.5
condition n/a
subroutine 11 13 84.6
pod 6 6 100.0
total 57 70 81.4


line stmt bran cond sub pod time code
1             # ABSTRACT: a minimal, pure perl TOML parser and serializer
2             $TOML::Tiny::VERSION = '0.15';
3             use strict;
4 285     285   55335755 use warnings;
  285         2152  
  285         6476  
5 285     285   1190 no warnings qw(experimental);
  285         452  
  285         6343  
6 285     285   1016 use v5.18;
  285         722  
  285         7115  
7 285     285   2844  
  285         756  
8             use TOML::Tiny::Parser;
9 285     285   100067 use TOML::Tiny::Writer;
  285         711  
  285         9046  
10 285     285   97928  
  285         651  
  285         8160  
11             use parent 'Exporter';
12 285     285   1560  
  285         478  
  285         1540  
13             our @EXPORT = qw(
14             from_toml
15             to_toml
16             );
17              
18             #-------------------------------------------------------------------------------
19             # TOML module compatibility
20             #-------------------------------------------------------------------------------
21             my ($source, %param) = @_;
22              
23 425     425 1 364304 # strict was previously strict_arrays; accept both for backward
24             # compatibility.
25             if (exists $param{strict_arrays}) {
26             $param{strict} = $param{strict_arrays};
27 425 50       1552 delete $param{strict_arrays};
28 0         0 }
29 0         0  
30             my $parser = TOML::Tiny::Parser->new(%param);
31             my $toml = eval{ $parser->parse($source) };
32 425         3307  
33 425         892 if (wantarray) {
  425         1539  
34             return ($toml, $@);
35 425 50       1701 } else {
36 0         0 die $@ if $@;
37             return $toml;
38 425 100       4083 }
39 240         2079 }
40              
41             my ($data, %param) = @_;
42              
43             # strict was previously strict_arrays; accept both for backward
44 104     104 1 616894 # compatibility.
45             if (exists $param{strict_arrays}) {
46             $param{strict} = $param{strict_arrays};
47             delete $param{strict_arrays};
48 104 50       609 }
49 0         0  
50 0         0 TOML::Tiny::Writer::to_toml($data, %param);
51             }
52              
53 104         579 #-------------------------------------------------------------------------------
54             # Object API
55             #-------------------------------------------------------------------------------
56             my ($class, %param) = @_;
57             bless{ %param, parser => TOML::Tiny::Parser->new(%param) }, $class;
58             }
59              
60 2     2 1 4515 my ($self, $source) = @_;
61 2         12 $self->{parser}->parse($source);
62             }
63              
64             my ($self, $data) = @_;
65 2     2 1 4201 TOML::Tiny::Writer::to_toml($data, strict => $self->{strict});
66 2         13 }
67              
68             #-------------------------------------------------------------------------------
69             # For compatibility with TOML::from_toml's use of $TOML::Parser
70 0     0 1   #-------------------------------------------------------------------------------
71 0           goto \&decode;
72             }
73              
74             1;
75              
76              
77             =pod
78 0     0 1    
79             =encoding UTF-8
80              
81             =head1 NAME
82              
83             TOML::Tiny - a minimal, pure perl TOML parser and serializer
84              
85             =head1 VERSION
86              
87             version 0.15
88              
89             =head1 SYNOPSIS
90              
91             use TOML::Tiny qw(from_toml to_toml);
92              
93             binmode STDIN, ':encoding(UTF-8)';
94             binmode STDOUT, ':encoding(UTF-8)';
95              
96             # Decoding TOML
97             my $toml = do{ local $/; <STDIN> };
98             my ($parsed, $error) = from_toml $toml;
99              
100             # Encoding TOML
101             say to_toml({
102             stuff => {
103             about => ['other', 'stuff'],
104             },
105             });
106              
107             # Object API
108             my $parser = TOML::Tiny->new;
109             my $data = $parser->decode($toml);
110             say $parser->encode($data);
111              
112             =head1 DESCRIPTION
113              
114             =for html <p>
115             <a href="https://github.com/sysread/TOML-Tiny/actions?query=workflow%3Arun-tests">
116             <img src="https://github.com/sysread/TOML-Tiny/workflows/run-tests/badge.svg" alt="Build status" />
117             </a>
118             </p>
119              
120             C<TOML::Tiny> implements a pure-perl parser and generator for the
121             L<TOML|https://github.com/toml-lang/toml> data format. It conforms to TOML v1.0
122             (with a few caveats; see L</strict>).
123              
124             C<TOML::Tiny> strives to maintain an interface compatible to the L<TOML> and
125             L<TOML::Parser> modules, and could even be used to override C<$TOML::Parser>:
126              
127             use TOML;
128             use TOML::Tiny;
129              
130             local $TOML::Parser = TOML::Tiny->new(...);
131             say to_toml(...);
132              
133             =head1 EXPORTS
134              
135             C<TOML::Tiny> exports the following to functions for compatibility with the
136             L<TOML> module. See L<TOML/FUNCTIONS>.
137              
138             =head2 from_toml
139              
140             Parses a string of C<TOML>-formatted source and returns the resulting data
141             structure. Any arguments after the first are passed to L<TOML::Tiny::Parser>'s
142             constructor.
143              
144             If there is a syntax error in the C<TOML> source, C<from_toml> will die with
145             an explanation which includes the line number of the error.
146              
147             my $result = eval{ from_toml($toml_string) };
148              
149             Alternately, this routine may be called in list context, in which case syntax
150             errors will result in returning two values, C<undef> and an error message.
151              
152             my ($result, $error) = from_toml($toml_string);
153              
154             Additional arguments may be passed after the toml source string; see L</new>.
155              
156             =head3 GOTCHAS
157              
158             =over
159              
160             =item Big integers and floats
161              
162             C<TOML> supports integers and floats larger than what many perls support. When
163             C<TOML::Tiny> encounters a value it may not be able to represent as a number,
164             it will instead return a L<Math::BigInt> or L<Math::BigFloat>. This behavior
165             can be overridden by providing inflation routines:
166              
167             my $toml = TOML::Tiny->new(
168             inflate_float => sub{
169             return do_something_else_with_floats( $_[0] );
170             };
171             );
172              
173             =back
174              
175             =head2 to_toml
176              
177             Encodes a hash ref as a C<TOML>-formatted string.
178              
179             my $toml = to_toml({foo => {'bar' => 'bat'}});
180              
181             # [foo]
182             # bar="bat"
183              
184             =head3 mapping perl to TOML types
185              
186             =head4 table
187              
188             =over
189              
190             =item C<HASH> ref
191              
192             =back
193              
194             =head4 array
195              
196             =over
197              
198             =item C<ARRAY> ref
199              
200             =back
201              
202             =head4 boolean
203              
204             =over
205              
206             =item C<\0> or C<\1>
207              
208             =item L<JSON::PP::Boolean>
209              
210             =item L<Types::Serializer::Boolean>
211              
212             =back
213              
214             =head4 numeric types
215              
216             These are tricky in perl. When encountering a C<Math::Big[Int|Float]>,
217             that representation is used.
218              
219             If the value is a defined (non-ref) scalar with the C<SVf_IOK> or C<SVf_NOK>
220             flags set, the value will be emitted unchanged. This is in line with most
221             other packages, so the normal hinting hacks for typed output apply:
222              
223             number => 0 + $number,
224             string => "" . $string,
225              
226             =over
227              
228             =item L<Math::BigInt>
229              
230             =item L<Math::BigFloat>
231              
232             =item numerical scalars
233              
234             =back
235              
236             =head4 datetime
237              
238             =over
239              
240             =item RFC3339-formatted string
241              
242             e.g., C<"1985-04-12T23:20:50.52Z">
243              
244             =item L<DateTime>
245              
246             L<DateTime>s are formatted as C<RFC3339>, as expected by C<TOML>. However,
247             C<TOML> supports the concept of a "local" time zone, which strays from
248             C<RFC3339> by allowing a datetime without a time zone offset. This is
249             represented in perl by a C<DateTime> with a B<floating time zone>.
250              
251             =back
252              
253             =head4 string
254              
255             All other non-ref scalars are treated as strings.
256              
257             =head1 OBJECT API
258              
259             =head2 new
260              
261             =over
262              
263             =item inflate_datetime
264              
265             By default, C<TOML::Tiny> treats TOML datetimes as strings in the generated
266             data structure. The C<inflate_datetime> parameter allows the caller to provide
267             a routine to intercept those as they are generated:
268              
269             use DateTime::Format::RFC3339;
270              
271             my $parser = TOML::Tiny->new(
272             inflate_datetime => sub{
273             my ($dt_string) = @_;
274             # DateTime::Format::RFC3339 will set the resulting DateTime's formatter
275             # to itself. Fallback is the DateTime default, ISO8601, with a possibly
276             # floating time zone.
277             return eval{ DateTime::Format::RFC3339->parse_datetime($dt_string) }
278             || DateTime::Format::ISO8601->parse_datetime($dt_string);
279             },
280             );
281              
282             =item inflate_boolean
283              
284             By default, boolean values in a C<TOML> document result in a C<1> or C<0>.
285             If L<Types::Serialiser> is installed, they will instead be C<Types::Serialiser::true>
286             or C<Types::Serialiser::false>.
287              
288             If you wish to override this, you can provide your own routine to generate values:
289              
290             my $parser = TOML::Tiny->new(
291             inflate_boolean => sub{
292             my $bool = shift;
293             if ($bool eq 'true') {
294             return 'The Truth';
295             } else {
296             return 'A Lie';
297             }
298             },
299             );
300              
301             =item inflate_integer
302              
303             TOML integers are 64 bit and may not match the size of the compiled perl's
304             internal integer type. By default, C<TOML::Tiny> coerces numbers that fit
305             within a perl number by adding C<0>. For bignums, a L<Math::BigInt> is
306             returned. This may be overridden by providing an inflation routine:
307              
308             my $parser = TOML::Tiny->new(
309             inflate_integer => sub{
310             my $parsed = shift;
311             return sprintf 'the number "%d"', $parsed;
312             };
313             );
314              
315             =item inflate_float
316              
317             TOML floats are 64 bit and may not match the size of the compiled perl's
318             internal float type. As with integers, floats are coerced to numbers and large
319             floats are upgraded to L<Math::BigFloat>s. The special strings C<NaN> and
320             C<inf> may also be returned. You can override this by specifying an inflation
321             routine.
322              
323             my $parser = TOML::Tiny->new(
324             inflate_float => sub{
325             my $parsed = shift;
326             return sprintf '"%0.8f" is a float', $parsed;
327             };
328             );
329              
330             =item strict
331              
332             C<strict> imposes some miscellaneous strictures on C<TOML> input, such as
333             disallowing trailing commas in inline tables and failing on invalid UTF8 input.
334              
335             B<Note:> C<strict> was previously called C<strict_arrays>. Both are accepted
336             for backward compatibility, although enforcement of homogenous arrays is no
337             longer supported as it has been dropped from the spec.
338              
339             =back
340              
341             =head2 decode
342              
343             Decodes C<TOML> and returns a hash ref. Dies on parse error.
344              
345             =head2 encode
346              
347             Encodes a perl hash ref as a C<TOML>-formatted string.
348              
349             =head2 parse
350              
351             Alias for C<decode> to provide compatibility with C<TOML::Parser> when
352             overriding the parser by setting C<$TOML::Parser>.
353              
354             =head1 DIFFERENCES FROM L<TOML> AND L<TOML::Parser>
355              
356             C<TOML::Tiny> differs in a few significant ways from the L<TOML> module,
357             particularly in adding support for newer C<TOML> features and strictness.
358              
359             L<TOML> defaults to lax parsing and provides C<strict_mode> to (slightly)
360             tighten things up. C<TOML::Tiny> defaults to (somehwat) stricter parsing,
361             enabling some extra strictures with L</strict>.
362              
363             C<TOML::Tiny> supports a number of options which do not exist in L<TOML>:
364             L</inflate_integer>, L</inflate_float>, and L</strict>.
365              
366             C<TOML::Tiny> ignores invalid surrogate pairs within basic and multiline
367             strings (L<TOML> may attempt to decode an invalid pair). Additionally, only
368             those character escapes officially supported by TOML are interpreted as such by
369             C<TOML::Tiny>.
370              
371             C<TOML::Tiny> supports stripping initial whitespace and handles lines
372             terminating with a backslash correctly in multilne strings:
373              
374             # TOML input
375             x="""
376             foo"""
377              
378             y="""\
379             how now \
380             brown \
381             bureaucrat.\
382             """
383              
384             # Perl output
385             {x => 'foo', y => 'how now brown bureaucrat.'}
386              
387             C<TOML::Tiny> includes support for integers specified in binary, octal or hex
388             as well as the special float values C<inf> and C<nan>.
389              
390             =head1 SEE ALSO
391              
392             =over
393              
394             =item L<TOML::Tiny::Grammar>
395              
396             Regexp scraps used by C<TOML::Tiny> to parse TOML source.
397              
398             =back
399              
400             =head1 ACKNOWLEDGEMENTS
401              
402             Thanks to L<ZipRecruiter|https://www.ziprecruiter.com> for encouraging their
403             employees to contribute back to the open source ecosystem. Without their
404             dedication to quality software development this distribution would not exist.
405              
406             A big thank you to those who have contributed code or bug reports:
407              
408             =over
409              
410             =item L<ijackson|https://github.com/ijackson>
411              
412             =item L<noctux|https://github.com/noctux>
413              
414             =item L<oschwald|https://github.com/oschwald>
415              
416             =item L<jjatria|https://metacpan.org/author/JJATRIA>
417              
418             =back
419              
420             =head1 AUTHOR
421              
422             Jeff Ober <sysread@fastmail.fm>
423              
424             =head1 COPYRIGHT AND LICENSE
425              
426             This software is copyright (c) 2021 by Jeff Ober.
427              
428             This is free software; you can redistribute it and/or modify it under
429             the same terms as the Perl 5 programming language system itself.
430              
431             =cut