chiark / gitweb /
4597fe8f93fb4e60ba0cfa8362f1ed751fee5935
[nailing-cargo.git] / lib / TOML / Tiny.pm
1 package TOML::Tiny;
2 # ABSTRACT: a minimal, pure perl TOML parser and serializer
3
4 use strict;
5 use warnings;
6 no warnings qw(experimental);
7 use v5.18;
8
9 use TOML::Tiny::Parser;
10 use TOML::Tiny::Writer;
11
12 use parent 'Exporter';
13
14 our @EXPORT = qw(
15   from_toml
16   to_toml
17 );
18
19 #-------------------------------------------------------------------------------
20 # TOML module compatibility
21 #-------------------------------------------------------------------------------
22 sub from_toml {
23   my $source = shift;
24   my $parser = TOML::Tiny::Parser->new(@_);
25   my $toml = eval{ $parser->parse($source) };
26   if (wantarray) {
27     return ($toml, $@);
28   } else {
29     die $@ if $@;
30     return $toml;
31   }
32 }
33
34 sub to_toml {
35   goto \&TOML::Tiny::Writer::to_toml;
36 }
37
38 #-------------------------------------------------------------------------------
39 # Object API
40 #-------------------------------------------------------------------------------
41 sub new {
42   my ($class, %param) = @_;
43   bless{ %param, parser => TOML::Tiny::Parser->new(%param) }, $class;
44 }
45
46 sub decode {
47   my ($self, $source) = @_;
48   $self->{parser}->parse($source);
49 }
50
51 sub encode {
52   my ($self, $data) = @_;
53   TOML::Tiny::Writer::to_toml($data,
54     strict_arrays => $self->{strict_arrays},
55     no_string_guessing => $self->{no_string_guessing},
56   );
57 }
58
59 #-------------------------------------------------------------------------------
60 # For compatibility with TOML::from_toml's use of $TOML::Parser
61 #-------------------------------------------------------------------------------
62 sub parse {
63   goto \&decode;
64 }
65
66 1;
67
68 =head1 SYNOPSIS
69
70   use TOML::Tiny qw(from_toml to_toml);
71
72   binmode STDIN,  ':encoding(UTF-8)';
73   binmode STDOUT, ':encoding(UTF-8)';
74
75   # Decoding TOML
76   my $toml = do{ local $/; <STDIN> };
77   my ($parsed, $error) = from_toml $toml;
78
79   # Encoding TOML
80   say to_toml({
81     stuff => {
82       about => ['other', 'stuff'],
83     },
84   });
85
86   # Object API
87   my $parser = TOML::Tiny->new;
88   my $data = $parser->decode($toml);
89   say $parser->encode($data);
90
91
92 =head1 DESCRIPTION
93
94 C<TOML::Tiny> implements a pure-perl parser and generator for the
95 L<TOML|https://github.com/toml-lang/toml> data format. It conforms to TOML v5
96 (with a few caveats; see L</strict_arrays>) with support for more recent
97 changes in pursuit of v6.
98
99 C<TOML::Tiny> strives to maintain an interface compatible to the L<TOML> and
100 L<TOML::Parser> modules, and could even be used to override C<$TOML::Parser>:
101
102   use TOML;
103   use TOML::Tiny;
104
105   local $TOML::Parser = TOML::Tiny->new(...);
106   say to_toml(...);
107
108
109 =head1 EXPORTS
110
111 C<TOML::Tiny> exports the following to functions for compatibility with the
112 L<TOML> module. See L<TOML/FUNCTIONS>.
113
114 =head2 from_toml
115
116 Parses a string of C<TOML>-formatted source and returns the resulting data
117 structure. Any arguments after the first are passed to L<TOML::Tiny::Parser>'s
118 constructor.
119
120 If there is a syntax error in the C<TOML> source, C<from_toml> will die with
121 an explanation which includes the line number of the error.
122
123   my $result = eval{ from_toml($toml_string) };
124
125 Alternately, this routine may be called in list context, in which case syntax
126 errors will result in returning two values, C<undef> and an error message.
127
128   my ($result, $error) = from_toml($toml_string);
129
130 Homogenous array strictures are enabled by passing C<strict_arrays>:
131
132   # Croaks
133   my $result = from_toml(q{mixed=[1, 2, "three"]})
134
135 Additional arguments may be passed after the toml source string; see L</new>.
136
137 =head2 to_toml
138
139 Encodes a hash ref as a C<TOML>-formatted string.
140
141   my $toml = to_toml({foo => {'bar' => 'bat'}});
142
143   # [foo]
144   # bar="bat"
145
146 Homogenous array strictures are enabled by passing C<strict_arrays>:
147
148   # Croaks
149   my $toml = to_toml({mixed => [1, 2, "three"]}, strict_arrays => 1);
150
151 =head1 OBJECT API
152
153 =head2 new
154
155 =over
156
157 =item inflate_datetime
158
159 By default, C<TOML::Tiny> treats TOML datetimes as strings in the generated
160 data structure. The C<inflate_datetime> parameter allows the caller to provide
161 a routine to intercept those as they are generated:
162
163   use DateTime::Format::RFC3339;
164
165   my $parser = TOML::Tiny->new(
166     inflate_datetime => sub{
167       my $dt_string = shift;
168       return DateTime::Format::RFC3339->parse_datetime($dt_string);
169     },
170   );
171
172 =item inflate_boolean
173
174 By default, boolean values in a C<TOML> document result in a C<1> or C<0>.
175 If L<Types::Serialiser> is installed, they will instead be C<Types::Serialiser::true>
176 or C<Types::Serialiser::false>.
177
178 If you wish to override this, you can provide your own routine to generate values:
179
180   my $parser = TOML::Tiny->new(
181     inflate_boolean => sub{
182       my $bool = shift;
183       if ($bool eq 'true') {
184         return 'The Truth';
185       } else {
186         return 'A Lie';
187       }
188     },
189   );
190
191 =item inflate_integer
192
193 TOML integers are 64 bit and may not match the size of the compiled perl's
194 internal integer type. By default, integers are left as-is as perl strings
195 which may be upgraded as needed by the caller.
196
197   my $parser = TOML::Tiny->new(
198     inflate_integer => sub{
199       use bignum;
200       return 0 + shift;
201     }
202   );
203
204 =item inflate_float
205
206 TOML floats are 64 bit and may not match the size of the compiled perl's
207 internal float type. By default, integers are left as-is as perl strings which
208 may be upgraded as needed by the caller.
209
210   my $parser = TOML::Tiny->new(
211     inflate_float => sub{
212       use bignum;
213       return 0 + shift;
214     }
215   );
216
217 =item strict_arrays
218
219 C<TOML v5> specified homogenous arrays. This has since been removed and will no
220 longer be part of the standard as of C<v6> (as of the time of writing; the
221 author of C<TOML> has gone back and forth on the issue, so no guarantees).
222
223 By default, C<TOML::Tiny> is flexible and supports heterogenous arrays. If you
224 wish to require strictly typed arrays (for C<TOML>'s definition of "type",
225 anyway), C<strict_arrays> will produce an error when encountering arrays with
226 heterogenous types.
227
228 =item no_string_guessing
229
230 When encoding a Perl scalar it is not always clear what the TOML type
231 of the value is supposed to be.  By default, C<TOML::Tiny> will, for
232 unblessed scalars, guess based on the scalar's appearance.  Strings
233 that look like numbers, or like datetimes, will be encoded as such.
234
235 With no_string_guessing, C<TOML::Tiny> will look at the perl innards
236 to find the currently stored value type.  If it is a number, the
237 scalar will be encoded as a number.  If it's a string, as a string.
238 Dates and times which weren't built with DateTime come out as strings.
239
240 Specifying C<inflate_float>, C<inflate_integer>, and
241 C<inflate_datetime> is likely to be helpful with this option.
242
243 =back
244
245 =head2 decode
246
247 Decodes C<TOML> and returns a hash ref. Dies on parse error.
248
249 =head2 encode
250
251 Encodes a perl hash ref as a C<TOML>-formatted string. Dies when encountering
252 an array of mixed types if C<strict_arrays> was set.
253
254 =head2 parse
255
256 Alias for C<decode> to provide compatibility with C<TOML::Parser> when
257 overriding the parser by setting C<$TOML::Parser>.
258
259
260 =head1 DIFFERENCES FROM L<TOML> AND L<TOML::Parser>
261
262 C<TOML::Tiny> differs in a few significant ways from the L<TOML> module,
263 particularly in adding support for newer C<TOML> features and strictness.
264
265 L<TOML> defaults to lax parsing and provides C<strict_mode> to (slightly)
266 tighten things up. C<TOML::Tiny> defaults to (somehwat) stricter parsing, with
267 the exception of permitting heterogenous arrays (illegal in v4 and v5, but
268 permissible in the upcoming v6); optional enforcement of homogenous arrays is
269 supported with C<strict_arrays>.
270
271 C<TOML::Tiny> supports a number of options which do not exist in L<TOML>:
272 L</inflate_integer>, L</inflate_float>, and L</strict_arrays>.
273
274 C<TOML::Tiny> ignores invalid surrogate pairs within basic and multiline
275 strings (L<TOML> may attempt to decode an invalid pair). Additionally, only
276 those character escapes officially supported by TOML are interpreted as such by
277 C<TOML::Tiny>.
278
279 C<TOML::Tiny> supports stripping initial whitespace and handles lines
280 terminating with a backslash correctly in multilne strings:
281
282   # TOML input
283   x="""
284   foo"""
285
286   y="""\
287      how now \
288        brown \
289   bureaucrat.\
290   """
291
292   # Perl output
293   {x => 'foo', y => 'how now brown bureaucrat.'}
294
295 C<TOML::Tiny> includes support for integers specified in binary, octal or hex
296 as well as the special float values C<inf> and C<nan>.
297
298 =head1 SEE ALSO
299
300 =over
301
302 =item L<TOML::Tiny::Grammar>
303
304 Regexp scraps used by C<TOML::Tiny> to parse TOML source.
305
306 =back
307
308 =head1 ACKNOWLEDGEMENTS
309
310 Thanks to L<ZipRecruiter|https://www.ziprecruiter.com> for encouraging their
311 employees to contribute back to the open source ecosystem. Without their
312 dedication to quality software development this distribution would not exist.