# `locus_mmdb`
[🔗](https://github.com/g-andrade/locus/blob/2.3.15/src/locus_mmdb.erl#L24)

API for working with MMDB.

See [MaxMind DB File Format Specification](https://maxmind.github.io/MaxMind-DB/).

# `database`

```erlang
-type database() ::
          #{metadata := locus_mmdb_metadata:t(), tree := locus_mmdb_tree:t(), data_section := binary()}.
```

# `failed_to_unpack_tree_data_and_data_section`

```erlang
-type failed_to_unpack_tree_data_and_data_section() ::
          {intermediate_128bits_of_zero_not_found_after_tree,
           {{not_zeroes, binary()},
            {at_offset, non_neg_integer()},
            {with_metadata, locus_mmdb_metadata:t()}}} |
          {missing_data_after_tree,
           {{required, {128, bits}},
            {but_got, {0..127, bits}},
            {at_offset, non_neg_integer()},
            {with_metadata, locus_mmdb_metadata:t()}}} |
          {not_enough_data_for_tree,
           {{required, {pos_integer(), bytes}},
            {but_got, {non_neg_integer(), bytes}},
            {with_metadata, locus_mmdb_metadata:t()}}}.
```

# `unpack_error`

```erlang
-type unpack_error() ::
          {bad_metadata, locus_mmdb_metadata:parse_or_validation_error()} |
          failed_to_unpack_tree_data_and_data_section() |
          {bad_tree,
           {{because, locus_mmdb_tree:bad_tree_error()}, {with_metadata, locus_mmdb_metadata:t()}}}.
```

# `lookup_address`

```erlang
-spec lookup_address(Address, Database) -> {ok, Entry} | not_found | {error, ErrorReason}
                        when
                            Address :: inet:ip_address() | string() | unicode:unicode_binary(),
                            Database :: database(),
                            Entry :: locus_mmdb_data:value(),
                            ErrorReason ::
                                database_unknown | database_not_loaded |
                                {invalid_address, Address} |
                                ipv4_database.
```

Looks up for an entry matching `Address` within `Database`.

# `parse_all_data_section_values`

```erlang
-spec parse_all_data_section_values(file:name_all()) -> [locus_mmdb_data_raw:value()].
```

# `parse_data_section_value`

```erlang
-spec parse_data_section_value(file:name_all(), locus_mmdb_data_codec:index()) ->
                                  locus_mmdb_data_raw:value().
```

# `unpack_database`

```erlang
-spec unpack_database(EncodedDatabase) -> {ok, Database} | {error, ErrorReason}
                         when
                             EncodedDatabase :: binary(),
                             Database :: database(),
                             ErrorReason :: unpack_error().
```

Unpacks an `EncodedDatabase` binary into a ready-to-use `Database`.

# `unpack_tree_data_and_data_section`

```erlang
-spec unpack_tree_data_and_data_section(Metadata, TreeAndDataSection) ->
                                           {ok, TreeData, DataSection} | {error, Reason}
                                           when
                                               Metadata :: locus_mmdb_metadata:t(),
                                               TreeAndDataSection :: binary(),
                                               TreeData :: binary(),
                                               DataSection :: binary(),
                                               Reason :: failed_to_unpack_tree_data_and_data_section().
```

Unpacks a single `TreeAndDataSection` binary into separate `TreeData` and `DataSection`
binaries, leveraging `Metadata` to calculate the size of `TreeData`.

You can then use `TreeData` on your own or leverage it to instantiate a new
`t:locus_mmdb_tree:t/0`, through `locus_mmdb_tree:new/5`.

As for `DataSection`, you can also either use it on your own or pass it to the API
defined under `m:locus_mmdb_data_codec`.

For how to obtain `Metadata` and `TreeAndDataSection` in the first place,
see `locus_mmdb_metadata:parse_and_validate/1`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
