Commit 5575e2a168

Andrew Kelley <andrew@ziglang.org>
2020-01-02 00:08:40
std.mem.compare: breaking API changes
* `std.mem.Compare` is now `std.math.Order` and the enum tags renamed to follow new style convention. * `std.mem.compare` is renamed to `std.mem.order`. * new function `std.math.order`
1 parent 7b62d5d
Changed files (5)
lib/std/crypto/chacha20.zig
@@ -224,7 +224,7 @@ test "crypto.chacha20 test vector sunscreen" {
     // Chacha20 is self-reversing.
     var plaintext: [114]u8 = undefined;
     chaCha20IETF(plaintext[0..], result[0..], 1, key, nonce);
-    testing.expect(mem.compare(u8, input, &plaintext) == mem.Compare.Equal);
+    testing.expect(mem.order(u8, input, &plaintext) == .eq);
 }
 
 // https://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04#section-7
lib/std/http/headers.zig
@@ -70,12 +70,12 @@ const HeaderEntry = struct {
             }
 
             // Sort lexicographically on header name
-            return mem.compare(u8, a.name, b.name) == mem.Compare.LessThan;
+            return mem.order(u8, a.name, b.name) == .lt;
         }
 
         // Sort lexicographically on header value
         if (!mem.eql(u8, a.value, b.value)) {
-            return mem.compare(u8, a.value, b.value) == mem.Compare.LessThan;
+            return mem.order(u8, a.value, b.value) == .lt;
         }
 
         // Doesn't matter here; need to pick something for sort consistency
lib/std/math.zig
@@ -926,9 +926,6 @@ test "minInt and maxInt" {
 }
 
 test "max value type" {
-    // If the type of maxInt(i32) was i32 then this implicit cast to
-    // u32 would not work. But since the value is a number literal,
-    // it works fine.
     const x: u32 = maxInt(i32);
     testing.expect(x == 2147483647);
 }
@@ -944,7 +941,32 @@ test "math.mulWide" {
     testing.expect(mulWide(u8, 100, 100) == 10000);
 }
 
-/// Not to be confused with `std.mem.Compare`.
+/// See also `CompareOperator`.
+pub const Order = enum {
+    /// Less than (`<`)
+    lt,
+
+    /// Equal (`==`)
+    eq,
+
+    /// Greater than (`>`)
+    gt,
+};
+
+/// Given two numbers, this function returns the order they are with respect to each other.
+pub fn order(a: var, b: var) Order {
+    if (a == b) {
+        return .eq;
+    } else if (a < b) {
+        return .lt;
+    } else if (a > b) {
+        return .gt;
+    } else {
+        unreachable;
+    }
+}
+
+/// See also `Order`.
 pub const CompareOperator = enum {
     /// Less than (`<`)
     lt,
@@ -979,7 +1001,7 @@ pub fn compare(a: var, op: CompareOperator, b: var) bool {
     };
 }
 
