2 package TOML::Tiny::Faithful;
4 use DateTime::Format::ISO8601;
5 use DateTime::Format::RFC3339;
8 use Types::Serialiser; # ensures that Parser DTRT with booleans
16 inflate_datetime => sub {
17 # RFC3339 bombs out if there is no timezone, so we parse with 8601
18 DateTime::Format::ISO8601->parse_datetime(shift)
20 inflate_integer => sub {
24 ? Math::BigInt->from_oct($')
25 : Math::BigInt->new($s);
27 inflate_float => sub { 0. + shift; },
28 no_string_guessing => 1,
29 datetime_formatter => TOML::Tiny::Faithful::DateTime::Formatter->new(),
33 my ($class, %param) = @_;
34 bless TOML::Tiny->new(_options(), %param), $class;
38 TOML::Tiny::from_toml($source, _options(), @_);
42 TOML::Tiny::to_toml($source, _options(), @_);
45 package TOML::Tiny::Faithful::DateTime::Formatter;
46 use DateTime::Format::RFC3339;
48 our $base = DateTime::Format::RFC3339->new();
57 # RFC3339 always prints a timezone. This is correct for RFC3339
58 # but in our application we sometimes have "local datetime"s
59 # where the time_zone is DateTime::TimeZone::Floating.
60 # We could use ISO8601 but it never prints the nanoseconds.
61 # It is easier to strip the timezone offset than add the ns.
62 my $r = DateTime::Format::RFC3339->new()->format_datetime($dt);
63 if ((ref $dt->time_zone()) =~ m/Floating/) {
64 $r =~ s/\+[0-9:.]+$//;
73 use TOML::Tiny::Faithful qw(from_toml to_toml);
75 binmode STDIN, ':encoding(UTF-8)';
76 binmode STDOUT, ':encoding(UTF-8)';
79 my $toml = do{ local $/; <STDIN> };
80 my ($parsed, $error) = from_toml $toml;
85 about => ['other', 'stuff'],
90 my $parser = TOML::Tiny::Faithful->new;
91 my $data = $parser->decode($toml);
92 say $parser->encode($data);
97 C<TOML::Tiny::Faithful> is a trivial wrapper around C<TOML::Tiny>
98 which sets C<inflate_integer>, C<inflate_float>, C<inflate_datetime>,
99 C<no_string_guessing> and C<datetime_formatter> to try to make the
100 TOML output faithful to any input TOML.