]> git.proxmox.com Git - rustc.git/blob - src/libcore/ops/bit.rs
New upstream version 1.22.1+dfsg1
[rustc.git] / src / libcore / ops / bit.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /// The unary logical negation operator `!`.
12 ///
13 /// # Examples
14 ///
15 /// An implementation of `Not` for `Answer`, which enables the use of `!` to
16 /// invert its value.
17 ///
18 /// ```
19 /// use std::ops::Not;
20 ///
21 /// #[derive(Debug, PartialEq)]
22 /// enum Answer {
23 /// Yes,
24 /// No,
25 /// }
26 ///
27 /// impl Not for Answer {
28 /// type Output = Answer;
29 ///
30 /// fn not(self) -> Answer {
31 /// match self {
32 /// Answer::Yes => Answer::No,
33 /// Answer::No => Answer::Yes
34 /// }
35 /// }
36 /// }
37 ///
38 /// assert_eq!(!Answer::Yes, Answer::No);
39 /// assert_eq!(!Answer::No, Answer::Yes);
40 /// ```
41 #[lang = "not"]
42 #[stable(feature = "rust1", since = "1.0.0")]
43 pub trait Not {
44 /// The resulting type after applying the `!` operator.
45 #[stable(feature = "rust1", since = "1.0.0")]
46 type Output;
47
48 /// Performs the unary `!` operation.
49 #[stable(feature = "rust1", since = "1.0.0")]
50 fn not(self) -> Self::Output;
51 }
52
53 macro_rules! not_impl {
54 ($($t:ty)*) => ($(
55 #[stable(feature = "rust1", since = "1.0.0")]
56 impl Not for $t {
57 type Output = $t;
58
59 #[inline]
60 fn not(self) -> $t { !self }
61 }
62
63 forward_ref_unop! { impl Not, not for $t }
64 )*)
65 }
66
67 not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
68
69 /// The bitwise AND operator `&`.
70 ///
71 /// Note that `RHS` is `Self` by default, but this is not mandatory.
72 ///
73 /// # Examples
74 ///
75 /// An implementation of `BitAnd` for a wrapper around `bool`.
76 ///
77 /// ```
78 /// use std::ops::BitAnd;
79 ///
80 /// #[derive(Debug, PartialEq)]
81 /// struct Scalar(bool);
82 ///
83 /// impl BitAnd for Scalar {
84 /// type Output = Self;
85 ///
86 /// // rhs is the "right-hand side" of the expression `a & b`
87 /// fn bitand(self, rhs: Self) -> Self {
88 /// Scalar(self.0 & rhs.0)
89 /// }
90 /// }
91 ///
92 /// assert_eq!(Scalar(true) & Scalar(true), Scalar(true));
93 /// assert_eq!(Scalar(true) & Scalar(false), Scalar(false));
94 /// assert_eq!(Scalar(false) & Scalar(true), Scalar(false));
95 /// assert_eq!(Scalar(false) & Scalar(false), Scalar(false));
96 /// ```
97 ///
98 /// An implementation of `BitAnd` for a wrapper around `Vec<bool>`.
99 ///
100 /// ```
101 /// use std::ops::BitAnd;
102 ///
103 /// #[derive(Debug, PartialEq)]
104 /// struct BooleanVector(Vec<bool>);
105 ///
106 /// impl BitAnd for BooleanVector {
107 /// type Output = Self;
108 ///
109 /// fn bitand(self, BooleanVector(rhs): Self) -> Self {
110 /// let BooleanVector(lhs) = self;
111 /// assert_eq!(lhs.len(), rhs.len());
112 /// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect())
113 /// }
114 /// }
115 ///
116 /// let bv1 = BooleanVector(vec![true, true, false, false]);
117 /// let bv2 = BooleanVector(vec![true, false, true, false]);
118 /// let expected = BooleanVector(vec![true, false, false, false]);
119 /// assert_eq!(bv1 & bv2, expected);
120 /// ```
121 #[lang = "bitand"]
122 #[stable(feature = "rust1", since = "1.0.0")]
123 #[rustc_on_unimplemented = "no implementation for `{Self} & {RHS}`"]
124 pub trait BitAnd<RHS=Self> {
125 /// The resulting type after applying the `&` operator.
126 #[stable(feature = "rust1", since = "1.0.0")]
127 type Output;
128
129 /// Performs the `&` operation.
130 #[stable(feature = "rust1", since = "1.0.0")]
131 fn bitand(self, rhs: RHS) -> Self::Output;
132 }
133
134 macro_rules! bitand_impl {
135 ($($t:ty)*) => ($(
136 #[stable(feature = "rust1", since = "1.0.0")]
137 impl BitAnd for $t {
138 type Output = $t;
139
140 #[inline]
141 fn bitand(self, rhs: $t) -> $t { self & rhs }
142 }
143
144 forward_ref_binop! { impl BitAnd, bitand for $t, $t }
145 )*)
146 }
147
148 bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
149
150 /// The bitwise OR operator `|`.
151 ///
152 /// Note that `RHS` is `Self` by default, but this is not mandatory.
153 ///
154 /// # Examples
155 ///
156 /// An implementation of `BitOr` for a wrapper around `bool`.
157 ///
158 /// ```
159 /// use std::ops::BitOr;
160 ///
161 /// #[derive(Debug, PartialEq)]
162 /// struct Scalar(bool);
163 ///
164 /// impl BitOr for Scalar {
165 /// type Output = Self;
166 ///
167 /// // rhs is the "right-hand side" of the expression `a | b`
168 /// fn bitor(self, rhs: Self) -> Self {
169 /// Scalar(self.0 | rhs.0)
170 /// }
171 /// }
172 ///
173 /// assert_eq!(Scalar(true) | Scalar(true), Scalar(true));
174 /// assert_eq!(Scalar(true) | Scalar(false), Scalar(true));
175 /// assert_eq!(Scalar(false) | Scalar(true), Scalar(true));
176 /// assert_eq!(Scalar(false) | Scalar(false), Scalar(false));
177 /// ```
178 ///
179 /// An implementation of `BitOr` for a wrapper around `Vec<bool>`.
180 ///
181 /// ```
182 /// use std::ops::BitOr;
183 ///
184 /// #[derive(Debug, PartialEq)]
185 /// struct BooleanVector(Vec<bool>);
186 ///
187 /// impl BitOr for BooleanVector {
188 /// type Output = Self;
189 ///
190 /// fn bitor(self, BooleanVector(rhs): Self) -> Self {
191 /// let BooleanVector(lhs) = self;
192 /// assert_eq!(lhs.len(), rhs.len());
193 /// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x || *y).collect())
194 /// }
195 /// }
196 ///
197 /// let bv1 = BooleanVector(vec![true, true, false, false]);
198 /// let bv2 = BooleanVector(vec![true, false, true, false]);
199 /// let expected = BooleanVector(vec![true, true, true, false]);
200 /// assert_eq!(bv1 | bv2, expected);
201 /// ```
202 #[lang = "bitor"]
203 #[stable(feature = "rust1", since = "1.0.0")]
204 #[rustc_on_unimplemented = "no implementation for `{Self} | {RHS}`"]
205 pub trait BitOr<RHS=Self> {
206 /// The resulting type after applying the `|` operator.
207 #[stable(feature = "rust1", since = "1.0.0")]
208 type Output;
209
210 /// Performs the `|` operation.
211 #[stable(feature = "rust1", since = "1.0.0")]
212 fn bitor(self, rhs: RHS) -> Self::Output;
213 }
214
215 macro_rules! bitor_impl {
216 ($($t:ty)*) => ($(
217 #[stable(feature = "rust1", since = "1.0.0")]
218 impl BitOr for $t {
219 type Output = $t;
220
221 #[inline]
222 fn bitor(self, rhs: $t) -> $t { self | rhs }
223 }
224
225 forward_ref_binop! { impl BitOr, bitor for $t, $t }
226 )*)
227 }
228
229 bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
230
231 /// The bitwise XOR operator `^`.
232 ///
233 /// Note that `RHS` is `Self` by default, but this is not mandatory.
234 ///
235 /// # Examples
236 ///
237 /// An implementation of `BitXor` that lifts `^` to a wrapper around `bool`.
238 ///
239 /// ```
240 /// use std::ops::BitXor;
241 ///
242 /// #[derive(Debug, PartialEq)]
243 /// struct Scalar(bool);
244 ///
245 /// impl BitXor for Scalar {
246 /// type Output = Self;
247 ///
248 /// // rhs is the "right-hand side" of the expression `a ^ b`
249 /// fn bitxor(self, rhs: Self) -> Self {
250 /// Scalar(self.0 ^ rhs.0)
251 /// }
252 /// }
253 ///
254 /// assert_eq!(Scalar(true) ^ Scalar(true), Scalar(false));
255 /// assert_eq!(Scalar(true) ^ Scalar(false), Scalar(true));
256 /// assert_eq!(Scalar(false) ^ Scalar(true), Scalar(true));
257 /// assert_eq!(Scalar(false) ^ Scalar(false), Scalar(false));
258 /// ```
259 ///
260 /// An implementation of `BitXor` trait for a wrapper around `Vec<bool>`.
261 ///
262 /// ```
263 /// use std::ops::BitXor;
264 ///
265 /// #[derive(Debug, PartialEq)]
266 /// struct BooleanVector(Vec<bool>);
267 ///
268 /// impl BitXor for BooleanVector {
269 /// type Output = Self;
270 ///
271 /// fn bitxor(self, BooleanVector(rhs): Self) -> Self {
272 /// let BooleanVector(lhs) = self;
273 /// assert_eq!(lhs.len(), rhs.len());
274 /// BooleanVector(lhs.iter()
275 /// .zip(rhs.iter())
276 /// .map(|(x, y)| (*x || *y) && !(*x && *y))
277 /// .collect())
278 /// }
279 /// }
280 ///
281 /// let bv1 = BooleanVector(vec![true, true, false, false]);
282 /// let bv2 = BooleanVector(vec![true, false, true, false]);
283 /// let expected = BooleanVector(vec![false, true, true, false]);
284 /// assert_eq!(bv1 ^ bv2, expected);
285 /// ```
286 #[lang = "bitxor"]
287 #[stable(feature = "rust1", since = "1.0.0")]
288 #[rustc_on_unimplemented = "no implementation for `{Self} ^ {RHS}`"]
289 pub trait BitXor<RHS=Self> {
290 /// The resulting type after applying the `^` operator.
291 #[stable(feature = "rust1", since = "1.0.0")]
292 type Output;
293
294 /// Performs the `^` operation.
295 #[stable(feature = "rust1", since = "1.0.0")]
296 fn bitxor(self, rhs: RHS) -> Self::Output;
297 }
298
299 macro_rules! bitxor_impl {
300 ($($t:ty)*) => ($(
301 #[stable(feature = "rust1", since = "1.0.0")]
302 impl BitXor for $t {
303 type Output = $t;
304
305 #[inline]
306 fn bitxor(self, other: $t) -> $t { self ^ other }
307 }
308
309 forward_ref_binop! { impl BitXor, bitxor for $t, $t }
310 )*)
311 }
312
313 bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
314
315 /// The left shift operator `<<`.
316 ///
317 /// # Examples
318 ///
319 /// An implementation of `Shl` that lifts the `<<` operation on integers to a
320 /// wrapper around `usize`.
321 ///
322 /// ```
323 /// use std::ops::Shl;
324 ///
325 /// #[derive(PartialEq, Debug)]
326 /// struct Scalar(usize);
327 ///
328 /// impl Shl<Scalar> for Scalar {
329 /// type Output = Self;
330 ///
331 /// fn shl(self, Scalar(rhs): Self) -> Scalar {
332 /// let Scalar(lhs) = self;
333 /// Scalar(lhs << rhs)
334 /// }
335 /// }
336 ///
337 /// assert_eq!(Scalar(4) << Scalar(2), Scalar(16));
338 /// ```
339 ///
340 /// An implementation of `Shl` that spins a vector leftward by a given amount.
341 ///
342 /// ```
343 /// use std::ops::Shl;
344 ///
345 /// #[derive(PartialEq, Debug)]
346 /// struct SpinVector<T: Clone> {
347 /// vec: Vec<T>,
348 /// }
349 ///
350 /// impl<T: Clone> Shl<usize> for SpinVector<T> {
351 /// type Output = Self;
352 ///
353 /// fn shl(self, rhs: usize) -> SpinVector<T> {
354 /// // Rotate the vector by `rhs` places.
355 /// let (a, b) = self.vec.split_at(rhs);
356 /// let mut spun_vector: Vec<T> = vec![];
357 /// spun_vector.extend_from_slice(b);
358 /// spun_vector.extend_from_slice(a);
359 /// SpinVector { vec: spun_vector }
360 /// }
361 /// }
362 ///
363 /// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2,
364 /// SpinVector { vec: vec![2, 3, 4, 0, 1] });
365 /// ```
366 #[lang = "shl"]
367 #[stable(feature = "rust1", since = "1.0.0")]
368 #[rustc_on_unimplemented = "no implementation for `{Self} << {RHS}`"]
369 pub trait Shl<RHS> {
370 /// The resulting type after applying the `<<` operator.
371 #[stable(feature = "rust1", since = "1.0.0")]
372 type Output;
373
374 /// Performs the `<<` operation.
375 #[stable(feature = "rust1", since = "1.0.0")]
376 fn shl(self, rhs: RHS) -> Self::Output;
377 }
378
379 macro_rules! shl_impl {
380 ($t:ty, $f:ty) => (
381 #[stable(feature = "rust1", since = "1.0.0")]
382 impl Shl<$f> for $t {
383 type Output = $t;
384
385 #[inline]
386 #[rustc_inherit_overflow_checks]
387 fn shl(self, other: $f) -> $t {
388 self << other
389 }
390 }
391
392 forward_ref_binop! { impl Shl, shl for $t, $f }
393 )
394 }
395
396 macro_rules! shl_impl_all {
397 ($($t:ty)*) => ($(
398 shl_impl! { $t, u8 }
399 shl_impl! { $t, u16 }
400 shl_impl! { $t, u32 }
401 shl_impl! { $t, u64 }
402 shl_impl! { $t, u128 }
403 shl_impl! { $t, usize }
404
405 shl_impl! { $t, i8 }
406 shl_impl! { $t, i16 }
407 shl_impl! { $t, i32 }
408 shl_impl! { $t, i64 }
409 shl_impl! { $t, i128 }
410 shl_impl! { $t, isize }
411 )*)
412 }
413
414 shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
415
416 /// The right shift operator `>>`.
417 ///
418 /// # Examples
419 ///
420 /// An implementation of `Shr` that lifts the `>>` operation on integers to a
421 /// wrapper around `usize`.
422 ///
423 /// ```
424 /// use std::ops::Shr;
425 ///
426 /// #[derive(PartialEq, Debug)]
427 /// struct Scalar(usize);
428 ///
429 /// impl Shr<Scalar> for Scalar {
430 /// type Output = Self;
431 ///
432 /// fn shr(self, Scalar(rhs): Self) -> Scalar {
433 /// let Scalar(lhs) = self;
434 /// Scalar(lhs >> rhs)
435 /// }
436 /// }
437 ///
438 /// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4));
439 /// ```
440 ///
441 /// An implementation of `Shr` that spins a vector rightward by a given amount.
442 ///
443 /// ```
444 /// use std::ops::Shr;
445 ///
446 /// #[derive(PartialEq, Debug)]
447 /// struct SpinVector<T: Clone> {
448 /// vec: Vec<T>,
449 /// }
450 ///
451 /// impl<T: Clone> Shr<usize> for SpinVector<T> {
452 /// type Output = Self;
453 ///
454 /// fn shr(self, rhs: usize) -> SpinVector<T> {
455 /// // Rotate the vector by `rhs` places.
456 /// let (a, b) = self.vec.split_at(self.vec.len() - rhs);
457 /// let mut spun_vector: Vec<T> = vec![];
458 /// spun_vector.extend_from_slice(b);
459 /// spun_vector.extend_from_slice(a);
460 /// SpinVector { vec: spun_vector }
461 /// }
462 /// }
463 ///
464 /// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2,
465 /// SpinVector { vec: vec![3, 4, 0, 1, 2] });
466 /// ```
467 #[lang = "shr"]
468 #[stable(feature = "rust1", since = "1.0.0")]
469 #[rustc_on_unimplemented = "no implementation for `{Self} >> {RHS}`"]
470 pub trait Shr<RHS> {
471 /// The resulting type after applying the `>>` operator.
472 #[stable(feature = "rust1", since = "1.0.0")]
473 type Output;
474
475 /// Performs the `>>` operation.
476 #[stable(feature = "rust1", since = "1.0.0")]
477 fn shr(self, rhs: RHS) -> Self::Output;
478 }
479
480 macro_rules! shr_impl {
481 ($t:ty, $f:ty) => (
482 #[stable(feature = "rust1", since = "1.0.0")]
483 impl Shr<$f> for $t {
484 type Output = $t;
485
486 #[inline]
487 #[rustc_inherit_overflow_checks]
488 fn shr(self, other: $f) -> $t {
489 self >> other
490 }
491 }
492
493 forward_ref_binop! { impl Shr, shr for $t, $f }
494 )
495 }
496
497 macro_rules! shr_impl_all {
498 ($($t:ty)*) => ($(
499 shr_impl! { $t, u8 }
500 shr_impl! { $t, u16 }
501 shr_impl! { $t, u32 }
502 shr_impl! { $t, u64 }
503 shr_impl! { $t, u128 }
504 shr_impl! { $t, usize }
505
506 shr_impl! { $t, i8 }
507 shr_impl! { $t, i16 }
508 shr_impl! { $t, i32 }
509 shr_impl! { $t, i64 }
510 shr_impl! { $t, i128 }
511 shr_impl! { $t, isize }
512 )*)
513 }
514
515 shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
516
517 /// The bitwise AND assignment operator `&=`.
518 ///
519 /// # Examples
520 ///
521 /// An implementation of `BitAndAssign` that lifts the `&=` operator to a
522 /// wrapper around `bool`.
523 ///
524 /// ```
525 /// use std::ops::BitAndAssign;
526 ///
527 /// #[derive(Debug, PartialEq)]
528 /// struct Scalar(bool);
529 ///
530 /// impl BitAndAssign for Scalar {
531 /// // rhs is the "right-hand side" of the expression `a &= b`
532 /// fn bitand_assign(&mut self, rhs: Self) {
533 /// *self = Scalar(self.0 & rhs.0)
534 /// }
535 /// }
536 ///
537 /// let mut scalar = Scalar(true);
538 /// scalar &= Scalar(true);
539 /// assert_eq!(scalar, Scalar(true));
540 ///
541 /// let mut scalar = Scalar(true);
542 /// scalar &= Scalar(false);
543 /// assert_eq!(scalar, Scalar(false));
544 ///
545 /// let mut scalar = Scalar(false);
546 /// scalar &= Scalar(true);
547 /// assert_eq!(scalar, Scalar(false));
548 ///
549 /// let mut scalar = Scalar(false);
550 /// scalar &= Scalar(false);
551 /// assert_eq!(scalar, Scalar(false));
552 /// ```
553 ///
554 /// Here, the `BitAndAssign` trait is implemented for a wrapper around
555 /// `Vec<bool>`.
556 ///
557 /// ```
558 /// use std::ops::BitAndAssign;
559 ///
560 /// #[derive(Debug, PartialEq)]
561 /// struct BooleanVector(Vec<bool>);
562 ///
563 /// impl BitAndAssign for BooleanVector {
564 /// // `rhs` is the "right-hand side" of the expression `a &= b`.
565 /// fn bitand_assign(&mut self, rhs: Self) {
566 /// assert_eq!(self.0.len(), rhs.0.len());
567 /// *self = BooleanVector(self.0
568 /// .iter()
569 /// .zip(rhs.0.iter())
570 /// .map(|(x, y)| *x && *y)
571 /// .collect());
572 /// }
573 /// }
574 ///
575 /// let mut bv = BooleanVector(vec![true, true, false, false]);
576 /// bv &= BooleanVector(vec![true, false, true, false]);
577 /// let expected = BooleanVector(vec![true, false, false, false]);
578 /// assert_eq!(bv, expected);
579 /// ```
580 #[lang = "bitand_assign"]
581 #[stable(feature = "op_assign_traits", since = "1.8.0")]
582 #[rustc_on_unimplemented = "no implementation for `{Self} &= {Rhs}`"]
583 pub trait BitAndAssign<Rhs=Self> {
584 /// Performs the `&=` operation.
585 #[stable(feature = "op_assign_traits", since = "1.8.0")]
586 fn bitand_assign(&mut self, rhs: Rhs);
587 }
588
589 macro_rules! bitand_assign_impl {
590 ($($t:ty)+) => ($(
591 #[stable(feature = "op_assign_traits", since = "1.8.0")]
592 impl BitAndAssign for $t {
593 #[inline]
594 fn bitand_assign(&mut self, other: $t) { *self &= other }
595 }
596
597 forward_ref_op_assign! { impl BitAndAssign, bitand_assign for $t, $t }
598 )+)
599 }
600
601 bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
602
603 /// The bitwise OR assignment operator `|=`.
604 ///
605 /// # Examples
606 ///
607 /// ```
608 /// use std::ops::BitOrAssign;
609 ///
610 /// #[derive(Debug, PartialEq)]
611 /// struct PersonalPreferences {
612 /// likes_cats: bool,
613 /// likes_dogs: bool,
614 /// }
615 ///
616 /// impl BitOrAssign for PersonalPreferences {
617 /// fn bitor_assign(&mut self, rhs: Self) {
618 /// self.likes_cats |= rhs.likes_cats;
619 /// self.likes_dogs |= rhs.likes_dogs;
620 /// }
621 /// }
622 ///
623 /// let mut prefs = PersonalPreferences { likes_cats: true, likes_dogs: false };
624 /// prefs |= PersonalPreferences { likes_cats: false, likes_dogs: true };
625 /// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true });
626 /// ```
627 #[lang = "bitor_assign"]
628 #[stable(feature = "op_assign_traits", since = "1.8.0")]
629 #[rustc_on_unimplemented = "no implementation for `{Self} |= {Rhs}`"]
630 pub trait BitOrAssign<Rhs=Self> {
631 /// Performs the `|=` operation.
632 #[stable(feature = "op_assign_traits", since = "1.8.0")]
633 fn bitor_assign(&mut self, rhs: Rhs);
634 }
635
636 macro_rules! bitor_assign_impl {
637 ($($t:ty)+) => ($(
638 #[stable(feature = "op_assign_traits", since = "1.8.0")]
639 impl BitOrAssign for $t {
640 #[inline]
641 fn bitor_assign(&mut self, other: $t) { *self |= other }
642 }
643
644 forward_ref_op_assign! { impl BitOrAssign, bitor_assign for $t, $t }
645 )+)
646 }
647
648 bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
649
650 /// The bitwise XOR assignment operator `^=`.
651 ///
652 /// # Examples
653 ///
654 /// ```
655 /// use std::ops::BitXorAssign;
656 ///
657 /// #[derive(Debug, PartialEq)]
658 /// struct Personality {
659 /// has_soul: bool,
660 /// likes_knitting: bool,
661 /// }
662 ///
663 /// impl BitXorAssign for Personality {
664 /// fn bitxor_assign(&mut self, rhs: Self) {
665 /// self.has_soul ^= rhs.has_soul;
666 /// self.likes_knitting ^= rhs.likes_knitting;
667 /// }
668 /// }
669 ///
670 /// let mut personality = Personality { has_soul: false, likes_knitting: true };
671 /// personality ^= Personality { has_soul: true, likes_knitting: true };
672 /// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false});
673 /// ```
674 #[lang = "bitxor_assign"]
675 #[stable(feature = "op_assign_traits", since = "1.8.0")]
676 #[rustc_on_unimplemented = "no implementation for `{Self} ^= {Rhs}`"]
677 pub trait BitXorAssign<Rhs=Self> {
678 /// Performs the `^=` operation.
679 #[stable(feature = "op_assign_traits", since = "1.8.0")]
680 fn bitxor_assign(&mut self, rhs: Rhs);
681 }
682
683 macro_rules! bitxor_assign_impl {
684 ($($t:ty)+) => ($(
685 #[stable(feature = "op_assign_traits", since = "1.8.0")]
686 impl BitXorAssign for $t {
687 #[inline]
688 fn bitxor_assign(&mut self, other: $t) { *self ^= other }
689 }
690
691 forward_ref_op_assign! { impl BitXorAssign, bitxor_assign for $t, $t }
692 )+)
693 }
694
695 bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
696
697 /// The left shift assignment operator `<<=`.
698 ///
699 /// # Examples
700 ///
701 /// An implementation of `ShlAssign` for a wrapper around `usize`.
702 ///
703 /// ```
704 /// use std::ops::ShlAssign;
705 ///
706 /// #[derive(Debug, PartialEq)]
707 /// struct Scalar(usize);
708 ///
709 /// impl ShlAssign<usize> for Scalar {
710 /// fn shl_assign(&mut self, rhs: usize) {
711 /// self.0 <<= rhs;
712 /// }
713 /// }
714 ///
715 /// let mut scalar = Scalar(4);
716 /// scalar <<= 2;
717 /// assert_eq!(scalar, Scalar(16));
718 /// ```
719 #[lang = "shl_assign"]
720 #[stable(feature = "op_assign_traits", since = "1.8.0")]
721 #[rustc_on_unimplemented = "no implementation for `{Self} <<= {Rhs}`"]
722 pub trait ShlAssign<Rhs> {
723 /// Performs the `<<=` operation.
724 #[stable(feature = "op_assign_traits", since = "1.8.0")]
725 fn shl_assign(&mut self, rhs: Rhs);
726 }
727
728 macro_rules! shl_assign_impl {
729 ($t:ty, $f:ty) => (
730 #[stable(feature = "op_assign_traits", since = "1.8.0")]
731 impl ShlAssign<$f> for $t {
732 #[inline]
733 #[rustc_inherit_overflow_checks]
734 fn shl_assign(&mut self, other: $f) {
735 *self <<= other
736 }
737 }
738
739 forward_ref_op_assign! { impl ShlAssign, shl_assign for $t, $f }
740 )
741 }
742
743 macro_rules! shl_assign_impl_all {
744 ($($t:ty)*) => ($(
745 shl_assign_impl! { $t, u8 }
746 shl_assign_impl! { $t, u16 }
747 shl_assign_impl! { $t, u32 }
748 shl_assign_impl! { $t, u64 }
749 shl_assign_impl! { $t, u128 }
750 shl_assign_impl! { $t, usize }
751
752 shl_assign_impl! { $t, i8 }
753 shl_assign_impl! { $t, i16 }
754 shl_assign_impl! { $t, i32 }
755 shl_assign_impl! { $t, i64 }
756 shl_assign_impl! { $t, i128 }
757 shl_assign_impl! { $t, isize }
758 )*)
759 }
760
761 shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
762
763 /// The right shift assignment operator `>>=`.
764 ///
765 /// # Examples
766 ///
767 /// An implementation of `ShrAssign` for a wrapper around `usize`.
768 ///
769 /// ```
770 /// use std::ops::ShrAssign;
771 ///
772 /// #[derive(Debug, PartialEq)]
773 /// struct Scalar(usize);
774 ///
775 /// impl ShrAssign<usize> for Scalar {
776 /// fn shr_assign(&mut self, rhs: usize) {
777 /// self.0 >>= rhs;
778 /// }
779 /// }
780 ///
781 /// let mut scalar = Scalar(16);
782 /// scalar >>= 2;
783 /// assert_eq!(scalar, Scalar(4));
784 /// ```
785 #[lang = "shr_assign"]
786 #[stable(feature = "op_assign_traits", since = "1.8.0")]
787 #[rustc_on_unimplemented = "no implementation for `{Self} >>= {Rhs}`"]
788 pub trait ShrAssign<Rhs=Self> {
789 /// Performs the `>>=` operation.
790 #[stable(feature = "op_assign_traits", since = "1.8.0")]
791 fn shr_assign(&mut self, rhs: Rhs);
792 }
793
794 macro_rules! shr_assign_impl {
795 ($t:ty, $f:ty) => (
796 #[stable(feature = "op_assign_traits", since = "1.8.0")]
797 impl ShrAssign<$f> for $t {
798 #[inline]
799 #[rustc_inherit_overflow_checks]
800 fn shr_assign(&mut self, other: $f) {
801 *self >>= other
802 }
803 }
804
805 forward_ref_op_assign! { impl ShrAssign, shr_assign for $t, $f }
806 )
807 }
808
809 macro_rules! shr_assign_impl_all {
810 ($($t:ty)*) => ($(
811 shr_assign_impl! { $t, u8 }
812 shr_assign_impl! { $t, u16 }
813 shr_assign_impl! { $t, u32 }
814 shr_assign_impl! { $t, u64 }
815 shr_assign_impl! { $t, u128 }
816 shr_assign_impl! { $t, usize }
817
818 shr_assign_impl! { $t, i8 }
819 shr_assign_impl! { $t, i16 }
820 shr_assign_impl! { $t, i32 }
821 shr_assign_impl! { $t, i64 }
822 shr_assign_impl! { $t, i128 }
823 shr_assign_impl! { $t, isize }
824 )*)
825 }
826
827 shr_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }