/
githubmirror
/
sway
Обзор
Документация
Войти
/
githubmirror
/
sway
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
sway-lib-std/src/ops.sw
1 767 строк
41 KB
Igor Rončević
Refactor and tidy up `std` tests for execution speed and discoverability (#7669)
29 июн 2026, 20:19
Не верифицирован
29 июн 2026, 20:19
4fa77a8
Код
Авторство
О чём код?
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 } }