@@ -1630,12 +1630,60 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
16301630}
16311631
16321632//
1633- // Boilerplate traits
1633+ // Comparison traits
16341634//
16351635
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+
16361647#[ stable( feature = "rust1" , since = "1.0.0" ) ]
16371648impl < A , B > PartialEq < [ B ] > for [ A ] where A : PartialEq < B > {
16381649 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 {
16391687 if self . len ( ) != other. len ( ) {
16401688 return false ;
16411689 }
@@ -1648,7 +1696,8 @@ impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
16481696
16491697 true
16501698 }
1651- fn ne ( & self , other : & [ B ] ) -> bool {
1699+
1700+ default fn not_equal ( & self , other : & [ B ] ) -> bool {
16521701 if self . len ( ) != other. len ( ) {
16531702 return true ;
16541703 }
@@ -1663,12 +1712,36 @@ impl<A, B> PartialEq<[B]> for [A] where A: PartialEq<B> {
16631712 }
16641713}
16651714
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+ }
16681729
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 > {
16721745 let l = cmp:: min ( self . len ( ) , other. len ( ) ) ;
16731746
16741747 // Slice to the loop iteration range to enable bound check
@@ -1677,19 +1750,33 @@ impl<T: Ord> Ord for [T] {
16771750 let rhs = & other[ ..l] ;
16781751
16791752 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 ) => ( ) ,
16821755 non_eq => return non_eq,
16831756 }
16841757 }
16851758
1686- self . len ( ) . cmp ( & other. len ( ) )
1759+ self . len ( ) . partial_cmp ( & other. len ( ) )
16871760 }
16881761}
16891762
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 {
16931780 let l = cmp:: min ( self . len ( ) , other. len ( ) ) ;
16941781
16951782 // Slice to the loop iteration range to enable bound check
@@ -1698,12 +1785,48 @@ impl<T: PartialOrd> PartialOrd for [T] {
16981785 let rhs = & other[ ..l] ;
16991786
17001787 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 => ( ) ,
17031790 non_eq => return non_eq,
17041791 }
17051792 }
17061793
1707- self . len ( ) . partial_cmp ( & other. len ( ) )
1794+ self . len ( ) . cmp ( & other. len ( ) )
17081795 }
17091796}
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