use Assign;
use ops::{AddFrom, BitAndFrom, BitOrFrom, BitXorFrom, DivFrom, DivRounding,
DivRoundingAssign, DivRoundingFrom, MulFrom, NegAssign, NotAssign,
Pow, PowAssign, PowFrom, RemFrom, RemRounding, RemRoundingAssign,
RemRoundingFrom, ShlFrom, ShrFrom, SubFrom};
use std::borrow::Cow;
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Rem, Shl, Shr, Sub};
macro_rules! assign_from {
{ $T:ty; $op:ident; $Imp:ident $method:ident } => {
impl $Imp for $T {
#[inline]
fn $method(&mut self, lhs: $T) {
*self = lhs.$op(*self);
}
}
}
}
macro_rules! int_ops {
{ $($T:ty)* } => {
$(
impl Assign for $T {
#[inline]
fn assign(&mut self, src: $T) {
*self = src;
}
}
impl NotAssign for $T {
#[inline]
fn not_assign(&mut self) {
*self = !*self;
}
}
impl Pow<u32> for $T {
type Output = $T;
#[inline]
fn pow(self, rhs: u32) -> $T {
self.pow(rhs)
}
}
impl PowAssign<u32> for $T {
#[inline]
fn pow_assign(&mut self, rhs: u32) {
*self = self.pow(rhs);
}
}
assign_from! { $T; add; AddFrom add_from }
assign_from! { $T; sub; SubFrom sub_from }
assign_from! { $T; mul; MulFrom mul_from }
assign_from! { $T; div; DivFrom div_from }
assign_from! { $T; rem; RemFrom rem_from }
assign_from! { $T; bitand; BitAndFrom bitand_from }
assign_from! { $T; bitor; BitOrFrom bitor_from }
assign_from! { $T; bitxor; BitXorFrom bitxor_from }
assign_from! { $T; shl; ShlFrom shl_from }
assign_from! { $T; shr; ShrFrom shr_from }
)*
}
}
macro_rules! int_neg {
{ $($T:ty)* } => {
$(
impl NegAssign for $T {
#[inline]
fn neg_assign(&mut self) {
*self = -*self;
}
}
)*
}
}
macro_rules! float_ops {
{ $($T:ty)* } => {
$(
impl Assign for $T {
#[inline]
fn assign(&mut self, src: $T) {
*self = src;
}
}
impl Pow<i32> for $T {
type Output = $T;
#[inline]
fn pow(self, rhs: i32) -> $T {
self.powi(rhs)
}
}
impl PowAssign<i32> for $T {
#[inline]
fn pow_assign(&mut self, rhs: i32) {
*self = self.powi(rhs);
}
}
impl Pow<$T> for $T {
type Output = $T;
#[inline]
fn pow(self, rhs: $T) -> $T {
self.powf(rhs)
}
}
impl PowAssign<$T> for $T {
#[inline]
fn pow_assign(&mut self, rhs: $T) {
*self = self.powf(rhs);
}
}
assign_from!{ $T; add; AddFrom add_from }
assign_from!{ $T; sub; SubFrom sub_from }
assign_from!{ $T; mul; MulFrom mul_from }
assign_from!{ $T; div; DivFrom div_from }
assign_from!{ $T; pow; PowFrom pow_from }
)*
}
}
macro_rules! div_signed {
{ $($T:ty)* } => {
$(
impl DivRounding for $T {
type Output = $T;
#[inline]
fn div_trunc(self, rhs: $T) -> $T {
self / rhs
}
#[inline]
fn div_ceil(self, rhs: $T) -> $T {
let (q, r) = (self / rhs, self % rhs);
let change = if rhs > 0 { r > 0 } else { r < 0 };
if change {
q + 1
} else {
q
}
}
#[inline]
fn div_floor(self, rhs: $T) -> $T {
let (q, r) = (self / rhs, self % rhs);
let change = if rhs > 0 { r < 0 } else { r > 0 };
if change {
q - 1
} else {
q
}
}
#[inline]
fn div_euc(self, rhs: $T) -> $T {
let (q, r) = (self / rhs, self % rhs);
if r < 0 {
if rhs < 0 {
q + 1
} else {
q - 1
}
} else {
q
}
}
}
impl RemRounding for $T {
type Output = $T;
#[inline]
fn rem_trunc(self, rhs: $T) -> $T {
self % rhs
}
#[inline]
fn rem_ceil(self, rhs: $T) -> $T {
let r = self % rhs;
let change = if rhs > 0 { r > 0 } else { r < 0 };
if change {
r - rhs
} else {
r
}
}
#[inline]
fn rem_floor(self, rhs: $T) -> $T {
let r = self % rhs;
let change = if rhs > 0 { r < 0 } else { r > 0 };
if change {
r + rhs
} else {
r
}
}
#[inline]
fn rem_euc(self, rhs: $T) -> $T {
let r = self % rhs;
if r < 0 {
if rhs < 0 {
r - rhs
} else {
r + rhs
}
} else {
r
}
}
}
impl DivRoundingAssign for $T {
#[inline]
fn div_trunc_assign(&mut self, rhs: $T) {
*self = self.div_trunc(rhs);
}
#[inline]
fn div_ceil_assign(&mut self, rhs: $T) {
*self = self.div_ceil(rhs);
}
#[inline]
fn div_floor_assign(&mut self, rhs: $T) {
*self = self.div_floor(rhs);
}
#[inline]
fn div_euc_assign(&mut self, rhs: $T) {
*self = self.div_euc(rhs);
}
}
impl DivRoundingFrom for $T {
#[inline]
fn div_trunc_from(&mut self, lhs: $T) {
*self = lhs.div_trunc(*self);
}
#[inline]
fn div_ceil_from(&mut self, lhs: $T) {
*self = lhs.div_ceil(*self);
}
#[inline]
fn div_floor_from(&mut self, lhs: $T) {
*self = lhs.div_floor(*self);
}
#[inline]
fn div_euc_from(&mut self, lhs: $T) {
*self = lhs.div_euc(*self);
}
}
impl RemRoundingAssign for $T {
#[inline]
fn rem_trunc_assign(&mut self, rhs: $T) {
*self = self.rem_trunc(rhs);
}
#[inline]
fn rem_ceil_assign(&mut self, rhs: $T) {
*self = self.rem_ceil(rhs);
}
#[inline]
fn rem_floor_assign(&mut self, rhs: $T) {
*self = self.rem_floor(rhs);
}
#[inline]
fn rem_euc_assign(&mut self, rhs: $T) {
*self = self.rem_euc(rhs);
}
}
impl RemRoundingFrom for $T {
#[inline]
fn rem_trunc_from(&mut self, lhs: $T) {
*self = lhs.rem_trunc(*self);
}
#[inline]
fn rem_ceil_from(&mut self, lhs: $T) {
*self = lhs.rem_ceil(*self);
}
#[inline]
fn rem_floor_from(&mut self, lhs: $T) {
*self = lhs.rem_floor(*self);
}
#[inline]
fn rem_euc_from(&mut self, lhs: $T) {
*self = lhs.rem_euc(*self);
}
}
)*
}
}
int_ops!{ i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
int_neg!{ i8 i16 i32 i64 isize }
assign_from! { u32; pow; PowFrom pow_from }
float_ops!{ f32 f64 }
div_signed!{ i8 i16 i32 i64 isize }
impl<'a> AddFrom<&'a str> for String {
#[inline]
fn add_from(&mut self, lhs: &str) {
self.insert_str(0, lhs);
}
}
impl<'a> AddFrom<&'a str> for Cow<'a, str> {
fn add_from(&mut self, lhs: &'a str) {
if lhs.is_empty() {
} else if self.is_empty() {
*self = Cow::Borrowed(lhs)
} else {
match *self {
Cow::Borrowed(rhs) => {
let mut s = String::with_capacity(lhs.len() + rhs.len());
s.push_str(lhs);
s.push_str(rhs);
*self = Cow::Owned(s);
}
Cow::Owned(ref mut s) => {
s.insert_str(0, lhs);
}
}
}
}
}
impl<'a> AddFrom<Cow<'a, str>> for Cow<'a, str> {
fn add_from(&mut self, lhs: Cow<'a, str>) {
if lhs.is_empty() {
} else if self.is_empty() {
*self = lhs;
} else {
match *self {
Cow::Borrowed(rhs) => {
let mut s = String::with_capacity(lhs.len() + rhs.len());
s.push_str(&lhs);
s.push_str(rhs);
*self = Cow::Owned(s);
}
Cow::Owned(ref mut s) => {
s.insert_str(0, &lhs);
}
}
}
}
}