diff options
author | sobolevn <mail@sobolevn.me> | 2024-08-19 22:50:02 +0300 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2024-08-24 13:07:53 +0100 |
commit | 8f9d8b1969270d0786cd4eeb369ed3d42a62e541 (patch) | |
tree | c453ecd6e0f9af396b5acc1749bf6075beeadb8a | |
parent | 29b639db064deba392e056ec9a1b499fae7b4f75 (diff) | |
download | gleam_stdlib-8f9d8b1969270d0786cd4eeb369ed3d42a62e541.tar.gz gleam_stdlib-8f9d8b1969270d0786cd4eeb369ed3d42a62e541.zip |
Address review
-rw-r--r-- | src/gleam/bit_array.gleam | 25 | ||||
-rw-r--r-- | src/gleam_stdlib.erl | 7 | ||||
-rw-r--r-- | test/gleam/bit_array_test.gleam | 37 |
3 files changed, 52 insertions, 17 deletions
diff --git a/src/gleam/bit_array.gleam b/src/gleam/bit_array.gleam index af78fcc..909d9f1 100644 --- a/src/gleam/bit_array.gleam +++ b/src/gleam/bit_array.gleam @@ -205,20 +205,23 @@ fn do_inspect(input: BitArray, accumulator: String) -> String { /// ``` /// pub fn compare(first: BitArray, second: BitArray) -> order.Order { - do_compare(first, second, 0) -} - -fn do_compare(first: BitArray, second: BitArray, index: Int) -> order.Order { - case slice(first, index, 1), slice(second, index, 1) { - Ok(<<first_byte>>), Ok(<<second_byte>>) -> + case first, second { + <<first_byte, first_rest:bits>>, <<second_byte, second_rest:bits>> -> int.compare(first_byte, second_byte) - |> order.lazy_break_tie(fn() { do_compare(first, second, index + 1) }) + |> order.lazy_break_tie(fn() { compare(first_rest, second_rest) }) + <<>>, <<>> -> order.Eq // First has more items, example: "AB" > "A": - Ok(_), Error(_) -> order.Gt + _, <<>> -> order.Gt // Second has more items, example: "A" < "AB": - Error(_), Ok(_) -> order.Lt - // Both have the same length, fallback: - _, _ -> order.Eq + <<>>, _ -> order.Lt + // This happens when there's unusually sized elements. + // Handle these special cases via custom erlang function. + // This cannot be reached in JS right now. + first, second -> + int.compare(bit_array_to_int(first), bit_array_to_int(second)) } } + +@external(erlang, "gleam_stdlib", "bit_array_to_int") +fn bit_array_to_int(first: BitArray) -> Int diff --git a/src/gleam_stdlib.erl b/src/gleam_stdlib.erl index 0941a33..96a35b7 100644 --- a/src/gleam_stdlib.erl +++ b/src/gleam_stdlib.erl @@ -14,7 +14,7 @@ decode_tuple5/1, decode_tuple6/1, tuple_get/2, classify_dynamic/1, print/1, println/1, print_error/1, println_error/1, inspect/1, float_to_string/1, int_from_base_string/2, utf_codepoint_list_to_string/1, contains_string/2, - crop_string/2, base16_decode/1, string_replace/3, regex_replace/3, slice/3 + crop_string/2, base16_decode/1, string_replace/3, regex_replace/3, slice/3, bit_array_to_int/1 ]). %% Taken from OTP's uri_string module @@ -492,6 +492,11 @@ inspect_bit_array(Rest, Acc) -> Segment = <<X1/binary, ":size(", Size1/binary, ")">>, inspect_bit_array(<<>>, append_segment(Acc, Segment)). +bit_array_to_int(A) -> + Size = bit_size(A), + <<A1:Size>> = A, + A1. + append_segment(<<"<<">>, Segment) -> <<"<<", Segment/binary>>; append_segment(Acc, Segment) -> diff --git a/test/gleam/bit_array_test.gleam b/test/gleam/bit_array_test.gleam index 56b6bf5..38dcb2e 100644 --- a/test/gleam/bit_array_test.gleam +++ b/test/gleam/bit_array_test.gleam @@ -390,10 +390,25 @@ pub fn compare_utf16_test() { } @target(erlang) +pub fn compare_utf32_test() { + bit_array.compare(<<"ABC":utf32>>, <<"ABC":utf32>>) + |> should.equal(order.Eq) + + bit_array.compare(<<"ABC":utf32>>, <<"AB":utf32>>) + |> should.equal(order.Gt) + + bit_array.compare(<<"A":utf32>>, <<"Z":utf32>>) + |> should.equal(order.Lt) +} + +@target(erlang) pub fn compare_mixed_utfs_test() { bit_array.compare(<<"A":utf16>>, <<"A":utf8>>) |> should.equal(order.Lt) + bit_array.compare(<<"A":utf32>>, <<"A":utf16>>) + |> should.equal(order.Lt) + bit_array.compare(<<"A":utf8>>, <<"A":utf16>>) |> should.equal(order.Gt) @@ -403,11 +418,20 @@ pub fn compare_mixed_utfs_test() { bit_array.compare(<<"":utf16>>, <<"A":utf8>>) |> should.equal(order.Lt) + bit_array.compare(<<"":utf32>>, <<"A":utf8>>) + |> should.equal(order.Lt) + + bit_array.compare(<<"":utf32>>, <<"A":utf16>>) + |> should.equal(order.Lt) + bit_array.compare(<<"":utf16>>, <<"":utf8>>) |> should.equal(order.Eq) bit_array.compare(<<"":utf8>>, <<"":utf16>>) |> should.equal(order.Eq) + + bit_array.compare(<<"":utf8>>, <<"":utf32>>) + |> should.equal(order.Eq) } @target(erlang) @@ -416,19 +440,22 @@ pub fn compare_different_sizes_test() { |> should.equal(order.Eq) bit_array.compare(<<3:5>>, <<4:5>>) - |> should.equal(order.Eq) + |> should.equal(order.Lt) + + bit_array.compare(<<3:7>>, <<4:7>>) + |> should.equal(order.Lt) bit_array.compare(<<5:5>>, <<4:5>>) - |> should.equal(order.Eq) + |> should.equal(order.Gt) bit_array.compare(<<4:8>>, <<4:5>>) - |> should.equal(order.Gt) + |> should.equal(order.Eq) bit_array.compare(<<4:5>>, <<4:8>>) - |> should.equal(order.Lt) + |> should.equal(order.Eq) bit_array.compare(<<0:5>>, <<0:8>>) - |> should.equal(order.Lt) + |> should.equal(order.Eq) bit_array.compare(<<0:2>>, <<0:1>>) |> should.equal(order.Eq) |