From e1d1e71ce1c9a9354f445fe8b0ae9fcb42b0247f Mon Sep 17 00:00:00 2001 From: Brad Chase Date: Tue, 20 May 2025 12:51:11 +0900 Subject: [PATCH 1/3] run `gleam update` --- manifest.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/manifest.toml b/manifest.toml index 37300bd..aa0e303 100644 --- a/manifest.toml +++ b/manifest.toml @@ -2,9 +2,9 @@ # You typically do not need to edit this file packages = [ - { name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" }, - { name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" }, - { name = "gleeunit", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "72CDC3D3F719478F26C4E2C5FED3E657AC81EC14A47D2D2DEBB8693CA3220C3B" }, + { name = "gleam_erlang", version = "0.34.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "0C38F2A128BAA0CEF17C3000BD2097EB80634E239CE31A86400C4416A5D0FDCC" }, + { name = "gleam_stdlib", version = "0.60.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "621D600BB134BC239CB2537630899817B1A42E60A1D46C5E9F3FAE39F88C800B" }, + { name = "gleeunit", version = "1.3.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "A7DD6C07B7DA49A6E28796058AA89E651D233B357D5607006D70619CD89DAAAB" }, ] [requirements] From 1b62db182cdc3658e872913787dd223835755a85 Mon Sep 17 00:00:00 2001 From: Brad Chase Date: Tue, 20 May 2025 12:51:17 +0900 Subject: [PATCH 2/3] use `gleam/dynamic/decode` --- src/nessie.gleam | 63 ++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/src/nessie.gleam b/src/nessie.gleam index b793fe7..37acca1 100644 --- a/src/nessie.gleam +++ b/src/nessie.gleam @@ -4,12 +4,13 @@ //// `inet_res` and `inet` modules. Most of the functions and types are simply //// Gleam representations of their Erlang counterparts. -import gleam/list -import gleam/function -import gleam/result -import gleam/dynamic.{type Decoder, type Dynamic} +import gleam/dynamic.{type Dynamic} +import gleam/dynamic/decode.{type DecodeError, type Decoder} import gleam/erlang/atom.{type Atom} import gleam/erlang/charlist.{type Charlist} +import gleam/function +import gleam/list +import gleam/result /// Nameserver address and port. pub type Nameserver = @@ -126,39 +127,37 @@ pub fn string_to_ip(ip_addr: String) -> Result(IPAddress, String) { |> result.map_error(atom.to_string) |> result.map(fn(dyn) { dyn - |> dynamic.tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int) - |> result.map(IPV4) - |> result.or( - dyn - |> ip_decoder(), - ) + |> decode.run(ip_decoder()) |> result.replace_error("decode_error") }) |> result.flatten() } -/// Returns a `gleam/dynamic.Decoder` for decoding an IP address tuple. +/// Returns a `gleam/dynamic/decode.Decoder` for decoding an IP address tuple. pub fn ip_decoder() -> Decoder(IPAddress) { - fn(value) { - value - |> dynamic.tuple4(dynamic.int, dynamic.int, dynamic.int, dynamic.int) - |> result.map(IPV4) - |> result.lazy_or(fn() { - value - |> dynamic.decode8( - fn(i1, i2, i3, i4, i5, i6, i7, i8) { #(i1, i2, i3, i4, i5, i6, i7, i8) }, - dynamic.element(0, dynamic.int), - dynamic.element(1, dynamic.int), - dynamic.element(2, dynamic.int), - dynamic.element(3, dynamic.int), - dynamic.element(4, dynamic.int), - dynamic.element(5, dynamic.int), - dynamic.element(6, dynamic.int), - dynamic.element(7, dynamic.int), - ) - |> result.map(IPV6) - }) - } + decode.one_of(ipv6_decoder(), [ipv4_decoder()]) +} + +fn ipv4_decoder() -> Decoder(IPAddress) { + use x1 <- decode.field(0, decode.int) + use x2 <- decode.field(1, decode.int) + use x3 <- decode.field(2, decode.int) + use x4 <- decode.field(3, decode.int) + + decode.success(IPV4(#(x1, x2, x3, x4))) +} + +fn ipv6_decoder() -> Decoder(IPAddress) { + use x1 <- decode.field(0, decode.int) + use x2 <- decode.field(1, decode.int) + use x3 <- decode.field(2, decode.int) + use x4 <- decode.field(3, decode.int) + use x5 <- decode.field(4, decode.int) + use x6 <- decode.field(5, decode.int) + use x7 <- decode.field(6, decode.int) + use x8 <- decode.field(7, decode.int) + + decode.success(IPV6(#(x1, x2, x3, x4, x5, x6, x7, x8))) } /// Looks up a record of the specified type for the given name. @@ -390,7 +389,7 @@ fn to_soa(erl_soa: ErlSoa) -> SOARecord { } @external(erlang, "nessie_inet_res_ffi", "charlist_from_dynamic") -fn charlist_from_dynamic(d: Dynamic) -> Result(Charlist, dynamic.DecodeErrors) +fn charlist_from_dynamic(d: Dynamic) -> Result(Charlist, List(DecodeError)) @external(erlang, "nessie_inet_res_ffi", "getbyname") fn do_getbyname_string( From 5ed7bf1f011f3c012419305bb5ef29ce74a73635 Mon Sep 17 00:00:00 2001 From: Brad Chase Date: Tue, 11 Nov 2025 13:44:53 +0900 Subject: [PATCH 3/3] attempt to fix `stdlib` removal of `dynamic.from` --- manifest.toml | 4 ++-- src/nessie.gleam | 56 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/manifest.toml b/manifest.toml index aa0e303..61c32de 100644 --- a/manifest.toml +++ b/manifest.toml @@ -2,8 +2,8 @@ # You typically do not need to edit this file packages = [ - { name = "gleam_erlang", version = "0.34.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "0C38F2A128BAA0CEF17C3000BD2097EB80634E239CE31A86400C4416A5D0FDCC" }, - { name = "gleam_stdlib", version = "0.60.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "621D600BB134BC239CB2537630899817B1A42E60A1D46C5E9F3FAE39F88C800B" }, + { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" }, + { name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" }, { name = "gleeunit", version = "1.3.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "A7DD6C07B7DA49A6E28796058AA89E651D233B357D5607006D70619CD89DAAAB" }, ] diff --git a/src/nessie.gleam b/src/nessie.gleam index 37acca1..3379494 100644 --- a/src/nessie.gleam +++ b/src/nessie.gleam @@ -286,30 +286,55 @@ pub fn gethostbyaddr( fn to_erl_resolver_option(option: ResolverOption) -> ErlOptionTuple { let #(opt_name, opt_value) = case option { - INet6(inet6) -> #("inet6", dynamic.from(inet6)) - Recurse(recurse) -> #("recurse", dynamic.from(recurse)) - Retry(retry) -> #("retry", dynamic.from(retry)) - TimeoutMillis(timeout) -> #("timeout", dynamic.from(timeout)) + INet6(inet6) -> #("inet6", dynamic.bool(inet6)) + Recurse(recurse) -> #("recurse", dynamic.bool(recurse)) + Retry(retry) -> #("retry", dynamic.int(retry)) + TimeoutMillis(timeout) -> #("timeout", dynamic.int(timeout)) NxdomainReply(nxdomain_reply) -> #( "nxdomain_reply", - dynamic.from(nxdomain_reply), + dynamic.bool(nxdomain_reply), ) Nameservers(nameservers) -> { let erl_nameservers = - list.map(nameservers, fn(ip_port) { + nameservers + |> list.map(fn(ip_port) { let #(ip, port) = ip_port - let ip = case ip { - IPV4(ip) -> dynamic.from(ip) - IPV6(ip) -> dynamic.from(ip) - } - #(ip, port) + dynamic.array([ + dynamic_ip(ip), + dynamic.int(port), + ]) }) - #("nameservers", dynamic.from(erl_nameservers)) + |> dynamic.list + + #("nameservers", erl_nameservers) } } - #(atom.create_from_string(opt_name), opt_value) + #(atom.create(opt_name), opt_value) +} + +fn dynamic_ip(ip ip: IPAddress) -> Dynamic { + case ip { + IPV4(ip) -> + dynamic.array([ + dynamic.int(ip.0), + dynamic.int(ip.1), + dynamic.int(ip.2), + dynamic.int(ip.3), + ]) + IPV6(ip) -> + dynamic.array([ + dynamic.int(ip.0), + dynamic.int(ip.1), + dynamic.int(ip.2), + dynamic.int(ip.3), + dynamic.int(ip.4), + dynamic.int(ip.5), + dynamic.int(ip.6), + dynamic.int(ip.7), + ]) + } } type ErlOptionTuple = @@ -359,8 +384,9 @@ fn to_hostent( fn from_dns_name(dyn: Dynamic) -> String { let atom_from_dynamic = fn() { dyn - |> atom.from_dynamic() - |> result.map(atom.to_string) + |> atom.cast_from_dynamic() + |> atom.to_string + |> Ok } dyn