Skip to content

Commit 32f6534

Browse files
authoredJul 28, 2024
Rollup merge of #128282 - pitaj:nonzero_bitwise, r=workingjubilee
bitwise and bytewise methods on `NonZero` Implementation for `nonzero_bitwise` Tracking issue #128281 ACP rust-lang/libs-team#413
·
1.88.01.82.0
2 parents 9920404 + c9e408e commit 32f6534

File tree

1 file changed

+430
-3
lines changed

1 file changed

+430
-3
lines changed
 

‎library/core/src/num/nonzero.rs

Lines changed: 430 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,12 @@ macro_rules! nonzero_integer {
455455
UnsignedPrimitive = $Uint:ty,
456456

457457
// Used in doc comments.
458+
rot = $rot:literal,
459+
rot_op = $rot_op:literal,
460+
rot_result = $rot_result:literal,
461+
swap_op = $swap_op:literal,
462+
swapped = $swapped:literal,
463+
reversed = $reversed:literal,
458464
leading_zeros_test = $leading_zeros_test:expr,
459465
) => {
460466
/// An integer that is known not to equal zero.
@@ -604,6 +610,270 @@ macro_rules! nonzero_integer {
604610
unsafe { NonZero::new_unchecked(self.get().count_ones()) }
605611
}
606612

613+
/// Shifts the bits to the left by a specified amount, `n`,
614+
/// wrapping the truncated bits to the end of the resulting integer.
615+
///
616+
/// Please note this isn't the same operation as the `<<` shifting operator!
617+
///
618+
/// # Examples
619+
///
620+
/// Basic usage:
621+
///
622+
/// ```
623+
/// #![feature(nonzero_bitwise)]
624+
/// # use std::num::NonZero;
625+
/// #
626+
/// # fn main() { test().unwrap(); }
627+
/// # fn test() -> Option<()> {
628+
#[doc = concat!("let n = NonZero::new(", $rot_op, stringify!($Int), ")?;")]
629+
#[doc = concat!("let m = NonZero::new(", $rot_result, ")?;")]
630+
///
631+
#[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")]
632+
/// # Some(())
633+
/// # }
634+
/// ```
635+
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
636+
#[must_use = "this returns the result of the operation, \
637+
without modifying the original"]
638+
#[inline(always)]
639+
pub const fn rotate_left(self, n: u32) -> Self {
640+
let result = self.get().rotate_left(n);
641+
// SAFETY: Rotating bits preserves the property int > 0.
642+
unsafe { Self::new_unchecked(result) }
643+
}
644+
645+
/// Shifts the bits to the right by a specified amount, `n`,
646+
/// wrapping the truncated bits to the beginning of the resulting
647+
/// integer.
648+
///
649+
/// Please note this isn't the same operation as the `>>` shifting operator!
650+
///
651+
/// # Examples
652+
///
653+
/// Basic usage:
654+
///
655+
/// ```
656+
/// #![feature(nonzero_bitwise)]
657+
/// # use std::num::NonZero;
658+
/// #
659+
/// # fn main() { test().unwrap(); }
660+
/// # fn test() -> Option<()> {
661+
#[doc = concat!("let n = NonZero::new(", $rot_result, stringify!($Int), ")?;")]
662+
#[doc = concat!("let m = NonZero::new(", $rot_op, ")?;")]
663+
///
664+
#[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")]
665+
/// # Some(())
666+
/// # }
667+
/// ```
668+
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
669+
#[must_use = "this returns the result of the operation, \
670+
without modifying the original"]
671+
#[inline(always)]
672+
pub const fn rotate_right(self, n: u32) -> Self {
673+
let result = self.get().rotate_right(n);
674+
// SAFETY: Rotating bits preserves the property int > 0.
675+
unsafe { Self::new_unchecked(result) }
676+
}
677+
678+
/// Reverses the byte order of the integer.
679+
///
680+
/// # Examples
681+
///
682+
/// Basic usage:
683+
///
684+
/// ```
685+
/// #![feature(nonzero_bitwise)]
686+
/// # use std::num::NonZero;
687+
/// #
688+
/// # fn main() { test().unwrap(); }
689+
/// # fn test() -> Option<()> {
690+
#[doc = concat!("let n = NonZero::new(", $swap_op, stringify!($Int), ")?;")]
691+
/// let m = n.swap_bytes();
692+
///
693+
#[doc = concat!("assert_eq!(m, NonZero::new(", $swapped, ")?);")]
694+
/// # Some(())
695+
/// # }
696+
/// ```
697+
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
698+
#[must_use = "this returns the result of the operation, \
699+
without modifying the original"]
700+
#[inline(always)]
701+
pub const fn swap_bytes(self) -> Self {
702+
let result = self.get().swap_bytes();
703+
// SAFETY: Shuffling bytes preserves the property int > 0.
704+
unsafe { Self::new_unchecked(result) }
705+
}
706+
707+
/// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
708+
/// second least-significant bit becomes second most-significant bit, etc.
709+
///
710+
/// # Examples
711+
///
712+
/// Basic usage:
713+
///
714+
/// ```
715+
/// #![feature(nonzero_bitwise)]
716+
/// # use std::num::NonZero;
717+
/// #
718+
/// # fn main() { test().unwrap(); }
719+
/// # fn test() -> Option<()> {
720+
#[doc = concat!("let n = NonZero::new(", $swap_op, stringify!($Int), ")?;")]
721+
/// let m = n.reverse_bits();
722+
///
723+
#[doc = concat!("assert_eq!(m, NonZero::new(", $reversed, ")?);")]
724+
/// # Some(())
725+
/// # }
726+
/// ```
727+
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
728+
#[must_use = "this returns the result of the operation, \
729+
without modifying the original"]
730+
#[inline(always)]
731+
pub const fn reverse_bits(self) -> Self {
732+
let result = self.get().reverse_bits();
733+
// SAFETY: Reversing bits preserves the property int > 0.
734+
unsafe { Self::new_unchecked(result) }
735+
}
736+
737+
/// Converts an integer from big endian to the target's endianness.
738+
///
739+
/// On big endian this is a no-op. On little endian the bytes are
740+
/// swapped.
741+
///
742+
/// # Examples
743+
///
744+
/// Basic usage:
745+
///
746+
/// ```
747+
/// #![feature(nonzero_bitwise)]
748+
/// # use std::num::NonZero;
749+
#[doc = concat!("use std::num::", stringify!($Ty), ";")]
750+
/// #
751+
/// # fn main() { test().unwrap(); }
752+
/// # fn test() -> Option<()> {
753+
#[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")]
754+
///
755+
/// if cfg!(target_endian = "big") {
756+
#[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_be(n), n)")]
757+
/// } else {
758+
#[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_be(n), n.swap_bytes())")]
759+
/// }
760+
/// # Some(())
761+
/// # }
762+
/// ```
763+
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
764+
#[must_use]
765+
#[inline(always)]
766+
pub const fn from_be(x: Self) -> Self {
767+
let result = $Int::from_be(x.get());
768+
// SAFETY: Shuffling bytes preserves the property int > 0.
769+
unsafe { Self::new_unchecked(result) }
770+
}
771+
772+
/// Converts an integer from little endian to the target's endianness.
773+
///
774+
/// On little endian this is a no-op. On big endian the bytes are
775+
/// swapped.
776+
///
777+
/// # Examples
778+
///
779+
/// Basic usage:
780+
///
781+
/// ```
782+
/// #![feature(nonzero_bitwise)]
783+
/// # use std::num::NonZero;
784+
#[doc = concat!("use std::num::", stringify!($Ty), ";")]
785+
/// #
786+
/// # fn main() { test().unwrap(); }
787+
/// # fn test() -> Option<()> {
788+
#[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")]
789+
///
790+
/// if cfg!(target_endian = "little") {
791+
#[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_le(n), n)")]
792+
/// } else {
793+
#[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_le(n), n.swap_bytes())")]
794+
/// }
795+
/// # Some(())
796+
/// # }
797+
/// ```
798+
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
799+
#[must_use]
800+
#[inline(always)]
801+
pub const fn from_le(x: Self) -> Self {
802+
let result = $Int::from_le(x.get());
803+
// SAFETY: Shuffling bytes preserves the property int > 0.
804+
unsafe { Self::new_unchecked(result) }
805+
}
806+
807+
/// Converts `self` to big endian from the target's endianness.
808+
///
809+
/// On big endian this is a no-op. On little endian the bytes are
810+
/// swapped.
811+
///
812+
/// # Examples
813+
///
814+
/// Basic usage:
815+
///
816+
/// ```
817+
/// #![feature(nonzero_bitwise)]
818+
/// # use std::num::NonZero;
819+
/// #
820+
/// # fn main() { test().unwrap(); }
821+
/// # fn test() -> Option<()> {
822+
#[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")]
823+
///
824+
/// if cfg!(target_endian = "big") {
825+
/// assert_eq!(n.to_be(), n)
826+
/// } else {
827+
/// assert_eq!(n.to_be(), n.swap_bytes())
828+
/// }
829+
/// # Some(())
830+
/// # }
831+
/// ```
832+
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
833+
#[must_use = "this returns the result of the operation, \
834+
without modifying the original"]
835+
#[inline(always)]
836+
pub const fn to_be(self) -> Self {
837+
let result = self.get().to_be();
838+
// SAFETY: Shuffling bytes preserves the property int > 0.
839+
unsafe { Self::new_unchecked(result) }
840+
}
841+
842+
/// Converts `self` to little endian from the target's endianness.
843+
///
844+
/// On little endian this is a no-op. On big endian the bytes are
845+
/// swapped.
846+
///
847+
/// # Examples
848+
///
849+
/// Basic usage:
850+
///
851+
/// ```
852+
/// #![feature(nonzero_bitwise)]
853+
/// # use std::num::NonZero;
854+
/// #
855+
/// # fn main() { test().unwrap(); }
856+
/// # fn test() -> Option<()> {
857+
#[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")]
858+
///
859+
/// if cfg!(target_endian = "little") {
860+
/// assert_eq!(n.to_le(), n)
861+
/// } else {
862+
/// assert_eq!(n.to_le(), n.swap_bytes())
863+
/// }
864+
/// # Some(())
865+
/// # }
866+
/// ```
867+
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
868+
#[must_use = "this returns the result of the operation, \
869+
without modifying the original"]
870+
#[inline(always)]
871+
pub const fn to_le(self) -> Self {
872+
let result = self.get().to_le();
873+
// SAFETY: Shuffling bytes preserves the property int > 0.
874+
unsafe { Self::new_unchecked(result) }
875+
}
876+
607877
nonzero_integer_signedness_dependent_methods! {
608878
Primitive = $signedness $Int,
609879
UnsignedPrimitive = $Uint,
@@ -826,22 +1096,54 @@ macro_rules! nonzero_integer {
8261096
nonzero_integer_signedness_dependent_impls!($signedness $Int);
8271097
};
8281098

829-
(Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => {
1099+
(
1100+
Self = $Ty:ident,
1101+
Primitive = unsigned $Int:ident,
1102+
rot = $rot:literal,
1103+
rot_op = $rot_op:literal,
1104+
rot_result = $rot_result:literal,
1105+
swap_op = $swap_op:literal,
1106+
swapped = $swapped:literal,
1107+
reversed = $reversed:literal,
1108+
$(,)?
1109+
) => {
8301110
nonzero_integer! {
8311111
#[stable(feature = "nonzero", since = "1.28.0")]
8321112
Self = $Ty,
8331113
Primitive = unsigned $Int,
8341114
UnsignedPrimitive = $Int,
1115+
rot = $rot,
1116+
rot_op = $rot_op,
1117+
rot_result = $rot_result,
1118+
swap_op = $swap_op,
1119+
swapped = $swapped,
1120+
reversed = $reversed,
8351121
leading_zeros_test = concat!(stringify!($Int), "::MAX"),
8361122
}
8371123
};
8381124

839-
(Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => {
1125+
(
1126+
Self = $Ty:ident,
1127+
Primitive = signed $Int:ident,
1128+
UnsignedPrimitive = $UInt:ident,
1129+
rot = $rot:literal,
1130+
rot_op = $rot_op:literal,
1131+
rot_result = $rot_result:literal,
1132+
swap_op = $swap_op:literal,
1133+
swapped = $swapped:literal,
1134+
reversed = $reversed:literal,
1135+
) => {
8401136
nonzero_integer! {
8411137
#[stable(feature = "signed_nonzero", since = "1.34.0")]
8421138
Self = $Ty,
8431139
Primitive = signed $Int,
844-
$($rest)*
1140+
UnsignedPrimitive = $UInt,
1141+
rot = $rot,
1142+
rot_op = $rot_op,
1143+
rot_result = $rot_result,
1144+
swap_op = $swap_op,
1145+
swapped = $swapped,
1146+
reversed = $reversed,
8451147
leading_zeros_test = concat!("-1", stringify!($Int)),
8461148
}
8471149
};
@@ -1241,6 +1543,7 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
12411543
/// assert_eq!(ten.isqrt(), three);
12421544
/// # Some(())
12431545
/// # }
1546+
/// ```
12441547
#[unstable(feature = "isqrt", issue = "116226")]
12451548
#[rustc_const_unstable(feature = "isqrt", issue = "116226")]
12461549
#[must_use = "this returns the result of the operation, \
@@ -1704,65 +2007,189 @@ macro_rules! sign_dependent_expr {
17042007
nonzero_integer! {
17052008
Self = NonZeroU8,
17062009
Primitive = unsigned u8,
2010+
rot = 2,
2011+
rot_op = "0x82",
2012+
rot_result = "0xa",
2013+
swap_op = "0x12",
2014+
swapped = "0x12",
2015+
reversed = "0x48",
17072016
}
17082017

17092018
nonzero_integer! {
17102019
Self = NonZeroU16,
17112020
Primitive = unsigned u16,
2021+
rot = 4,
2022+
rot_op = "0xa003",
2023+
rot_result = "0x3a",
2024+
swap_op = "0x1234",
2025+
swapped = "0x3412",
2026+
reversed = "0x2c48",
17122027
}
17132028

17142029
nonzero_integer! {
17152030
Self = NonZeroU32,
17162031
Primitive = unsigned u32,
2032+
rot = 8,
2033+
rot_op = "0x10000b3",
2034+
rot_result = "0xb301",
2035+
swap_op = "0x12345678",
2036+
swapped = "0x78563412",
2037+
reversed = "0x1e6a2c48",
17172038
}
17182039

17192040
nonzero_integer! {
17202041
Self = NonZeroU64,
17212042
Primitive = unsigned u64,
2043+
rot = 12,
2044+
rot_op = "0xaa00000000006e1",
2045+
rot_result = "0x6e10aa",
2046+
swap_op = "0x1234567890123456",
2047+
swapped = "0x5634129078563412",
2048+
reversed = "0x6a2c48091e6a2c48",
17222049
}
17232050

17242051
nonzero_integer! {
17252052
Self = NonZeroU128,
17262053
Primitive = unsigned u128,
2054+
rot = 16,
2055+
rot_op = "0x13f40000000000000000000000004f76",
2056+
rot_result = "0x4f7613f4",
2057+
swap_op = "0x12345678901234567890123456789012",
2058+
swapped = "0x12907856341290785634129078563412",
2059+
reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
2060+
}
2061+
2062+
#[cfg(target_pointer_width = "16")]
2063+
nonzero_integer! {
2064+
Self = NonZeroUsize,
2065+
Primitive = unsigned usize,
2066+
rot = 4,
2067+
rot_op = "0xa003",
2068+
rot_result = "0x3a",
2069+
swap_op = "0x1234",
2070+
swapped = "0x3412",
2071+
reversed = "0x2c48",
17272072
}
17282073

2074+
#[cfg(target_pointer_width = "32")]
17292075
nonzero_integer! {
17302076
Self = NonZeroUsize,
17312077
Primitive = unsigned usize,
2078+
rot = 8,
2079+
rot_op = "0x10000b3",
2080+
rot_result = "0xb301",
2081+
swap_op = "0x12345678",
2082+
swapped = "0x78563412",
2083+
reversed = "0x1e6a2c48",
2084+
}
2085+
2086+
#[cfg(target_pointer_width = "64")]
2087+
nonzero_integer! {
2088+
Self = NonZeroUsize,
2089+
Primitive = unsigned usize,
2090+
rot = 12,
2091+
rot_op = "0xaa00000000006e1",
2092+
rot_result = "0x6e10aa",
2093+
swap_op = "0x1234567890123456",
2094+
swapped = "0x5634129078563412",
2095+
reversed = "0x6a2c48091e6a2c48",
17322096
}
17332097

17342098
nonzero_integer! {
17352099
Self = NonZeroI8,
17362100
Primitive = signed i8,
17372101
UnsignedPrimitive = u8,
2102+
rot = 2,
2103+
rot_op = "-0x7e",
2104+
rot_result = "0xa",
2105+
swap_op = "0x12",
2106+
swapped = "0x12",
2107+
reversed = "0x48",
17382108
}
17392109

17402110
nonzero_integer! {
17412111
Self = NonZeroI16,
17422112
Primitive = signed i16,
17432113
UnsignedPrimitive = u16,
2114+
rot = 4,
2115+
rot_op = "-0x5ffd",
2116+
rot_result = "0x3a",
2117+
swap_op = "0x1234",
2118+
swapped = "0x3412",
2119+
reversed = "0x2c48",
17442120
}
17452121

17462122
nonzero_integer! {
17472123
Self = NonZeroI32,
17482124
Primitive = signed i32,
17492125
UnsignedPrimitive = u32,
2126+
rot = 8,
2127+
rot_op = "0x10000b3",
2128+
rot_result = "0xb301",
2129+
swap_op = "0x12345678",
2130+
swapped = "0x78563412",
2131+
reversed = "0x1e6a2c48",
17502132
}
17512133

17522134
nonzero_integer! {
17532135
Self = NonZeroI64,
17542136
Primitive = signed i64,
17552137
UnsignedPrimitive = u64,
2138+
rot = 12,
2139+
rot_op = "0xaa00000000006e1",
2140+
rot_result = "0x6e10aa",
2141+
swap_op = "0x1234567890123456",
2142+
swapped = "0x5634129078563412",
2143+
reversed = "0x6a2c48091e6a2c48",
17562144
}
17572145

17582146
nonzero_integer! {
17592147
Self = NonZeroI128,
17602148
Primitive = signed i128,
17612149
UnsignedPrimitive = u128,
2150+
rot = 16,
2151+
rot_op = "0x13f40000000000000000000000004f76",
2152+
rot_result = "0x4f7613f4",
2153+
swap_op = "0x12345678901234567890123456789012",
2154+
swapped = "0x12907856341290785634129078563412",
2155+
reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
2156+
}
2157+
2158+
#[cfg(target_pointer_width = "16")]
2159+
nonzero_integer! {
2160+
Self = NonZeroIsize,
2161+
Primitive = signed isize,
2162+
UnsignedPrimitive = usize,
2163+
rot = 4,
2164+
rot_op = "-0x5ffd",
2165+
rot_result = "0x3a",
2166+
swap_op = "0x1234",
2167+
swapped = "0x3412",
2168+
reversed = "0x2c48",
2169+
}
2170+
2171+
#[cfg(target_pointer_width = "32")]
2172+
nonzero_integer! {
2173+
Self = NonZeroIsize,
2174+
Primitive = signed isize,
2175+
UnsignedPrimitive = usize,
2176+
rot = 8,
2177+
rot_op = "0x10000b3",
2178+
rot_result = "0xb301",
2179+
swap_op = "0x12345678",
2180+
swapped = "0x78563412",
2181+
reversed = "0x1e6a2c48",
17622182
}
17632183

2184+
#[cfg(target_pointer_width = "64")]
17642185
nonzero_integer! {
17652186
Self = NonZeroIsize,
17662187
Primitive = signed isize,
17672188
UnsignedPrimitive = usize,
2189+
rot = 12,
2190+
rot_op = "0xaa00000000006e1",
2191+
rot_result = "0x6e10aa",
2192+
swap_op = "0x1234567890123456",
2193+
swapped = "0x5634129078563412",
2194+
reversed = "0x6a2c48091e6a2c48",
17682195
}

0 commit comments

Comments
 (0)
Please sign in to comment.