-module(nessie). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([ip_decoder/0, getbyname/3, getbyname_soa/2, getbyname_ipv4/2, getbyname_ipv6/2, getbyname_mx/2, gethostbyaddr/2, lookup_ipv4/3, lookup_ipv6/3, lookup/4, lookup_soa/3, lookup_mx/3, ip_to_string/1, string_to_ip/1]). -export_type([dns_class/0, resolver_option/0, soa_record/0, error_reason/0, mx_record/0, timeout_/0, hostent/1, ip_address/0, string_record_type/0]). -type dns_class() :: in | chaos | hs | any. -type resolver_option() :: {nameservers, list({ip_address(), integer()})} | {i_net6, boolean()} | {recurse, boolean()} | {retry, integer()} | {timeout_millis, integer()} | {nxdomain_reply, boolean()}. -type soa_record() :: {soa_record, binary(), binary(), integer(), integer(), integer(), integer(), integer()}. -type error_reason() :: formerr | qfmterr | servfail | nxdomain | notimp | refused | badvers | timeout_err | {other, binary()}. -type mx_record() :: {mx_record, integer(), binary()}. -type timeout_() :: {timeout, integer()} | infinity. -type hostent(FWQ) :: {hostent, binary(), list(binary()), binary(), integer(), list(FWQ)}. -type ip_address() :: {ipv4, {integer(), integer(), integer(), integer()}} | {ipv6, {integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer()}}. -type string_record_type() :: cname | txt | ns. -spec ip_decoder() -> fun((gleam@dynamic:dynamic_()) -> {ok, ip_address()} | {error, list(gleam@dynamic:decode_error())}). ip_decoder() -> fun(Value) -> _pipe = Value, _pipe@1 = (gleam@dynamic:tuple4( fun gleam@dynamic:int/1, fun gleam@dynamic:int/1, fun gleam@dynamic:int/1, fun gleam@dynamic:int/1 ))(_pipe), _pipe@2 = gleam@result:map(_pipe@1, fun(Field@0) -> {ipv4, Field@0} end), gleam@result:lazy_or(_pipe@2, fun() -> _pipe@3 = Value, _pipe@4 = (gleam@dynamic:decode8( fun(I1, I2, I3, I4, I5, I6, I7, I8) -> {I1, I2, I3, I4, I5, I6, I7, I8} end, gleam@dynamic:element(0, fun gleam@dynamic:int/1), gleam@dynamic:element(1, fun gleam@dynamic:int/1), gleam@dynamic:element(2, fun gleam@dynamic:int/1), gleam@dynamic:element(3, fun gleam@dynamic:int/1), gleam@dynamic:element(4, fun gleam@dynamic:int/1), gleam@dynamic:element(5, fun gleam@dynamic:int/1), gleam@dynamic:element(6, fun gleam@dynamic:int/1), gleam@dynamic:element(7, fun gleam@dynamic:int/1) ))(_pipe@3), gleam@result:map(_pipe@4, fun(Field@0) -> {ipv6, Field@0} end) end) end. -spec to_erl_resolver_option(resolver_option()) -> {gleam@erlang@atom:atom_(), gleam@dynamic:dynamic_()}. to_erl_resolver_option(Option) -> {Opt_name, Opt_value} = case Option of {i_net6, Inet6} -> {<<"inet6"/utf8>>, gleam@dynamic:from(Inet6)}; {recurse, Recurse} -> {<<"recurse"/utf8>>, gleam@dynamic:from(Recurse)}; {retry, Retry} -> {<<"retry"/utf8>>, gleam@dynamic:from(Retry)}; {timeout_millis, Timeout} -> {<<"timeout"/utf8>>, gleam@dynamic:from(Timeout)}; {nxdomain_reply, Nxdomain_reply} -> {<<"nxdomain_reply"/utf8>>, gleam@dynamic:from(Nxdomain_reply)}; {nameservers, Nameservers} -> Erl_nameservers = gleam@list:map( Nameservers, fun(Ip_port) -> {Ip, Port} = Ip_port, Ip@3 = case Ip of {ipv4, Ip@1} -> gleam@dynamic:from(Ip@1); {ipv6, Ip@2} -> gleam@dynamic:from(Ip@2) end, {Ip@3, Port} end ), {<<"nameservers"/utf8>>, gleam@dynamic:from(Erl_nameservers)} end, {erlang:binary_to_atom(Opt_name), Opt_value}. -spec to_dns_err(gleam@erlang@atom:atom_()) -> error_reason(). to_dns_err(E) -> E@1 = erlang:atom_to_binary(E), case E@1 of <<"formerr"/utf8>> -> formerr; <<"qfmterror"/utf8>> -> qfmterr; <<"servfail"/utf8>> -> servfail; <<"nxdomain"/utf8>> -> nxdomain; <<"notimp"/utf8>> -> notimp; <<"refused"/utf8>> -> refused; <<"badvers"/utf8>> -> badvers; <<"timeout"/utf8>> -> timeout_err; _ -> {other, E@1} end. -spec from_dns_name(gleam@dynamic:dynamic_()) -> binary(). from_dns_name(Dyn) -> Atom_from_dynamic = fun() -> _pipe = Dyn, _pipe@1 = gleam_erlang_ffi:atom_from_dynamic(_pipe), gleam@result:map(_pipe@1, fun erlang:atom_to_binary/1) end, _pipe@2 = Dyn, _pipe@3 = nessie_inet_res_ffi:charlist_from_dynamic(_pipe@2), _pipe@4 = gleam@result:map(_pipe@3, fun unicode:characters_to_binary/1), _pipe@5 = gleam@result:lazy_or(_pipe@4, Atom_from_dynamic), gleam@result:unwrap(_pipe@5, <<""/utf8>>). -spec to_hostent( {gleam@erlang@atom:atom_(), gleam@dynamic:dynamic_(), list(gleam@dynamic:dynamic_()), gleam@erlang@atom:atom_(), integer(), list(FYB)}, fun((FYB) -> FYD) ) -> hostent(FYD). to_hostent(Erl_hostent, Addr_list_transform) -> {_, Name, Aliases, Addrtype, Length, Addr_list} = Erl_hostent, Gleam_aliases = gleam@list:map(Aliases, fun from_dns_name/1), {hostent, from_dns_name(Name), Gleam_aliases, erlang:atom_to_binary(Addrtype), Length, gleam@list:map(Addr_list, Addr_list_transform)}. -spec to_mx({integer(), gleam@dynamic:dynamic_()}) -> mx_record(). to_mx(Erl_mx) -> {Priority, Exchange} = Erl_mx, {mx_record, Priority, from_dns_name(Exchange)}. -spec to_soa( {gleam@dynamic:dynamic_(), gleam@dynamic:dynamic_(), integer(), integer(), integer(), integer(), integer()} ) -> soa_record(). to_soa(Erl_soa) -> {Mname, Rname, Serial, Refresh, Retry, Expire, Minimum} = Erl_soa, {soa_record, from_dns_name(Mname), from_dns_name(Rname), Serial, Refresh, Retry, Expire, Minimum}. -spec getbyname(binary(), string_record_type(), timeout_()) -> {ok, hostent(binary())} | {error, error_reason()}. getbyname(Name, Srt, Timeout) -> _pipe = Name, _pipe@1 = nessie_inet_res_ffi:getbyname(_pipe, Srt, Timeout), _pipe@2 = gleam@result:map( _pipe@1, fun(_capture) -> to_hostent(_capture, fun unicode:characters_to_binary/1) end ), gleam@result:map_error(_pipe@2, fun to_dns_err/1). -spec getbyname_soa(binary(), timeout_()) -> {ok, hostent(soa_record())} | {error, error_reason()}. getbyname_soa(Name, Timeout) -> _pipe = Name, _pipe@1 = nessie_inet_res_ffi:getbyname_soa(_pipe, Timeout), _pipe@2 = gleam@result:map( _pipe@1, fun(_capture) -> to_hostent(_capture, fun to_soa/1) end ), gleam@result:map_error(_pipe@2, fun to_dns_err/1). -spec getbyname_ipv4(binary(), timeout_()) -> {ok, hostent({integer(), integer(), integer(), integer()})} | {error, error_reason()}. getbyname_ipv4(Name, Timeout) -> _pipe = Name, _pipe@1 = nessie_inet_res_ffi:getbyname_ipv4(_pipe, Timeout), _pipe@2 = gleam@result:map( _pipe@1, fun(_capture) -> to_hostent(_capture, fun gleam@function:identity/1) end ), gleam@result:map_error(_pipe@2, fun to_dns_err/1). -spec getbyname_ipv6(binary(), timeout_()) -> {ok, hostent({integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer()})} | {error, error_reason()}. getbyname_ipv6(Name, Timeout) -> _pipe = Name, _pipe@1 = nessie_inet_res_ffi:getbyname_ipv6(_pipe, Timeout), _pipe@2 = gleam@result:map( _pipe@1, fun(_capture) -> to_hostent(_capture, fun gleam@function:identity/1) end ), gleam@result:map_error(_pipe@2, fun to_dns_err/1). -spec getbyname_mx(binary(), timeout_()) -> {ok, hostent(mx_record())} | {error, error_reason()}. getbyname_mx(Name, Timeout) -> _pipe = Name, _pipe@1 = nessie_inet_res_ffi:getbyname_mx(_pipe, Timeout), _pipe@2 = gleam@result:map( _pipe@1, fun(_capture) -> to_hostent(_capture, fun to_mx/1) end ), gleam@result:map_error(_pipe@2, fun to_dns_err/1). -spec gethostbyaddr(ip_address(), timeout_()) -> {ok, hostent(binary())} | {error, error_reason()}. gethostbyaddr(Address, Timeout) -> _pipe = Address, _pipe@1 = nessie_inet_res_ffi:gethostbyaddr(_pipe, Timeout), _pipe@2 = gleam@result:map( _pipe@1, fun(_capture) -> to_hostent(_capture, fun unicode:characters_to_binary/1) end ), gleam@result:map_error(_pipe@2, fun to_dns_err/1). -spec lookup_ipv4(binary(), dns_class(), list(resolver_option())) -> list({integer(), integer(), integer(), integer()}). lookup_ipv4(Name, Class, Options) -> Erl_options = gleam@list:map(Options, fun to_erl_resolver_option/1), nessie_inet_res_ffi:lookup_ipv4(Name, Class, Erl_options). -spec lookup_ipv6(binary(), dns_class(), list(resolver_option())) -> list({integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer()}). lookup_ipv6(Name, Class, Options) -> Erl_options = gleam@list:map(Options, fun to_erl_resolver_option/1), nessie_inet_res_ffi:lookup_ipv6(Name, Class, Erl_options). -spec lookup( binary(), dns_class(), string_record_type(), list(resolver_option()) ) -> list(binary()). lookup(Name, Class, Srt, Options) -> Erl_options = gleam@list:map(Options, fun to_erl_resolver_option/1), _pipe = Name, _pipe@1 = nessie_inet_res_ffi:lookup(_pipe, Class, Srt, Erl_options), gleam@list:map(_pipe@1, fun unicode:characters_to_binary/1). -spec lookup_soa(binary(), dns_class(), list(resolver_option())) -> list(soa_record()). lookup_soa(Name, Class, Options) -> Erl_options = gleam@list:map(Options, fun to_erl_resolver_option/1), _pipe = Name, _pipe@1 = nessie_inet_res_ffi:lookup_soa(_pipe, Class, Erl_options), gleam@list:map(_pipe@1, fun to_soa/1). -spec lookup_mx(binary(), dns_class(), list(resolver_option())) -> list(mx_record()). lookup_mx(Name, Class, Options) -> Erl_options = gleam@list:map(Options, fun to_erl_resolver_option/1), _pipe = Name, _pipe@1 = nessie_inet_res_ffi:lookup_mx(_pipe, Class, Erl_options), gleam@list:map(_pipe@1, fun to_mx/1). -spec ip_to_string(ip_address()) -> {ok, binary()} | {error, binary()}. ip_to_string(Ip_addr) -> _pipe = Ip_addr, _pipe@1 = nessie_inet_ffi:ntoa(_pipe), _pipe@2 = gleam@result:map(_pipe@1, fun unicode:characters_to_binary/1), gleam@result:map_error(_pipe@2, fun erlang:atom_to_binary/1). -spec string_to_ip(binary()) -> {ok, ip_address()} | {error, binary()}. string_to_ip(Ip_addr) -> _pipe = Ip_addr, _pipe@1 = nessie_inet_ffi:parse_address(_pipe), _pipe@2 = gleam@result:map_error(_pipe@1, fun erlang:atom_to_binary/1), _pipe@8 = gleam@result:map(_pipe@2, fun(Dyn) -> _pipe@3 = Dyn, _pipe@4 = (gleam@dynamic:tuple4( fun gleam@dynamic:int/1, fun gleam@dynamic:int/1, fun gleam@dynamic:int/1, fun gleam@dynamic:int/1 ))(_pipe@3), _pipe@5 = gleam@result:map( _pipe@4, fun(Field@0) -> {ipv4, Field@0} end ), _pipe@7 = gleam@result:'or'( _pipe@5, begin _pipe@6 = Dyn, (ip_decoder())(_pipe@6) end ), gleam@result:replace_error(_pipe@7, <<"decode_error"/utf8>>) end), gleam@result:flatten(_pipe@8).