diff --git a/src/bech32/bech32.zig b/src/bech32/bech32.zig index 3216482..2136c3a 100644 --- a/src/bech32/bech32.zig +++ b/src/bech32/bech32.zig @@ -153,7 +153,7 @@ pub const Variant = enum { fn splitAndDecode(allocator: std.mem.Allocator, s: []const u8) Error!struct { std.ArrayList(u8), std.ArrayList(u5) } { // Split at separator and check for two pieces - const raw_hrp, const raw_data = if (std.mem.indexOfScalar(u8, s, SEP)) |sep| .{ + const raw_hrp, const raw_data = if (std.mem.lastIndexOfScalar(u8, s, SEP)) |sep| .{ s[0..sep], s[sep + 1 ..], } else return Error.MissingSeparator; @@ -177,20 +177,27 @@ fn splitAndDecode(allocator: std.mem.Allocator, s: []const u8) Error!struct { st var data = std.ArrayList(u5).init(allocator); errdefer data.deinit(); + var it = std.unicode.Utf8View.initUnchecked(raw_data).iterator(); // Check data payload - for (raw_data) |c| { + while (it.nextCodepoint()) |c| { // Only check if c is in the ASCII range, all invalid ASCII // characters have the value -1 in CHARSET_REV (which covers // the whole ASCII range) and will be filtered out later. - if (!std.ascii.isAscii(c)) return error.InvalidChar; + if (c >= 128) return error.InvalidChar; - if (std.ascii.isLower(c)) { + if (switch (c) { + 'a'...'z' => true, + else => false, + }) { switch (case) { .upper => return Error.MixedCase, .none => case = .lower, .lower => {}, } - } else if (std.ascii.isUpper(c)) { + } else if (switch (c) { + 'A'...'Z' => true, + else => false, + }) { switch (case) { .lower => return Error.MixedCase, .none => case = .upper, @@ -531,6 +538,15 @@ test "roundtrip_without_checksum" { try std.testing.expectEqualSlices(u5, data.items, decoded_data.items); } +test "decode ln" { + const str = "lnbc10n1pnw2hkzdqqpp5ve584t0cv27hwmy0cx9ca8uwyqyfw9y9dm3r8vus9fv36r2l9yjssp59g4z52329g4z52329g4z52329g4z52329g4z52329g4z52329g4qcqzysc39n3w6zq50y3775yc66mmvt2fe5aa9mzzdnvq5palgyw6j9uu04qnm0g4ftm5ehtm5aulwtuy0hfrtqcdaxcl2r7wz2x4503levlacqswkkem"; + + const h, const d, const v = try decode(std.testing.allocator, str); + _ = v; // autofix + defer h.deinit(); + defer d.deinit(); +} + test "test_hrp_case_decode" { const hrp, const data, const variant = try decode(std.testing.allocator, "hrp1qqqq40atq3"); defer hrp.deinit();