1package MaxMind::DB::Writer::Util;
2
3use strict;
4use warnings;
5
6our $VERSION = '0.300003';
7
8use Digest::SHA1 qw( sha1_base64 );
9use Encode qw( encode );
10use Sereal::Encoder 3.002 qw( sereal_encode_with_object );
11
12use Exporter qw( import );
13our @EXPORT_OK = qw( key_for_data );
14
15{
16    # Although this mostly works fine when canonical and canonical_refs are
17    # enabled, it is still somewhat broken. See:
18    #
19    # https://metacpan.org/pod/distribution/Sereal-Encoder/lib/Sereal/Encoder.pm#CANONICAL-REPRESENTATION
20    #
21    # The arrays in the example, for instance, would have distinct keys
22    # despite being structurally equivalent. Requires Sereal 3.002.
23    my $Encoder = Sereal::Encoder->new(
24        {
25            canonical      => 1,
26            canonical_refs => 1,
27        }
28    );
29
30    sub key_for_data {
31
32        # We need to use sha1 because the Sereal structure has \0 bytes which
33        # confuse the C code. As a bonus, this makes the keys smaller so they
34        # take up less space. As an un-bonus, this makes the code a little
35        # slower.
36        my $key
37            = ref $_[0]
38            ? sereal_encode_with_object( $Encoder, $_[0] )
39            : encode( 'UTF-8', $_[0] );
40
41        return sha1_base64($key);
42    }
43}
44
451;
46