-test "math.lt, et al < <= > >= between signed and unsigned" {
+test "compare between signed and unsigned" {
     testing.expect(compare(@as(i8, -1), .lt, @as(u8, 255)));
     testing.expect(compare(@as(i8, 2), .gt, @as(u8, 1)));
     testing.expect(!compare(@as(i8, -1), .gte, @as(u8, 255)));
lib/std/mem.zig
@@ -239,12 +239,6 @@ pub const Allocator = struct {
     }
 };
 
-pub const Compare = enum {
-    LessThan,
-    Equal,
-    GreaterThan,
-};
-
 /// Copy all of source into dest at position 0.
 /// dest.len must be >= source.len.
 /// dest.ptr must be <= src.ptr.
@@ -297,46 +291,30 @@ test "mem.secureZero" {
     testing.expectEqualSlices(u8, a[0..], b[0..]);
 }
 
-pub fn compare(comptime T: type, lhs: []const T, rhs: []const T) Compare {
+pub fn order(comptime T: type, lhs: []const T, rhs: []const T) math.Order {
     const n = math.min(lhs.len, rhs.len);
     var i: usize = 0;
     while (i < n) : (i += 1) {
-        if (lhs[i] == rhs[i]) {
-            continue;
-        } else if (lhs[i] < rhs[i]) {
-            return Compare.LessThan;
-        } else if (lhs[i] > rhs[i]) {
-            return Compare.GreaterThan;
-        } else {
-            unreachable;
+        switch (math.order(lhs[i], rhs[i])) {
+            .eq => continue,
+            .lt => return .lt,
+            .gt => return .gt,
         }
     }
-
-    if (lhs.len == rhs.len) {
-        return Compare.Equal;
-    } else if (lhs.len < rhs.len) {
-        return Compare.LessThan;
-    } else if (lhs.len > rhs.len) {
-        return Compare.GreaterThan;
-    }
-    unreachable;
+    return math.order(lhs.len, rhs.len);
 }
 
-test "mem.compare" {
-    testing.expect(compare(u8, "abcd", "bee") == Compare.LessThan);
-    testing.expect(compare(u8, "abc", "abc") == Compare.Equal);
-    testing.expect(compare(u8, "abc", "abc0") == Compare.LessThan);
-    testing.expect(compare(u8, "", "") == Compare.Equal);
-    testing.expect(compare(u8, "", "a") == Compare.LessThan);
+test "order" {
+    testing.expect(order(u8, "abcd", "bee") == .lt);
+    testing.expect(order(u8, "abc", "abc") == .eq);
+    testing.expect(order(u8, "abc", "abc0") == .lt);
+    testing.expect(order(u8, "", "") == .eq);
+    testing.expect(order(u8, "", "a") == .lt);
 }
 
 /// Returns true if lhs < rhs, false otherwise
 pub fn lessThan(comptime T: type, lhs: []const T, rhs: []const T) bool {
-    var result = compare(T, lhs, rhs);
-    if (result == Compare.LessThan) {
-        return true;
-    } else
-        return false;
+    return order(T, lhs, rhs) == .lt;
 }
 
 test "mem.lessThan" {
lib/std/rb.zig
@@ -1,7 +1,7 @@
 const std = @import("std.zig");
 const assert = std.debug.assert;
 const testing = std.testing;
-const mem = std.mem; // For mem.Compare
+const Order = std.math.Order;
 
 const Color = enum(u1) {
     Black,
@@ -132,7 +132,7 @@ pub const Node = struct {
 
 pub const Tree = struct {
     root: ?*Node,
-    compareFn: fn (*Node, *Node) mem.Compare,
+    compareFn: fn (*Node, *Node) Order,
 
     /// If you have a need for a version that caches this, please file a bug.
     pub fn first(tree: *Tree) ?*Node {
@@ -389,7 +389,7 @@ pub const Tree = struct {
         var new = newconst;
 
         // I assume this can get optimized out if the caller already knows.
-        if (tree.compareFn(old, new) != mem.Compare.Equal) return ReplaceError.NotEqual;
+        if (tree.compareFn(old, new) != .eq) return ReplaceError.NotEqual;
 
         if (old.getParent()) |parent| {
             parent.setChild(new, parent.left == old);
@@ -404,7 +404,7 @@ pub const Tree = struct {
         new.* = old.*;
     }
 
-    pub fn init(tree: *Tree, f: fn (*Node, *Node) mem.Compare) void {
+    pub fn init(tree: *Tree, f: fn (*Node, *Node) Order) void {
         tree.root = null;
         tree.compareFn = f;
     }
@@ -469,19 +469,21 @@ fn doLookup(key: *Node, tree: *Tree, pparent: *?*Node, is_left: *bool) ?*Node {
     is_left.* = false;
 
     while (maybe_node) |node| {
-        var res: mem.Compare = tree.compareFn(node, key);
-        if (res == mem.Compare.Equal) {
+        const res = tree.compareFn(node, key);
+        if (res == .eq) {
             return node;
         }
         pparent.* = node;
-        if (res == mem.Compare.GreaterThan) {
-            is_left.* = true;
-            maybe_node = node.left;
-        } else if (res == mem.Compare.LessThan) {
-            is_left.* = false;
-            maybe_node = node.right;
-        } else {
-            unreachable;
+        switch (res) {
+            .gt => {
+                is_left.* = true;
+                maybe_node = node.left;
+            },
+            .lt => {
+                is_left.* = false;
+                maybe_node = node.right;
+            },
+            .eq => unreachable, // handled above
         }
     }
     return null;
@@ -496,16 +498,16 @@ fn testGetNumber(node: *Node) *testNumber {
     return @fieldParentPtr(testNumber, "node", node);
 }
 
-fn testCompare(l: *Node, r: *Node) mem.Compare {
+fn testCompare(l: *Node, r: *Node) Order {
     var left = testGetNumber(l);
     var right = testGetNumber(r);
 
     if (left.value < right.value) {
-        return mem.Compare.LessThan;
+        return .lt;
     } else if (left.value == right.value) {
-        return mem.Compare.Equal;
+        return .eq;
     } else if (left.value > right.value) {
-        return mem.Compare.GreaterThan;
+        return .gt;
     }
     unreachable;
 }