@@ -1630,12 +1630,59 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
1630
1630
}
1631
1631
1632
1632
//
1633
- // Boilerplate traits
1633
+ // Comparison traits
1634
1634
//
1635
1635
1636
+ extern {
1637
+ /// Call implementation provided memcmp
1638
+ ///
1639
+ /// Interprets the data as u8.
1640
+ ///
1641
+ /// Return 0 for equal, < 0 for less than and > 0 for greater
1642
+ /// than.
1643
+ // FIXME(#32610): Return type should be c_int
1644
+ fn memcmp ( s1 : * const u8 , s2 : * const u8 , n : usize ) -> i32 ;
1645
+ }
1646
+
1636
1647
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1637
1648
impl < A , B > PartialEq < [ B ] > for [ A ] where A : PartialEq < B > {
1638
1649
fn eq ( & self , other : & [ B ] ) -> bool {
1650
+ SlicePartialEq :: equal ( self , other)
1651
+ }
1652
+
1653
+ fn ne ( & self , other : & [ B ] ) -> bool {
1654
+ SlicePartialEq :: not_equal ( self , other)
1655
+ }
1656
+ }
1657
+
1658
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1659
+ impl < T : Eq > Eq for [ T ] { }
1660
+
1661
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1662
+ impl < T : Ord > Ord for [ T ] {
1663
+ fn cmp ( & self , other : & [ T ] ) -> Ordering {
1664
+ SliceOrd :: compare ( self , other)
1665
+ }
1666
+ }
1667
+
1668
+ #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1669
+ impl < T : PartialOrd > PartialOrd for [ T ] {
1670
+ fn partial_cmp ( & self , other : & [ T ] ) -> Option < Ordering > {
1671
+ SlicePartialOrd :: partial_compare ( self , other)
1672
+ }
1673
+ }
1674
+
1675
+ // intermediate trait for specialization of slice's PartialEq
1676
+ trait SlicePartialEq < B > {
1677
+ fn equal ( & self , other : & [ B ] ) -> bool ;
1678
+ fn not_equal ( & self , other : & [ B ] ) -> bool ;
1679
+ }
1680
+
1681
+ // Generic slice equality
1682
+ impl < A , B > SlicePartialEq < B > for [ A ]
1683
+ where A : PartialEq < B >
1684
+ {
1685
+ default fn equal ( & self , other : & [ B ] ) -> bool {
1639
1686
if self . len ( ) != other. len ( ) {
1640
1687
return false ;
1641
1688
}
@@ -1648,7 +1695,8 @@ impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
1648
1695
1649
1696
true
1650
1697
}
1651
- fn ne ( & self , other : & [ B ] ) -> bool {
1698
+
1699
+ default fn not_equal ( & self , other : & [ B ] ) -> bool {
1652
1700
if self . len ( ) != other. len ( ) {
1653
1701
return true ;
1654
1702
}
@@ -1663,12 +1711,35 @@ impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
1663
1711
}
1664
1712
}
1665
1713
1666
- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1667
- impl < T : Eq > Eq for [ T ] { }
1714
+ // Use memcmp for bytewise equality when the types allow
1715
+ impl < A > SlicePartialEq < A > for [ A ]
1716
+ where A : PartialEq < A > + BytewiseEquality
1717
+ {
1718
+ fn equal ( & self , other : & [ A ] ) -> bool {
1719
+ if self . len ( ) != other. len ( ) {
1720
+ return false ;
1721
+ }
1722
+ unsafe {
1723
+ let size = mem:: size_of_val ( self ) ;
1724
+ memcmp ( self . as_ptr ( ) as * const u8 ,
1725
+ other. as_ptr ( ) as * const u8 , size) == 0
1726
+ }
1727
+ }
1668
1728
1669
- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1670
- impl < T : Ord > Ord for [ T ] {
1671
- fn cmp ( & self , other : & [ T ] ) -> Ordering {
1729
+ fn not_equal ( & self , other : & [ A ] ) -> bool {
1730
+ !self . equal ( other)
1731
+ }
1732
+ }
1733
+
1734
+ // intermediate trait for specialization of slice's PartialOrd
1735
+ trait SlicePartialOrd < B > {
1736
+ fn partial_compare ( & self , other : & [ B ] ) -> Option < Ordering > ;
1737
+ }
1738
+
1739
+ impl < A > SlicePartialOrd < A > for [ A ]
1740
+ where A : PartialOrd
1741
+ {
1742
+ default fn partial_compare ( & self , other : & [ A ] ) -> Option < Ordering > {
1672
1743
let l = cmp:: min ( self . len ( ) , other. len ( ) ) ;
1673
1744
1674
1745
// Slice to the loop iteration range to enable bound check
@@ -1677,19 +1748,32 @@ impl<T: Ord> Ord for [T] {
1677
1748
let rhs = & other[ ..l] ;
1678
1749
1679
1750
for i in 0 ..l {
1680
- match lhs[ i] . cmp ( & rhs[ i] ) {
1681
- Ordering :: Equal => ( ) ,
1751
+ match lhs[ i] . partial_cmp ( & rhs[ i] ) {
1752
+ Some ( Ordering :: Equal ) => ( ) ,
1682
1753
non_eq => return non_eq,
1683
1754
}
1684
1755
}
1685
1756
1686
- self . len ( ) . cmp ( & other. len ( ) )
1757
+ self . len ( ) . partial_cmp ( & other. len ( ) )
1687
1758
}
1688
1759
}
1689
1760
1690
- #[ stable( feature = "rust1" , since = "1.0.0" ) ]
1691
- impl < T : PartialOrd > PartialOrd for [ T ] {
1692
- fn partial_cmp ( & self , other : & [ T ] ) -> Option < Ordering > {
1761
+ impl SlicePartialOrd < u8 > for [ u8 ] {
1762
+ #[ inline]
1763
+ fn partial_compare ( & self , other : & [ u8 ] ) -> Option < Ordering > {
1764
+ Some ( SliceOrd :: compare ( self , other) )
1765
+ }
1766
+ }
1767
+
1768
+ // intermediate trait for specialization of slice's Ord
1769
+ trait SliceOrd < B > {
1770
+ fn compare ( & self , other : & [ B ] ) -> Ordering ;
1771
+ }
1772
+
1773
+ impl < A > SliceOrd < A > for [ A ]
1774
+ where A : Ord
1775
+ {
1776
+ default fn compare ( & self , other : & [ A ] ) -> Ordering {
1693
1777
let l = cmp:: min ( self . len ( ) , other. len ( ) ) ;
1694
1778
1695
1779
// Slice to the loop iteration range to enable bound check
@@ -1698,12 +1782,47 @@ impl<T: PartialOrd> PartialOrd for [T] {
1698
1782
let rhs = & other[ ..l] ;
1699
1783
1700
1784
for i in 0 ..l {
1701
- match lhs[ i] . partial_cmp ( & rhs[ i] ) {
1702
- Some ( Ordering :: Equal ) => ( ) ,
1785
+ match lhs[ i] . cmp ( & rhs[ i] ) {
1786
+ Ordering :: Equal => ( ) ,
1703
1787
non_eq => return non_eq,
1704
1788
}
1705
1789
}
1706
1790
1707
- self . len ( ) . partial_cmp ( & other. len ( ) )
1791
+ self . len ( ) . cmp ( & other. len ( ) )
1792
+ }
1793
+ }
1794
+
1795
+ // memcmp compares a sequence of unsigned bytes lexicographically.
1796
+ // this matches the order we want for [u8], but no others (not even [i8]).
1797
+ impl SliceOrd < u8 > for [ u8 ] {
1798
+ #[ inline]
1799
+ fn compare ( & self , other : & [ u8 ] ) -> Ordering {
1800
+ let order = unsafe {
1801
+ memcmp ( self . as_ptr ( ) , other. as_ptr ( ) ,
1802
+ cmp:: min ( self . len ( ) , other. len ( ) ) )
1803
+ } ;
1804
+ if order == 0 {
1805
+ self . len ( ) . cmp ( & other. len ( ) )
1806
+ } else if order < 0 {
1807
+ Less
1808
+ } else {
1809
+ Greater
1810
+ }
1811
+ }
1812
+ }
1813
+
1814
+ /// Trait implemented for types that can be compared for equality using
1815
+ /// their bytewise representation
1816
+ trait BytewiseEquality { }
1817
+
1818
+ macro_rules! impl_marker_for {
1819
+ ( $traitname: ident, $( $ty: ty) * ) => {
1820
+ $(
1821
+ impl $traitname for $ty { }
1822
+ ) *
1708
1823
}
1709
1824
}
1825
+
1826
+ impl_marker_for ! ( BytewiseEquality ,
1827
+ u8 i8 u16 i16 u32 i32 u64 i64 usize isize char bool ) ;
1828
+
0 commit comments