Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add support for Sereal as an input/output format

Add support for Sereal as an input/output format. We now have a hard
dependency on because it's awesome and you should use it instead of
using JSON.

The addition of Sereal support in the "serialize" subroutine mostly
involved copy/paste, the only original piece of code there is:

  if ($sereal_decoder_object->looks_like_sereal($uncompr)) {
    print STDERR "FlexSerializer: Detected that the input was Sereal\n" if DEBUG;
    print STDERR "FlexSerializer: This was the Sereal input: '%s'\n",
          substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
    my $structure;
    $sereal_decoder_object->decode($uncompr, $structure);
    push @out, $structure;
  }

The rest is just copy/pasting to deal with us now needing to detect
some combination of Storable, JSON and Sereal. This patch is best
viewed with "git show -w" to make that easier to read.

Also do a major update to the documentation, with some changes to
SYNOPSIS that could have been split up into another patch, but it was
easier to make the change this way.

This also adds exhaustive testing for the new format, the only caveat
is that we're skipping some tests because under Sereal the serialized
string may not be the same, but the result will be, so we have these
TODO tests:

    $ perl -Ilib t/10basic.t | grep -C3 TODO | grep -a srl
    #          got: '=srl(*cbazCcfoocbar'
    #     expected: '=srlRcbazCcfoocbar'
    #          got: '=srl(*cbazCcfoocbar'
    #     expected: '=srlRcbazCcfoocbar'

They still deserialize to the same objects though, so this should be
OK. It might be hash ordering differences or the caveat that Serial
might choose to use the PV slot of an IV/PV where JSON/Storable will
pick both or the IV.
  • Loading branch information...
