1use 5.010001;
2use strict;
3use warnings;
4
5package BSON;
6# ABSTRACT: BSON serialization and deserialization (EOL)
7
8use base 'Exporter';
9our @EXPORT_OK = qw/encode decode/;
10
11use version;
12our $VERSION = 'v1.12.2';
13
14use Carp;
15use Config;
16use Scalar::Util qw/blessed looks_like_number/;
17
18use Moo 2.002004; # safer generated code
19use boolean;
20use BSON::OID;
21
22use constant {
23    HAS_INT64 => $Config{use64bitint},
24    HAS_LD    => $Config{uselongdouble},
25};
26
27use if !HAS_INT64, "Math::BigInt";
28
29my $bools_re = qr/::(?:Boolean|_Bool|Bool)\z/;
30
31use namespace::clean -except => 'meta';
32
33my $max_int32 = 2147483647;
34
35# Dependency-free equivalent of what we need from Module::Runtime
36sub _try_load {
37    my ( $mod, $ver ) = @_;
38    ( my $file = "$mod.pm" ) =~ s{::}{/}g;
39    my $load = eval { require $file; $mod->VERSION($ver) if defined $ver; 1 };
40    delete $INC{$file} if !$load; # for old, broken perls
41    die $@ if !$load;
42    return 1;
43}
44
45BEGIN {
46    my ($class, @errs);
47    if ( $class = $ENV{PERL_BSON_BACKEND} ) {
48        eval { _try_load($class) };
49        if ( my $err = $@ ) {
50            $err =~ s{ at \S+ line .*}{};
51            die "Error: PERL_BSON_BACKEND '$class' could not be loaded: $err\n";
52        }
53        unless ($class->can("_encode_bson") && $class->can("_decode_bson") ) {
54            die "Error: PERL_BSON_BACKEND '$class' does not implement the correct API.\n";
55        }
56    }
57    elsif ( eval { _try_load( $class = "BSON::XS" ) } or do { push @errs, $@; 0 } ) {
58        # module loaded; nothing else to do
59    }
60    elsif ( eval { _try_load( $class = "BSON::PP" ) } or do { push @errs, $@; 0 } ) {
61        # module loaded; nothing else to do
62    }
63    else {
64        s/\n/ /g for @errs;
65        die join( "\n* ", "Error: Couldn't load a BSON backend:", @errs ) . "\n";
66    }
67
68    *_encode_bson = $class->can("_encode_bson");
69    *_decode_bson = $class->can("_decode_bson");
70    *_backend_class = sub { $class }; # for debugging
71}
72
73# LOAD AFTER XS/PP, so that modules can pick up right version of helpers
74use BSON::Types (); # loads types for extjson inflation
75
76#--------------------------------------------------------------------------#
77# public attributes
78#--------------------------------------------------------------------------#
79
80#pod =attr error_callback
81#pod
82#pod This attribute specifies a function reference that will be called with
83#pod three positional arguments:
84#pod
85#pod =for :list
86#pod * an error string argument describing the error condition
87#pod * a reference to the problematic document or byte-string
88#pod * the method in which the error occurred (e.g. C<encode_one> or C<decode_one>)
89#pod
90#pod Note: for decoding errors, the byte-string is passed as a reference to avoid
91#pod copying possibly large strings.
92#pod
93#pod If not provided, errors messages will be thrown with C<Carp::croak>.
94#pod
95#pod =cut
96
97has error_callback => (
98    is      => 'ro',
99    isa     => sub { die "not a code reference" if defined $_[0] && ! ref $_[0] eq 'CODE' },
100);
101
102#pod =attr invalid_chars
103#pod
104#pod A string containing ASCII characters that must not appear in keys.  The default
105#pod is the empty string, meaning there are no invalid characters.
106#pod
107#pod =cut
108
109has invalid_chars => (
110    is      => 'ro',
111    isa     => sub { die "not a string" if ! defined $_[0] || ref $_[0] },
112);
113
114#pod =attr max_length
115#pod
116#pod This attribute defines the maximum document size. The default is 0, which
117#pod disables any maximum.
118#pod
119#pod If set to a positive number, it applies to both encoding B<and> decoding (the
120#pod latter is necessary for prevention of resource consumption attacks).
121#pod
122#pod =cut
123
124has max_length => (
125    is      => 'ro',
126    isa     => sub { die "not a non-negative number" unless defined $_[0] && $_[0] >= 0 },
127);
128
129#pod =attr op_char
130#pod
131#pod This is a single character to use for special MongoDB-specific query
132#pod operators.  If a key starts with C<op_char>, the C<op_char> character will
133#pod be replaced with "$".
134#pod
135#pod The default is "$", meaning that no replacement is necessary.
136#pod
137#pod =cut
138
139has op_char => (
140    is  => 'ro',
141    isa => sub { die "not a single character" if defined $_[0] && length $_[0] > 1 },
142);
143
144#pod =attr ordered
145#pod
146#pod If set to a true value, then decoding will return a reference to a tied
147#pod hash that preserves key order. Otherwise, a regular (unordered) hash
148#pod reference will be returned.
149#pod
150#pod B<IMPORTANT CAVEATS>:
151#pod
152#pod =for :list
153#pod * When 'ordered' is true, users must not rely on the return value being any
154#pod   particular tied hash implementation.  It may change in the future for
155#pod   efficiency.
156#pod * Turning this option on entails a significant speed penalty as tied hashes
157#pod   are slower than regular Perl hashes.
158#pod
159#pod The default is false.
160#pod
161#pod =cut
162
163has ordered => (
164    is => 'ro',
165);
166
167#pod =attr prefer_numeric
168#pod
169#pod When false, scalar values will be encoded as a number if they were
170#pod originally a number or were ever used in a numeric context.  However, a
171#pod string that looks like a number but was never used in a numeric context
172#pod (e.g. "42") will be encoded as a string.
173#pod
174#pod If C<prefer_numeric> is set to true, the encoder will attempt to coerce
175#pod strings that look like a number into a numeric value.  If the string
176#pod doesn't look like a double or integer, it will be encoded as a string.
177#pod
178#pod B<IMPORTANT CAVEAT>: the heuristics for determining whether something is a
179#pod string or number are less accurate on older Perls.  See L<BSON::Types>
180#pod for wrapper classes that specify exact serialization types.
181#pod
182#pod The default is false.
183#pod
184#pod =cut
185
186has prefer_numeric => (
187    is => 'ro',
188);
189
190#pod =attr wrap_dbrefs
191#pod
192#pod If set to true, during decoding, documents with the fields C<'$id'> and
193#pod C<'$ref'> (literal dollar signs, not variables) will be wrapped as
194#pod L<BSON::DBRef> objects.  If false, they are decoded into ordinary hash
195#pod references (or ordered hashes, if C<ordered> is true).
196#pod
197#pod The default is true.
198#pod
199#pod =cut
200
201has wrap_dbrefs  => (
202    is => 'ro',
203);
204
205#pod =attr wrap_numbers
206#pod
207#pod If set to true, during decoding, numeric values will be wrapped into
208#pod BSON type-wrappers: L<BSON::Double>, L<BSON::Int64> or L<BSON::Int32>.
209#pod While very slow, this can help ensure fields can round-trip if unmodified.
210#pod
211#pod The default is false.
212#pod
213#pod =cut
214
215has wrap_numbers => (
216    is => 'ro',
217);
218
219#pod =attr wrap_strings
220#pod
221#pod If set to true, during decoding, string values will be wrapped into a BSON
222#pod type-wrappers, L<BSON::String>.  While very slow, this can help ensure
223#pod fields can round-trip if unmodified.
224#pod
225#pod The default is false.
226#pod
227#pod =cut
228
229has wrap_strings => (
230    is => 'ro',
231);
232
233#pod =attr dt_type (Discouraged)
234#pod
235#pod Sets the type of object which is returned for BSON DateTime fields. The
236#pod default is C<undef>, which returns objects of type L<BSON::Time>.  This is
237#pod overloaded to be the integer epoch value when used as a number or string,
238#pod so is somewhat backwards compatible with C<dt_type> in the L<MongoDB>
239#pod driver.
240#pod
241#pod Other acceptable values are L<BSON::Time> (explicitly), L<DateTime>,
242#pod L<Time::Moment>, L<DateTime::Tiny>, L<Mango::BSON::Time>.
243#pod
244#pod Because BSON::Time objects have methods to convert to DateTime,
245#pod Time::Moment or DateTime::Tiny, use of this field is discouraged.  Users
246#pod should use these methods on demand.  This option is provided for backwards
247#pod compatibility only.
248#pod
249#pod =cut
250
251has dt_type => (
252    is      => 'ro',
253    isa     => sub { return if !defined($_[0]); die "not a string" if ref $_[0] },
254);
255
256sub BUILD {
257    my ($self) = @_;
258    $self->{wrap_dbrefs} = 1 unless defined $self->{wrap_dbrefs};
259    $self->{invalid_chars} = "" unless defined $self->{invalid_chars};
260}
261
262#--------------------------------------------------------------------------#
263# public methods
264#--------------------------------------------------------------------------#
265
266#pod =method encode_one
267#pod
268#pod     $byte_string = $codec->encode_one( $doc );
269#pod     $byte_string = $codec->encode_one( $doc, \%options );
270#pod
271#pod Takes a "document", typically a hash reference, an array reference, or a
272#pod Tie::IxHash object and returns a byte string with the BSON representation of
273#pod the document.
274#pod
275#pod An optional hash reference of options may be provided.  Valid options include:
276#pod
277#pod =for :list
278#pod * first_key – if C<first_key> is defined, it and C<first_value>
279#pod   will be encoded first in the output BSON; any matching key found in the
280#pod   document will be ignored.
281#pod * first_value - value to assign to C<first_key>; will encode as Null if omitted
282#pod * error_callback – overrides codec default
283#pod * invalid_chars – overrides codec default
284#pod * max_length – overrides codec default
285#pod * op_char – overrides codec default
286#pod * prefer_numeric – overrides codec default
287#pod
288#pod =cut
289
290sub encode_one {
291    my ( $self, $document, $options ) = @_;
292    my $type = ref($document);
293
294    Carp::croak "Can't encode scalars" unless $type;
295    # qr// is blessed to 'Regexp';
296    if ( $type eq "Regexp"
297        || !( blessed($document) || $type eq 'HASH' || $type eq 'ARRAY' ) )
298    {
299        Carp::croak "Can't encode non-container of type '$type'";
300    }
301
302    $document = BSON::Doc->new(@$document)
303        if $type eq 'ARRAY';
304
305    my $merged_opts = { %$self, ( $options ? %$options : () ) };
306
307    my $bson = eval { _encode_bson( $document, $merged_opts ) };
308    # XXX this is a late max_length check -- it should be checked during
309    # encoding after each key
310    if ( $@ or ( $merged_opts->{max_length} && length($bson) > $merged_opts->{max_length} ) ) {
311        my $msg = $@ || "Document exceeds maximum size $merged_opts->{max_length}";
312        if ( $merged_opts->{error_callback} ) {
313            $merged_opts->{error_callback}->( $msg, $document, 'encode_one' );
314        }
315        else {
316            Carp::croak("During encode_one, $msg");
317        }
318    }
319
320    return $bson;
321}
322
323#pod =method decode_one
324#pod
325#pod     $doc = $codec->decode_one( $byte_string );
326#pod     $doc = $codec->decode_one( $byte_string, \%options );
327#pod
328#pod Takes a byte string with a BSON-encoded document and returns a
329#pod hash reference representing the decoded document.
330#pod
331#pod An optional hash reference of options may be provided.  Valid options include:
332#pod
333#pod =for :list
334#pod * dt_type – overrides codec default
335#pod * error_callback – overrides codec default
336#pod * max_length – overrides codec default
337#pod * ordered - overrides codec default
338#pod * wrap_dbrefs - overrides codec default
339#pod * wrap_numbers - overrides codec default
340#pod * wrap_strings - overrides codec default
341#pod
342#pod =cut
343
344sub decode_one {
345    my ( $self, $string, $options ) = @_;
346
347    my $merged_opts = { %$self, ( $options ? %$options : () ) };
348
349    if ( $merged_opts->{max_length} && length($string) > $merged_opts->{max_length} ) {
350        my $msg = "Document exceeds maximum size $merged_opts->{max_length}";
351        if ( $merged_opts->{error_callback} ) {
352            $merged_opts->{error_callback}->( $msg, \$string, 'decode_one' );
353        }
354        else {
355            Carp::croak("During decode_one, $msg");
356        }
357    }
358
359    my $document = eval { _decode_bson( $string, $merged_opts ) };
360    if ( $@ ) {
361        if ( $merged_opts->{error_callback} ) {
362            $merged_opts->{error_callback}->( $@, \$string, 'decode_one' );
363        }
364        else {
365            Carp::croak("During decode_one, $@");
366        }
367    }
368
369    return $document;
370}
371
372#pod =method clone
373#pod
374#pod     $copy = $codec->clone( ordered => 1 );
375#pod
376#pod Constructs a copy of the original codec, but allows changing
377#pod attributes in the copy.
378#pod
379#pod =cut
380
381sub clone {
382    my ($self, @args) = @_;
383    my $class = ref($self);
384    if ( @args == 1 && ref( $args[0] ) eq 'HASH' ) {
385        return $class->new( %$self, %{$args[0]} );
386    }
387
388    return $class->new( %$self, @args );
389}
390
391
392#--------------------------------------------------------------------------#
393# public class methods
394#--------------------------------------------------------------------------#
395
396#pod =method create_oid
397#pod
398#pod     $oid = BSON->create_oid;
399#pod
400#pod This class method returns a new L<BSON::OID>.  This abstracts OID
401#pod generation away from any specific Object ID class and makes it an interface
402#pod on a BSON codec.  Alternative BSON codecs should define a similar class
403#pod method that returns an Object ID of whatever type is appropriate.
404#pod
405#pod =cut
406
407sub create_oid { return BSON::OID->new }
408
409#pod =method inflate_extjson (DEPRECATED)
410#pod
411#pod This legacy method does not follow the L<MongoDB Extended JSON|https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>
412#pod specification.
413#pod
414#pod Use L</extjson_to_perl> instead.
415#pod
416#pod =cut
417
418sub inflate_extjson {
419    my ( $self, $hash ) = @_;
420
421    for my $k ( keys %$hash ) {
422        my $v = $hash->{$k};
423        if ( substr( $k, 0, 1 ) eq '$' ) {
424            croak "Dollar-prefixed key '$k' is not legal in top-level hash";
425        }
426        my $type = ref($v);
427        $hash->{$k} =
428            $type eq 'HASH'    ? $self->_inflate_hash($v)
429          : $type eq 'ARRAY'   ? $self->_inflate_array($v)
430          : $type =~ $bools_re ? ( $v ? true : false )
431          :                      $v;
432    }
433
434    return $hash;
435}
436
437#pod =method perl_to_extjson
438#pod
439#pod     use JSON::MaybeXS;
440#pod     my $ext = BSON->perl_to_extjson($data, \%options);
441#pod     my $json = encode_json($ext);
442#pod
443#pod Takes a perl data structure (i.e. hashref) and turns it into an
444#pod L<MongoDB Extended JSON|https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>
445#pod structure. Note that the structure will still have to be serialized.
446#pod
447#pod Possible options are:
448#pod
449#pod =for :list
450#pod * C<relaxed> A boolean indicating if "relaxed extended JSON" should
451#pod be generated. If not set, the default value is taken from the
452#pod C<BSON_EXTJSON_RELAXED> environment variable.
453#pod
454#pod =cut
455
456my $use_win32_specials = ($^O eq 'MSWin32' && $] lt "5.022");
457
458my $is_inf = $use_win32_specials ? qr/^1.\#INF/i : qr/^inf/i;
459my $is_ninf = $use_win32_specials ? qr/^-1.\#INF/i : qr/^-inf/i;
460my $is_nan = $use_win32_specials ? qr/^-?1.\#(?:IND|QNAN)/i : qr/^-?nan/i;
461
462sub perl_to_extjson {
463    my ($class, $data, $options) = @_;
464
465    local $ENV{BSON_EXTJSON} = 1;
466    local $ENV{BSON_EXTJSON_RELAXED} = $ENV{BSON_EXTJSON_RELAXED};
467    $ENV{BSON_EXTJSON_RELAXED} = $options->{relaxed};
468
469    if (not defined $data) {
470        return undef; ## no critic
471    }
472
473    if (blessed($data) and $data->can('TO_JSON')) {
474        my $json_data = $data->TO_JSON;
475        return $json_data;
476    }
477
478    if (not ref $data) {
479
480        if (looks_like_number($data)) {
481            if ($ENV{BSON_EXTJSON_RELAXED}) {
482                return $data;
483            }
484
485            if ($data =~ m{\A-?[0-9_]+\z}) {
486                if ($data <= $max_int32) {
487                    return { '$numberInt' => "$data" };
488                }
489                else {
490                    return { '$numberLong' => "$data" };
491                }
492            }
493            else {
494                return { '$numberDouble' => 'Infinity' }
495                    if $data =~ $is_inf;
496                return { '$numberDouble' => '-Infinity' }
497                    if $data =~ $is_ninf;
498                return { '$numberDouble' => 'NaN' }
499                    if $data =~ $is_nan;
500                my $value = "$data";
501                $value = $value / 1.0;
502                return { '$numberDouble' => "$value" };
503            }
504        }
505
506        return $data;
507    }
508
509    if (boolean::isBoolean($data)) {
510        return $data;
511    }
512
513    if (ref $data eq 'HASH') {
514        for my $key (keys %$data) {
515            my $value = $data->{$key};
516            $data->{$key} = $class->perl_to_extjson($value, $options);
517        }
518        return $data;
519    }
520
521    if (ref $data eq 'ARRAY') {
522        for my $index (0 .. $#$data) {
523            my $value = $data->[$index];
524            $data->[$index] = $class->perl_to_extjson($value, $options);
525        }
526        return $data;
527    }
528
529    if (blessed($data) and $data->isa('JSON::PP::Boolean')) {
530        return $data;
531    }
532
533    if (
534        blessed($data) and (
535            $data->isa('Math::BigInt') or
536            $data->isa('Math::BigFloat')
537        )
538    ) {
539        return $data;
540    }
541
542    die sprintf "Unsupported ref value (%s)", ref($data);
543}
544
545#pod =method extjson_to_perl
546#pod
547#pod     use JSON::MaybeXS;
548#pod     my $ext = decode_json($json);
549#pod     my $data = $bson->extjson_to_perl($ext);
550#pod
551#pod Takes an
552#pod L<MongoDB Extended JSON|https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>
553#pod data structure and inflates it into a Perl data structure. Note that
554#pod you have to decode the JSON string manually beforehand.
555#pod
556#pod Canonically specified numerical values like C<{"$numberInt":"23"}> will
557#pod be inflated into their respective C<BSON::*> wrapper types. Plain numeric
558#pod values will be left as-is.
559#pod
560#pod =cut
561
562sub extjson_to_perl {
563    my ($class, $data) = @_;
564    # top level keys are never extended JSON elements, so we wrap the
565    # _extjson_to_perl inflater so it applies only to values, not the
566    # original data structure
567    for my $key (keys %$data) {
568        my $value = $data->{$key};
569        $data->{$key} = $class->_extjson_to_perl($value);
570    }
571    return $data;
572}
573
574sub _extjson_to_perl {
575    my ($class, $data) = @_;
576
577    if (ref $data eq 'HASH') {
578
579        if ( exists $data->{'$oid'} ) {
580            return BSON::OID->new( oid => pack( "H*", $data->{'$oid'} ) );
581        }
582
583        if ( exists $data->{'$numberInt'} ) {
584            return BSON::Int32->new( value => $data->{'$numberInt'} );
585        }
586
587        if ( exists $data->{'$numberLong'} ) {
588            if (HAS_INT64) {
589                return BSON::Int64->new( value => $data->{'$numberLong'} );
590            }
591            else {
592                return BSON::Int64->new( value => Math::BigInt->new($data->{'$numberLong'}) );
593            }
594        }
595
596        if ( exists $data->{'$binary'} ) {
597            require MIME::Base64;
598            if (exists $data->{'$type'}) {
599                return BSON::Bytes->new(
600                    data    => MIME::Base64::decode_base64($data->{'$binary'}),
601                    subtype => hex( $data->{'$type'} || 0 ),
602                );
603            }
604            else {
605                my $value = $data->{'$binary'};
606                return BSON::Bytes->new(
607                    data    => MIME::Base64::decode_base64($value->{base64}),
608                    subtype => hex( $value->{subType} || 0 ),
609                );
610            }
611        }
612
613        if ( exists $data->{'$date'} ) {
614            my $v = $data->{'$date'};
615            $v = ref($v) eq 'HASH' ? $class->_extjson_to_perl($v) : _iso8601_to_epochms($v);
616            return BSON::Time->new( value => $v );
617        }
618
619        if ( exists $data->{'$minKey'} ) {
620            return BSON::MinKey->new;
621        }
622
623        if ( exists $data->{'$maxKey'} ) {
624            return BSON::MaxKey->new;
625        }
626
627        if ( exists $data->{'$timestamp'} ) {
628            return BSON::Timestamp->new(
629                seconds   => $data->{'$timestamp'}{t},
630                increment => $data->{'$timestamp'}{i},
631            );
632        }
633
634        if ( exists $data->{'$regex'} and not ref $data->{'$regex'}) {
635            return BSON::Regex->new(
636                pattern => $data->{'$regex'},
637                ( exists $data->{'$options'} ? ( flags => $data->{'$options'} ) : () ),
638            );
639        }
640
641        if ( exists $data->{'$regularExpression'} ) {
642            my $value = $data->{'$regularExpression'};
643            return BSON::Regex->new(
644                pattern => $value->{pattern},
645                ( exists $value->{options} ? ( flags => $value->{options} ) : () ),
646            );
647        }
648
649        if ( exists $data->{'$code'} ) {
650            return BSON::Code->new(
651                code => $data->{'$code'},
652                ( exists $data->{'$scope'}
653                    ? ( scope => $class->_extjson_to_perl($data->{'$scope'}) )
654                    : ()
655                ),
656            );
657        }
658
659        if ( exists $data->{'$undefined'} ) {
660            return undef; ## no critic
661        }
662
663        if ( exists $data->{'$dbPointer'} ) {
664            my $data = $data->{'$dbPointer'};
665            my $id = $data->{'$id'};
666            $id = $class->_extjson_to_perl($id) if ref($id) eq 'HASH';
667            return BSON::DBPointer->new(
668                '$ref' => $data->{'$ref'},
669                '$id' => $id,
670            );
671        }
672
673        if ( exists $data->{'$ref'} ) {
674            my $id = delete $data->{'$id'};
675            $id = $class->_extjson_to_perl($id) if ref($id) eq 'HASH';
676            return BSON::DBRef->new(
677                '$ref' => delete $data->{'$ref'},
678                '$id' => $id,
679                '$db' => delete $data->{'$db'},
680                %$data, # extra
681            );
682        }
683
684        if ( exists $data->{'$numberDecimal'} ) {
685            return BSON::Decimal128->new( value => $data->{'$numberDecimal'} );
686        }
687
688        # Following extended JSON is non-standard
689
690        if ( exists $data->{'$numberDouble'} ) {
691            if ( $data->{'$numberDouble'} eq '-0' && $] lt '5.014' && ! HAS_LD ) {
692                $data->{'$numberDouble'} = '-0.0';
693            }
694            return BSON::Double->new( value => $data->{'$numberDouble'} );
695        }
696
697        if ( exists $data->{'$symbol'} ) {
698            return BSON::Symbol->new(value => $data->{'$symbol'});
699        }
700
701        for my $key (keys %$data) {
702            my $value = $data->{$key};
703            $data->{$key} = $class->_extjson_to_perl($value);
704        }
705        return $data;
706    }
707
708    if (ref $data eq 'ARRAY') {
709        for my $index (0 .. $#$data) {
710            my $value = $data->[$index];
711            $data->[$index] = ref($value)
712                ? $class->_extjson_to_perl($value)
713                : $value;
714        }
715        return $data;
716    }
717
718    return $data;
719}
720
721#--------------------------------------------------------------------------#
722# legacy functional interface
723#--------------------------------------------------------------------------#
724
725#pod =func encode
726#pod
727#pod     my $bson = encode({ bar => 'foo' }, \%options);
728#pod
729#pod This is the legacy, functional interface and is only exported on demand.
730#pod It takes a hashref and returns a BSON string.
731#pod It uses an internal codec singleton with default attributes.
732#pod
733#pod =func decode
734#pod
735#pod     my $hash = decode( $bson, \%options );
736#pod
737#pod This is the legacy, functional interface and is only exported on demand.
738#pod It takes a BSON string and returns a hashref.
739#pod It uses an internal codec singleton with default attributes.
740#pod
741#pod =cut
742
743{
744    my $CODEC;
745
746    sub encode {
747        if ( defined $_[0] && ( $_[0] eq 'BSON' || ( blessed($_[0]) && $_[0]->isa('BSON') ) ) ) {
748            Carp::croak("Error: 'encode' is a function, not a method");
749        }
750        my $doc = shift;
751        $CODEC = BSON->new unless defined $CODEC;
752        if ( @_ == 1 && ref( $_[0] ) eq 'HASH' ) {
753            return $CODEC->encode_one( $doc, $_[0] );
754        }
755        elsif ( @_ % 2 == 0 ) {
756            return $CODEC->encode_one( $doc, {@_} );
757        }
758        else {
759            Carp::croak("Options for 'encode' must be a hashref or key-value pairs");
760        }
761    }
762
763    sub decode {
764        if ( defined $_[0] && ( $_[0] eq 'BSON' || ( blessed($_[0]) && $_[0]->isa('BSON') ) ) ) {
765            Carp::croak("Error: 'decode' is a function, not a method");
766        }
767        my $doc = shift;
768        $CODEC = BSON->new unless defined $CODEC;
769        my $args;
770        if ( @_ == 1 && ref( $_[0] ) eq 'HASH' ) {
771            $args = shift;
772        }
773        elsif ( @_ % 2 == 0 ) {
774            $args = { @_ };
775        }
776        else {
777            Carp::croak("Options for 'decode' must be a hashref or key-value pairs");
778        }
779        $args->{ordered} = delete $args->{ixhash}
780          if exists $args->{ixhash} && !exists $args->{ordered};
781        return $CODEC->decode_one( $doc, $args );
782    }
783}
784
785#--------------------------------------------------------------------------#
786# private functions
787#--------------------------------------------------------------------------#
788
789sub _inflate_hash {
790    my ( $class, $hash ) = @_;
791
792    if ( exists $hash->{'$oid'} ) {
793        return BSON::OID->new( oid => pack( "H*", $hash->{'$oid'} ) );
794    }
795
796    if ( exists $hash->{'$numberInt'} ) {
797        return BSON::Int32->new( value => $hash->{'$numberInt'} );
798    }
799
800    if ( exists $hash->{'$numberLong'} ) {
801        if (HAS_INT64) {
802            return BSON::Int64->new( value => $hash->{'$numberLong'} );
803        }
804        else {
805            return BSON::Int64->new( value => Math::BigInt->new($hash->{'$numberLong'}) );
806        }
807    }
808
809    if ( exists $hash->{'$binary'} ) {
810        require MIME::Base64;
811        return BSON::Bytes->new(
812            data    => MIME::Base64::decode_base64($hash->{'$binary'}),
813            subtype => hex( $hash->{'$type'} || 0 )
814        );
815    }
816
817    if ( exists $hash->{'$date'} ) {
818        my $v = $hash->{'$date'};
819        $v = ref($v) eq 'HASH' ? BSON->_inflate_hash($v) : _iso8601_to_epochms($v);
820        return BSON::Time->new( value => $v );
821    }
822
823    if ( exists $hash->{'$minKey'} ) {
824        return BSON::MinKey->new;
825    }
826
827    if ( exists $hash->{'$maxKey'} ) {
828        return BSON::MaxKey->new;
829    }
830
831    if ( exists $hash->{'$timestamp'} ) {
832        return BSON::Timestamp->new(
833            seconds   => $hash->{'$timestamp'}{t},
834            increment => $hash->{'$timestamp'}{i},
835        );
836    }
837
838    if ( exists $hash->{'$regex'} ) {
839        return BSON::Regex->new(
840            pattern => $hash->{'$regex'},
841            ( exists $hash->{'$options'} ? ( flags => $hash->{'$options'} ) : () ),
842        );
843    }
844
845    if ( exists $hash->{'$code'} ) {
846        return BSON::Code->new(
847            code => $hash->{'$code'},
848            ( exists $hash->{'$scope'} ? ( scope => $hash->{'$scope'} ) : () ),
849        );
850    }
851
852    if ( exists $hash->{'$undefined'} ) {
853        return undef; ## no critic
854    }
855
856    if ( exists $hash->{'$ref'} ) {
857        my $id = $hash->{'$id'};
858        $id = BSON->_inflate_hash($id) if ref($id) eq 'HASH';
859        return BSON::DBRef->new( '$ref' => $hash->{'$ref'}, '$id' => $id );
860    }
861
862    if ( exists $hash->{'$numberDecimal'} ) {
863        return BSON::Decimal128->new( value => $hash->{'$numberDecimal'} );
864    }
865
866    # Following extended JSON is non-standard
867
868    if ( exists $hash->{'$numberDouble'} ) {
869        if ( $hash->{'$numberDouble'} eq '-0' && $] lt '5.014' && ! HAS_LD ) {
870            $hash->{'$numberDouble'} = '-0.0';
871        }
872        return BSON::Double->new( value => $hash->{'$numberDouble'} );
873    }
874
875    if ( exists $hash->{'$symbol'} ) {
876        return $hash->{'$symbol'};
877    }
878
879    return $hash;
880}
881
882sub _inflate_array {
883    my ($class, $array) = @_;
884    if (@$array) {
885        for my $i ( 0 .. $#$array ) {
886            my $v = $array->[$i];
887            $array->[$i] =
888                ref($v) eq 'HASH'  ? BSON->_inflate_hash($v)
889              : ref($v) eq 'ARRAY' ? _inflate_array($v)
890              :                       $v;
891        }
892    }
893    return $array;
894}
895
896my $iso8601_re = qr{
897    (\d{4}) - (\d{2}) - (\d{2}) T               # date
898    (\d{2}) : (\d{2}) : ( \d+ (?:\. \d+ )? )    # time
899    (?: Z | ([+-] \d{2} :? (?: \d{2} )? ) )?    # maybe TZ
900}x;
901
902sub _iso8601_to_epochms {
903    my ($date) = shift;
904    require Time::Local;
905
906    my $zone_offset = 0;;
907    if ( substr($date,-1,1) eq 'Z' ) {
908        chop($date);
909    }
910
911    if ( $date =~ /\A$iso8601_re\z/ ) {
912        my ($Y,$M,$D,$h,$m,$s,$z) = ($1,$2-1,$3,$4,$5,$6,$7);
913        if (defined($z) && length($z))  {
914            $z =~ tr[:][];
915            $z .= "00" if length($z) < 5;
916            my $zd = substr($z,0,1);
917            my $zh = substr($z,1,2);
918            my $zm = substr($z,3,2);
919            $zone_offset = ($zd eq '-' ? -1 : 1 ) * (3600 * $zh + 60 * $zm);
920        }
921        my $frac = $s - int($s);
922        my $epoch = Time::Local::timegm(int($s), $m, $h, $D, $M, $Y) - $zone_offset;
923        $epoch = HAS_INT64 ? 1000 * $epoch : Math::BigInt->new($epoch) * 1000;
924        $epoch += HAS_INT64 ? $frac * 1000 : Math::BigFloat->new($frac) * 1000;
925        return $epoch;
926    }
927    else {
928        Carp::croak("Couldn't parse '\$date' field: $date\n");
929    }
930}
931
9321;
933
934=pod
935
936=encoding UTF-8
937
938=head1 NAME
939
940BSON - BSON serialization and deserialization (EOL)
941
942=head1 VERSION
943
944version v1.12.2
945
946=head1 END OF LIFE NOTICE
947
948Version v1.12.0 was the final feature release of the MongoDB BSON library
949and version v1.12.2 is the final patch release.
950
951B<As of August 13, 2020, the MongoDB Perl driver and related libraries have
952reached end of life and are no longer supported by MongoDB.> See the
953L<August 2019 deprecation
954notice|https://www.mongodb.com/blog/post/the-mongodb-perl-driver-is-being-deprecated>
955for rationale.
956
957If members of the community wish to continue development, they are welcome
958to fork the code under the terms of the Apache 2 license and release it
959under a new namespace.  Specifications and test files for MongoDB drivers
960and libraries are published in an open repository:
961L<mongodb/specifications|https://github.com/mongodb/specifications/tree/master/source>.
962
963=head1 SYNOPSIS
964
965    use BSON;
966    use BSON::Types ':all';
967    use boolean;
968
969    my $codec = BSON->new;
970
971    my $document = {
972        _id             => bson_oid(),
973        creation_time   => bson_time(), # now
974        zip_code        => bson_string("08544"),
975        hidden          => false,
976    };
977
978    my $bson = $codec->encode_one( $document );
979    my $doc  = $codec->decode_one( $bson     );
980
981=head1 DESCRIPTION
982
983This class implements a BSON encoder/decoder ("codec").  It consumes
984"documents" (typically hash references) and emits BSON strings and vice
985versa in accordance with the L<BSON Specification|http://bsonspec.org>.
986
987BSON is the primary data representation for L<MongoDB>.  While this module
988has several features that support MongoDB-specific needs and conventions,
989it can be used as a standalone serialization format.
990
991The codec may be customized through attributes on the codec option as well
992as encode/decode specific options on methods:
993
994    my $codec = BSON->new( \%global_attributes );
995
996    my $bson = $codec->encode_one( $document, \%encode_options );
997    my $doc  = $codec->decode_one( $bson    , \%decode_options );
998
999Because BSON is strongly-typed and Perl is not, this module supports
1000a number of "type wrappers" – classes that wrap Perl data to indicate how
1001they should serialize. The L<BSON::Types> module describes these and
1002provides associated helper functions.  See L</PERL-BSON TYPE MAPPING>
1003for more details.
1004
1005When decoding, type wrappers are used for any data that has no native Perl
1006representation.  Optionally, all data may be wrapped for precise control of
1007round-trip encoding.
1008
1009Please read the configuration attributes carefully to understand more about
1010how to control encoding and decoding.
1011
1012At compile time, this module will select an implementation backend.  It
1013will prefer C<BSON::XS> (released separately) if available, or will fall
1014back to L<BSON::PP> (bundled with this module).  See L</ENVIRONMENT> for
1015a way to control the selection of the backend.
1016
1017=head1 ATTRIBUTES
1018
1019=head2 error_callback
1020
1021This attribute specifies a function reference that will be called with
1022three positional arguments:
1023
1024=over 4
1025
1026=item *
1027
1028an error string argument describing the error condition
1029
1030=item *
1031
1032a reference to the problematic document or byte-string
1033
1034=item *
1035
1036the method in which the error occurred (e.g. C<encode_one> or C<decode_one>)
1037
1038=back
1039
1040Note: for decoding errors, the byte-string is passed as a reference to avoid
1041copying possibly large strings.
1042
1043If not provided, errors messages will be thrown with C<Carp::croak>.
1044
1045=head2 invalid_chars
1046
1047A string containing ASCII characters that must not appear in keys.  The default
1048is the empty string, meaning there are no invalid characters.
1049
1050=head2 max_length
1051
1052This attribute defines the maximum document size. The default is 0, which
1053disables any maximum.
1054
1055If set to a positive number, it applies to both encoding B<and> decoding (the
1056latter is necessary for prevention of resource consumption attacks).
1057
1058=head2 op_char
1059
1060This is a single character to use for special MongoDB-specific query
1061operators.  If a key starts with C<op_char>, the C<op_char> character will
1062be replaced with "$".
1063
1064The default is "$", meaning that no replacement is necessary.
1065
1066=head2 ordered
1067
1068If set to a true value, then decoding will return a reference to a tied
1069hash that preserves key order. Otherwise, a regular (unordered) hash
1070reference will be returned.
1071
1072B<IMPORTANT CAVEATS>:
1073
1074=over 4
1075
1076=item *
1077
1078When 'ordered' is true, users must not rely on the return value being any particular tied hash implementation.  It may change in the future for efficiency.
1079
1080=item *
1081
1082Turning this option on entails a significant speed penalty as tied hashes are slower than regular Perl hashes.
1083
1084=back
1085
1086The default is false.
1087
1088=head2 prefer_numeric
1089
1090When false, scalar values will be encoded as a number if they were
1091originally a number or were ever used in a numeric context.  However, a
1092string that looks like a number but was never used in a numeric context
1093(e.g. "42") will be encoded as a string.
1094
1095If C<prefer_numeric> is set to true, the encoder will attempt to coerce
1096strings that look like a number into a numeric value.  If the string
1097doesn't look like a double or integer, it will be encoded as a string.
1098
1099B<IMPORTANT CAVEAT>: the heuristics for determining whether something is a
1100string or number are less accurate on older Perls.  See L<BSON::Types>
1101for wrapper classes that specify exact serialization types.
1102
1103The default is false.
1104
1105=head2 wrap_dbrefs
1106
1107If set to true, during decoding, documents with the fields C<'$id'> and
1108C<'$ref'> (literal dollar signs, not variables) will be wrapped as
1109L<BSON::DBRef> objects.  If false, they are decoded into ordinary hash
1110references (or ordered hashes, if C<ordered> is true).
1111
1112The default is true.
1113
1114=head2 wrap_numbers
1115
1116If set to true, during decoding, numeric values will be wrapped into
1117BSON type-wrappers: L<BSON::Double>, L<BSON::Int64> or L<BSON::Int32>.
1118While very slow, this can help ensure fields can round-trip if unmodified.
1119
1120The default is false.
1121
1122=head2 wrap_strings
1123
1124If set to true, during decoding, string values will be wrapped into a BSON
1125type-wrappers, L<BSON::String>.  While very slow, this can help ensure
1126fields can round-trip if unmodified.
1127
1128The default is false.
1129
1130=head2 dt_type (Discouraged)
1131
1132Sets the type of object which is returned for BSON DateTime fields. The
1133default is C<undef>, which returns objects of type L<BSON::Time>.  This is
1134overloaded to be the integer epoch value when used as a number or string,
1135so is somewhat backwards compatible with C<dt_type> in the L<MongoDB>
1136driver.
1137
1138Other acceptable values are L<BSON::Time> (explicitly), L<DateTime>,
1139L<Time::Moment>, L<DateTime::Tiny>, L<Mango::BSON::Time>.
1140
1141Because BSON::Time objects have methods to convert to DateTime,
1142Time::Moment or DateTime::Tiny, use of this field is discouraged.  Users
1143should use these methods on demand.  This option is provided for backwards
1144compatibility only.
1145
1146=head1 METHODS
1147
1148=head2 encode_one
1149
1150    $byte_string = $codec->encode_one( $doc );
1151    $byte_string = $codec->encode_one( $doc, \%options );
1152
1153Takes a "document", typically a hash reference, an array reference, or a
1154Tie::IxHash object and returns a byte string with the BSON representation of
1155the document.
1156
1157An optional hash reference of options may be provided.  Valid options include:
1158
1159=over 4
1160
1161=item *
1162
1163first_key – if C<first_key> is defined, it and C<first_value> will be encoded first in the output BSON; any matching key found in the document will be ignored.
1164
1165=item *
1166
1167first_value - value to assign to C<first_key>; will encode as Null if omitted
1168
1169=item *
1170
1171error_callback – overrides codec default
1172
1173=item *
1174
1175invalid_chars – overrides codec default
1176
1177=item *
1178
1179max_length – overrides codec default
1180
1181=item *
1182
1183op_char – overrides codec default
1184
1185=item *
1186
1187prefer_numeric – overrides codec default
1188
1189=back
1190
1191=head2 decode_one
1192
1193    $doc = $codec->decode_one( $byte_string );
1194    $doc = $codec->decode_one( $byte_string, \%options );
1195
1196Takes a byte string with a BSON-encoded document and returns a
1197hash reference representing the decoded document.
1198
1199An optional hash reference of options may be provided.  Valid options include:
1200
1201=over 4
1202
1203=item *
1204
1205dt_type – overrides codec default
1206
1207=item *
1208
1209error_callback – overrides codec default
1210
1211=item *
1212
1213max_length – overrides codec default
1214
1215=item *
1216
1217ordered - overrides codec default
1218
1219=item *
1220
1221wrap_dbrefs - overrides codec default
1222
1223=item *
1224
1225wrap_numbers - overrides codec default
1226
1227=item *
1228
1229wrap_strings - overrides codec default
1230
1231=back
1232
1233=head2 clone
1234
1235    $copy = $codec->clone( ordered => 1 );
1236
1237Constructs a copy of the original codec, but allows changing
1238attributes in the copy.
1239
1240=head2 create_oid
1241
1242    $oid = BSON->create_oid;
1243
1244This class method returns a new L<BSON::OID>.  This abstracts OID
1245generation away from any specific Object ID class and makes it an interface
1246on a BSON codec.  Alternative BSON codecs should define a similar class
1247method that returns an Object ID of whatever type is appropriate.
1248
1249=head2 inflate_extjson (DEPRECATED)
1250
1251This legacy method does not follow the L<MongoDB Extended JSON|https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>
1252specification.
1253
1254Use L</extjson_to_perl> instead.
1255
1256=head2 perl_to_extjson
1257
1258    use JSON::MaybeXS;
1259    my $ext = BSON->perl_to_extjson($data, \%options);
1260    my $json = encode_json($ext);
1261
1262Takes a perl data structure (i.e. hashref) and turns it into an
1263L<MongoDB Extended JSON|https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>
1264structure. Note that the structure will still have to be serialized.
1265
1266Possible options are:
1267
1268=over 4
1269
1270=item *
1271
1272C<relaxed> A boolean indicating if "relaxed extended JSON" should
1273
1274be generated. If not set, the default value is taken from the
1275C<BSON_EXTJSON_RELAXED> environment variable.
1276
1277=back
1278
1279=head2 extjson_to_perl
1280
1281    use JSON::MaybeXS;
1282    my $ext = decode_json($json);
1283    my $data = $bson->extjson_to_perl($ext);
1284
1285Takes an
1286L<MongoDB Extended JSON|https://github.com/mongodb/specifications/blob/master/source/extended-json.rst>
1287data structure and inflates it into a Perl data structure. Note that
1288you have to decode the JSON string manually beforehand.
1289
1290Canonically specified numerical values like C<{"$numberInt":"23"}> will
1291be inflated into their respective C<BSON::*> wrapper types. Plain numeric
1292values will be left as-is.
1293
1294=head1 FUNCTIONS
1295
1296=head2 encode
1297
1298    my $bson = encode({ bar => 'foo' }, \%options);
1299
1300This is the legacy, functional interface and is only exported on demand.
1301It takes a hashref and returns a BSON string.
1302It uses an internal codec singleton with default attributes.
1303
1304=head2 decode
1305
1306    my $hash = decode( $bson, \%options );
1307
1308This is the legacy, functional interface and is only exported on demand.
1309It takes a BSON string and returns a hashref.
1310It uses an internal codec singleton with default attributes.
1311
1312=for Pod::Coverage BUILD
1313
1314=head1 PERL-BSON TYPE MAPPING
1315
1316BSON has numerous data types and Perl does not.
1317
1318When B<decoding>, each BSON type should result in a single, predictable
1319Perl type.  Where no native Perl type is appropriate, BSON decodes to an
1320object of a particular class (a "type wrapper").
1321
1322When B<encoding>, for historical reasons, there may be many Perl
1323representations that should encode to a particular BSON type.  For example,
1324all the popular "boolean" type modules on CPAN should encode to the BSON
1325boolean type.  Likewise, as this module is intended to supersede the
1326type wrappers that have shipped with the L<MongoDB> module, those
1327type wrapper are supported by this codec.
1328
1329The table below describes the BSON/Perl mapping for both encoding and
1330decoding.
1331
1332On the left are all the Perl types or classes this BSON codec
1333knows how to serialize to BSON.  The middle column is the BSON type for
1334each class.  The right-most column is the Perl type or class that the BSON
1335type deserializes to.  Footnotes indicate variations or special behaviors.
1336
1337    Perl type/class ->          BSON type        -> Perl type/class
1338    -------------------------------------------------------------------
1339    float[1]                    0x01 DOUBLE         float[2]
1340    BSON::Double
1341    -------------------------------------------------------------------
1342    string[3]                   0x02 UTF8           string[2]
1343    BSON::String
1344    -------------------------------------------------------------------
1345    hashref                     0x03 DOCUMENT       hashref[4][5]
1346    BSON::Doc
1347    BSON::Raw
1348    MongoDB::BSON::Raw[d]
1349    Tie::IxHash
1350    -------------------------------------------------------------------
1351    arrayref                    0x04 ARRAY          arrayref
1352    -------------------------------------------------------------------
1353    BSON::Bytes                 0x05 BINARY         BSON::Bytes
1354    scalarref
1355    BSON::Binary[d]
1356    MongoDB::BSON::Binary[d]
1357    -------------------------------------------------------------------
1358    n/a                         0x06 UNDEFINED[d]   undef
1359    -------------------------------------------------------------------
1360    BSON::OID                   0x07 OID            BSON::OID
1361    BSON::ObjectId[d]
1362    MongoDB::OID[d]
1363    -------------------------------------------------------------------
1364    boolean                     0x08 BOOL           boolean
1365    BSON::Bool[d]
1366    JSON::XS::Boolean
1367    JSON::PP::Boolean
1368    JSON::Tiny::_Bool
1369    Mojo::JSON::_Bool
1370    Cpanel::JSON::XS::Boolean
1371    Types::Serialiser::Boolean
1372    -------------------------------------------------------------------
1373    BSON::Time                  0x09 DATE_TIME      BSON::Time
1374    DateTime
1375    DateTime::Tiny
1376    Time::Moment
1377    Mango::BSON::Time
1378    -------------------------------------------------------------------
1379    undef                       0x0a NULL           undef
1380    -------------------------------------------------------------------
1381    BSON::Regex                 0x0b REGEX          BSON::Regex
1382    qr// reference
1383    MongoDB::BSON::Regexp[d]
1384    -------------------------------------------------------------------
1385    n/a                         0x0c DBPOINTER[d]   BSON::DBRef
1386    -------------------------------------------------------------------
1387    BSON::Code[6]               0x0d CODE           BSON::Code
1388    MongoDB::Code[6]
1389    -------------------------------------------------------------------
1390    n/a                         0x0e SYMBOL[d]      string
1391    -------------------------------------------------------------------
1392    BSON::Code[6]               0x0f CODEWSCOPE     BSON::Code
1393    MongoDB::Code[6]
1394    -------------------------------------------------------------------
1395    integer[7][8]               0x10 INT32          integer[2]
1396    BSON::Int32
1397    -------------------------------------------------------------------
1398    BSON::Timestamp             0x11 TIMESTAMP      BSON::Timestamp
1399    MongoDB::Timestamp[d]
1400    -------------------------------------------------------------------
1401    integer[7]                  0x12 INT64          integer[2][9]
1402    BSON::Int64
1403    Math::BigInt
1404    Math::Int64
1405    -------------------------------------------------------------------
1406    BSON::MaxKey                0x7F MAXKEY         BSON::MaxKey
1407    MongoDB::MaxKey[d]
1408    -------------------------------------------------------------------
1409    BSON::MinKey                0xFF MINKEY         BSON::MinKey
1410    MongoDB::MinKey[d]
1411
1412    [d] Deprecated or soon to be deprecated.
1413    [1] Scalar with "NV" internal representation or a string that looks
1414        like a float if the 'prefer_numeric' option is true.
1415    [2] If the 'wrap_numbers' option is true, numeric types will be wrapped
1416        as BSON::Double, BSON::Int32 or BSON::Int64 as appropriate to ensure
1417        round-tripping. If the 'wrap_strings' option is true, strings will
1418        be wrapped as BSON::String, likewise.
1419    [3] Scalar without "NV" or "IV" representation and not identified as a
1420        number by notes [1] or [7].
1421    [4] If 'ordered' option is set, will return a tied hash that preserves
1422        order (deprecated 'ixhash' option still works).
1423    [5] If the document appears to contain a DBRef and a 'dbref_callback'
1424        exists, that callback is executed with the deserialized document.
1425    [6] Code is serialized as CODE or CODEWSCOPE depending on whether a
1426        scope hashref exists in BSON::Code/MongoDB::Code.
1427    [7] Scalar with "IV" internal representation or a string that looks like
1428        an integer if the 'prefer_numeric' option is true.
1429    [8] Only if the integer fits in 32 bits.
1430    [9] On 32-bit platforms, 64-bit integers are deserialized to
1431        Math::BigInt objects (even if subsequently wrapped into
1432        BSON::Int64 if 'wrap_scalars' is true).
1433
1434=head1 THREADS
1435
1436Threads are never recommended in Perl, but this module is thread safe.
1437
1438=head1 ENVIRONMENT
1439
1440=over 4
1441
1442=item *
1443
1444PERL_BSON_BACKEND – if set at compile time, this will be treated as a module name.  The module will be loaded and used as the BSON backend implementation.  It must implement the same API as C<BSON::PP>.
1445
1446=item *
1447
1448BSON_EXTJSON - if set, serializing BSON type wrappers via C<TO_JSON> will produce Extended JSON v2 output.
1449
1450=item *
1451
1452BSON_EXTJSON_RELAXED - if producing Extended JSON output, if this is true, values will use the "Relaxed" form of Extended JSON, which sacrifices type round-tripping for improved human readability.
1453
1454=back
1455
1456=head1 SEMANTIC VERSIONING SCHEME
1457
1458Starting with BSON C<v0.999.0>, this module is using a "tick-tock"
1459three-part version-tuple numbering scheme: C<vX.Y.Z>
1460
1461=over 4
1462
1463=item *
1464
1465In stable releases, C<X> will be incremented for incompatible API changes.
1466
1467=item *
1468
1469Even-value increments of C<Y> indicate stable releases with new functionality.  C<Z> will be incremented for bug fixes.
1470
1471=item *
1472
1473Odd-value increments of C<Y> indicate unstable ("development") releases that should not be used in production.  C<Z> increments have no semantic meaning; they indicate only successive development releases.  Development releases may have API-breaking changes, usually indicated by C<Y> equal to "999".
1474
1475=back
1476
1477=head1 HISTORY AND ROADMAP
1478
1479This module was originally written by Stefan G.  In 2014, he graciously
1480transferred ongoing maintenance to MongoDB, Inc.
1481
1482The C<bson_xxxx> helper functions in L<BSON::Types> were inspired by similar
1483work in L<Mango::BSON> by Sebastian Riedel.
1484
1485=head1 AUTHORS
1486
1487=over 4
1488
1489=item *
1490
1491David Golden <david@mongodb.com>
1492
1493=item *
1494
1495Stefan G. <minimalist@lavabit.com>
1496
1497=back
1498
1499=head1 CONTRIBUTORS
1500
1501=for stopwords Eric Daniels Finn Olivier Duclos Pat Gunn Petr Písař Robert Sedlacek Thomas Bloor Tobias Leich Wallace Reis Yury Zavarin Oleg Kostyuk
1502
1503=over 4
1504
1505=item *
1506
1507Eric Daniels <eric.daniels@mongodb.com>
1508
1509=item *
1510
1511Finn <toyou1995@gmail.com>
1512
1513=item *
1514
1515Olivier Duclos <odc@cpan.org>
1516
1517=item *
1518
1519Pat Gunn <pgunn@mongodb.com>
1520
1521=item *
1522
1523Petr Písař <ppisar@redhat.com>
1524
1525=item *
1526
1527Robert Sedlacek <rs@474.at>
1528
1529=item *
1530
1531Thomas Bloor <tbsliver@shadow.cat>
1532
1533=item *
1534
1535Tobias Leich <email@froggs.de>
1536
1537=item *
1538
1539Wallace Reis <wallace@reis.me>
1540
1541=item *
1542
1543Yury Zavarin <yury.zavarin@gmail.com>
1544
1545=item *
1546
1547Oleg Kostyuk <cub@cpan.org>
1548
1549=back
1550
1551=head1 COPYRIGHT AND LICENSE
1552
1553This software is Copyright (c) 2020 by Stefan G. and MongoDB, Inc.
1554
1555This is free software, licensed under:
1556
1557  The Apache License, Version 2.0, January 2004
1558
1559=cut
1560
1561__END__
1562
1563
1564# vim: set ts=4 sts=4 sw=4 et tw=75:
1565