library;
use ::primitives::*;
use ::registers::flags;
use ::flags::{disable_panic_on_overflow, panic_on_overflow_enabled, set_flags};
const MAX_U32_U64: u64 = __transmute::<u32, u64>(u32::max());
const MAX_U16_U64: u64 = __transmute::<u16, u64>(u16::max());
/// Trait for the addition of two values.
pub trait Add {
/// Add two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value to add to self.
///
/// # Returns
///
/// * [Self] - The result of the two values added.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Add for MyStruct {
/// fn add(self, other: Self) -> Self {
/// let val = self.val + other.val;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 1 };
/// let struct2 = MyStruct { val: 2 };
/// let result_struct = struct1 + struct2;
/// assert(result_struct.val == 3);
/// }
/// ```
fn add(self, other: Self) -> Self;
}
impl Add for u256 {
fn add(self, other: Self) -> Self {
__add(self, other)
}
}
impl Add for u64 {
fn add(self, other: Self) -> Self {
__add(self, other)
}
}
// Emulate overflowing arithmetic for non-64-bit integer types
impl Add for u32 {
fn add(self, other: Self) -> Self {
let res_u64 = __add(
__transmute::<Self, u64>(self),
__transmute::<Self, u64>(other),
);
if __gt(res_u64, MAX_U32_U64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__transmute::<u64, Self>(__mod(res_u64, __add(MAX_U32_U64, 1)))
}
} else {
__transmute::<u64, Self>(res_u64)
}
}
}
impl Add for u16 {
fn add(self, other: Self) -> Self {
let res_u64 = __add(
__transmute::<Self, u64>(self),
__transmute::<Self, u64>(other),
);
if __gt(res_u64, MAX_U16_U64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__transmute::<u64, Self>(__mod(res_u64, __add(MAX_U16_U64, 1)))
}
} else {
__transmute::<u64, Self>(res_u64)
}
}
}
impl Add for u8 {
fn add(self, other: Self) -> Self {
let res_u64 = __add(u8_as_u64(self), u8_as_u64(other));
let max_u8_u64 = u8_as_u64(Self::max());
if __gt(res_u64, max_u8_u64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
u64_as_u8(__mod(res_u64, __add(max_u8_u64, 1)))
}
} else {
u64_as_u8(res_u64)
}
}
}
/// Trait for the subtraction of two values.
pub trait Subtract {
/// Subtract two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value to subtract from self.
///
/// # Returns
///
/// * [Self] - The result of the two values subtracted.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Subtract for MyStruct {
/// fn subtract(self, other: Self) -> Self {
/// let val = self.val - other.val;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 3 };
/// let struct2 = MyStruct { val: 1 };
/// let result_struct = struct1 - struct2;
/// assert(result_struct.val == 2);
/// }
/// ```
fn subtract(self, other: Self) -> Self;
}
impl Subtract for u256 {
fn subtract(self, other: Self) -> Self {
__sub(self, other)
}
}
impl Subtract for u64 {
fn subtract(self, other: Self) -> Self {
__sub(self, other)
}
}
impl Subtract for u32 {
fn subtract(self, other: Self) -> Self {
let res_u64 = __sub(
__transmute::<Self, u64>(self),
__transmute::<Self, u64>(other),
);
if __gt(res_u64, MAX_U32_U64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__transmute::<u64, Self>(__mod(res_u64, __add(MAX_U32_U64, 1)))
}
} else {
__transmute::<u64, Self>(res_u64)
}
}
}
impl Subtract for u16 {
fn subtract(self, other: Self) -> Self {
let res_u64 = __sub(
__transmute::<Self, u64>(self),
__transmute::<Self, u64>(other),
);
if __gt(res_u64, MAX_U16_U64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__transmute::<u64, Self>(__mod(res_u64, __add(MAX_U16_U64, 1)))
}
} else {
__transmute::<u64, Self>(res_u64)
}
}
}
impl Subtract for u8 {
fn subtract(self, other: Self) -> Self {
let res_u64 = __sub(u8_as_u64(self), u8_as_u64(other));
let max_u8_u64 = u8_as_u64(Self::max());
if __gt(res_u64, max_u8_u64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
u64_as_u8(__mod(res_u64, __add(max_u8_u64, 1)))
}
} else {
u64_as_u8(res_u64)
}
}
}
/// Trait for the multiplication of two values.
pub trait Multiply {
/// Multiply two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value to multiply with self.
///
/// # Returns
///
/// * [Self] - The result of the two values multiplied.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Multiply for MyStruct {
/// fn multiply(self, other: Self) -> Self {
/// let val = self.val * other.val;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 3 };
/// let struct2 = MyStruct { val: 2 };
/// let result_struct = struct1 * struct2;
/// assert(result_struct.val == 6);
/// }
/// ```
fn multiply(self, other: Self) -> Self;
}
impl Multiply for u256 {
fn multiply(self, other: Self) -> Self {
__mul(self, other)
}
}
impl Multiply for u64 {
fn multiply(self, other: Self) -> Self {
__mul(self, other)
}
}
// Emulate overflowing arithmetic for non-64-bit integer types
impl Multiply for u32 {
fn multiply(self, other: Self) -> Self {
let res_u64 = __mul(
__transmute::<Self, u64>(self),
__transmute::<Self, u64>(other),
);
if __gt(res_u64, MAX_U32_U64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__transmute::<u64, Self>(__mod(res_u64, __add(MAX_U32_U64, 1)))
}
} else {
__transmute::<u64, Self>(res_u64)
}
}
}
impl Multiply for u16 {
fn multiply(self, other: Self) -> Self {
let res_u64 = __mul(
__transmute::<Self, u64>(self),
__transmute::<Self, u64>(other),
);
if __gt(res_u64, MAX_U16_U64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
__transmute::<u64, Self>(__mod(res_u64, __add(MAX_U16_U64, 1)))
}
} else {
__transmute::<u64, Self>(res_u64)
}
}
}
impl Multiply for u8 {
fn multiply(self, other: Self) -> Self {
let res_u64 = __mul(u8_as_u64(self), u8_as_u64(other));
let max_u8_u64 = u8_as_u64(Self::max());
if __gt(res_u64, max_u8_u64) {
if panic_on_overflow_enabled() {
__revert(0)
} else {
// overflow enabled
// res % (Self::max() + 1)
u64_as_u8(__mod(res_u64, __add(max_u8_u64, 1)))
}
} else {
u64_as_u8(res_u64)
}
}
}
/// Trait for the division of two values.
pub trait Divide {
/// Divide two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value to divide with self.
///
/// # Returns
///
/// * [Self] - The result of the two values divided.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Divide for MyStruct {
/// fn divide(self, other: Self) -> Self {
/// let val = self.val / other.val;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 2 };
/// let result_struct = struct1 / struct2;
/// assert(result_struct.val == 5);
/// }
/// ```
fn divide(self, other: Self) -> Self;
}
impl Divide for u256 {
fn divide(self, other: Self) -> Self {
__div(self, other)
}
}
impl Divide for u64 {
fn divide(self, other: Self) -> Self {
__div(self, other)
}
}
// division for unsigned integers cannot overflow,
// but if signed integers are ever introduced,
// overflow needs to be handled, since
// Self::max() / -1 overflows
impl Divide for u32 {
fn divide(self, other: Self) -> Self {
__div(self, other)
}
}
impl Divide for u16 {
fn divide(self, other: Self) -> Self {
__div(self, other)
}
}
impl Divide for u8 {
fn divide(self, other: Self) -> Self {
__div(self, other)
}
}
/// Trait for the modulo of two values.
pub trait Mod {
/// Modulo two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value to mod with self.
///
/// # Returns
///
/// * [Self] - The modulo of the two values.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Mod for MyStruct {
/// fn modulo(self, other: Self) -> Self {
/// let val = self.val % other.val;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 2 };
/// let result_struct = struct1 % struct2;
/// assert(result_struct.val == 0);
/// }
/// ```
fn modulo(self, other: Self) -> Self;
}
impl Mod for u256 {
fn modulo(self, other: Self) -> Self {
__mod(self, other)
}
}
impl Mod for u64 {
fn modulo(self, other: Self) -> Self {
__mod(self, other)
}
}
impl Mod for u32 {
fn modulo(self, other: Self) -> Self {
__mod(self, other)
}
}
impl Mod for u16 {
fn modulo(self, other: Self) -> Self {
__mod(self, other)
}
}
impl Mod for u8 {
fn modulo(self, other: Self) -> Self {
__mod(self, other)
}
}
/// Trait to invert a type.
pub trait Not {
/// Inverts the value of the type.
///
/// # Returns
///
/// * [Self] - The result of the inverse.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: bool,
/// }
///
/// impl Not for MyStruct {
/// fn not(self) -> Self {
/// Self {
/// val: !self.val,
/// }
/// }
/// }
///
/// fn foo() {
/// let struct = MyStruct { val: true };
/// let result_struct = !struct;
/// assert(!result_struct.val);
/// }
/// ```
fn not(self) -> Self;
}
impl Not for bool {
fn not(self) -> Self {
__eq(self, false)
}
}
impl Not for u256 {
fn not(self) -> Self {
__not(self)
}
}
impl Not for b256 {
fn not(self) -> Self {
__not(self)
}
}
impl Not for u64 {
fn not(self) -> Self {
__not(self)
}
}
impl Not for u32 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u32::max())
}
}
impl Not for u16 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u16::max())
}
}
impl Not for u8 {
fn not(self) -> Self {
let v = __not(self);
__and(v, u8::max())
}
}
/// Trait for comparing type instances using the equality operator.
///
/// Implementing this trait provides `==` and `!=` operators on a type.
///
/// This trait allows comparisons for types that do not have a full equivalence relation.
/// In other words, it is not required that each instance of the type must be
/// equal to itself. While most of the types used in blockchain development do have this
/// property, called reflexivity, we can encounter types that are not reflexive.
///
/// A typical example of a type supporting partial equivalence, but not equivalence,
/// is a floating point number, where `NaN` is different from any other number,
/// including itself: `NaN != NaN`.
pub trait PartialEq {
/// Evaluates if two values of the same type are equal.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [bool] - `true` if the values are equal, otherwise `false`.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl PartialEq for MyStruct {
/// fn eq(self, other: Self) -> bool {
/// self.val == other.val
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 2 };
/// let struct2 = MyStruct { val: 2 };
/// let result = struct1 == struct2;
/// assert(result);
/// }
/// ```
fn eq(self, other: Self) -> bool;
} {
/// Evaluates if two values of the same type are not equal.
///
/// # Additional Information
///
/// This function is inherited when `eq()` is implemented.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [bool] - `true` if the two values are not equal, otherwise `false`.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl PartialEq for MyStruct {
/// fn eq(self, other: Self) -> bool {
/// self.val == other.val
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 2 };
/// let result = struct1 != struct2;
/// assert(result);
/// }
/// ```
fn neq(self, other: Self) -> bool {
(self.eq(other)).not()
}
}
/// Trait for comparing type instances corresponding to equivalence relations.
///
/// The difference between [Eq] and [PartialEq] is the additional requirement for reflexivity.
/// [PartialEq] guarantees symmetry and transitivity, but not reflexivity.
///
/// E.g., a type that implements [PartialEq] guarantees that for all `a`, `b`, and `c`:
/// - `a == b` implies `b == a` (symmetry)
/// - `a == b` and `b == c` implies `a == c` (transitivity)
///
/// [Eq], additionally implies:
/// - `a == a` for every `a` (reflexivity)
///
/// Reflexivity property cannot be checked by the compiler, and therefore `Eq`
/// does not have any methods, but only [PartialEq] as a supertrait.
///
/// **Implementing [Eq] for a type that does not have reflexivity property is a logic error**.
pub trait Eq: PartialEq {
}
impl PartialEq for bool {
fn eq(self, other: Self) -> bool {
__eq(self, other)
}
}
impl Eq for bool {}
impl PartialEq for u256 {
fn eq(self, other: Self) -> bool {
__eq(self, other)
}
}
impl Eq for u256 {}
impl PartialEq for b256 {
fn eq(self, other: Self) -> bool {
__eq(self, other)
}
}
impl Eq for b256 {}
impl PartialEq for u64 {
fn eq(self, other: Self) -> bool {
__eq(self, other)
}
}
impl Eq for u64 {}
impl PartialEq for u32 {
fn eq(self, other: Self) -> bool {
__eq(self, other)
}
}
impl Eq for u32 {}
impl PartialEq for u16 {
fn eq(self, other: Self) -> bool {
__eq(self, other)
}
}
impl Eq for u16 {}
impl PartialEq for u8 {
fn eq(self, other: Self) -> bool {
__eq(self, other)
}
}
impl Eq for u8 {}
impl PartialEq for () {
fn eq(self, other: Self) -> bool {
true
}
}
impl Eq for () {}
impl<T> PartialEq for (T, )
where
T: PartialEq,
{
fn eq(self, other: Self) -> bool {
self.0 == other.0
}
}
impl<T> Eq for (T, )
where
T: Eq,
{}
impl<T1, T2> PartialEq for (T1, T2)
where
T1: PartialEq,
T2: PartialEq,
{
fn eq(self, other: Self) -> bool {
self.0 == other.0 && self.1 == other.1
}
}
impl<T1, T2> Eq for (T1, T2)
where
T1: Eq,
T2: Eq,
{}
impl<T1, T2, T3> PartialEq for (T1, T2, T3)
where
T1: PartialEq,
T2: PartialEq,
T3: PartialEq,
{
fn eq(self, other: Self) -> bool {
self.0 == other.0 && self.1 == other.1 && self.2 == other.2
}
}
impl<T1, T2, T3> Eq for (T1, T2, T3)
where
T1: Eq,
T2: Eq,
T3: Eq,
{}
impl<T, const N: u64> PartialEq for [T; N]
where
T: PartialEq,
{
fn eq(self, other: Self) -> bool {
let mut i = 0;
while __lt(i, N) {
let a: T = *__elem_at(&self, i);
let b: T = *__elem_at(&other, i);
if !a.eq(b) {
return false;
}
i = __add(i, 1);
};
true
}
}
impl<T, const N: u64> Eq for [T; N]
where
T: Eq,
{}
impl<const N: u64> PartialEq for str[N] {
fn eq(self, other: Self) -> bool {
asm(result, left: self, right: other, len: N) {
meq result left right len;
result: bool
}
}
}
impl<const N: u64> Eq for str[N] {}
/// Trait to evaluate if one value is greater or less than another of the same type.
pub trait Ord {
/// Evaluates if one value of the same type is greater than another.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [bool] - `true` if `self` is greater than `other`, otherwise `false`.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Ord for MyStruct {
/// fn gt(self, other: Self) -> bool {
/// self.val > other.val
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 2 };
/// let result = struct1 > struct2;
/// assert(result);
/// }
/// ```
fn gt(self, other: Self) -> bool;
/// Evaluates if one value of the same type is less than another.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [bool] - `true` if `self` is less than `other`, otherwise `false`.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Ord for MyStruct {
/// fn lt(self, other: Self) -> bool {
/// self.val < other.val
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 2 };
/// let result = struct1 < struct2;
/// assert(!result);
/// }
/// ```
fn lt(self, other: Self) -> bool;
}
impl Ord for u256 {
fn gt(self, other: Self) -> bool {
__gt(self, other)
}
fn lt(self, other: Self) -> bool {
__lt(self, other)
}
}
impl Ord for b256 {
fn gt(self, other: Self) -> bool {
__gt(self, other)
}
fn lt(self, other: Self) -> bool {
__lt(self, other)
}
}
impl Ord for u64 {
fn gt(self, other: Self) -> bool {
__gt(self, other)
}
fn lt(self, other: Self) -> bool {
__lt(self, other)
}
}
impl Ord for u32 {
fn gt(self, other: Self) -> bool {
__gt(self, other)
}
fn lt(self, other: Self) -> bool {
__lt(self, other)
}
}
impl Ord for u16 {
fn gt(self, other: Self) -> bool {
__gt(self, other)
}
fn lt(self, other: Self) -> bool {
__lt(self, other)
}
}
impl Ord for u8 {
fn gt(self, other: Self) -> bool {
__gt(self, other)
}
fn lt(self, other: Self) -> bool {
__lt(self, other)
}
}
/// Trait to bitwise AND two values of the same type.
pub trait BitwiseAnd {
/// Bitwise AND two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [Self] - The result of the bitwise AND of the two values.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl BitwiseAnd for MyStruct {
/// fn binary_and(self, other: Self) -> Self {
/// let val = self.val & other.val;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 11 };
/// let result_struct = struct1 & struct2;
/// assert(result_struct.val == 10);
/// }
/// ```
fn binary_and(self, other: Self) -> Self;
}
impl BitwiseAnd for u256 {
fn binary_and(self, other: Self) -> Self {
__and(self, other)
}
}
impl BitwiseAnd for b256 {
fn binary_and(self, other: Self) -> Self {
__and(self, other)
}
}
impl BitwiseAnd for u64 {
fn binary_and(self, other: Self) -> Self {
__and(self, other)
}
}
impl BitwiseAnd for u32 {
fn binary_and(self, other: Self) -> Self {
__and(self, other)
}
}
impl BitwiseAnd for u16 {
fn binary_and(self, other: Self) -> Self {
__and(self, other)
}
}
impl BitwiseAnd for u8 {
fn binary_and(self, other: Self) -> Self {
__and(self, other)
}
}
/// Trait to bitwise OR two values of the same type.
pub trait BitwiseOr {
/// Bitwise OR two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [Self] - The result of the bitwise OR of the two values.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl BitwiseOr for MyStruct {
/// fn binary_or(self, other: Self) -> Self {
/// let val = self.val | other.val;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 11 };
/// let result_struct = struct1 | struct2;
/// assert(result_struct.val == 11);
/// }
/// ```
fn binary_or(self, other: Self) -> Self;
}
impl BitwiseOr for u256 {
fn binary_or(self, other: Self) -> Self {
__or(self, other)
}
}
impl BitwiseOr for b256 {
fn binary_or(self, other: Self) -> Self {
__or(self, other)
}
}
impl BitwiseOr for u64 {
fn binary_or(self, other: Self) -> Self {
__or(self, other)
}
}
impl BitwiseOr for u32 {
fn binary_or(self, other: Self) -> Self {
__or(self, other)
}
}
impl BitwiseOr for u16 {
fn binary_or(self, other: Self) -> Self {
__or(self, other)
}
}
impl BitwiseOr for u8 {
fn binary_or(self, other: Self) -> Self {
__or(self, other)
}
}
/// Trait to bitwise XOR two values of the same type.
pub trait BitwiseXor {
/// Bitwise XOR two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [Self] - The result of the bitwise XOR of the two values.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl BitwiseXOr for MyStruct {
/// fn binary_xor(self, other: Self) -> Self {
/// let val = self.val ^ other.val;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 11 };
/// let result_struct = struct1 ^ struct2;
/// assert(result_struct.val == 1);
/// }
/// ```
fn binary_xor(self, other: Self) -> Self;
}
impl BitwiseXor for u256 {
fn binary_xor(self, other: Self) -> Self {
__xor(self, other)
}
}
impl BitwiseXor for b256 {
fn binary_xor(self, other: Self) -> Self {
__xor(self, other)
}
}
impl BitwiseXor for u64 {
fn binary_xor(self, other: Self) -> Self {
__xor(self, other)
}
}
impl BitwiseXor for u32 {
fn binary_xor(self, other: Self) -> Self {
__xor(self, other)
}
}
impl BitwiseXor for u16 {
fn binary_xor(self, other: Self) -> Self {
__xor(self, other)
}
}
impl BitwiseXor for u8 {
fn binary_xor(self, other: Self) -> Self {
__xor(self, other)
}
}
pub trait OrdEq: Ord + PartialEq {
} {
/// Evaluates if one value of the same type is greater or equal to than another.
///
/// # Additional Information
///
/// This trait requires that the `Ord` and `Eq` traits are implemented.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [bool] - `true` if `self` is greater than or equal to `other`, otherwise `false`.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Eq for MyStruct {
/// fn eq(self, other: Self) -> bool {
/// self.val == other.val
/// }
/// }
///
/// impl Ord for MyStruct {
/// fn gt(self, other: Self) -> bool {
/// self.val > other.val
/// }
/// }
///
/// impl OrdEq for MyStruct {}
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 10 };
/// let result = struct1 >= struct2;
/// assert(result);
/// }
/// ```
fn ge(self, other: Self) -> bool {
self.gt(other) || self.eq(other)
}
/// Evaluates if one value of the same type is less or equal to than another.
///
/// # Additional Information
///
/// This trait requires that the `Ord` and `Eq` traits are implemented.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * [bool] - `true` if `self` is less than or equal to `other`, otherwise `false`.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Eq for MyStruct {
/// fn eq(self, other: Self) -> bool {
/// self.val == other.val
/// }
/// }
///
/// impl Ord for MyStruct {
/// fn lt(self, other: Self) -> bool {
/// self.val < other.val
/// }
/// }
///
/// impl OrdEq for MyStruct {}
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 10 };
/// let result = struct1 <= struct2;
/// assert(result);
/// }
/// ```
fn le(self, other: Self) -> bool {
self.lt(other) || self.eq(other)
}
}
impl OrdEq for u256 {}
impl OrdEq for u64 {}
impl OrdEq for u32 {}
impl OrdEq for u16 {}
impl OrdEq for u8 {}
impl OrdEq for b256 {}
/// Trait to bit shift a value.
pub trait Shift {
/// Bit shift left by an amount.
///
/// # Arguments
///
/// * `other`: [u64] - The amount to bit shift by.
///
/// # Returns
///
/// * [Self] - The result of the value bit shifted to the left.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Shift for MyStruct {
/// fn lsh(self, other: u64) -> Self {
/// let val = self.val << other;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let result_struct = struct1 << 3;
/// assert(result_struct.val == 80);
/// }
/// ```
fn lsh(self, other: u64) -> Self;
/// Bit shift right by an amount.
///
/// # Arguments
///
/// * `other`: [u64] - The amount to bit shift by.
///
/// # Returns
///
/// * [Self] - The result of the value bit shifted to the right.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl Shift for MyStruct {
/// fn rsh(self, other: u64) -> Self {
/// let val = self.val >> other;
/// Self {
/// val
/// }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let result_struct = struct1 >> 1;
/// assert(result_struct.val == 5);
/// }
/// ```
fn rsh(self, other: u64) -> Self;
}
impl Shift for u256 {
fn lsh(self, other: u64) -> Self {
__lsh(self, other)
}
fn rsh(self, other: u64) -> Self {
__rsh(self, other)
}
}
impl Shift for b256 {
fn lsh(self, other: u64) -> Self {
__lsh(self, other)
}
fn rsh(self, other: u64) -> Self {
__rsh(self, other)
}
}
impl Shift for u64 {
fn lsh(self, other: u64) -> Self {
__lsh(self, other)
}
fn rsh(self, other: u64) -> Self {
__rsh(self, other)
}
}
impl Shift for u32 {
fn lsh(self, other: u64) -> Self {
// any non-64-bit value is compiled to a u64 value under-the-hood
// so we need to clear upper bits here
__and(__lsh(self, other), Self::max())
}
fn rsh(self, other: u64) -> Self {
__rsh(self, other)
}
}
impl Shift for u16 {
fn lsh(self, other: u64) -> Self {
__and(__lsh(self, other), Self::max())
}
fn rsh(self, other: u64) -> Self {
__rsh(self, other)
}
}
/// Trait to compare values of the same type.
pub trait TotalOrd {
/// Finds the minimum value of two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * Self - the minimum of the two values, or the same value if they are equal.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl TotalOrd for MyStruct {
/// fn min(self, other: Self) -> Self {
/// if self.val < other.val { self } else { other }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 20 };
/// let min = struct1.min(struct2);
/// assert(min.val == struct1.val);
/// }
/// ```
fn min(self, other: Self) -> Self;
/// Finds the maximum value of two values of the same type.
///
/// # Arguments
///
/// * `other`: [Self] - The value of the same type.
///
/// # Returns
///
/// * Self - the maximum of the two values, or the same value if they are equal.
///
/// # Examples
///
/// ```sway
/// struct MyStruct {
/// val: u64,
/// }
///
/// impl TotalOrd for MyStruct {
/// fn max(self, other: Self) -> Self {
/// if self.val > other.val { self } else { other }
/// }
/// }
///
/// fn foo() {
/// let struct1 = MyStruct { val: 10 };
/// let struct2 = MyStruct { val: 20 };
/// let max = struct1.max(struct2);
/// assert(max.val == struct2.val);
/// }
/// ```
fn max(self, other: Self) -> Self;
}
impl TotalOrd for u8 {
fn min(self, other: Self) -> Self {
if self < other { self } else { other }
}
fn max(self, other: Self) -> Self {
if self > other { self } else { other }
}
}
impl TotalOrd for u16 {
fn min(self, other: Self) -> Self {
if self < other { self } else { other }
}
fn max(self, other: Self) -> Self {
if self > other { self } else { other }
}
}
impl TotalOrd for u32 {
fn min(self, other: Self) -> Self {
if self < other { self } else { other }
}
fn max(self, other: Self) -> Self {
if self > other { self } else { other }
}
}
impl TotalOrd for u64 {
fn min(self, other: Self) -> Self {
if self < other { self } else { other }
}
fn max(self, other: Self) -> Self {
if self > other { self } else { other }
}
}
impl TotalOrd for u256 {
fn min(self, other: Self) -> Self {
if self < other { self } else { other }
}
fn max(self, other: Self) -> Self {
if self > other { self } else { other }
}
}
impl Shift for u8 {
fn lsh(self, other: u64) -> Self {
__and(__lsh(self, other), Self::max())
}
fn rsh(self, other: u64) -> Self {
__rsh(self, other)
}
}
use ::str::*;
impl PartialEq for str {
fn eq(self, other: Self) -> bool {
if self.len() != other.len() {
false
} else {
let self_ptr = self.as_ptr();
let other_ptr = other.as_ptr();
let l = self.len();
asm(r1: self_ptr, r2: other_ptr, r3: l, r4) {
meq r4 r1 r2 r3;
r4: bool
}
}
}
}
impl Eq for str {}
impl u8 {
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
pub fn wrapping_add(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self + other;
set_flags(f);
res
}
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
pub fn wrapping_sub(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self - other;
set_flags(f);
res
}
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
pub fn wrapping_mul(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self * other;
set_flags(f);
res
}
/// Returns whether a `u8` is set to zero.
///
/// # Returns
///
/// * [bool] -> True if the `u8` is zero, otherwise false.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let zero_u8 = u8::zero();
/// assert(zero_u8.is_zero());
/// }
/// ```
pub fn is_zero(self) -> bool {
self == 0u8
}
}
impl u16 {
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
pub fn wrapping_add(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self + other;
set_flags(f);
res
}
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
pub fn wrapping_sub(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self - other;
set_flags(f);
res
}
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
pub fn wrapping_mul(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self * other;
set_flags(f);
res
}
/// Returns whether a `u16` is set to zero.
///
/// # Returns
///
/// * [bool] -> True if the `u16` is zero, otherwise false.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let zero_u16 = u16::zero();
/// assert(zero_u16.is_zero());
/// }
/// ```
pub fn is_zero(self) -> bool {
self == 0u16
}
}
impl u32 {
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
pub fn wrapping_add(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self + other;
set_flags(f);
res
}
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
pub fn wrapping_sub(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self - other;
set_flags(f);
res
}
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
pub fn wrapping_mul(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self * other;
set_flags(f);
res
}
/// Returns whether a `u32` is set to zero.
///
/// # Returns
///
/// * [bool] -> True if the `u32` is zero, otherwise false.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let zero_u32 = u32::zero();
/// assert(zero_u32.is_zero());
/// }
/// ```
pub fn is_zero(self) -> bool {
self == 0u32
}
}
impl u64 {
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
pub fn wrapping_add(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self + other;
set_flags(f);
res
}
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
pub fn wrapping_sub(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self - other;
set_flags(f);
res
}
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
pub fn wrapping_mul(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self * other;
set_flags(f);
res
}
/// Returns whether a `u64` is set to zero.
///
/// # Returns
///
/// * [bool] -> True if the `u64` is zero, otherwise false.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let zero_u64 = u64::zero();
/// assert(zero_u64.is_zero());
/// }
/// ```
pub fn is_zero(self) -> bool {
self == 0u64
}
}
impl u256 {
/// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of the type.
pub fn wrapping_add(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self + other;
set_flags(f);
res
}
/// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary of the type.
pub fn wrapping_sub(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self - other;
set_flags(f);
res
}
/// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary of the type.
pub fn wrapping_mul(self, other: Self) -> Self {
let f = disable_panic_on_overflow();
let res = self * other;
set_flags(f);
res
}
/// Returns whether a `u256` is set to zero.
///
/// # Returns
///
/// * [bool] -> True if the `u256` is zero, otherwise false.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let zero_u256 = u256::zero();
/// assert(zero_u256.is_zero());
/// }
/// ```
pub fn is_zero(self) -> bool {
self == 0x00u256
}
}
impl b256 {
/// Returns whether a `b256` is set to zero.
///
/// # Returns
///
/// * [bool] -> True if the `b256` is zero, otherwise false.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let zero_b256 = b256::zero();
/// assert(zero_b256.is_zero());
/// }
/// ```
pub fn is_zero(self) -> bool {
self == 0x0000000000000000000000000000000000000000000000000000000000000000
}
}
fn u8_as_u64(val: u8) -> u64 {
asm(input: val) {
input: u64
}
}
fn u64_as_u8(val: u64) -> u8 {
asm(input: val) {
input: u8
}
}