The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/env perl

use strict;
use warnings;

use Getopt::Long;
use IO::Handle;
# JSON::XS seems to have a bad interaction with the TO_JSON() sub we define
# below. It dies with "Modification of a read-only value attempted at
# ./bin/dump-database line X."
use JSON::PP;
use MaxMind::DB::Reader;
use Net::Works::Network;

no warnings 'once';
*Math::UInt128::TO_JSON = sub { return $_[0] . q{} }
    unless Math::UInt128->can('TO_JSON');

sub main {
    my $file;
    GetOptions(
        'file:s' => \$file,
    );

    my $reader = MaxMind::DB::Reader->new( file => $file );
    my $ip_version = $reader->ip_version();

    # For large databases this iteration could take a long time so it's good
    # to send output as it's available.
    STDOUT->autoflush(1);
    print "[\n";
    $reader->iterate_search_tree( sub { _dump_entry( $ip_version, @_ ) } );
    print "]\n";
}

my $JSON = JSON::PP->new()->utf8->allow_nonref()->pretty()->convert_blessed();

sub _dump_entry {
    my $ip_version = shift;
    my $ipnum      = shift;
    my $depth      = shift;
    my $entry_data = shift;

    my $network = Net::Works::Network->new_from_integer(
        integer     => $ipnum,
        mask_length => $depth,
        ip_version  => $ip_version,
    );

    my $encoded = $JSON->encode( { $network->as_string => $entry_data } );
    $encoded =~ s/^/  /mg;
    $encoded =~ s/}$/},/s;

    print $encoded;
}

main();