#!/usr/bin/env perl
use strict;
use warnings;
use autodie;
use utf8;
use Carp qw( croak );
use Cwd qw( abs_path );
use File::Basename qw( dirname );
use MaxMind::DB::Writer::Serializer;
use MaxMind::DB::Writer::Tree::InMemory;
use MaxMind::DB::Writer::Tree::File;
use Net::Works::Network;
use Test::MaxMind::DB::Common::Util qw( standard_test_metadata );
my $Dir = dirname( abs_path($0) );
sub main {
my @sizes = ( 24, 28, 32 );
my @ipv4_range = ( '1.1.1.1', '1.1.1.32' );
my @ipv4_subnets = Net::Works::Network->range_as_subnets(@ipv4_range);
foreach my $record_size (@sizes) {
write_test_db(
$record_size,
\@ipv4_subnets,
{ ip_version => 4 },
'ipv4',
);
}
my @ipv6_subnets = Net::Works::Network->range_as_subnets(
'::1:ffff:ffff',
'::2:0000:0059'
);
foreach my $record_size (@sizes) {
write_test_db(
$record_size,
\@ipv6_subnets,
{ ip_version => 6 },
'ipv6',
);
write_test_db(
$record_size,
[
@ipv6_subnets,
Net::Works::Network->range_as_subnets( @ipv4_range, 6 ),
],
{ ip_version => 6 },
'mixed',
);
}
write_geoip2_city_db();
write_test_serialization_data();
}
sub write_test_db {
my $record_size = shift;
my $subnets = shift;
my $metadata = shift;
my $ip_version_name = shift;
my $tree = MaxMind::DB::Writer::Tree::InMemory->new(
ip_version => $subnets->[0]->version() );
for my $subnet ( @{$subnets} ) {
$tree->insert_subnet(
$subnet,
{ ip => $subnet->first()->as_string() }
);
}
my $writer = MaxMind::DB::Writer::Tree::File->new(
tree => $tree,
record_size => $record_size,
standard_test_metadata(),
%{$metadata},
alias_ipv6_to_ipv4 => ( $subnets->[0]->version() == 6 ? 1 : 0 ),
map_key_type_callback => sub { 'utf8_string' },
);
my $filename = sprintf(
"$Dir/MaxMind-DB-test-%s-%i.mmdb",
$ip_version_name,
$record_size,
);
open my $fh, '>', $filename;
$writer->write_tree($fh);
return ( $tree, $filename );
}
sub write_geoip2_city_db {
my $tree = MaxMind::DB::Writer::Tree::InMemory->new( ip_version => 6 );
my $json = JSON::XS->new()->utf8();
open my $source_fh, '<', "$Dir/../source-data/GeoIP2-City-Test.json";
while (<$source_fh>) {
my ( $network, $record ) = @{ $json->decode($_) };
$tree->insert_subnet(
Net::Works::Network->new_from_string( string => $network ),
$record
);
}
close $source_fh;
my %type_map = (
cellular => 'uint16',
city => 'map',
continent => 'map',
country => 'map',
geoname_id => 'uint32',
is_anonymous_proxy => 'boolean',
is_satellite_provider => 'boolean',
latitude => 'double',
location => 'map',
longitude => 'double',
names => 'map',
postal => 'map',
registered_country => 'map',
represented_country => 'map',
subdivisions => [ 'array', 'map' ],
traits => 'map',
);
my $type_cb = sub { $type_map{ $_[0] } // 'utf8_string' };
my $writer = MaxMind::DB::Writer::Tree::File->new(
tree => $tree,
record_size => 28,
ip_version => 6,
database_type => 'GeoIP2 City Test Database',
languages => [ 'en', 'zh' ],
description => {
en =>
'GeoIP2 City Test Database (a small sample of real GeoIP2 data)',
zh => '小型数据库',
},
alias_ipv6_to_ipv4 => 1,
map_key_type_callback => $type_cb,
);
open my $output_fh, '>', "$Dir/GeoIP2-City-Test.mmdb";
$writer->write_tree($output_fh);
close $output_fh;
return;
}
sub write_test_serialization_data {
my $serializer = MaxMind::DB::Writer::Serializer->new(
map_key_type_callback => sub { 'utf8_string' } );
$serializer->store_data( map => { long_key => 'long_value1' } );
$serializer->store_data( map => { long_key => 'long_value2' } );
$serializer->store_data( map => { long_key2 => 'long_value1' } );
$serializer->store_data( map => { long_key2 => 'long_value2' } );
$serializer->store_data( map => { long_key => 'long_value1' } );
$serializer->store_data( map => { long_key2 => 'long_value2' } );
open my $fh, '>', 'maps-with-pointers.raw';
print {$fh} ${ $serializer->buffer() }
or die "Cannot write to maps-with-pointers.raw: $!";
close $fh;
return;
}
main();