Skip to content

Instantly share code, notes, and snippets.

@dagolden

dagolden/nopaste

Created May 20, 2015
Embed
What would you like to do?
commit 38d79a190b9f2adf34c2c84c4014f90912f368d9
Author: David Golden <dagolden@cpan.org>
Date: Wed May 20 19:47:03 2015 -0400
encode integers as BSON Int32 if they fit
diff --git a/perl_mongo.c b/perl_mongo.c
index 54833fe..9cc619b 100644
--- a/perl_mongo.c
+++ b/perl_mongo.c
@@ -908,7 +908,13 @@ sv_to_bson_elem (bson_t * bson, const char * in_key, SV *sv, HV *opts, stackette
/* if it's publicly an int OR (privately an int AND not publicly a string) */
if (aggressively_number || (!is_string && (SvIOK(sv) || (SvIOKp(sv) && !SvPOK(sv))))) {
#if defined(MONGO_USE_64_BIT_INT)
- bson_append_int64(bson, key, -1, (int64_t)SvIV(sv));
+ IV i = SvIV(sv);
+ if ( i >= INT32_MIN && i <= INT32_MAX) {
+ bson_append_int32(bson, key, -1, (int)i);
+ }
+ else {
+ bson_append_int64(bson, key, -1, (int64_t)i);
+ }
#else
bson_append_int32(bson, key, -1, (int)SvIV(sv));
#endif
diff --git a/t/bson_codec/elements.t b/t/bson_codec/elements.t
index bbcc7e0..e0c769d 100644
--- a/t/bson_codec/elements.t
+++ b/t/bson_codec/elements.t
@@ -19,6 +19,7 @@ use Test::More 0.96;
use Test::Deep 0.086; # num() function
use Test::Fatal;
+use Config;
use DateTime;
use DateTime::Tiny;
use MongoDB;
@@ -69,6 +70,8 @@ use constant {
BSON_DATETIME => "\x09",
BSON_NULL => "\x0A",
BSON_REGEXP => "\x0B",
+ BSON_INT32 => "\x10",
+ BSON_INT64 => "\x12",
};
my $class = "MongoDB::BSON";
@@ -144,8 +147,37 @@ my @cases = (
output =>
{ a => [ '$db' => $dbref->db, '$id' => $dbref->id, '$ref' => $dbref->ref ] },
},
+ {
+ label => "BSON Int32",
+ input => { a => 66 },
+ bson => _doc( BSON_INT32 . _ename("a") . _int32(66) ),
+ output => { a => 66 },
+ },
+ {
+ label => "BSON Int64 (max 32 bit int)",
+ input => { a => 2147483647 },
+ bson => _doc( BSON_INT32 . _ename("a") . _int32(2147483647) ),
+ output => { a => 2147483647 },
+ },
+ {
+ label => "BSON Int64 (min 32 bit int)",
+ input => { a => -2147483647-1 },
+ bson => _doc( BSON_INT32 . _ename("a") . _int32(-2147483647-1) ),
+ output => { a => -2147483647-1 },
+ },
);
+if ( $Config{use64bitint} ) {
+ my $big = 20 << 40;
+ push @cases,
+ {
+ label => "BSON Int64",
+ input => { a => $big },
+ bson => _doc( BSON_INT64 . _ename("a") . _int64($big) ),
+ output => { a => $big },
+ };
+}
+
for my $c (@cases) {
my ( $label, $input, $bson, $output ) = @{$c}{qw/label input bson output/};
my $encoded = $codec->encode_one( $input, $c->{enc_opts} || {} );
@@ -175,6 +207,10 @@ BEGIN { *_ename = \&_cstring }
sub _double { return pack( "d", shift ) }
+sub _int32 { return pack( P_INT32, shift ) }
+
+sub _int64 { return pack( P_INT64, shift ) }
+
sub _string {
my ($string) = shift;
return pack( P_INT32, 1 + length($string) ) . $string . "\x00";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment