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