commit 8bd2f6d7a25bba36e667e0c87b364197345302c3 1 parent 8e12134
@avar avar authored
View
5 Changes
@@ -1,5 +1,10 @@
Revision history for Perl extension Data::FlexSerializer
+1.07 Fri Nov 2 14:59:07 CET 2012
+
+ - Add support for the Sereal format. This adds a dependency on
+ Sereal::{Decoder,Encoder}.
+
- Remove redundant check of the close() exit code under the autodie
pragma.
View
1  MANIFEST
@@ -5,4 +5,5 @@ MANIFEST This list of files
t/01load.t
t/10basic.t
t/20file.t
+t/30sereal.t
t/lib/Data/FlexSerializer/EmptySubclass.pm
View
2  Makefile.PL
@@ -11,6 +11,8 @@ WriteMakefile(
PREREQ_PM => {
'Storable' => '0',
'JSON::XS' => '0',
+ 'Sereal::Decoder' => '0.15',
+ 'Sereal::Encoder' => '0.17',
'Moose' => '0',
'MooseX::Types' => '0',
'List::Util' => '0',
View
258 lib/Data/FlexSerializer.pm
@@ -1,13 +1,13 @@
package Data::FlexSerializer;
use Moose;
use Moose::Util::TypeConstraints qw(enum);
-use MooseX::Types::Moose qw(Maybe Bool Int Str);
+use MooseX::Types::Moose qw(Maybe Bool Int Str Object);
use MooseX::Types -declare => [ qw(
DataFlexSerializerOutputFormats
) ];
use autodie;
-our $VERSION = '1.06';
+our $VERSION = '1.07';
# Get the DEBUG constant from $Data::FlexSerializer::DEBUG or
# $ENV{DATA_FLEXSERIALIZER_DEBUG}
@@ -16,6 +16,8 @@ use Constant::FromGlobal DEBUG => { int => 1, default => 0, env => 1 };
use List::Util qw(min);
use Storable qw();
use JSON::XS qw();
+use Sereal::Decoder qw();
+use Sereal::Encoder qw();
use Compress::Zlib qw(Z_DEFAULT_COMPRESSION);
use IO::Uncompress::AnyInflate qw();
use Carp ();
@@ -50,9 +52,16 @@ has detect_storable => (
default => 0,
);
+has detect_sereal => (
+ is => 'ro',
+ isa => Bool,
+ default => 0,
+);
+
enum DataFlexSerializerOutputFormats, [ qw(
storable
json
+ sereal
) ];
coerce DataFlexSerializerOutputFormats,
@@ -66,6 +75,22 @@ has output_format => (
coerce => 1,
);
+has sereal_encoder => (
+ is => 'ro',
+ isa => Object,
+ lazy_build => 1,
+);
+
+sub _build_sereal_encoder { Sereal::Encoder->new }
+
+has sereal_decoder => (
+ is => 'ro',
+ isa => Object,
+ lazy_build => 1,
+);
+
+sub _build_sereal_decoder { Sereal::Decoder->new }
+
around BUILDARGS => sub {
my ( $orig, $class, %args ) = @_;
@@ -89,15 +114,22 @@ around BUILDARGS => sub {
return $rv;
};
-my %OutputMethods = (
- json => sub { JSON::XS::encode_json( $_[0] ) },
- storable => sub { Storable::nfreeze( $_[0] ) },
-);
+sub BUILD {
+ my ($self) = @_;
+
+ # We may or may not have Sereal::{Decoder,Encoder} objects, if not
+ # build them
+ $self->sereal_decoder if $self->detect_sereal;
+ $self->sereal_encoder if $self->output_format eq 'sereal';
+
+ return;
+}
sub serialize {
my $self = shift;
my $do_compress = $self->{compress_output}; # hot path, bypass accessor
+ my $output_format = $self->{output_format}; # hot path, bypass accessor
my $comp_level;
$comp_level = $self->{compression_level} if $do_compress; # hot path, bypass accessor
@@ -110,10 +142,15 @@ sub serialize {
));
}
- my $output_sub = $OutputMethods{ $self->{output_format} }; # hot path, bypass accessor
my @out;
foreach my $data (@_) {
- my $serialized = $output_sub->($data);
+ my $serialized = $output_format eq 'json'
+ ? JSON::XS::encode_json($data)
+ : $output_format eq 'storable'
+ ? Storable::nfreeze($data)
+ : $output_format eq 'sereal'
+ ? $self->{sereal_encoder}->encode($data)
+ : die "PANIC: unknown output format '$output_format'";
if ($do_compress) {
$serialized = Compress::Zlib::compress(\$serialized,
(defined($comp_level) ? ($comp_level) : (Z_DEFAULT_COMPRESSION)));
@@ -132,13 +169,15 @@ sub deserialize {
my $do_uncompress = $self->{assume_compression}; # hot path, bypass accessor
my $detect_compression = $self->{detect_compression}; # hot path, bypass accessor
my $detect_storable = $self->{detect_storable}; # hot path, bypass accessor
+ my $detect_sereal = $self->{detect_sereal}; # hot path, bypass accessor
+ my $sereal_decoder = $detect_sereal ? $self->{sereal_decoder} : undef;
if (DEBUG) {
warn(sprintf(
"FlexSerializer using the following options for deserialization: "
- . "assume_compression=%s, detect_compression=%s, detect_storable=%s\n",
+ . "assume_compression=%s, detect_compression=%s, detect_storable=%s, detect_sereal=%s\n",
map {defined $self->{$_} ? $self->{$_} : '<undef>'}
- qw(assume_compression detect_compression detect_storable)
+ qw(assume_compression detect_compression detect_storable detect_sereal)
));
}
@@ -163,28 +202,63 @@ sub deserialize {
$uncompr = $serialized;
}
- if ($detect_storable) {
- if ($uncompr =~ /^(?:\{|\[)/) {
- warn "FlexSerializer: Detected that the input was JSON" if DEBUG;
- warn "FlexSerializer: This was the start of the JSON input: '%s'",
+ # Copy-paste galore ahead for performance reasons. We can either
+ # make it pruttah or fast.
+ if ($detect_sereal) {
+ if ($sereal_decoder->looks_like_sereal($uncompr)) {
+ warn "FlexSerializer: Detected that the input was Sereal" if DEBUG;
+ warn "FlexSerializer: This was the Sereal input: '%s'",
substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
+ my $structure;
+ $sereal_decoder->decode($uncompr, $structure);
+ push @out, $structure;
+ }
+ elsif ($detect_storable) {
+ if ($uncompr =~ /^(?:\{|\[)/) {
+ warn "FlexSerializer: Detected that the input was JSON" if DEBUG;
+ warn "FlexSerializer: This was the start of the JSON input: '%s'",
+ substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
+ push @out, JSON::XS::decode_json($uncompr);
+ }
+ else {
+ #elsif (defined Storable::read_magic(substr($uncompr, 0, 21))) {
+ warn "FlexSerializer: Detected that the input was Storable" if DEBUG;
+ warn "FlexSerializer: This was the Storable input: '%s'",
+ substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
+ $uncompr =~ s/^pst0//; # remove Storable file magic if necessary
+ push @out, Storable::thaw($uncompr);
+ }
+ }
+ else {
+ warn "FlexSerializer: Assuming that the input is JSON" if DEBUG;
+ warn "FlexSerializer: This was the JSON input: '%s'",
+ substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
push @out, JSON::XS::decode_json($uncompr);
}
+ } else {
+ if ($detect_storable) {
+ if ($uncompr =~ /^(?:\{|\[)/) {
+ warn "FlexSerializer: Detected that the input was JSON" if DEBUG;
+ warn "FlexSerializer: This was the start of the JSON input: '%s'",
+ substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
+ push @out, JSON::XS::decode_json($uncompr);
+ }
+ else {
+ #elsif (defined Storable::read_magic(substr($uncompr, 0, 21))) {
+ warn "FlexSerializer: Detected that the input was Storable" if DEBUG;
+ warn "FlexSerializer: This was the Storable input: '%s'",
+ substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
+ $uncompr =~ s/^pst0//; # remove Storable file magic if necessary
+ push @out, Storable::thaw($uncompr);
+ }
+ }
else {
- #elsif (defined Storable::read_magic(substr($uncompr, 0, 21))) {
- warn "FlexSerializer: Detected that the input was Storable" if DEBUG;
- warn "FlexSerializer: This was the Storable input: '%s'",
- substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
- $uncompr =~ s/^pst0//; # remove Storable file magic if necessary
- push @out, Storable::thaw($uncompr);
+ warn "FlexSerializer: Assuming that the input is JSON" if DEBUG;
+ warn "FlexSerializer: This was the JSON input: '%s'",
+ substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
+ push @out, JSON::XS::decode_json($uncompr);
}
}
- else {
- warn "FlexSerializer: Assuming that the input is JSON" if DEBUG;
- warn "FlexSerializer: This was the JSON input: '%s'",
- substr($uncompr, 0, min(length($uncompr), 100)) if DEBUG >= 2;
- push @out, JSON::XS::decode_json($uncompr);
- }
}
return wantarray ? @out
@@ -269,37 +343,93 @@ Data::FlexSerializer - (De-)serialization from/to (compressed) JSON or Storable
=head1 SYNOPSIS
+This module was originally written to convert away from persistent use
+of Storable to using JSON at Booking.com. Since then mostly due to
+various issues with JSON not accurately being able to represent Perl
+datastructures (e.g. preserve encoding flags) we've started to migrate
+to L<Sereal::Encoder|Sereal> instead.
+
+However the API of this module is now slightly awkward because now it
+needs to deal with the possible detection and emission of these three
+formats, and it still uses the JSON format by default which is no
+longer the recommended way to use it.
+
+ # For all of the below
use Data::FlexSerializer;
-
- # Strictly handling compressed JSON by default:
+
+=head2 Reading and writing compressed JSON
+
+ # We *only* read/write compressed JSON by default:
my $strict_serializer = Data::FlexSerializer->new;
my @blobs = $strict_serializer->serialize(@perl_datastructures);
my @perl_datastructures = $strict_serializer->deserialize(@blobs);
-
- my $lax_compress = Data::FlexSerializer->new(
- detect_compression => 1, # accept uncompressed JSON as well
+
+=head2 Reading maybe compressed JSON and writing compressed JSON
+
+ # We can optionally detect compressed JSON as well, will accept
+ # mixed compressed/uncompressed data. This works for all the input
+ # formats.
+ my $lax_serializer = Data::FlexSerializer->new(
+ detect_compression => 1,
);
-
- my $weak_compress = Data::FlexSerializer->new(
- compression_level => 1, # use fastest compression
+
+=head2 Reading definitely compressed JSON and writing compressed JSON
+
+ # If we know that all our data is compressed we can skip the
+ # detection step. This works for all the input formats.
+ my $lax_compress = Data::FlexSerializer->new(
+ assume_compression => 1,
+ compress_output => 1, # This is the default
);
-
- my $backcompat = Data::FlexSerializer->new(
+
+=head2 Migrate from maybe compressed Storable to compressed JSON
+
+ my $storable_to_json = Data::FlexSerializer->new(
detect_compression => 1, # check whether the input is compressed
detect_storable => 1, # accept Storable images as input
+ compress_output => 1, # This is the default
+ );
+
+=head2 Migrate from maybe compressed JSON to Sereal
+
+ my $storable_to_sereal = Data::FlexSerializer->new(
+ detect_sereal => 1,
+ output_format => 'sereal',
);
-
- my $no_compression = Data::FlexSerializer->new(
- compress_output => 0,
+
+=head2 Migrate date from Sereal to JSON
+
+ my $sereal_backcompat = Data::FlexSerializer->new(
+ detect_sereal => 1, # accept Sereal images as input
+ );
+
+=head2 Migrate from JSON OR Storable to Sereal
+
+ my $flex_to_json = Data::FlexSerializer->new(
+ detect_compression => 1,
+ detect_sereal => 1,
+ detect_storable => 1,
+ output_format => 'sereal',
+ );
+
+=head2 Migrate from JSON OR Storable to Sereal with custom Sereal objects
+
+ my $flex_to_json = Data::FlexSerializer->new(
+ detect_compression => 1,
+ detect_sereal => 1,
+ detect_storable => 1,
+ output_format => 'sereal',
+ sereal_decoder => Sereal::Decoder->new(...),
+ sereal_encoder => Sereal::Encoder->new(...),
);
=head1 DESCRIPTION
-This simple OO module implements a serializer/deserializer for the basic
-builtin Perl data structures (no blessed structures, no filehandles,
-no regexes, no self-referential structures). It can produce JSON or
-Storable images. The output can be zlib-compressed or uncompressed
-depending on settings.
+This simple OO module implements a serializer/deserializer for the
+basic builtin Perl data structures (no blessed structures, no
+filehandles, no regexes, no self-referential structures). It can
+produce JSON, Storable or Sereal images. The output can be
+zlib-compressed or uncompressed depending on settings.
The deserialization phase is more powerful: Depending on the serializer
settings, it can be strict in only accepting compressed or uncompressed
@@ -317,29 +447,59 @@ are more restrictive, see below.
Constructor. Takes named arguments.
+=head3 assume_compression
+
C<assume_compression> is a flag that makes the deserialization assume
that the data will be compressed. It won't have to guess, making the
deserialization faster. Defaults to true.
+=head3 detect_compression
+
C<detect_compression> is a flag that also affects only the deserialization
step. If set, it'll auto-detect whether the input is compressed. Mutually
exclusive with C<assume_compression>. If C<detect_compression> is set, but
C<assume_compression> is not explicitly specified, C<assume_compression> will
be disabled (where it otherwise defaults to true).
+=head3 compress_output
+
C<compress_output> is a flag indicating whether compressed or uncompressed
dumps are to be generated during the serialization. Defaults to true.
+=head3 compression_level
+
C<compression_level> is an integer indicating the compression level (0-9).
-C<output_format> can be either set to the string C<json> (default) or C<storable>.
-It has the obvious effect. Its value can be changed at runtime via the accessor
-to facilitate having certain output formats in experiments.
+=head3 output_format
+
+C<output_format> can be either set to the string C<json> (default),
+C<storable> or C<sereal>. It has the obvious effect. Its value can be
+changed at runtime via the accessor to facilitate having certain
+output formats in experiments.
+
+=head3 detect_storable
C<detect_storable>, if set, forces C<Data::FlexSerializer> into
Storable-compatibility mode. Apart from JSON input, it will also detect whether
the provided blob is in valid Storable format. Defaults to off.
+=head3 detect_sereal
+
+C<detect_sereal>, if set, forces C<Data::FlexSerializer> into
+Sereal-compatibility mode. Apart from JSON input, it will also detect whether
+the provided blob is in valid Sereal format. Defaults to off.
+
+=head3 sereal_encoder
+
+=head3 sereal_decoder
+
+You can supply C<sereal_encoder> or C<sereal_decoder> arguments with
+your own Serial decoder/encoder objects. Handy if you want to pass
+custom options to the encoder or decoder.
+
+By default we create objects for you at BUILD time. So you don't need
+to supply this for optimization purposes either.
+
=head2 serialize
Given a list of things to serialize, this does the job on each of them and
@@ -393,10 +553,10 @@ their gratitude.
=head1 COPYRIGHT AND LICENSE
(C) 2011, 2012 Steffen Mueller and others. All rights reserved.
-
+
This code is available under the same license as Perl version
5.8.1 or higher.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
View
58 t/10basic.t
@@ -5,6 +5,7 @@ use Data::FlexSerializer;
use Storable qw/nfreeze thaw/;
use Compress::Zlib qw(Z_DEFAULT_COMPRESSION);
use JSON::XS qw/encode_json decode_json/;
+use Sereal::Encoder qw(encode_sereal);
use Test::More;
use File::Spec;
@@ -25,13 +26,14 @@ foreach my $class ('Data::FlexSerializer', 'Data::FlexSerializer::EmptySubclass'
compression_level => undef,
detect_storable => 0,
output_format => 'json',
+ detect_sereal => 0,
);
foreach my $setting (sort keys %defaults) {
is($default_szer->$setting, $defaults{$setting}, "defaults for $setting");
}
# Test constructor coercion cases
- for my $output_format (qw(json storable JSON STORABLE jSON stORABLE)) {
+ for my $output_format (qw(json storable JSON STORABLE jSON stORABLE sereal Sereal sEreal)) {
my $object = $class->new(output_format => $output_format);
isa_ok($object, $class, "We can construct with output_format => $output_format");
cmp_ok($object->output_format, 'eq', lc $output_format, "Once constructed the output_format is normalized");
@@ -75,23 +77,34 @@ foreach my $class ('Data::FlexSerializer', 'Data::FlexSerializer::EmptySubclass'
my %opt_flex_in = (
%opt_accept_compress,
detect_storable => 1,
+ detect_sereal => 1,
);
my %opt_storable = (
output_format => 'storable',
detect_storable => 1,
);
+ my %opt_sereal = (
+ output_format => 'sereal',
+ detect_sereal => 1,
+ );
my %serializers = (
default => $default_szer,
json_compress => $default_szer,
json_no_compress => $class->new(%opt_no_compress),
json_flex_compress => $class->new(%opt_accept_compress, compress_output => 1),
- flex_compress => $class->new(detect_storable => 1, compress_output => 1),
+ # Accept everything
+ flex_compress => $class->new(detect_storable => 1, detect_sereal => 1, compress_output => 1),
flex_no_compress => $class->new(%opt_flex_in, %opt_no_compress),
flex_flex_compress => $class->new(%opt_flex_in),
+ # Storable
s_compress => $class->new(%opt_storable),
s_no_compress => $class->new(%opt_storable, %opt_no_compress),
s_flex_compress => $class->new(%opt_storable, %opt_accept_compress, compress_output => 1),
+ # Sereal
+ sereal_compress => $class->new(%opt_sereal),
+ sereal_no_compress => $class->new(%opt_sereal, %opt_no_compress),
+ sereal_flex_compress => $class->new(%opt_sereal, %opt_accept_compress, compress_output => 1),
);
isa_ok($serializers{$_}, $class, 'Serializer for "$_"') for sort keys %serializers;
@@ -102,8 +115,10 @@ foreach my $class ('Data::FlexSerializer', 'Data::FlexSerializer::EmptySubclass'
);
$data{storable} = nfreeze($data{raw});
$data{json} = encode_json($data{raw});
+ $data{sereal} = encode_sereal($data{raw});
$data{comp_json} = Compress::Zlib::compress(\$data{json}, Z_DEFAULT_COMPRESSION);
$data{comp_storable} = Compress::Zlib::compress(\$data{storable}, Z_DEFAULT_COMPRESSION);
+ $data{comp_sereal} = Compress::Zlib::compress(\$data{sereal}, Z_DEFAULT_COMPRESSION);
$data{comp_garbage} = Compress::Zlib::compress(\$data{garbage}, Z_DEFAULT_COMPRESSION); # dubious
# assert that serialize and deserialize die if called in scalar context and
@@ -126,12 +141,18 @@ foreach my $class ('Data::FlexSerializer', 'Data::FlexSerializer::EmptySubclass'
'flex_compress' => 'comp_json',
'flex_no_compress' => 'json',
'flex_flex_compress' => 'json',
+ # Storable
's_compress' => 'comp_storable',
's_no_compress' => 'storable',
's_flex_compress' => 'comp_storable',
+ # Sereal
+ 'sereal_compress' => 'comp_sereal',
+ 'sereal_no_compress' => 'sereal',
+ 'sereal_flex_compress' => 'comp_sereal',
);
foreach my $s_name (sort keys %results_serialize) {
- my $serializer = $serializers{$s_name} or die;
+ my $serializer = $serializers{$s_name} or die "We don't have '\$serializers{$s_name}'";
+ my $is_sereal = $s_name =~ /sereal/;
my $data = $data{raw}; # always raw input for serialization
my $tname = "serialization with $s_name";
my $res;
@@ -147,11 +168,22 @@ foreach my $class ('Data::FlexSerializer', 'Data::FlexSerializer::EmptySubclass'
is($res, $res[0], "$tname same result in array and scalar context");
# test actual output
- my $expected_output = $data{ $results_serialize{$s_name} } or die;
- is($res, $expected_output, "$tname output as expected");
+ my $expected_output = $data{ $results_serialize{$s_name} } or die "We don't have \$results_serialize{$s_name}";
+ TODO: {
+ local $TODO = $is_sereal ? "Different serialized strings are OK if they decode to the same results" : undef;
+ is($res, $expected_output, "$tname output as expected");
+ }
- # now assert that garbage throws exceptions
- ok(not eval {$res = $serializer->serialize($data{garbage}); 1});
+ # Test that we either serialize or don't serialize plain SvPV's
+ my $eval_died = not eval {
+ $res = $serializer->serialize($data{garbage});
+ 1;
+ };
+ if ($is_sereal) {
+ ok(!$eval_died, "Under Sereal we support serializing plain SvPV");
+ } else {
+ ok($eval_died, "We should die under Storable and JSON when fed a plain SvPV");
+ }
}
# maps input => expected output for each serializer.
@@ -197,6 +229,18 @@ foreach my $class ('Data::FlexSerializer', 'Data::FlexSerializer::EmptySubclass'
(map {$_ => 'raw'} qw(comp_json comp_storable json storable)),
(map {$_ => \undef} qw(garbage)),
},
+ 'sereal_compress' => {
+ (map {$_ => 'raw'} qw(comp_json comp_sereal)),
+ (map {$_ => \undef} qw(json sereal garbage)),
+ },
+ 'sereal_no_compress' => {
+ (map {$_ => 'raw'} qw(json sereal)),
+ (map {$_ => \undef} qw(comp_json comp_sereal garbage)),
+ },
+ 'sereal_flex_compress' => {
+ (map {$_ => 'raw'} qw(comp_json comp_sereal json sereal)),
+ (map {$_ => \undef} qw(garbage)),
+ },
);
foreach my $s_name (sort keys %results_deserialize) {
View
3  t/20file.t
@@ -14,7 +14,7 @@ use Data::FlexSerializer::EmptySubclass;
foreach my $class ('Data::FlexSerializer', 'Data::FlexSerializer::EmptySubclass') {
- foreach my $format ('json', 'storable') {
+ foreach my $format ('json', 'storable', 'sereal') {
foreach my $compression (0, 1) {
@@ -23,6 +23,7 @@ foreach my $class ('Data::FlexSerializer', 'Data::FlexSerializer::EmptySubclass'
assume_compression => $compression,
compress_output => $compression,
detect_storable => $format eq 'storable' ? 1 : 0,
+ detect_sereal => $format eq 'sereal' ? 1 : 0,
);
isa_ok($serializer, $class);
View
34 t/30sereal.t
@@ -0,0 +1,34 @@
+use strict;
+use warnings;
+use Test::More tests => 8;
+use Data::FlexSerializer;
+use Sereal::Encoder qw();
+use Sereal::Decoder qw();
+use Scalar::Util qw(blessed);
+
+# Make sure we properly build Sereal objects at object construction time
+{
+ my $flex_enc = Data::FlexSerializer->new(output_format => 'sereal');
+ ok(blessed($flex_enc->{sereal_encoder}), "We have a Sereal encoder object");
+ ok(!exists $flex_enc->{sereal_decoder}, "No need for a decoder, we're only encoding");
+ my $flex_dec = Data::FlexSerializer->new(detect_sereal => 1);
+ ok(blessed($flex_dec->{sereal_decoder}), "We have a Sereal decoder object");
+ ok(!exists $flex_dec->{sereal_encoder}, "No need for a decoder, we're only encoding");
+ my $flex_both = Data::FlexSerializer->new(detect_sereal => 1, output_format => 'sereal');
+ ok(blessed($flex_both->{sereal_decoder}), "We have a Sereal decoder object");
+ ok(blessed($flex_both->{sereal_encoder}), "We have a Sereal encoder object ");
+}
+
+# Check that we can provide a custom objects
+{
+ my $encoder = Sereal::Encoder->new;
+ my $decoder = Sereal::Decoder->new;
+ my $flex_both = Data::FlexSerializer->new(
+ detect_sereal => 1,
+ output_format => 'sereal',
+ sereal_encoder => $encoder,
+ sereal_decoder => $decoder,
+ );
+ ok($encoder == $flex_both->{sereal_encoder}, "We use encoder objects passed to us");
+ ok($decoder == $flex_both->{sereal_decoder}, "We use decoder objects passed to us");
+}
Please sign in to comment.
Something went wrong with that request. Please try again.