Repository: uutils/coreutils (Rust)

Issue:
`sort`: Make sure hexadecimal numbers/floats are handled correctly
I wanted to do this as part of #8031, but handling hex numbers might be a bit tricky (need to figure out which parameters accept those, probably only `-g`), as there's a lot of custom logic in `get_leading_gen`.

Failing test:
```
#[test]
// Test hexadecimal numbers (and hex floats)
fn test_g_float_hex() {
    let input = "0x123\n0x0\n0x2p10\n0x9p-10\n";
    let output = "0x0\n0x9p-10\n0x123\n0x2p10\n";
    new_ucmd!()
        .args(&["-g"])
        .pipe_in(input)
        .succeeds()
        .stdout_is(output);
}
```

I'll probably pick this up after #8031.


Discussion:
I think we also do not handle negative exponents correctly: `1.0e-1` is not parsed correctly.



Patch:
diff --git a/src/uu/sort/src/sort.rs b/src/uu/sort/src/sort.rs
index 4928dd17d39..5c97abba347 100644
--- a/src/uu/sort/src/sort.rs
+++ b/src/uu/sort/src/sort.rs
@@ -7,7 +7,7 @@
 // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html
 // https://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html
 
-// spell-checker:ignore (misc) HFKJFK Mbdfhn getrlimit RLIMIT_NOFILE rlim bigdecimal extendedbigdecimal
+// spell-checker:ignore (misc) HFKJFK Mbdfhn getrlimit RLIMIT_NOFILE rlim bigdecimal extendedbigdecimal hexdigit
 
 mod check;
 mod chunks;
@@ -1834,15 +1834,27 @@ fn get_leading_gen(input: &str) -> Range<usize> {
 
     let mut had_e_notation = false;
     let mut had_decimal_pt = false;
+    let mut had_hex_notation: bool = false;
     while let Some((idx, c)) = char_indices.next() {
+        if had_hex_notation && c.is_ascii_hexdigit() {
+            continue;
+        }
+
         if c.is_ascii_digit() {
+            if c == '0' && matches!(char_indices.peek(), Some((_, 'x' | 'X'))) {
+                had_hex_notation = true;
+                char_indices.next();
+            }
             continue;
         }
+
         if c == DECIMAL_PT && !had_decimal_pt && !had_e_notation {
             had_decimal_pt = true;
             continue;
         }
-        if (c == 'e' || c == 'E') && !had_e_notation {
+        let is_decimal_e = (c == 'e' || c == 'E') && !had_hex_notation;
+        let is_hex_e = (c == 'p' || c == 'P') && had_hex_notation;
+        if (is_decimal_e || is_hex_e) && !had_e_notation {
             // we can only consume the 'e' if what follow is either a digit, or a sign followed by a digit.
             if let Some(&(_, next_char)) = char_indices.peek() {
                 if (next_char == '+' || next_char == '-')


Test patch:
diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs
index 9a9022e2910..657a3addd5f 100644
--- a/tests/by-util/test_sort.rs
+++ b/tests/by-util/test_sort.rs
@@ -1556,3 +1556,15 @@ fn test_g_arbitrary() {
         .succeeds()
         .stdout_is(output);
 }
+
+#[test]
+// Test hexadecimal numbers (and hex floats)
+fn test_g_float_hex() {
+    let input = "0x123\n0x0\n0x2p10\n0x9p-10\n";
+    let output = "0x0\n0x9p-10\n0x123\n0x2p10\n";
+    new_ucmd!()
+        .args(&["-g"])
+        .pipe_in(input)
+        .succeeds()
+        .stdout_is(output);
+}
diff --git a/tests/fixtures/sort/exponents_general.expected b/tests/fixtures/sort/exponents_general.expected
index 308a82e1e34..0aa6e07514b 100644
--- a/tests/fixtures/sort/exponents_general.expected
+++ b/tests/fixtures/sort/exponents_general.expected
@@ -8,11 +8,11 @@
 
  	 -12e-5555.5
 0b10 // binary not supported
-0x10 // hexadecimal not supported, but it should be
 55e-20
 55e-20.10
 5.5.5.5
 10E
+0x10
 64e+
 99e-
 1000EDKLD
diff --git a/tests/fixtures/sort/exponents_general.expected.debug b/tests/fixtures/sort/exponents_general.expected.debug
index a7238d10e8c..657a3615949 100644
--- a/tests/fixtures/sort/exponents_general.expected.debug
+++ b/tests/fixtures/sort/exponents_general.expected.debug
@@ -28,9 +28,6 @@ ______________
 0b10 // binary not supported
 _
 ____________________________
-0x10 // hexadecimal not supported, but it should be
-_
-___________________________________________________
 55e-20
 ______
 ______
@@ -43,6 +40,9 @@ _______
 10E
 __
 ___
+0x10
+____
+____
 64e+
 __
 ____
diff --git a/tests/fixtures/sort/exponents_general.txt b/tests/fixtures/sort/exponents_general.txt
index 4a9bbba2e02..f6b88b8f5c3 100644
--- a/tests/fixtures/sort/exponents_general.txt
+++ b/tests/fixtures/sort/exponents_general.txt
@@ -4,7 +4,7 @@
 +100000
 
 10000K78
-0x10 // hexadecimal not supported, but it should be
+0x10
 10E
 0b10 // binary not supported
 64e+