diff --git a/sway-lib-core/src/never.sw b/sway-lib-core/src/never.sw index 6c1a0c2c748..5c9760b6e1d 100644 --- a/sway-lib-core/src/never.sw +++ b/sway-lib-core/src/never.sw @@ -4,10 +4,12 @@ use ::ops::{Eq, Not, Ord}; /// `Never` represents the type of computations which never resolve to any value at all. /// +/// # Additional Information +/// /// `break`, `continue` and `return` expressions also have type `Never`. For example we are allowed to /// write: /// -/// ``` +/// ```sway /// let x: Never = { /// return 123 /// }; @@ -20,7 +22,7 @@ use ::ops::{Eq, Not, Ord}; /// /// A more realistic usage of `Never` is in this code: /// -/// ``` +/// ```sway /// let num: u32 = match get_a_number() { /// Some(num) => num, /// None => break, @@ -33,13 +35,24 @@ use ::ops::{Eq, Not, Ord}; /// /// Note that `Never` type coerces into any other type, another example of this would be: /// -/// ``` +/// ```sway /// let x: u32 = { /// return 123 /// }; /// ``` /// /// Regardless of the type of `x`, the return block of type `Never` will always coerce into `x` type. +/// +/// # Examples +/// +/// ```sway +/// fn foo() { +/// let num: u64 = match Option::None:: { +/// Some(num) => num, +/// None => return, +/// }; +/// } +/// ``` pub enum Never {} impl Not for Never { diff --git a/sway-lib-core/src/ops.sw b/sway-lib-core/src/ops.sw index 8179f049aac..d624e2e2d05 100644 --- a/sway-lib-core/src/ops.sw +++ b/sway-lib-core/src/ops.sw @@ -2,7 +2,41 @@ library; use ::primitives::*; +/// 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; } @@ -56,7 +90,41 @@ impl Add for u8 { } } +/// 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; } @@ -92,7 +160,41 @@ impl Subtract for u8 { } } +/// 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; } @@ -146,7 +248,41 @@ impl Multiply for u8 { } } +/// 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; } @@ -184,7 +320,41 @@ impl Divide for u8 { } } +/// 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; } @@ -218,7 +388,35 @@ impl Mod for u8 { } } +/// 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; } @@ -234,9 +432,74 @@ impl Not for u256 { } } +/// Trait to evaluate if two types are equal. pub trait Eq { + /// 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 Eq 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 Eq 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() } @@ -295,8 +558,70 @@ impl Eq for raw_ptr { } } +/// 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; } @@ -372,7 +697,41 @@ impl Ord for b256 { } } +/// 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; } @@ -400,7 +759,41 @@ impl BitwiseAnd for u8 { } } +/// 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; } @@ -428,7 +821,41 @@ impl BitwiseOr for u8 { } } +/// 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; } @@ -522,11 +949,97 @@ impl BitwiseXor for b256 { } } +/// Trait to evaluate if one value is greater than or equal, or less than or equal to another of the same type. trait OrdEq: Ord + Eq { } { + /// 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) } @@ -538,8 +1051,74 @@ 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; } diff --git a/sway-lib-core/src/primitive_conversions.sw b/sway-lib-core/src/primitive_conversions.sw index c6e435cefa1..72fd6506297 100644 --- a/sway-lib-core/src/primitive_conversions.sw +++ b/sway-lib-core/src/primitive_conversions.sw @@ -1,6 +1,29 @@ library; impl u64 { + /// Converts the `u64` to a sequence of little-endian bytes. + /// + /// # Returns + /// + /// * [[u8; 8]] - An array of 8 `u8` bytes that compose the `u64`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: u64 = 578437695752307201; + /// let result = x.to_le_bytes(); + /// + /// assert(result[0] == 1_u8); + /// assert(result[1] == 2_u8); + /// assert(result[2] == 3_u8); + /// assert(result[3] == 4_u8); + /// assert(result[4] == 5_u8); + /// assert(result[5] == 6_u8); + /// assert(result[6] == 7_u8); + /// assert(result[7] == 8_u8); + /// } + /// ``` pub fn to_le_bytes(self) -> [u8; 8] { let output = [0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8]; @@ -40,6 +63,26 @@ impl u64 { } } + /// Converts a sequence of little-endian bytes to a `u64`. + /// + /// # Arguments + /// + /// * `bytes`: [[u8; 8]] - A sequence of 8 `u8` bytes that represent a `u64`. + /// + /// # Returns + /// + /// * [u64] - The resulting `u64` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [1_u8, 2_u8, 3_u8, 4_u8, 5_u8, 6_u8, 7_u8, 8_u8]; + /// let result = u64::from_le_bytes(bytes); + /// + /// assert(result == 578437695752307201); + /// } + /// ``` pub fn from_le_bytes(bytes: [u8; 8]) -> Self { let a = bytes[0]; let b = bytes[1]; @@ -70,6 +113,29 @@ impl u64 { } } + /// Converts the `u64` to a sequence of big-endian bytes. + /// + /// # Returns + /// + /// * [[u8; 8]] - An array of 8 `u8` bytes that compose the `u64`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: u64 = 578437695752307201; + /// let result = x.to_be_bytes(); + /// + /// assert(result[0] == 8_u8); + /// assert(result[1] == 7_u8); + /// assert(result[2] == 6_u8); + /// assert(result[3] == 5_u8); + /// assert(result[4] == 4_u8); + /// assert(result[5] == 3_u8); + /// assert(result[6] == 2_u8); + /// assert(result[7] == 1_u8); + /// } + /// ``` pub fn to_be_bytes(self) -> [u8; 8] { let output = [0; 8]; @@ -109,6 +175,26 @@ impl u64 { } } + /// Converts a sequence of big-endian bytes to a `u64`. + /// + /// # Arguments + /// + /// * `bytes`: [[u8; 8]] - A sequence of 8 `u8` bytes that represent a `u64`. + /// + /// # Returns + /// + /// * [u64] - The resulting `u64` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [8_u8, 7_u8, 6_u8, 5_u8, 4_u8, 3_u8, 2_u8, 1_u8]; + /// let result = u64::from_be_bytes(bytes); + /// + /// assert(result == 578437695752307201); + /// } + /// ``` pub fn from_be_bytes(bytes: [u8; 8]) -> Self { let a = bytes[0]; let b = bytes[1]; @@ -141,12 +227,46 @@ impl u64 { } impl u32 { + /// Extends a `u32` to a `u64`. + /// + /// # Returns + /// + /// * [u64] - The converted `u32` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = 10u32; + /// let result = val.as_u64(); + /// assert(result == 10); + /// } + /// ``` pub fn as_u64(self) -> u64 { asm(input: self) { input: u64 } } + /// Converts the `u32` to a sequence of little-endian bytes. + /// + /// # Returns + /// + /// * [[u8; 4]] - An array of 4 `u8` bytes that compose the `u32`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: u32 = 67305985; + /// let result = x.to_le_bytes(); + /// + /// assert(result[0] == 1_u8); + /// assert(result[1] == 2_u8); + /// assert(result[2] == 3_u8); + /// assert(result[3] == 4_u8); + /// } + /// ``` pub fn to_le_bytes(self) -> [u8; 4] { let output = [0_u8, 0_u8, 0_u8, 0_u8]; @@ -170,6 +290,26 @@ impl u32 { } } + /// Converts a sequence of little-endian bytes to a `u32`. + /// + /// # Arguments + /// + /// * `bytes`: [[u8; 4]] - A sequence of 4 `u8` bytes that represent a `u32`. + /// + /// # Returns + /// + /// * [u32] - The resulting `u32` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [1_u8, 2_u8, 3_u8, 4_u8]; + /// let result = u32::from_le_bytes(bytes); + /// + /// assert(result == 67305985_u32); + /// } + /// ``` pub fn from_le_bytes(bytes: [u8; 4]) -> Self { asm(a: bytes[0], b: bytes[1], c: bytes[2], d: bytes[3], i: 0x8, j: 0x10, k: 0x18, r1, r2, r3) { sll r1 c j; @@ -182,6 +322,25 @@ impl u32 { } } + /// Converts the `u32` to a sequence of big-endian bytes. + /// + /// # Returns + /// + /// * [[u8; 4]] - An array of 4 `u8` bytes that compose the `u32`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: u32 = 67305985; + /// let result = x.to_be_bytes(); + /// + /// assert(result[0] == 4_u8); + /// assert(result[1] == 3_u8); + /// assert(result[2] == 2_u8); + /// assert(result[3] == 1_u8); + /// } + /// ``` pub fn to_be_bytes(self) -> [u8; 4] { let output = [0_u8, 0_u8, 0_u8, 0_u8]; @@ -205,6 +364,26 @@ impl u32 { } } + /// Converts a sequence of big-endian bytes to a `u32`. + /// + /// # Arguments + /// + /// * `bytes`: [[u8; 4]] - A sequence of 4 `u8` bytes that represent a `u32`. + /// + /// # Returns + /// + /// * [u32] - The resulting `u32` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [4_u8, 3_u8, 2_u8, 1_u8]; + /// let result = u32::from_be_bytes(bytes); + /// + /// assert(result == 67305985_u32); + /// } + /// ``` pub fn from_be_bytes(bytes: [u8; 4]) -> Self { asm(a: bytes[0], b: bytes[1], c: bytes[2], d: bytes[3], i: 0x8, j: 0x10, k: 0x18, r1, r2, r3) { sll r1 a k; @@ -219,18 +398,65 @@ impl u32 { } impl u16 { + /// Extends a `u16` to a `u32`. + /// + /// # Returns + /// + /// * [u32] - The converted `u16` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = 10u16; + /// let result = val.as_u32(); + /// assert(result == 10u32); + /// } + /// ``` pub fn as_u32(self) -> u32 { asm(input: self) { input: u32 } } + /// Extends a `u16` to a `u64`. + /// + /// # Returns + /// + /// * [u64] - The converted `u16` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = 10u16; + /// let result = val.as_u64(); + /// assert(result == 10); + /// } + /// ``` pub fn as_u64(self) -> u64 { asm(input: self) { input: u64 } } + /// Converts the `u16` to a sequence of little-endian bytes. + /// + /// # Returns + /// + /// * [[u8; 2]] - An array of 2 `u8` bytes that compose the `u16`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: u16 = 513; + /// let result = x.to_le_bytes(); + /// + /// assert(result[0] == 1_u8); + /// assert(result[1] == 2_u8); + /// } + /// ``` pub fn to_le_bytes(self) -> [u8; 2] { let output = [0_u8, 0_u8]; @@ -246,6 +472,26 @@ impl u16 { } } + /// Converts a sequence of little-endian bytes to a `u16`. + /// + /// # Arguments + /// + /// * `bytes`: [[u8; 2]] - A sequence of 2 `u8` bytes that represent a `u16`. + /// + /// # Returns + /// + /// * [u16] - The resulting `u16` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [1_u8, 2_u8]; + /// let result = u16::from_le_bytes(bytes); + /// + /// assert(result == 513_u16); + /// } + /// ``` pub fn from_le_bytes(bytes: [u8; 2]) -> Self { asm(a: bytes[0], b: bytes[1], i: 0x8, r1) { sll r1 b i; @@ -254,6 +500,23 @@ impl u16 { } } + /// Converts the `u16` to a sequence of big-endian bytes. + /// + /// # Returns + /// + /// * [[u8; 2]] - An array of 2 `u8` bytes that compose the `u16`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: u16 = 513; + /// let result = x.to_be_bytes(); + /// + /// assert(result[0] == 2_u8); + /// assert(result[1] == 1_u8); + /// } + /// ``` pub fn to_be_bytes(self) -> [u8; 2] { let output = [0_u8, 0_u8]; @@ -268,6 +531,26 @@ impl u16 { } } + /// Converts a sequence of big-endian bytes to a `u16`. + /// + /// # Arguments + /// + /// * `bytes`: [[u8; 2]] - A sequence of 2 `u8` bytes that represent a `u16`. + /// + /// # Returns + /// + /// * [u32] - The resulting `u16` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [2_u8, 1_u8]; + /// let result = u16::from_be_bytes(bytes); + /// + /// assert(result == 513_u16); + /// } + /// ``` pub fn from_be_bytes(bytes: [u8; 2]) -> Self { asm(a: bytes[0], b: bytes[1], i: 0x8, r1) { sll r1 a i; @@ -278,18 +561,63 @@ impl u16 { } impl u8 { + /// Extends a `u8` to a `u16`. + /// + /// # Returns + /// + /// * [u16] - The converted `u8` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = 2u8; + /// let result = val.as_u16(); + /// assert(result == 2u16); + /// } + /// ``` pub fn as_u16(self) -> u16 { asm(input: self) { input: u16 } } + /// Extends a `u8` to a `u32`. + /// + /// # Returns + /// + /// * [u32] - The converted `u8` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = 2u8; + /// let result = val.as_u32(); + /// assert(result == 2u32); + /// } + /// ``` pub fn as_u32(self) -> u32 { asm(input: self) { input: u32 } } + /// Extends a `u8` to a `u64`. + /// + /// # Returns + /// + /// * [u64] - The converted `u8` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = 2u8; + /// let result = val.as_u64(); + /// assert(result == 2); + /// } + /// ``` pub fn as_u64(self) -> u64 { asm(input: self) { input: u64 @@ -298,6 +626,26 @@ impl u8 { } impl b256 { + /// Converts the `b256` to a sequence of little-endian bytes. + /// + /// # Returns + /// + /// * [[u8; 32]] - An array of 32 `u8` bytes that compose the `b256`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [32_u8, 31_u8, 30_u8, 29_u8, 28_u8, 27_u8, 26_u8, 25_u8, 24_u8, 23_u8, + /// 22_u8, 21_u8, 20_u8, 19_u8, 18_u8, 17_u8, 16_u8, 15_u8, 14_u8, 13_u8, + /// 12_u8, 11_u8, 10_u8, 9_u8, 8_u8, 7_u8, 6_u8, 5_u8, 4_u8, 3_u8, + /// 2_u8, 1_u8]; + /// + /// let x = b256::from_le_bytes(bytes); + /// + /// assert(x == 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20); + /// } + /// ``` pub fn to_le_bytes(self) -> [u8; 32] { let (a, b, c, d): (u64, u64, u64, u64) = asm(r1: self) {r1: (u64, u64, u64, u64)}; let a = a.to_le_bytes(); @@ -315,6 +663,29 @@ impl b256 { output } + /// Converts a sequence of little-endian bytes to a `b256`. + /// + /// # Arguments + /// + /// * `bytes`: [[u8; 32]] - A sequence of 32 `u8` bytes that represent a `b256`. + /// + /// # Returns + /// + /// * [b256] - The resulting `b256` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [32_u8, 31_u8, 30_u8, 29_u8, 28_u8, 27_u8, 26_u8, 25_u8, 24_u8, 23_u8, + /// 22_u8, 21_u8, 20_u8, 19_u8, 18_u8, 17_u8, 16_u8, 15_u8, 14_u8, 13_u8, + /// 12_u8, 11_u8, 10_u8, 9_u8, 8_u8, 7_u8, 6_u8, 5_u8, 4_u8, 3_u8, + /// 2_u8, 1_u8]; + /// + /// let x = b256::from_le_bytes(bytes); + /// + /// assert(x == 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20); + /// ``` pub fn from_le_bytes(bytes: [u8; 32]) -> Self { let a = u64::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]]); let b = u64::from_le_bytes([bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]]); @@ -328,6 +699,26 @@ impl b256 { } } + /// Converts the `b256` to a sequence of big-endian bytes. + /// + /// # Returns + /// + /// * [[u8; 32]] - An array of 32 `u8` bytes that compose the `b256`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: b256 = 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20; + /// let bytes = x.to_be_bytes(); + /// + /// let mut i: u8 = 0; + /// while i < 32_u8 { + /// assert(bytes[i.as_u64()] == i + 1_u8); + /// i += 1_u8; + /// } + /// } + /// ``` pub fn to_be_bytes(self) -> [u8; 32] { let (a, b, c, d): (u64, u64, u64, u64) = asm(r1: self) {r1: (u64, u64, u64, u64)}; let a = a.to_be_bytes(); @@ -343,6 +734,29 @@ impl b256 { output } + /// Converts a sequence of big-endian bytes to a `b256`. + /// + /// # Arguments + /// + /// * `bytes`: [[u8; 32]] - A sequence of 32 `u8` bytes that represent a `b256`. + /// + /// # Returns + /// + /// * [b256] - The resulting `b256` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bytes = [1_u8, 2_u8, 3_u8, 4_u8, 5_u8, 6_u8, 7_u8, 8_u8, 9_u8, 10_u8, + /// 11_u8, 12_u8, 13_u8, 14_u8, 15_u8, 16_u8, 17_u8, 18_u8, 19_u8, 20_u8, + /// 21_u8, 22_u8, 23_u8, 24_u8, 25_u8, 26_u8, 27_u8, 28_u8, 29_u8, 30_u8, + /// 31_u8, 32_u8]; + /// let x = b256::from_be_bytes(bytes); + /// + /// assert(x == 0x0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20); + /// } + /// ``` pub fn from_be_bytes(bytes: [u8; 32]) -> Self { let a = u64::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]]); let b = u64::from_be_bytes([bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15]]); diff --git a/sway-lib-core/src/primitives.sw b/sway-lib-core/src/primitives.sw index b6fb29117f3..e89d4fc9fb4 100644 --- a/sway-lib-core/src/primitives.sw +++ b/sway-lib-core/src/primitives.sw @@ -2,17 +2,56 @@ library; impl u64 { /// The smallest value that can be represented by this integer type. + /// + /// # Returns + /// + /// * [u64] - The smallest `u64` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = u64::min(); + /// assert(val == 0); + // } + /// ``` pub fn min() -> Self { 0 } /// The largest value that can be represented by this integer type, /// 264 - 1. + /// + /// # Returns + /// + /// * [u64] - The largest `u64` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = u64::max(); + /// assert(val == 18446744073709551615); + /// } + /// ``` pub fn max() -> Self { 18446744073709551615 } /// The size of this integer type in bits. + /// + /// # Returns + /// + /// * [u32] - The number of bits for a `u64`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bits = u64::bits(); + /// assert(bits == 64); + /// } + /// ``` pub fn bits() -> u64 { 64 } @@ -20,17 +59,56 @@ impl u64 { impl u32 { /// The smallest value that can be represented by this integer type. + /// + /// # Returns + /// + /// * [u32] - The smallest `u32` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val == u32::min(); + /// assert(val == 0u32); + /// } + /// ``` pub fn min() -> Self { 0 } /// The largest value that can be represented by this integer type, /// 232 - 1. + /// + /// # Returns + /// + /// * [u32] - The largest `u32` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val == u32:max(); + /// assert(val == 4294967295u32); + /// } + /// ``` pub fn max() -> Self { 4294967295 } /// The size of this integer type in bits. + /// + /// # Returns + /// + /// * [u32] - The number of bits for a `u32`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bits = u32::bits(); + /// assert(bits == 32); + /// } + /// ``` pub fn bits() -> u64 { 32 } @@ -38,17 +116,56 @@ impl u32 { impl u16 { /// The smallest value that can be represented by this integer type. + /// + /// # Returns + /// + /// * [u16] - The smallest `u16` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = u16::min(); + /// assert(val == 0u16); + /// } + /// ``` pub fn min() -> Self { 0 } /// The largest value that can be represented by this integer type, /// 216 - 1. + /// + /// # Returns + /// + /// * [u16] - The largest `u16` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = u16::max(); + /// assert(val == 65535u16); + /// } + /// ``` pub fn max() -> Self { 65535 } /// The size of this integer type in bits. + /// + /// # Returns + /// + /// * [u32] - The number of bits for a `u16`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bits = u16::bits(); + /// assert(bits == 16); + /// } + /// ``` pub fn bits() -> u64 { 16 } @@ -56,17 +173,56 @@ impl u16 { impl u8 { /// The smallest value that can be represented by this integer type. + /// + /// # Returns + /// + /// * [u8] - The smallest `u8` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = u8::min(); + /// assert(val == 0u8); + /// } + /// ``` pub fn min() -> Self { 0 } /// The largest value that can be represented by this integer type, /// 28 - 1. + /// + /// # Returns + /// + /// * [u8] - The largest `u8` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val = u8::max(); + /// assert(val == 255u8); + /// } + /// ``` pub fn max() -> Self { 255 } /// The size of this integer type in bits. + /// + /// # Returns + /// + /// * [u64] - The number of bits for a `u8`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bits = u8::bits(); + /// assert(bits == 8); + /// } + /// ``` pub fn bits() -> u64 { 8 } @@ -74,17 +230,58 @@ impl u8 { impl b256 { /// The smallest value that can be represented by this type. + /// + /// # Returns + /// + /// * [b256] - The smallest `b256` value. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let val = b256::min(); + /// assert(val == ZERO_B256); + /// } + /// ``` pub fn min() -> Self { 0x0000000000000000000000000000000000000000000000000000000000000000 } /// The largest value that can be represented by this type, /// 2256 - 1. + /// + /// # Returns + /// + /// * [b256] - The largest `b256` value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let val == b256::max(); + /// assert(val == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); + /// } + /// ``` pub fn max() -> Self { 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF } /// The size of this type in bits. + /// + /// # Returns + /// + /// * [u64] - The number of bits for a `b256`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let bits == b256::bits(); + /// assert(bits == 256); + /// } + /// ``` pub fn bits() -> u64 { 256 } diff --git a/sway-lib-core/src/raw_ptr.sw b/sway-lib-core/src/raw_ptr.sw index 8a2431a212f..a79f52d85b0 100644 --- a/sway-lib-core/src/raw_ptr.sw +++ b/sway-lib-core/src/raw_ptr.sw @@ -2,22 +2,94 @@ library; impl raw_ptr { /// Returns `true` if the pointer is null. + /// + /// # Returns + /// + /// * [bool] - `true` if the pointer is null, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(2); + /// assert(!ptr.is_null()); + /// } + /// ``` pub fn is_null(self) -> bool { let null_ptr = asm() { zero: raw_ptr }; __eq(self, null_ptr) } /// Calculates the offset from the pointer. + /// + /// # Arguments + /// + /// * `count`: [u64] - The number of `size_of` bytes to increase by. + /// + /// # Returns + /// + /// * [raw_ptr] - The pointer to the offset memory location. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(2); + /// let offset_ptr = ptr.add::(1); + /// assert(ptr != offset_ptr); + /// } + /// ``` pub fn add(self, count: u64) -> Self { __ptr_add::(self, count) } /// Calculates the offset from the pointer. + /// + /// # Arguments + /// + /// * `count`: [u64] - The number of `size_of` bytes to decrease by. + /// + /// # Returns + /// + /// * [raw_ptr] - The pointer to the offset memory location. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(2); + /// let offset_ptr = ptr.add::(1); + /// let subbed_offset = offset_ptr.sub::(1); + /// assert(ptr == subbed_offset); + /// } + /// ``` pub fn sub(self, count: u64) -> Self { __ptr_sub::(self, count) } /// Reads the given type of value from the address. + /// + /// # Returns + /// + /// * [T] - The value in memory at the location of the pointer. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(1); + /// ptr.write(5); + /// assert(ptr.read::() == 5); + /// } + /// ``` pub fn read(self) -> T { if __is_reference_type::() { asm(ptr: self) { ptr: T } @@ -30,6 +102,25 @@ impl raw_ptr { } /// Copies `count * size_of` bytes from `self` to `dst`. + /// + /// # Arguments + /// + /// * `dst`: [raw_ptr] - Pointer to the location in memory to copy the bytes to. + /// * `count`: [u64] - The number of `size_of` bytes to copy. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr_1 = alloc::(1); + /// let ptr_2 = alloc::(1); + /// ptr_1.write(5); + /// ptr_1.copy_to::(ptr_2, 1); + /// assert(ptr_2.read::() == 5); + /// } + /// ``` pub fn copy_to(self, dst: Self, count: u64) { let len = __mul(count, __size_of::()); asm(dst: dst, src: self, len: len) { @@ -38,6 +129,20 @@ impl raw_ptr { } /// Writes the given value to the address. + /// + /// # Arguments + /// + /// * `val`: [T] - The value to write to memory. + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(1); + /// ptr.write(5); + /// assert(ptr.read::() == 5); + /// } + /// ``` pub fn write(self, val: T) { if __is_reference_type::() { asm(dst: self, src: val, count: __size_of_val(val)) { @@ -51,6 +156,22 @@ impl raw_ptr { } /// Writes the given byte to the address. + /// + /// # Arguments + /// + /// * `val`: [u8] - The bytes to write. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(1); + /// ptr.write_byte(5u8); + /// assert(ptr.read::() == 5u8); + /// } + /// ``` pub fn write_byte(self, val: u8) { let val_ptr = asm(r1: val) { r1: raw_ptr }; asm(ptr: self, val: val_ptr) { @@ -58,7 +179,23 @@ impl raw_ptr { }; } - /// reads a byte from the given address. + /// Reads a byte from the given address. + /// + /// # Returns + /// + /// * [u8] - The byte in memory. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(1); + /// ptr.write_byte(5u8); + /// assert(ptr.read_byte() == 5u8); + /// } + /// ``` pub fn read_byte(self) -> u8 { asm(r1: self, r2) { lb r2 r1 i0; @@ -66,14 +203,54 @@ impl raw_ptr { } } - /// Copies `count` bytes from `self` to `dst` + /// Copies `count` bytes from `self` to `dst`. + /// + /// # Arguments + /// + /// * `dst`: [raw_ptr] - Pointer to the location in memory to copy the bytes to. + /// * `count`: [u64] - The number of bytes to copy. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr_1 = alloc::(1); + /// let ptr_2 = alloc::(1); + /// ptr_1.write_byte(5u8); + /// ptr_1.copy_bytes_to(ptr_2, 1); + /// assert(ptr_2.read_byte() == 5u8); + /// } + /// ``` pub fn copy_bytes_to(self, dst: Self, count: u64) { asm(dst: dst, src: self, len: count) { mcp dst src len; }; } - /// Add a u64 offset to a raw_ptr + /// Add a `u64` offset to a `raw_ptr`. + /// + /// # Arguments + /// + /// * `count`: [u64] - The number of `u64` bytes to increase by. + /// + /// # Returns + /// + /// * [raw_ptr] - The pointer to the offset memory location. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(2); + /// let offset_ptr_1 = ptr.add::(1); + /// let offset_ptr_2 = ptr.add_uint_offset(1); + /// assert(offset_ptr_1 == offset_ptr_1); + /// } + /// ``` pub fn add_uint_offset(self, offset: u64) -> Self { asm(ptr: self, offset: offset, new) { add new ptr offset; @@ -81,7 +258,28 @@ impl raw_ptr { } } - /// Subtract a u64 offset from a raw_ptr + /// Subtract a `u64` offset from a `raw_ptr`. + /// + /// # Arguments + /// + /// * `count`: [u64] - The number of `u64` bytes to decrease by. + /// + /// # Returns + /// + /// * [raw_ptr] - The pointer to the offset memory location. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(2); + /// let offset_ptr = ptr.add::(1); + /// let subbed_offset = offset_ptr.sub_uint_offset(1); + /// assert(ptr == subbed_offset); + /// } + /// ``` pub fn sub_uint_offset(self, offset: u64) -> Self { asm(ptr: self, offset: offset, new) { sub new ptr offset; diff --git a/sway-lib-core/src/raw_slice.sw b/sway-lib-core/src/raw_slice.sw index 48e9f6a6203..eddd6906f19 100644 --- a/sway-lib-core/src/raw_slice.sw +++ b/sway-lib-core/src/raw_slice.sw @@ -2,35 +2,156 @@ library; use ::raw_ptr::*; +/// Trait to return a type as a `raw_slice`. pub trait AsRawSlice { + /// Converts self into a `raw_slice`. + /// + /// # Returns + /// + /// * [raw_slice] - The newly created `raw_slice` from self. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc_bytes; + /// + /// struct MyType { + /// ptr: raw_ptr, + /// len: u64 + /// } + /// + /// impl AsRawSlice for MyType { + /// fn as_raw_slice(self) -> raw_slice { + /// from_parts(self.ptr, self.len) + /// } + /// } + /// + /// fn foo() { + /// let my_type = MyType { + /// ptr: alloc_bytes(0), + /// len: 0 + /// } + /// let slice = my_type.as_raw_slice(); + /// assert(slice.ptr() == my_type.ptr); + /// assert(slice.number_of_bytes() == my_type.len); + /// } + /// ``` fn as_raw_slice(self) -> raw_slice; } +/// Returns a `raw_slice` from a pointer and length. +/// +/// # Arguments +/// +/// * `parts`: [(raw_ptr, u64)] - A location in memory and a length to become a `raw_slice`. +/// +/// # Returns +/// +/// * [raw_slice] - The newly created `raw_slice`. fn from_parts(parts: (raw_ptr, u64)) -> raw_slice { asm(ptr: parts) { ptr: raw_slice } } +/// Returns a pointer and length from a `raw_slice`. +/// +/// # Arguments +/// +/// * `slice`: [raw_slice] - The slice to be broken into its parts. +/// +/// # Returns +/// +/// * [(raw_ptr, u64)] - A tuple of the location in memory of the original `raw_slice` and its length. fn into_parts(slice: raw_slice) -> (raw_ptr, u64) { asm(ptr: slice) { ptr: (raw_ptr, u64) } } impl raw_slice { /// Forms a slice from a pointer and a length. + /// + /// # Arguments + /// + /// * `ptr`: [raw_ptr] - The pointer to the location in memory. + /// * `count`: [u64] - The number of `__size_of::` bytes. + /// + /// # Returns + /// + /// * [raw_slice] - The newly created `raw_slice`. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(1); + /// let slice = raw_slice::from_parts::(ptr, 1); + /// assert(slice.len::() == 1); + /// } + /// ``` pub fn from_parts(ptr: raw_ptr, count: u64) -> Self { from_parts((ptr, __mul(count, __size_of::()))) } /// Returns the pointer to the slice. + /// + /// # Returns + /// + /// * [raw_ptr] - The pointer to the location in memory of the `raw_slice`. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(1); + /// let slice = raw_slice::from_parts::(ptr, 1); + /// let slice_ptr = slice.ptr(); + /// assert(slice_ptr == ptr); + /// } + /// ``` pub fn ptr(self) -> raw_ptr { into_parts(self).0 } /// Returns the number of elements in the slice. + /// + /// # Returns + /// + /// * [u64] - The length of the slice based on `size_of::`. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(1); + /// let slice = raw_slice::from_parts::(ptr, 1); + /// assert(slice.len::() == 1); + /// } + /// ``` pub fn len(self) -> u64 { __div(into_parts(self).1, __size_of::()) } /// Returns the number of elements in the slice when the elements are bytes. + /// + /// # Returns + /// + /// * [u64] - The number of bytes in the `raw_slice`. + /// + /// # Examples + /// + /// ```sway + /// use std::alloc::alloc; + /// + /// fn foo() { + /// let ptr = alloc::(1); + /// let slice = raw_slice::from_parts::(ptr, 1); + /// assert(slice.number_of_bytes() == 8); + /// } + /// ``` pub fn number_of_bytes(self) -> u64 { into_parts(self).1 } diff --git a/sway-lib-core/src/storage.sw b/sway-lib-core/src/storage.sw index 9437d1dbad1..3eb08801233 100644 --- a/sway-lib-core/src/storage.sw +++ b/sway-lib-core/src/storage.sw @@ -1,13 +1,20 @@ library; -/// Describes a location in storage specified by the `b256` key of a particular storage slot and an +/// Describes a location in storage. +/// +/// # Additional Information +/// +/// The location in storage is specified by the `b256` key of a particular storage slot and an /// offset, in words, from the start of the storage slot at `key`. The parameter `T` is the type of /// the data to be read from or written to at `offset`. /// `field_id` is a unique identifier for the storage field being referred to, it is different even /// for multiple zero sized fields that might live at the same location but /// represent different storage constructs. pub struct StorageKey { + /// The assigned location in storage. slot: b256, + /// The assigned offset based on the data structure `T`. offset: u64, + /// A unqiue identifier. field_id: b256, } diff --git a/sway-lib-std/src/address.sw b/sway-lib-std/src/address.sw index d3f11c48acc..6b725aea1a6 100644 --- a/sway-lib-std/src/address.sw +++ b/sway-lib-std/src/address.sw @@ -12,6 +12,7 @@ use ::outputs::{Output, output_amount, output_count, output_type}; /// The `Address` type, a struct wrapper around the inner `b256` value. pub struct Address { + /// The underlying raw `b256` data of the address. value: b256, } @@ -23,10 +24,46 @@ impl core::ops::Eq for Address { /// Functions for casting between the `b256` and `Address` types. impl From for Address { + /// Casts raw `b256` data to an `Address`. + /// + /// # Arguments + /// + /// * `bits`: [b256] - The raw `b256` data to be casted. + /// + /// # Returns + /// + /// * [Address] - The newly created `Address` from the raw `b256`. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let address = Address::from(ZERO_B256); + /// } + /// ``` fn from(bits: b256) -> Self { Self { value: bits } } + /// Casts an `Address` to raw `b256` data. + /// + /// # Returns + /// + /// * [b256] - The underlying raw `b256` data of the `Address`. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let address = Address::from(ZERO_B256); + /// let b256_data = address.into(); + /// assert(b256_data == ZERO_B256); + /// } + /// ``` fn into(self) -> b256 { self.value } @@ -36,25 +73,26 @@ impl Address { /// Transfer `amount` coins of type `asset_id` and send them to /// the Address. /// - /// ### Arguments + /// # Arguments /// - /// * `asset_id` - The `AssetId` of the token to transfer. - /// * `amount` - The amount of tokens to transfer. + /// * `asset_id`: [AssetId] - The `AssetId` of the token to transfer. + /// * `amount`: [u64] - The amount of tokens to transfer. /// - /// ### Reverts + /// # Reverts /// - /// * If `amount` is greater than the contract balance for `asset_id`. - /// * If `amount` is equal to zero. - /// * If there are no free variable outputs. + /// * When `amount` is greater than the contract balance for `asset_id`. + /// * When `amount` is equal to zero. + /// * When there are no free variable outputs. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::constants::{BASE_ASSET_ID, ZERO_B256}; /// - /// // replace the zero Address with your desired Address - /// let address = Address::from(ZERO_B256); - /// address.transfer(BASE_ASSET_ID, 500) + /// fn foo() { + /// let address = Address::from(ZERO_B256); + /// address.transfer(BASE_ASSET_ID, 500); + /// } /// ``` pub fn transfer(self, asset_id: AssetId, amount: u64) { // maintain a manual index as we only have `while` loops in sway atm: @@ -84,18 +122,20 @@ impl Address { /// Mint `amount` coins of the current contract's `asset_id` and send them to /// the Address. /// - /// ### Arguments + /// # Arguments /// - /// * `amount` - The amount of tokens to mint. + /// * `sub_id`: [SubId] - The sub id of the token to mint. + /// * `amount`: [u64] - The amount of tokens to mint. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::constants::ZERO_B256; /// - /// // replace the zero Address with your desired Address - /// let address = Address::from(ZERO_B256); - /// address.mint_to(ZERO_B256, 500); + /// fn foo() { + /// let address = Address::from(ZERO_B256); + /// address.mint_to(ZERO_B256, 500); + /// } /// ``` pub fn mint_to(self, sub_id: SubId, amount: u64) { asm(r1: amount, r2: sub_id) { diff --git a/sway-lib-std/src/alloc.sw b/sway-lib-std/src/alloc.sw index ad2511904c8..5d3790badb9 100644 --- a/sway-lib-std/src/alloc.sw +++ b/sway-lib-std/src/alloc.sw @@ -3,6 +3,8 @@ library; /// Allocates zeroed memory on the heap. /// +/// # Additional Information +/// /// In the FuelVM, the heap begins at `VM_MAX_RAM` and grows downward. /// The heap pointer(`$hp`) always points to the first allocated byte. /// @@ -26,6 +28,25 @@ library; /// ``` /// For more information, see the Fuel Spec for [VM Initialization](https://fuellabs.github.io/fuel-specs/master/vm#vm-initialization) /// and the VM Instruction Set for [Memory Allocation](https://fuellabs.github.io/fuel-specs/master/vm/instruction_set.html#aloc-allocate-memory). +/// +/// # Arguments +/// +/// * `count`: [u64] - The number of `size_of` bytes to allocate onto the heap. +/// +/// # Returns +/// +/// * [raw_ptr] - The pointer to the newly allocated memory. +/// +/// # Examples +/// +/// ```sway +/// use std::alloc::alloc; +/// +/// fn foo() { +/// let ptr = alloc::(2); +/// assert(!ptr.is_null()); +/// } +/// ``` pub fn alloc(count: u64) -> raw_ptr { asm(size: __size_of::() * count, ptr) { aloc size; @@ -35,6 +56,29 @@ pub fn alloc(count: u64) -> raw_ptr { } /// Reallocates the given area of memory. +/// +/// # Arguments +/// +/// * `ptr`: [raw_ptr] - The pointer to the area of memory to reallocate. +/// * `count`: [u64] - The number of `size_of` bytes kept when reallocating. These are not set to 0. +/// * `new_count`: [u64] - The number of new `size_of` bytes to allocate. These are set to 0. +/// +/// # Returns +/// +/// * [raw_ptr] - The pointer to the newly reallocated memory. +/// +/// # Examples +/// +/// ```sway +/// use std::alloc::{alloc, realloc}; +/// +/// fn foo() { +/// let ptr = alloc::(1); +/// ptr.write(5); +/// let reallocated_ptr = realloc::(ptr, 1, 2); +/// assert(reallocated_ptr.read::() == 5); +/// } +/// ``` pub fn realloc(ptr: raw_ptr, count: u64, new_count: u64) -> raw_ptr { if new_count > count { let new_ptr = alloc::(new_count); @@ -48,6 +92,25 @@ pub fn realloc(ptr: raw_ptr, count: u64, new_count: u64) -> raw_ptr { } /// Allocates zeroed memory on the heap in individual bytes. +/// +/// # Arguments +/// +/// * `count`: [u64] - The number of bytes to allocate onto the heap. +/// +/// # Returns +/// +/// * [raw_ptr] - The pointer to the newly allocated memory. +/// +/// # Examples +/// +/// ```sway +/// use std::alloc::alloc_bytes; +/// +/// fn foo() { +/// let ptr = alloc_bytes(2); +/// assert(!ptr.is_null()); +/// } +/// ``` pub fn alloc_bytes(count: u64) -> raw_ptr { asm(size: count, ptr) { aloc size; @@ -57,6 +120,29 @@ pub fn alloc_bytes(count: u64) -> raw_ptr { } /// Reallocates the given area of memory in individual bytes. +/// +/// # Arguments +/// +/// * `ptr`: [raw_ptr] - The pointer to the area of memory to reallocate. +/// * `count`: [u64] - The number of bytes kept when reallocating. These are not set to 0. +/// * `new_count`: [u64] - The number of new bytes to allocate. These are set to 0. +/// +/// # Returns +/// +/// * [raw_ptr] - The pointer to the newly reallocated memory. +/// +/// # Examples +/// +/// ```sway +/// use std::alloc::{alloc_bytes, realloc_bytes}; +/// +/// fn foo() { +/// let ptr = alloc_bytes(8); +/// ptr.write(5); +/// let reallocated_ptr = realloc_bytes(ptr, 8, 16); +/// assert(reallocated_ptr.read::() == 5); +/// } +/// ``` pub fn realloc_bytes(ptr: raw_ptr, count: u64, new_count: u64) -> raw_ptr { if new_count > count { let new_ptr = alloc_bytes(new_count); diff --git a/sway-lib-std/src/assert.sw b/sway-lib-std/src/assert.sw index 6f055280b65..d345e303bc7 100644 --- a/sway-lib-std/src/assert.sw +++ b/sway-lib-std/src/assert.sw @@ -7,18 +7,21 @@ use ::error_signals::{FAILED_ASSERT_SIGNAL, FAILED_ASSERT_EQ_SIGNAL}; /// Asserts that the given `condition` will always be `true` during runtime. +/// +/// # Additional Information +/// /// To check for conditions that may not be `true`, use `std::revert::require` instead. /// For more information, see the Wiki article on [Assertion](https://en.wikipedia.org/wiki/Assertion_(software_development)#Comparison_with_error_handling). /// -/// ### Arguments +/// # Arguments /// -/// * `condition` - The condition which will be asserted to be `true`. +/// * `condition`: [bool] - The condition which will be asserted to be `true`. /// -/// ### Reverts +/// # Reverts /// -/// Reverts when `condition` is `false`. +/// * Reverts when `condition` is `false`. /// -/// ### Examples +/// # Examples /// /// ```sway /// fn foo(a: u64, b: u64) { @@ -35,16 +38,16 @@ pub fn assert(condition: bool) { /// Asserts that the given values `v1` & `v2` will always be equal during runtime. /// -/// ### Arguments +/// # Arguments /// -/// * `v1` - The first value to compare. -/// * `v2` - The second value to compare. +/// * `v1`: [T] - The first value to compare. +/// * `v2`: [T] - The second value to compare. /// -/// ### Reverts +/// # Reverts /// -/// Reverts when `v1` != `v2`. +/// * Reverts when `v1` != `v2`. /// -/// ### Examples +/// # Examples /// /// ```sway /// fn foo(a: u64, b: u64) { diff --git a/sway-lib-std/src/auth.sw b/sway-lib-std/src/auth.sw index fb6472ca68d..bbeec129a80 100644 --- a/sway-lib-std/src/auth.sw +++ b/sway-lib-std/src/auth.sw @@ -10,12 +10,34 @@ use ::inputs::{Input, input_count, input_owner, input_type}; /// The error type used when an `Identity` cannot be determined. pub enum AuthError { + /// The caller is external, but the inputs to the transaction are not all owned by the same address. InputsNotAllOwnedBySameAddress: (), } /// Returns `true` if the caller is external (i.e. a `script`). -/// Otherwise, returns `false`. +/// Otherwise, if the caller is a contract, returns `false`. +/// +/// # Additional Information +/// /// For more information refer to the [VM Instruction Set](https://fuellabs.github.io/fuel-specs/master/vm/instruction_set#gm-get-metadata). +/// +/// # Returns +/// +/// * [bool] - `true` if the caller is external, `false` otherwise. +/// +/// # Examples +/// +/// ```sway +/// use std::auth::caller_is_external; +/// +/// fn foo() { +/// if caller_is_external() { +/// log("Caller is external.") +/// } else { +/// log("Caller is a contract.") +/// } +/// } +/// ``` pub fn caller_is_external() -> bool { asm(r1) { gm r1 i1; @@ -24,7 +46,27 @@ pub fn caller_is_external() -> bool { } /// If the caller is internal, returns the contract ID of the caller. -/// Otherwise, undefined behavior. +/// +/// # Additional Information +/// +/// External calls result in undefined behaviour. +/// +/// # Returns +/// +/// * [ContractId] - The contract ID of the caller. +/// +/// # Examples +/// +/// ```sway +/// use std::auth::{caller_is_external, caller_contract_id}; +/// +/// fn foo() { +/// if !caller_is_external() { +/// let caller_contract_id = caller_contract_id(); +/// log(caller_contract_id); +/// } +/// } +/// ``` pub fn caller_contract_id() -> ContractId { ContractId::from(asm(r1) { gm r1 i2; @@ -34,6 +76,26 @@ pub fn caller_contract_id() -> ContractId { /// Get the `Identity` (i.e. `Address` or `ContractId`) from which a call was made. /// Returns a `Ok(Identity)`, or `Err(AuthError)` if an identity cannot be determined. +/// +/// # Additional Information +/// +/// Returns a Err if the caller is external and the inputs to the transaction are not all owned by the same address. +/// +/// # Returns +/// +/// * [Result] - `Ok(Identity)` if the identity can be determined, `Err(AuthError)` otherwise. +/// +/// # Examples +/// +/// ```sway +/// fn foo() { +/// match msg_sender() { +/// Ok(Identity::Address(address)) => log(address), +/// Ok(Identity::ContractId(contract_id)) => log(contract_id), +/// Err(AuthError::InputsNotAllOwnedBySameAddress) => log("Inputs not all owned by same address."), +/// } +/// } +/// ``` pub fn msg_sender() -> Result { if caller_is_external() { inputs_owner() @@ -45,6 +107,28 @@ pub fn msg_sender() -> Result { /// Get the owner of the inputs (of type `Input::Coin` or `Input::Message`) to a /// `TransactionScript` if they all share the same owner. +/// +/// # Additional Information +/// +/// Will never return a Ok(Identity::ContractId). +/// +/// # Returns +/// +/// * [Result] - `Ok(Identity)` if the owner can be determined, `Err(AuthError)` otherwise. +/// +/// # Examples +/// +/// ```sway +/// use std::auth::inputs_owner; +/// +/// fn foo() { +/// match inputs_owner() { +/// Ok(Identity::Address(address)) => log(address), +/// Ok(Identity::ContractId(_)) => log("Hell froze over."), +/// Err(AuthError::InputsNotAllOwnedBySameAddress) => log("Inputs not all owned by same address."), +/// } +/// } +/// ``` fn inputs_owner() -> Result { let inputs = input_count(); let mut candidate = None; diff --git a/sway-lib-std/src/b512.sw b/sway-lib-std/src/b512.sw index 45fc47df2d0..63ec5b0baad 100644 --- a/sway-lib-std/src/b512.sw +++ b/sway-lib-std/src/b512.sw @@ -8,6 +8,7 @@ use ::convert::From; /// Stores two `b256`s in contiguous memory. /// Guaranteed to be contiguous for use with ec-recover: `std::ecr::ec_recover`. pub struct B512 { + /// The two `b256`s that make up the `B512`. bytes: [b256; 2], } @@ -33,6 +34,20 @@ impl From<(b256, b256)> for B512 { /// Methods on the `B512` type. impl B512 { /// Initializes a new, zeroed `B512`. + /// + /// # Returns + /// + /// * [B512] - A zero value B512. + /// + /// # Examples + /// + /// ```sway + /// use std::b512::B512; + /// + /// fn foo() { + /// let zero = B512::new(); + /// } + /// ``` pub fn new() -> Self { Self { bytes: [ZERO_B256, ZERO_B256], diff --git a/sway-lib-std/src/block.sw b/sway-lib-std/src/block.sw index 3eff124f378..bcf3ea33ed0 100644 --- a/sway-lib-std/src/block.sw +++ b/sway-lib-std/src/block.sw @@ -6,11 +6,28 @@ use ::constants::ZERO_B256; use ::result::Result::{self, *}; use ::logging::log; +/// Error type for when the block hash cannot be found. enum BlockHashError { + /// Error returned when the block hash cannot be found. BlockHeightTooHigh: (), } /// Get the current block height. +/// +/// # Returns +/// +/// * [u32] - The current block height. +/// +/// # Examples +/// +/// ```sway +/// use std::block::height; +/// +/// fn foo() { +/// let current_height = height(); +/// log(current_height); +/// } +/// ``` pub fn height() -> u32 { asm(height) { bhei height; @@ -19,11 +36,57 @@ pub fn height() -> u32 { } /// Get the TAI64 timestamp of the current block. +/// +/// # Additional Information +/// +/// The TAI64 timestamp begins at 2^62 seconds before 1970, and ends at 2^62 seconds after 1970, +/// with a TAI second defined as the duration of 9192631770 periods of the radiation corresponding +/// to the transition between the two hyperfine levels of the ground state of the cesium atom. +/// +/// # Returns +/// +/// * [u64] - The TAI64 timestamp of the current block. +/// +/// # Examples +/// +/// ```sway +/// use std::block::timestamp; +/// +/// fn foo() { +/// let current_timestamp = timestamp(); +/// log(current_timestamp); +/// } +/// ``` pub fn timestamp() -> u64 { timestamp_of_block(height()) } /// Get the TAI64 timestamp of a block at a given `block_height`. +/// +/// # Additional Information +/// +/// The TAI64 timestamp begins at 2^62 seconds before 1970, and ends at 2^62 seconds after 1970, +/// with a TAI second defined as the duration of 9192631770 periods of the radiation corresponding +/// to the transition between the two hyperfine levels of the ground state of the cesium atom. +/// +/// # Arguments +/// +/// * `block_height`: [u32] - The height of the block to get the timestamp of. +/// +/// # Returns +/// +/// * [u64] - The TAI64 timestamp of the block at `block_height`. +/// +/// # Examples +/// +/// ```sway +/// use std::block::timestamp_of_block; +/// +/// fn foo() { +/// let timestamp_of_block_100 = timestamp_of_block(100u32); +/// log(timestamp_of_block_100); +/// } +/// ``` pub fn timestamp_of_block(block_height: u32) -> u64 { asm(timestamp, height: block_height) { time timestamp height; @@ -32,6 +95,21 @@ pub fn timestamp_of_block(block_height: u32) -> u64 { } /// Get the header hash of the block at height `block_height` +/// +/// # Returns +/// +/// * [Result] - The header hash of the block at `block_height`, or a [BlockHashError] if the block is not found. +/// +/// # Examples +/// +/// ```sway +/// use std::block::block_header_hash; +/// +/// fn foo() { +/// let header_hash_of_block_100 = block_header_hash(100u32); +/// log(header_hash_of_block_100); +/// } +/// ``` pub fn block_header_hash(block_height: u32) -> Result { let mut header_hash = ZERO_B256; diff --git a/sway-lib-std/src/bytes.sw b/sway-lib-std/src/bytes.sw index 8125a49c9fc..ae02397c8b9 100644 --- a/sway-lib-std/src/bytes.sw +++ b/sway-lib-std/src/bytes.sw @@ -52,24 +52,33 @@ impl RawBytes { /// A type used to represent raw bytes. pub struct Bytes { + /// A barebones struct for the bytes. buf: RawBytes, + /// The number of bytes being stored. len: u64, } impl Bytes { /// Constructs a new, empty `Bytes`. /// - /// The `Bytes` will not allocate until elements are pushed onto it. + /// # Additional Information /// - /// ### Examples + /// The struct will not allocate until elements are pushed onto it. + /// + /// # Returns + /// + /// * [Bytes] - A new, empty `Bytes`. + /// + /// # Examples /// /// ```sway /// use std::bytes::Bytes; /// - /// let bytes = Bytes::new(); - /// // does not allocate - /// assert(bytes.len() == 0); - /// assert(bytes.capacity() == 0); + /// fn foo() { + /// let bytes = Bytes::new(); + /// assert(bytes.len() == 0); + /// assert(bytes.capacity() == 0); + /// } /// ``` pub fn new() -> Self { Self { @@ -80,22 +89,34 @@ impl Bytes { /// Constructs a new, empty `Bytes` with the specified capacity. /// + /// # Additional Information + /// /// The `Bytes` will be able to hold exactly `capacity` bytes without /// reallocating. If `capacity` is zero, the `Bytes` will not allocate. /// /// It is important to note that although the returned `Bytes` has the - /// capacity specified, the vector will have a zero length. + /// capacity specified, the type will have a zero length. /// - /// ### Examples + /// # Arguments + /// + /// * `capacity`: [u64] - The capacity with which to initialize the `Bytes`. + /// + /// # Returns + /// + /// * [Bytes] - A new, empty `Bytes` with the specified capacity. + /// + /// # Examples /// /// ```sway /// use std::bytes::Bytes; /// - /// let bytes = Bytes::with_capacity(2); - /// // does not allocate - /// bytes.push(5); - /// // does not re-allocate - /// bytes.push(10); + /// fn foo() { + /// let bytes = Bytes::with_capacity(2); + /// // does not allocate + /// bytes.push(5); + /// // does not re-allocate + /// bytes.push(10); + /// } /// ``` pub fn with_capacity(capacity: u64) -> Self { Self { @@ -106,17 +127,23 @@ impl Bytes { /// Appends an element to the back of a `Bytes` collection. /// - /// ### Examples + /// # Arguments + /// + /// * `byte`: [u8] - The element to be pushed onto the `Bytes`. + /// + /// # Examples /// /// ```sway /// use std::bytes::Bytes; /// - /// let mut bytes = Bytes::new(); - /// let a = 5u8; - /// let b = 7u8; - /// bytes.push(a); - /// bytes.push(b); - /// assert(bytes.len() == 2); + /// fn foo() { + /// let mut bytes = Bytes::new(); + /// let a = 5u8; + /// let b = 7u8; + /// bytes.push(a); + /// bytes.push(b); + /// assert(bytes.len() == 2); + /// } /// ``` pub fn push(ref mut self, byte: u8) { // If there is insufficient capacity, grow the buffer. @@ -138,20 +165,26 @@ impl Bytes { /// Removes the last element from a `Bytes` and returns it, or `None` if it /// is empty. /// - /// ### Examples + /// # Returns /// - /// ```sway - /// use std::bytes::Bytes; + /// * [Option] - The last element of the `Bytes`, or `None` if it is empty. /// - /// let bytes = Bytes::new(); + /// # Examples /// - /// let res = bytes.pop(); - /// assert(res.is_none()); + /// ```sway + /// use std::bytes::Bytes; /// - /// bytes.push(5); - /// let res = bytes.pop(); - /// assert(res.unwrap() == 5); - /// assert(bytes.is_empty()); + /// fn foo() { + /// let bytes = Bytes::new(); + /// + /// let res = bytes.pop(); + /// assert(res.is_none()); + /// + /// bytes.push(5); + /// let res = bytes.pop(); + /// assert(res.unwrap() == 5); + /// assert(bytes.is_empty()); + /// } /// ``` pub fn pop(ref mut self) -> Option { if self.len == 0 { @@ -167,19 +200,29 @@ impl Bytes { /// Returns `Some(byte)` at `index`, or `None` if `index` is out of /// bounds. /// - /// ### Examples + /// # Arguments + /// + /// * `index`: [u64] - The index of the element to be returned. + /// + /// # Returns + /// + /// * [Option] - The element at the specified index, or `None` if the index is out of bounds. + /// + /// # Examples /// /// ```sway /// use std::bytes::Byte; /// - /// let bytes = Bytes::new(); - /// bytes.push(5u8); - /// bytes.push(10u8); - /// bytes.push(15u8); - /// let item = bytes.get(1).unwrap(); - /// assert(item == 10u8); - /// let opt = bytes.get(10); - /// assert(opt.is_none()); // index out of bounds + /// fn foo() { + /// let bytes = Bytes::new(); + /// bytes.push(5u8); + /// bytes.push(10u8); + /// bytes.push(15u8); + /// let item = bytes.get(1).unwrap(); + /// assert(item == 10u8); + /// let opt = bytes.get(10); + /// assert(opt.is_none()); // index out of bounds + /// } /// ``` pub fn get(self, index: u64) -> Option { // First check that index is within bounds. @@ -194,36 +237,38 @@ impl Bytes { /// Updates an element at position `index` with a new element `value`. /// - /// ### Arguments + /// # Arguments /// - /// * index - The index of the element to be set - /// * value - The value of the element to be set + /// * `index`: [u64] - The index of the element to be set. + /// * `value`: [u8] - The value of the element to be set. /// - /// ### Reverts + /// # Reverts /// - /// * If `index` is greater than or equal to the length of Bytes. + /// * When `index` is greater than or equal to the length of Bytes. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::bytes::Bytes; /// - /// let bytes = Bytes::new(); - /// let a = 5u8; - /// let b = 7u8; - /// let c = 9u8; - /// bytes.push(a); - /// bytes.push(b); - /// bytes.push(c); - /// - /// let d = 11u8; - /// - /// bytes.set(1, d); - /// - /// assert(bytes.len() == 3); - /// assert(bytes.get(0).unwrap() == a); - /// assert(bytes.get(1).unwrap() == d); - /// assert(bytes.get(2).unwrap() == c); + /// fn foo() { + /// let bytes = Bytes::new(); + /// let a = 5u8; + /// let b = 7u8; + /// let c = 9u8; + /// bytes.push(a); + /// bytes.push(b); + /// bytes.push(c); + /// + /// let d = 11u8; + /// + /// bytes.set(1, d); + /// + /// assert(bytes.len() == 3); + /// assert(bytes.get(0).unwrap() == a); + /// assert(bytes.get(1).unwrap() == d); + /// assert(bytes.get(2).unwrap() == c); + /// } /// ``` pub fn set(ref mut self, index: u64, value: u8) { assert(index < self.len); @@ -236,29 +281,36 @@ impl Bytes { /// Inserts an element at position `index` within the Bytes, shifting all /// elements after it to the right. /// - /// ### Reverts + /// # Arguments /// - /// * If `index > len`. + /// * `index`: [u64] - The index at which to insert the element. + /// * `element`: [u8] - The element to be inserted. /// - /// ### Examples + /// # Reverts + /// + /// * When `index > len`. + /// + /// # Examples /// /// ```sway /// use std::bytes::Byte; /// - /// let vec = Vec::new(); - /// let a = 11u8; - /// let b = 11u8; - /// let c = 11u8; - /// let d = 11u8; - /// vec.push(a); - /// vec.push(b); - /// vec.push(c); - /// bytes.insert(1, d); - /// - /// assert(bytes.get(0).unwrap() == a); - /// assert(bytes.get(1).unwrap() == d); - /// assert(bytes.get(2).unwrap() == b); - /// assert(bytes.get(3).unwrap() == c); + /// fn foo() { + /// let bytes = Bytes::new(); + /// let a = 11u8; + /// let b = 11u8; + /// let c = 11u8; + /// let d = 11u8; + /// bytes.push(a); + /// bytes.push(b); + /// bytes.push(c); + /// bytes.insert(1, d); + /// + /// assert(bytes.get(0).unwrap() == a); + /// assert(bytes.get(1).unwrap() == d); + /// assert(bytes.get(2).unwrap() == b); + /// assert(bytes.get(3).unwrap() == c); + /// } /// ``` pub fn insert(ref mut self, index: u64, element: u8) { assert(index <= self.len); @@ -292,24 +344,34 @@ impl Bytes { /// Removes and returns the element at position `index` within the Bytes, /// shifting all elements after it to the left. /// - /// ### Reverts + /// # Arguments /// - /// * If `index >= self.len` + /// * `index`: [u64] - The index of the element to be removed. /// - /// ### Examples + /// # Returns + /// + /// * [u8] - The element at the specified index. + /// + /// # Reverts + /// + /// * When `index >= self.len`. + /// + /// # Examples /// /// ```sway /// use std::bytes::Byte; /// - /// let bytes = Byte::new(); - /// bytes.push(5); - /// bytes.push(10); - /// bytes.push(15); - /// let item = bytes.remove(1); - /// assert(item == 10); - /// assert(bytes.get(0).unwrap() == 5); - /// assert(bytes.get(1).unwrap() == 15); - /// assert(bytes.get(2).is_none()); + /// fn foo() { + /// let bytes = Byte::new(); + /// bytes.push(5); + /// bytes.push(10); + /// bytes.push(15); + /// let item = bytes.remove(1); + /// assert(item == 10); + /// assert(bytes.get(0).unwrap() == 5); + /// assert(bytes.get(1).unwrap() == 15); + /// assert(bytes.get(2).is_none()); + /// } /// ``` pub fn remove(ref mut self, index: u64) -> u8 { // Panic if index >= length. @@ -336,33 +398,35 @@ impl Bytes { /// Swaps two elements. /// - /// ### Arguments + /// # Arguments /// - /// * element1_index - The index of the first element - /// * element2_index - The index of the second element + /// * `element1_index`: [u64] - The index of the first element. + /// * `element2_index`: [u64] - The index of the second element. /// - /// ### Reverts + /// # Reverts /// - /// * If `element1_index` or `element2_index` is greater than or equal to the length of `Bytes`. + /// * When `element1_index` or `element2_index` is greater than or equal to the length of `Bytes`. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::bytes::Bytes; /// - /// let bytes = Bytes::new(); - /// let a = 5u8; - /// let b = 7u8; - /// let c = 9u8; - /// bytes.push(a); - /// bytes.push(b); - /// bytes.push(c); - /// - /// bytes.swap(0, 1); - /// - /// assert(bytes.get(0).unwrap() == b); - /// assert(bytes.get(1).unwrap() == a); - /// assert(bytes.get(2).unwrap() == c); + /// fn foo() { + /// let bytes = Bytes::new(); + /// let a = 5u8; + /// let b = 7u8; + /// let c = 9u8; + /// bytes.push(a); + /// bytes.push(b); + /// bytes.push(c); + /// + /// bytes.swap(0, 1); + /// + /// assert(bytes.get(0).unwrap() == b); + /// assert(bytes.get(1).unwrap() == a); + /// assert(bytes.get(2).unwrap() == c); + /// } /// ``` pub fn swap(ref mut self, element1_index: u64, element2_index: u64) { assert(element1_index < self.len); @@ -384,37 +448,65 @@ impl Bytes { /// Gets the capacity of the allocation. /// - /// ### Examples + /// # Returns + /// + /// * [u64] - The capacity of the allocation. + /// + /// # Examples /// /// ```sway /// use std::bytes::Bytes; /// - /// let bytes = Bytes::with_capacity(5); - /// let cap = bytes.capacity(); - /// assert(cap == 5); + /// fn foo() { + /// let bytes = Bytes::with_capacity(5); + /// let cap = bytes.capacity(); + /// assert(cap == 5); + /// } /// ``` pub fn capacity(self) -> u64 { self.buf.cap } + /// Gets the length of the `Bytes`. + /// + /// # Returns + /// + /// * [u64] - The length of the `Bytes`. + /// + /// # Examples + /// + /// ```sway + /// use std::bytes::Bytes; + /// + /// fn foo() { + /// let bytes = Bytes::new(); + /// assert(bytes.len() == 0); + /// bytes.push(5); + /// assert(bytes.len() == 1); + /// } + /// ``` pub fn len(self) -> u64 { self.len } /// Clears the `Bytes`, removing all values. /// + /// # Additional Information + /// /// Note that this method has no effect on the allocated capacity /// of the Bytes. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std:bytes::Bytes; /// - /// let bytes = Bytes::new(); - /// bytes.push(5); - /// bytes.clear() - /// assert(bytes.is_empty()); + /// fn foo() { + /// let bytes = Bytes::new(); + /// bytes.push(5); + /// bytes.clear() + /// assert(bytes.is_empty()); + /// } /// ``` pub fn clear(ref mut self) { self.buf.ptr = alloc_bytes(0); @@ -422,19 +514,25 @@ impl Bytes { self.buf.cap = 0; } - /// Returns `true` if the vector contains no elements. + /// Returns `true` if the type contains no elements. /// - /// ### Examples + /// # Returns + /// + /// * [bool] - `true` if the type contains no elements, `false` otherwise. + /// + /// # Examples /// /// ```sway /// use std:bytes::Bytes; /// - /// let bytes = Bytes::new(); - /// assert(bytes.is_empty()); - /// bytes.push(5); - /// assert(!bytes.is_empty()); - /// bytes.clear() - /// assert(bytes.is_empty()); + /// fn foo() { + /// let bytes = Bytes::new(); + /// assert(bytes.is_empty()); + /// bytes.push(5); + /// assert(!bytes.is_empty()); + /// bytes.clear() + /// assert(bytes.is_empty()); + /// } /// ``` pub fn is_empty(self) -> bool { self.len == 0 @@ -442,16 +540,22 @@ impl Bytes { /// Returns the `SHA-2-256` hash of the elements. /// - /// ### Examples + /// # Returns + /// + /// * [b256] - The `SHA-2-256` hash of the elements. + /// + /// # Examples /// /// ```sway /// use std:bytes::Bytes; /// - /// let bytes = Bytes::new(); - /// bytes.push(1); - /// bytes.push(2); - /// bytes.push(3); - /// let sha256_hash = bytes.sha256(); + /// fn foo() { + /// let bytes = Bytes::new(); + /// bytes.push(1); + /// bytes.push(2); + /// bytes.push(3); + /// let sha256_hash = bytes.sha256(); + /// } /// ``` pub fn sha256(self) -> b256 { let mut result_buffer = b256::min(); @@ -463,16 +567,22 @@ impl Bytes { /// Returns the `KECCAK-256` hash of the elements. /// - /// ### Examples + /// # Returns + /// + /// * [b256] - The `KECCAK-256` hash of the elements. + /// + /// # Examples /// /// ```sway /// use std:bytes::Bytes; /// - /// let bytes = Bytes::new(); - /// bytes.push(1); - /// bytes.push(2); - /// bytes.push(3); - /// let keccak256_hash = bytes.keccak256(); + /// fn foo() { + /// let bytes = Bytes::new(); + /// bytes.push(1); + /// bytes.push(2); + /// bytes.push(3); + /// let keccak256_hash = bytes.keccak256(); + /// } /// ``` pub fn keccak256(self) -> b256 { let mut result_buffer = b256::min(); @@ -487,31 +597,38 @@ impl Bytes { impl Bytes { /// Divides one Bytes into two at an index. /// + /// # Additional Information + /// /// The first will contain all indices from `[0, mid)` (excluding the index /// `mid` itself) and the second will contain all indices from `[mid, len)` /// (excluding the index `len` itself). /// - /// ### Arguments + /// # Arguments /// - /// * mid - Index at which the Bytes is to be split + /// * `mid`: [u64] - Index at which the Bytes is to be split. /// - /// ### Reverts + /// # Reverts /// - /// * if `mid > self.len` + /// * When `mid > self.len`. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std:bytes::Bytes; /// - /// let (mut bytes, a, b, c) = setup(); - /// assert(bytes.len() == 3); - /// let mid = 1; - /// let (left, right) = bytes.split_at(mid); - /// assert(left.capacity() == mid); - /// assert(right.capacity() == bytes.len() - mid); - /// assert(left.len() == 1); - /// assert(right.len() == 2); + /// fn foo() { + /// let mut bytes = Bytes::new(); + /// bytes.push(5u8); + /// bytes.push(7u8); + /// bytes.push(9u8); + /// assert(bytes.len() == 3); + /// let mid = 1; + /// let (left, right) = bytes.split_at(mid); + /// assert(left.capacity() == mid); + /// assert(right.capacity() == bytes.len() - mid); + /// assert(left.len() == 1); + /// assert(right.len() == 2); + /// } /// ``` pub fn split_at(self, mid: u64) -> (Self, Self) { assert(self.len >= mid); @@ -537,36 +654,37 @@ impl Bytes { /// Moves all elements of `other` into `self`, leaving `other` empty. /// - /// ### Arguments + /// # Arguments /// - /// * other - The Bytes to append to self. + /// * `other`: [Bytes] - The Bytes to append to self. /// - /// ### Examples + /// # Examples /// /// ```sway /// /// use std:bytes::Bytes; /// - /// - /// let mut bytes = Bytes::new(); - /// bytes.push(5u8); - /// bytes.push(7u8); - /// bytes.push(9u8); - /// assert(bytes.len() == 3); - /// - /// let mut bytes2 = Bytes::new(); - /// bytes2.push(5u8); - /// bytes2.push(7u8); - /// bytes2.push(9u8); - /// assert(bytes2.len() == 3); - /// - /// let first_length = bytes.len(); - /// let second_length = bytes2.len(); - /// let first_cap = bytes.capacity(); - /// let second_cap = bytes2.capacity(); - /// bytes.append(bytes2); - /// assert(bytes.len() == first_length + second_length); - /// assert(bytes.capacity() == first_length + first_length); + /// fn foo() { + /// let mut bytes = Bytes::new(); + /// bytes.push(5u8); + /// bytes.push(7u8); + /// bytes.push(9u8); + /// assert(bytes.len() == 3); + /// + /// let mut bytes2 = Bytes::new(); + /// bytes2.push(5u8); + /// bytes2.push(7u8); + /// bytes2.push(9u8); + /// assert(bytes2.len() == 3); + /// + /// let first_length = bytes.len(); + /// let second_length = bytes2.len(); + /// let first_cap = bytes.capacity(); + /// let second_cap = bytes2.capacity(); + /// bytes.append(bytes2); + /// assert(bytes.len() == first_length + second_length); + /// assert(bytes.capacity() == first_cap + second_cap); + /// } /// ``` pub fn append(ref mut self, ref mut other: self) { if other.len == 0 { @@ -616,7 +734,7 @@ impl core::ops::Eq for Bytes { } impl AsRawSlice for Bytes { - /// Returns a raw slice of all of the elements in the vector. + /// Returns a raw slice of all of the elements in the type. fn as_raw_slice(self) -> raw_slice { asm(ptr: (self.buf.ptr(), self.len)) { ptr: raw_slice } } diff --git a/sway-lib-std/src/call_frames.sw b/sway-lib-std/src/call_frames.sw index 478258f9e17..945d115a293 100644 --- a/sway-lib-std/src/call_frames.sw +++ b/sway-lib-std/src/call_frames.sw @@ -21,13 +21,47 @@ const SECOND_PARAMETER_OFFSET: u64 = 74; // Accessing the current call frame // /// Get the current contract's id when called in an internal context. +/// +/// # Additional Information +/// /// **_Note:_** If called in an external context, this will **not** return a contract ID. -// @dev If called externally, will actually return a pointer to the transaction ID. +/// If called externally, will actually return a pointer to the transaction ID. +/// +/// # Returns +/// +/// * [ContractId] - The contract id of this contract. +/// +/// # Examples +/// +/// ```sway +/// use std::{call_frames::contract_id, token::mint}; +/// +/// fn foo() { +/// let this_contract = contract_id(); +/// mint(50); +/// Address::from(ZERO_B256).transfer(50, this_contract); +/// } +/// ``` pub fn contract_id() -> ContractId { ContractId::from(asm() { fp: b256 }) } /// Get the `asset_id` of coins being sent from the current call frame. +/// +/// # Returns +/// +/// * [AssetId] - The asset included in the current call frame. +/// +/// # Examples +/// +/// ```sway +/// use std::{call_frames::msg_asset_id, constants::BASE_ASSET_ID}; +/// +/// fn foo() { +/// let asset = msg_asset_id(); +/// assert(asset == BASE_ASSET_ID); +/// } +/// ``` pub fn msg_asset_id() -> AssetId { asm(asset_id) { addi asset_id fp i32; @@ -36,6 +70,26 @@ pub fn msg_asset_id() -> AssetId { } /// Get the code size in bytes (padded to word alignment) from the current call frame. +/// +/// # Additional Information +/// +/// More information on data from call frames can be found in the Fuel Specs. +/// https://specs.fuel.network/master/fuel-vm/index.html?search=#call-frames +/// +/// # Returns +/// +/// * [u64] - The code size of the current call frame. +/// +/// # Examples +/// +/// ```sway +/// use std::call_frames::code_size; +/// +/// fn foo() { +/// let size = code_size(); +/// assert(size != 0); +/// } +/// ``` pub fn code_size() -> u64 { asm(size, ptr, offset: 576) { add size fp offset; @@ -44,11 +98,51 @@ pub fn code_size() -> u64 { } /// Get the first parameter from the current call frame. +/// +/// # Additional Information +/// +/// More information on data from call frames can be found in the Fuel Specs. +/// https://specs.fuel.network/master/fuel-vm/index.html?search=#call-frames +/// +/// # Returns +/// +/// * [u64] - The first parameter of the current call frame. +/// +/// # Examples +/// +/// ```sway +/// use std::call_frames::first_param; +/// +/// fn foo() { +/// let param = first_param(); +/// assert(param != 0); +/// } +/// ``` pub fn first_param() -> u64 { frame_ptr().add::(FIRST_PARAMETER_OFFSET).read() } /// Get the second parameter from the current call frame. +/// +/// # Additional Information +/// +/// More information on data from call frames can be found in the Fuel Specs. +/// https://specs.fuel.network/master/fuel-vm/index.html?search=#call-frames +/// +/// # Returns +/// +/// * [u64] - The second parameter of the current call frame. +/// +/// # Examples +/// +/// ```sway +/// use std::call_frames::second_param; +/// +/// fn foo() { +/// let param: u64 = second_param(); +/// assert(param != 0); +/// } +/// ``` pub fn second_param() -> T { if !is_reference_type::() { frame_ptr().add::(SECOND_PARAMETER_OFFSET).read::() @@ -60,6 +154,31 @@ pub fn second_param() -> T { // Accessing arbitrary call frames by pointer // /// Get a pointer to the previous (relative to the `frame_pointer` parameter) call frame using offsets from a pointer. +/// +/// # Additional Information +/// +/// More information on data from call frames can be found in the Fuel Specs. +/// https://specs.fuel.network/master/fuel-vm/index.html?search=#call-frames +/// +/// # Arguments +/// +/// * `frame_pointer`: [raw_ptr] - The call frame reference directly before the returned call frame pointer. +/// +/// # Returns +/// +/// * [raw_ptr] - The memory location of the previous call frame data. +/// +/// # Examples +/// +/// ```sway +/// use std::{call_frames::get_previous_frame_pointer, registers::frame_ptr}; +/// +/// fn foo() { +/// let current_call_frame = frame_ptr(); +/// let previous_call_frame = get_previous_frame_pointer(current_call_frame); +/// assert(!previous_call_frame.is_null()); +/// } +/// ``` pub fn get_previous_frame_pointer(frame_pointer: raw_ptr) -> raw_ptr { let offset = frame_pointer.add::(SAVED_REGISTERS_OFFSET + PREV_FRAME_POINTER_OFFSET); asm(res, ptr: offset) { @@ -69,6 +188,25 @@ pub fn get_previous_frame_pointer(frame_pointer: raw_ptr) -> raw_ptr { } /// Get the value of `ContractId` from any call frame on the stack. +/// +/// # Arguments +/// +/// * `frame_pointer`: [raw_ptr] - The call frame for which the Contract Id is to be returned. +/// +/// # Returns +/// +/// * [ContractId] - The Contract Id of for the call frame. +/// +/// # Examples +/// +/// ```sway +/// use std::{call_frames::get_contract_id_from_call_frame, registers::frame_ptr}; +/// +/// fn foo() { +/// let current_call_frame = frame_ptr(); +/// let contract_id = get_contract_id_from_call_frame(current_call_frame); +/// } +/// ``` pub fn get_contract_id_from_call_frame(frame_pointer: raw_ptr) -> ContractId { ContractId::from(asm(res, ptr: frame_pointer) { ptr: b256 }) } diff --git a/sway-lib-std/src/constants.sw b/sway-lib-std/src/constants.sw index e74d5cf4d01..bb61f346dd8 100644 --- a/sway-lib-std/src/constants.sw +++ b/sway-lib-std/src/constants.sw @@ -4,7 +4,31 @@ library; use ::contract_id::ContractId; /// The `BASE_ASSET_ID` represents the base asset of a chain. -/// This is currently hard coded as a zero address, but will be configurable in the future. +/// +/// # Additional Information +/// +/// On the Fuel network, the base asset is Ether. It is hardcoded as the 0x00..00 ContractId. +/// +/// # Examples +/// +/// ```sway +/// use std::{call_frames::msg_asset_id, constants::BASE_ASSET_ID}; +/// +/// fn foo() { +/// assert(BASE_ASSET_ID == msg_asset_id()); +/// } +/// ``` pub const BASE_ASSET_ID = ZERO_B256; -/// A B256 type zero address. + +/// A B256 of zero value. +/// +/// # Examples +/// +/// ```sway +/// use std::{call_frames::msg_asset_id, constants::ZERO_B256}; +/// +/// fn foo() { +/// assert(ZERO_B256 == msg_asset_id()); +/// } +/// ``` pub const ZERO_B256 = 0x0000000000000000000000000000000000000000000000000000000000000000; diff --git a/sway-lib-std/src/context.sw b/sway-lib-std/src/context.sw index 6456c05404b..da3ff1255bb 100644 --- a/sway-lib-std/src/context.sw +++ b/sway-lib-std/src/context.sw @@ -7,11 +7,50 @@ use ::call_frames::contract_id; use ::registers::balance; /// Get the balance of coin `asset_id` for the current contract. +/// +/// # Arguments +/// +/// * `asset_id`: [AssetId] - The asset of which the balance should be returned. +/// +/// # Returns +/// +/// * [u64] - The amount of the asset which the contract holds. +/// +/// # Examples +/// +/// ```sway +/// use std::{context::this_balance, constants::ZERO_B256, hash::sha256, token::mint, call_frames::contract_id}; +/// +/// fn foo() { +/// mint(ZERO_B256, 50); +/// assert(this_balance(sha256((ZERO_B256, contract_id()))) == 50); +/// } +/// ``` pub fn this_balance(asset_id: AssetId) -> u64 { balance_of(contract_id(), asset_id) } /// Get the balance of coin `asset_id` for the contract at 'target'. +/// +/// # Arguments +/// +/// * `target`: [ContractId] - The contract that contains the `asset_id`. +/// * `asset_id`: [AssetId] - The asset of which the balance should be returned. +/// +/// # Returns +/// +/// * [u64] - The amount of the asset which the `target` holds. +/// +/// # Examples +/// +/// ```sway +/// use std::{context::balance_of, constants::ZERO_B256, hash::sha256, token::mint, call_frames::contract_id}; +/// +/// fn foo() { +/// mint(ZERO_B256, 50); +/// assert(balance_of(contract_id(), sha256((ZERO_B256, contract_id()))) == 50); +/// } +/// ``` pub fn balance_of(target: ContractId, asset_id: AssetId) -> u64 { asm(balance, token: asset_id, id: target.value) { bal balance token id; @@ -20,6 +59,20 @@ pub fn balance_of(target: ContractId, asset_id: AssetId) -> u64 { } /// Get the amount of units of `call_frames::msg_asset_id()` being sent. +/// +/// # Returns +/// +/// * [u64] - The amount of tokens being sent. +/// +/// # Examples +/// +/// ```sway +/// use std::context::msg_amount; +/// +/// fn foo() { +/// assert(msg_amount() == 0); +/// } +/// ``` pub fn msg_amount() -> u64 { balance() } diff --git a/sway-lib-std/src/contract_id.sw b/sway-lib-std/src/contract_id.sw index ef927519736..a6a87b73598 100644 --- a/sway-lib-std/src/contract_id.sw +++ b/sway-lib-std/src/contract_id.sw @@ -7,6 +7,7 @@ use ::hash::*; /// The `ContractId` type, a struct wrapper around the inner `b256` value. pub struct ContractId { + /// The underlying raw `b256` data of the contract id. value: b256, } @@ -17,11 +18,48 @@ impl core::ops::Eq for ContractId { } /// Functions for casting between the `b256` and `ContractId` types. -impl From for ContractId { +impl From for ContractId { + /// Casts raw `b256` data to a `ContractId`. + /// + /// # Arguments + /// + /// * `bits`: [b256] - The raw `b256` data to be casted. + /// + /// # Returns + /// + /// * [ContractId] - The newly created `ContractId` from the raw `b256`. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let contract_id = ContractId::from(ZERO_B256); + /// } + /// ``` fn from(bits: b256) -> Self { Self { value: bits } } + + /// Casts a `ContractId` to raw `b256` data. + /// + /// # Returns + /// + /// * [b256] - The underlying raw `b256` data of the `ContractId`. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let contract_id = ContractId::from(ZERO_B256); + /// let b256_data = contract_id.into(); + /// assert(b256_data == ZERO_B256); + /// } + /// ``` fn into(self) -> b256 { self.value } @@ -31,30 +69,32 @@ impl ContractId { /// UNCONDITIONAL transfer of `amount` coins of type `asset_id` to /// the ContractId. /// - /// > **_WARNING:_** - /// > - /// > This will transfer coins to a contract even with no way to retrieve them - /// > (i.e. no withdrawal functionality on receiving contract), possibly leading - /// > to the **_PERMANENT LOSS OF COINS_** if not used with care. + /// # Additional Informations /// - /// ### Arguments + /// **_WARNING:_** + /// This will transfer coins to a contract even with no way to retrieve them + /// (i.e. no withdrawal functionality on receiving contract), possibly leading + /// to the **_PERMANENT LOSS OF COINS_** if not used with care. /// - /// * `asset_id` - The `AssetId` of the token to transfer. - /// * `amount` - The amount of tokens to transfer. + /// # Arguments /// - /// ### Reverts + /// * `asset_id`: [AssetId] - The `AssetId` of the token to transfer. + /// * `amount`: [u64] - The amount of tokens to transfer. /// - /// * If `amount` is greater than the contract balance for `asset_id`. - /// * If `amount` is equal to zero. + /// # Reverts /// - /// ### Examples + /// * When `amount` is greater than the contract balance for `asset_id`. + /// * When `amount` is equal to zero. + /// + /// # Examples /// /// ```sway /// use std::constants::{BASE_ASSET_ID, ZERO_B256}; /// - /// // replace the zero ContractId with your desired ContractId - /// let contract_id = ContractId::from(ZERO_B256); - /// contract_id.transfer(BASE_ASSET_ID, 500); + /// fn foo() { + /// let contract_id = ContractId::from(ZERO_B256); + /// contract_id.transfer(BASE_ASSET_ID, 500); + /// } /// ``` pub fn transfer(self, asset_id: AssetId, amount: u64) { asm(r1: amount, r2: asset_id, r3: self.value) { @@ -73,25 +113,27 @@ impl Hash for ContractId { impl ContractId { /// Mint `amount` coins of `sub_id` and send them UNCONDITIONALLY to the contract at `to`. /// - /// > **_WARNING:_** - /// > - /// > This will transfer coins to a contract even with no way to retrieve them - /// > (i.e: no withdrawal functionality on the receiving contract), possibly leading to - /// > the **_PERMANENT LOSS OF COINS_** if not used with care. + /// # Additional Information + /// + /// **_WARNING:_** + /// This will transfer coins to a contract even with no way to retrieve them + /// (i.e: no withdrawal functionality on the receiving contract), possibly leading to + /// the **_PERMANENT LOSS OF COINS_** if not used with care. /// - /// ### Arguments + /// # Arguments /// - /// * `sub_id` - The sub identfier of the asset which to mint. - /// * `amount` - The amount of tokens to mint. + /// * `sub_id`: [SubId] - The sub identfier of the asset which to mint. + /// * `amount`: [u64] - The amount of tokens to mint. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::constants::ZERO_B256; /// - /// // replace the zero ContractId with your desired ContractId - /// let contract_id = ContractId::from(ZERO_B256); - /// contract_id.mint_to(ZERO_B256, 500); + /// fn foo() { + /// let contract_id = ContractId::from(ZERO_B256); + /// contract_id.mint_to(ZERO_B256, 500); + /// } /// ``` pub fn mint_to(self, sub_id: SubId, amount: u64) { asm(r1: amount, r2: sub_id) { diff --git a/sway-lib-std/src/convert.sw b/sway-lib-std/src/convert.sw index 5c4bc4b447a..aae78310e01 100644 --- a/sway-lib-std/src/convert.sw +++ b/sway-lib-std/src/convert.sw @@ -5,7 +5,9 @@ use ::option::Option; /// Used to do value-to-value conversions. pub trait From { + /// Converts to this type from the input type. fn from(b: T) -> Self; + /// Converts this type into the (usually inferred) input type. fn into(self) -> T; } @@ -13,5 +15,6 @@ pub trait From { /// Used to attempt to do value-to-value conversions. /// Returns None if the conversion can't be performed in a lossless manner. pub trait TryFrom { + /// Performs the conversion. Returns None if the conversion can't be performed in a lossless manner. fn try_from(b: T) -> Option; } diff --git a/sway-lib-std/src/ecr.sw b/sway-lib-std/src/ecr.sw index 1388a0f76db..da2169a8747 100644 --- a/sway-lib-std/src/ecr.sw +++ b/sway-lib-std/src/ecr.sw @@ -9,11 +9,41 @@ use ::result::Result::{self, *}; /// The error type used when the `ec_recover` function fails. pub enum EcRecoverError { + /// The error varient used when the recover fails. UnrecoverablePublicKey: (), } /// Recover the public key derived from the private key used to sign a message. /// Returns a `Result` to let the caller choose an error handling strategy. +/// +/// # Arguments +/// +/// * `signature`: [B512] - The signature generated by signing a message hash. +/// * `msg_hash`: [b256] - The signed data. +/// +/// # Returns +/// +/// * [Result] - The recovered public key or an error. +/// +/// # Examples +/// +/// ```sway +/// use std::{erc::ec_recover, b512::B512}; +/// +/// fn foo() { +/// let hi = 0xbd0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c; +/// let lo = 0x44ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d; +/// let msg_hash = 0xee45573606c96c98ba970ff7cf9511f1b8b25e6bcd52ced30b89df1e4a9c4323; +/// let pub_hi = 0xD73A188181464CC84AE267E45041AEF6AB938F278E636AA1D02D3014C1BEF74E; +/// let pub_lo = 0xC44415635160ACFC87A84300EED97928C949A2D958FC0947C535F7539C59AE75; +/// let signature: B512 = B512::from((hi, lo)); +/// // A recovered public key pair. +/// let public_key = ec_recover(signature, msg_hash).unwrap(); +/// +/// assert(public_key.bytes[0] == pub_hi); +/// assert(public_key.bytes[1] == pub_lo); +/// } +/// ``` pub fn ec_recover(signature: B512, msg_hash: b256) -> Result { let public_key = B512::new(); let was_error = asm(buffer: public_key.bytes, sig: signature.bytes, hash: msg_hash) { @@ -30,6 +60,32 @@ pub fn ec_recover(signature: B512, msg_hash: b256) -> Result] - The recovered Fuel address or an error. +/// +/// # Examples +/// +/// ```sway +/// use std::{erc::ec_recover_address, b512::B512}; +/// +/// fn foo() { +/// let hi = 0xbd0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c; +/// let lo = 0x44ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d; +/// let msg_hash = 0xee45573606c96c98ba970ff7cf9511f1b8b25e6bcd52ced30b89df1e4a9c4323; +/// let address = Address::from(0x7AAE2D980BE4C3275C72CE5B527FA23FFB97B766966559DD062E2B78FD9D3766); +/// let signature: B512 = B512::from((hi, lo)); +/// // A recovered Fuel address. +/// let result_address = ec_recover_address(signature, msg_hash).unwrap(); +/// assert(result_address == address); +/// } +/// ``` pub fn ec_recover_address(signature: B512, msg_hash: b256) -> Result { let pub_key_result = ec_recover(signature, msg_hash); diff --git a/sway-lib-std/src/error_signals.sw b/sway-lib-std/src/error_signals.sw index 688530b7007..ae6dedefd7f 100644 --- a/sway-lib-std/src/error_signals.sw +++ b/sway-lib-std/src/error_signals.sw @@ -1,18 +1,30 @@ //! Values which signify special types of errors when passed to `std::revert::revert`. library; -/// Revert with this value for a failing call to `std::revert::require`. -/// 18446744073709486080 +/// A revert with this value signals that it was caused by a failing call to `std::revert::require`. +/// +/// # Additional Information +/// +/// The value is: 18446744073709486080 pub const FAILED_REQUIRE_SIGNAL = 0xffff_ffff_ffff_0000; -/// Revert with this value for a failing call to `std::token::transfer_to_address`. -/// 18446744073709486081 +/// A revert with this value signals that it was caused by a failing call to `std::token::transfer_to_address`. +/// +/// # Additional Information +/// +/// The value is: 18446744073709486081 pub const FAILED_TRANSFER_TO_ADDRESS_SIGNAL = 0xffff_ffff_ffff_0001; -/// Revert with this value for a failing call to `std::assert::assert_eq`. -/// 18446744073709486083 +/// A revert with this value signals that it was caused by a failing call to `std::assert::assert_eq`. +/// +/// # Additional Information +/// +/// The value is: 18446744073709486083 pub const FAILED_ASSERT_EQ_SIGNAL = 0xffff_ffff_ffff_0003; -/// Revert with this value for a failing call to `std::assert::assert`. -/// 18446744073709486084 +/// A revert with this value signals that it was caused by a failing call to `std::assert::assert`. +/// +/// # Additional Information +/// +/// The value is: 18446744073709486084 pub const FAILED_ASSERT_SIGNAL = 0xffff_ffff_ffff_0004; diff --git a/sway-lib-std/src/external.sw b/sway-lib-std/src/external.sw index 2b948cb2e04..21caeb21a22 100644 --- a/sway-lib-std/src/external.sw +++ b/sway-lib-std/src/external.sw @@ -5,6 +5,25 @@ use ::constants::ZERO_B256; use ::contract_id::ContractId; /// Get the root of the bytecode of the contract at 'contract_id'. +/// +/// # Arguments +/// +/// * `contract_id`: [ContractId] - The contract of which the the bytecode should be returned. +/// +/// # Returns +/// +/// * [b256] - The bytecode root of the contract. +/// +/// # Examples +/// +/// ```sway +/// use std::{external::bytecode_root, call_frames::contract_id, constants::ZERO_B256}; +/// +/// fn foo() { +/// let root_of_this_contract = bytecode_root(contract_id()); +/// assert(root_of_this_contract != ZERO_B256); +/// } +/// ``` pub fn bytecode_root(contract_id: ContractId) -> b256 { let root: b256 = ZERO_B256; diff --git a/sway-lib-std/src/flags.sw b/sway-lib-std/src/flags.sw index 0293b624958..46fd12fd631 100644 --- a/sway-lib-std/src/flags.sw +++ b/sway-lib-std/src/flags.sw @@ -14,11 +14,11 @@ const F_UNSAFEMATH_ENABLE_MASK: u64 = 0b11111111_11111111_11111111_11111111_1111 /// Sets the flag register to the given value. /// -/// ### Arguments +/// # Arguments /// -/// * `flags` - Binary encoded 64 bit value representing the flags to set. +/// * `new_flags`: [u64] - Binary encoded 64 bit value representing the flags to set. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::flags::{disable_panic_on_overflow_preserving, set_flags}; @@ -40,15 +40,17 @@ pub fn set_flags(new_flags: u64) { /// Allows overflowing operations to occur without a FuelVM panic. /// +/// # Additional Information +/// /// > **_WARNING:_** /// > /// > Don't forget to call `enable_panic_on_overflow` or `set_flags` after performing the operations for which you disabled the default `panic-on-overflow` behavior in the first place! /// -/// ### Returns +/// # Returns /// /// * [u64] - The flag prior to disabling panic on overflow. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::flags::{disable_panic_on_overflow, enable_panic_on_overflow}; @@ -90,11 +92,13 @@ pub fn disable_panic_on_overflow() -> u64 { /// Enables the default `panic-on-overflow` behavior in the FuelVM. /// +/// # Additional Information +/// /// > **_Note:_** /// > /// > `panic-on-overflow` is the default, so there is no need to use this function unless you have previously called `disable_panic_on_overflow`. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::flags::{disable_panic_on_overflow, enable_panic_on_overflow}; @@ -120,15 +124,17 @@ pub fn enable_panic_on_overflow() { /// Allows unsafe math operations to occur without a FuelVM panic. /// Sets the `$err` register to `true` whenever unsafe math occurs. /// +/// # Additional Information +/// /// > **_WARNING:_** /// > /// > Don't forget to call `enable_panic_on_unsafe_math` or `set_flags` after performing the operations for which you disabled the default `panic-on-unsafe-math` behavior in the first place! /// -/// ### Returns +/// # Returns /// /// * [u64] - The flag prior to disabling panic on overflow. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{assert::assert, flags::{disable_panic_on_unsafe_math, enable_panic_on_unsafe_math}, registers::error}; @@ -174,11 +180,13 @@ pub fn disable_panic_on_unsafe_math() -> u64 { /// Enables the default `panic-on-unsafe-math` behavior in the FuelVM. /// +/// # Additional Information +/// /// > **_Note:_** /// > /// > `panic-on-unsafe-math` is the default, so there is no need to use this function unless you have previously called `disable_panic_on_unsafe_math`. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{assert::assert, flags::{disable_panic_on_unsafe_math, enable_panic_on_unsafe_math}, registers::error}; diff --git a/sway-lib-std/src/hash.sw b/sway-lib-std/src/hash.sw index 478bdf8f5de..b83bc094add 100644 --- a/sway-lib-std/src/hash.sw +++ b/sway-lib-std/src/hash.sw @@ -263,6 +263,26 @@ impl Hash for [T; 10] where T: Hash { } } +/// Returns the `SHA-2-256` hash of `param`. +/// +/// # Arguments +/// +/// * `s`: [T] - The value to be hashed. +/// +/// # Returns +/// +/// * [b256] - The sha-256 hash of the value. +/// +/// # Examples +/// +/// ```sway +/// use std::hash::*; +/// +/// fn foo() { +/// let result = sha256("Fuel"); +/// assert(result = 0xa80f942f4112036dfc2da86daf6d2ef6ede3164dd56d1000eb82fa87c992450f); +/// } +/// ``` #![inline(never)] pub fn sha256(s: T) -> b256 where T: Hash { let mut hasher = Hasher::new(); @@ -270,6 +290,26 @@ pub fn sha256(s: T) -> b256 where T: Hash { hasher.sha256() } +/// Returns the `KECCAK-256` hash of `param`. +/// +/// # Arguments +/// +/// * `s`: [T] - The value to be hashed. +/// +/// # Returns +/// +/// * [b256] - The keccak-256 hash of the value. +/// +/// # Examples +/// +/// ```sway +/// use std::hash::keccak256; +/// +/// fn foo() { +/// let result = keccak256("Fuel"); +/// assert(result = 0x4375c8bcdc904e5f51752581202ae9ae2bb6eddf8de05d5567d9a6b0ae4789ad); +/// } +/// ``` #![inline(never)] pub fn keccak256(s: T) -> b256 where T: Hash { let mut hasher = Hasher::new(); diff --git a/sway-lib-std/src/identity.sw b/sway-lib-std/src/identity.sw index 4bad2305bb7..e86b8bb37fb 100644 --- a/sway-lib-std/src/identity.sw +++ b/sway-lib-std/src/identity.sw @@ -30,6 +30,23 @@ impl core::ops::Eq for Identity { } impl Identity { + /// Returns the `Address` of the `Identity`. + /// + /// # Returns + /// + /// * [Option
] - `Some(Address)` if the underlying type is an `Address`, otherwise `None`. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let identity = Identity::Address(Address::from(ZERO_B256)); + /// let address = identity.as_address(); + /// assert(address == Address::from(ZERO_B256)); + /// } + /// ``` pub fn as_address(self) -> Option
{ match self { Self::Address(addr) => Option::Some(addr), @@ -37,6 +54,23 @@ impl Identity { } } + /// Returns the `ContractId` of the `Identity`. + /// + /// # Returns + /// + /// * [Option] - `Some(Contract)` if the underlying type is an `ContractId`, otherwise `None`. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let identity = Identity::ContractId(ContractId::from(ZERO_B256)); + /// let contract_id = identity.as_contract_id(); + /// assert(contract_id == ContractId::from(ZERO_B256)); + /// } + /// ``` pub fn as_contract_id(self) -> Option { match self { Self::Address(_) => Option::None, @@ -44,6 +78,22 @@ impl Identity { } } + /// Returns whether the `Identity` represents an `Address`. + /// + /// # Returns + /// + /// * [bool] - Indicates whether the `Identity` holds an `Address`. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let identity = Identity::Address(Address::from(ZERO_B256)); + /// assert(identity.is_address()); + /// } + /// ``` pub fn is_address(self) -> bool { match self { Self::Address(_) => true, @@ -51,6 +101,22 @@ impl Identity { } } + /// Returns whether the `Identity` represents a `ContractId`. + /// + /// # Returns + /// + /// * [bool] - Indicates whether the `Identity` holds a `ContractId`. + /// + /// # Examples + /// + /// ```sway + /// use std::constants::ZERO_B256; + /// + /// fn foo() { + /// let identity = Identity::ContractId(ContractId::from(ZERO_B256)); + /// assert(identity.is_contract_id()); + /// } + /// ``` pub fn is_contract_id(self) -> bool { match self { Self::Address(_) => false, @@ -61,33 +127,35 @@ impl Identity { /// Transfer `amount` coins of the type `asset_id` and send them /// to the Identity. /// - /// > **_WARNING:_** - /// > - /// > If the Identity is a contract this may transfer coins to the contract even with no way to retrieve them - /// > (i.e. no withdrawal functionality on receiving contract), possibly leading - /// > to the **_PERMANENT LOSS OF COINS_** if not used with care. + /// # Additional Information + /// + /// **_WARNING:_** + /// If the Identity is a contract this may transfer coins to the contract even with no way to retrieve them + /// (i.e. no withdrawal functionality on receiving contract), possibly leading + /// to the **_PERMANENT LOSS OF COINS_** if not used with care. /// - /// ### Arguments + /// # Arguments /// - /// * `asset_id` - The `AssetId` of the token to transfer. - /// * `amount` - The amount of tokens to transfer. + /// * `asset_id`: [AssetId] - The `AssetId` of the token to transfer. + /// * `amount`: [u64] - The amount of tokens to transfer. /// - /// ### Reverts + /// # Reverts /// - /// * If `amount` is greater than the contract balance for `asset_id`. - /// * If `amount` is equal to zero. - /// * If there are no free variable outputs when transferring to an `Address`. + /// * When `amount` is greater than the contract balance for `asset_id`. + /// * When `amount` is equal to zero. + /// * When there are no free variable outputs when transferring to an `Address`. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::constants::{BASE_ASSET_ID, ZERO_B256}; /// - /// // replace the zero Address/ContractId with your desired Address/ContractId - /// let to_address = Identity::Address(Address::from(ZERO_B256)); - /// let to_contract_id = Identity::ContractId(ContractId::from(ZERO_B256)); - /// to_address.transfer(BASE_ASSET_ID, 500); - /// to_contract_id.transfer(BASE_ASSET_ID, 500); + /// fn foo() { + /// let to_address = Identity::Address(Address::from(ZERO_B256)); + /// let to_contract_id = Identity::ContractId(ContractId::from(ZERO_B256)); + /// to_address.transfer(BASE_ASSET_ID, 500); + /// to_contract_id.transfer(BASE_ASSET_ID, 500); + /// } /// ``` pub fn transfer(self, asset_id: AssetId, amount: u64) { match self { @@ -100,27 +168,29 @@ impl Identity { impl Identity { /// Mint `amount` coins of `sub_id` and transfer them to the Identity. /// - /// > **_WARNING:_** - /// > - /// > If the Identity is a contract, this will transfer coins to the contract even with no way to retrieve them - /// > (i.e: no withdrawal functionality on the receiving contract), possibly leading to - /// > the **_PERMANENT LOSS OF COINS_** if not used with care. + /// # Additional Information + /// + /// **_WARNING:_** + /// If the Identity is a contract, this will transfer coins to the contract even with no way to retrieve them + /// (i.e: no withdrawal functionality on the receiving contract), possibly leading to + /// the **_PERMANENT LOSS OF COINS_** if not used with care. /// - /// ### Arguments + /// # Arguments /// - /// * `sub_id` - The sub identfier of the asset which to mint. - /// * `amount` - The amount of tokens to mint. + /// * `sub_id`: [SubId] - The sub identfier of the asset which to mint. + /// * `amount`: [u64] - The amount of tokens to mint. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::constants::ZERO_B256; /// - /// // replace the zero Address/ContractId with your desired Address/ContractId - /// let address_identity = Identity::Address(Address::from(ZERO_B256)); - /// let contract_identity = Identity::ContractId(ContractId::from(ZERO_B256)); - /// address_identity.mint_to(ZERO_B256, 500); - /// contract_identity.mint_to(ZERO_B256, 500); + /// fn foo() { + /// let address_identity = Identity::Address(Address::from(ZERO_B256)); + /// let contract_identity = Identity::ContractId(ContractId::from(ZERO_B256)); + /// address_identity.mint_to(ZERO_B256, 500); + /// contract_identity.mint_to(ZERO_B256, 500); + /// } /// ``` pub fn mint_to(self, sub_id: SubId, amount: u64) { asm(r1: amount, r2: sub_id) { diff --git a/sway-lib-std/src/inputs.sw b/sway-lib-std/src/inputs.sw index 21b44cd1b83..f1d5b6af912 100644 --- a/sway-lib-std/src/inputs.sw +++ b/sway-lib-std/src/inputs.sw @@ -62,8 +62,11 @@ pub const GTF_INPUT_MESSAGE_PREDICATE_DATA = 0x11F; /// The input type for a transaction. pub enum Input { + /// A coin input. Coin: (), + /// A contract input. Contract: (), + /// A message input. Message: (), } @@ -79,8 +82,31 @@ impl Eq for Input { } // General Inputs -// -/// Get the type of the input at `index`. + +/// Gets the type of the input at `index`. +/// +/// # Additional Information +/// +/// The Input can be of 3 variants, `Input::Coin`, `Input::Contract` or `Input::Message`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Input] - The type of the input at `index`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_type; +/// +/// fn foo() { +/// let input_type = input_type(0); +/// assert(input_type == Input::Coin); +/// } +/// ``` pub fn input_type(index: u64) -> Input { match __gtf::(index, GTF_INPUT_TYPE) { 0u8 => Input::Coin, @@ -90,7 +116,22 @@ pub fn input_type(index: u64) -> Input { } } -/// Get the transaction inputs count. +/// Gets the transaction inputs count. +/// +/// # Returns +/// +/// * [u8] - The number of inputs in the transaction. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_count; +/// +/// fn foo() { +/// let input_count = input_count(); +/// assert(input_count == 1); +/// } +/// ``` pub fn input_count() -> u8 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_INPUTS_COUNT), @@ -98,7 +139,25 @@ pub fn input_count() -> u8 { } } -/// Get the pointer of the input at `index`. +/// Gets the pointer of the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [u64] - The pointer of the input at `index`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_pointer; +/// +/// fn foo() { +/// let input_pointer = input_pointer(0); +/// } +/// ``` pub fn input_pointer(index: u64) -> u64 { match tx_type() { Transaction::Script => __gtf::(index, GTF_SCRIPT_INPUT_AT_INDEX), @@ -106,10 +165,26 @@ pub fn input_pointer(index: u64) -> u64 { } } -/// Get amount field from input at `index`. -/// If the input's type is `Input::Coin` or `Input::Message`, -/// return the amount as an `Some(u64)`. -/// Otherwise, returns `None`. +/// Gets amount field from input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option] - The amount of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`, else `None`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_amount; +/// +/// fn foo() { +/// let input_amount = input_amount(0); +/// assert(input_amount.unwrap() == 100); +/// } +/// ``` pub fn input_amount(index: u64) -> Option { match input_type(index) { Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_AMOUNT)), @@ -118,9 +193,26 @@ pub fn input_amount(index: u64) -> Option { } } -/// If the input's type is `Input::Coin` return the owner as an `Some(owner)`. -/// If the input's type is `Input::Message` return the owner as an `Some(recipient)`. -/// Otherwise, returns None. +/// Gets owner field from input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option
] - The owner of the input at `index`, if the input's type is `Input::Coin`, else `None`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_owner; +/// +/// fn foo() { +/// let input_owner = input_owner(0); +/// assert(input_owner.is_some()); // Ensure the input is a coin input. +/// } +/// ``` pub fn input_owner(index: u64) -> Option
{ match input_type(index) { Input::Coin => Some(Address::from(__gtf::(index, GTF_INPUT_COIN_OWNER))), @@ -128,10 +220,25 @@ pub fn input_owner(index: u64) -> Option
{ } } -/// Get the predicate data pointer from the input at `index`. -/// If the input's type is `Input::Coin` or `Input::Message`, -/// return the data as an `Some(ptr)`. -/// Otherwise, returns `None`. +/// Gets the predicate data pointer from the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option] - The predicate data pointer of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`, else `None`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_predicate_data_pointer; +/// +/// fn foo() { +/// let input_predicate_data_pointer = input_predicate_data_pointer(0); +/// assert(input_predicate_data_pointer.is_some()); // Ensure the input is a coin or message input. +/// } pub fn input_predicate_data_pointer(index: u64) -> Option { match input_type(index) { Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_DATA)), @@ -140,9 +247,26 @@ pub fn input_predicate_data_pointer(index: u64) -> Option { } } -/// Get the predicate data from the input at `index`. -/// If the input's type is `Input::Coin` or `Input::Message`, -/// return the data, otherwise reverts. +/// Gets the predicate data from the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [T] - The predicate data of the input at `index`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_predicate_data; +/// +/// fn foo() { +/// let input_predicate_data: u64 = input_predicate_data(0); +/// assert(input_predicate_data == 100); +/// } +/// ``` pub fn input_predicate_data(index: u64) -> T { match input_predicate_data_pointer(index) { Some(d) => d.read::(), @@ -150,9 +274,26 @@ pub fn input_predicate_data(index: u64) -> T { } } -/// If the input's type is `Input::Coin` return the asset ID as an `Some(id)`. -/// If the input's type is `Input::Message` return the `BASE_ASSET_ID` as an `Some(id)`. -/// Otherwise, returns `None`. +/// Gets the AssetId of the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option] - The asset_id of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`, else `None`. +/// +/// # Examples +/// +/// ```sway +/// use std::{constants::BASE_ASSET_ID, inputs::input_asset_id}; +/// +/// fn foo() { +/// let input_asset_id = input_asset_id(0); +/// assert(input_asset_id.unwrap() == BASE_ASSET_ID); +/// } +/// ``` pub fn input_asset_id(index: u64) -> Option { match input_type(index) { Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_ASSET_ID)), @@ -161,10 +302,26 @@ pub fn input_asset_id(index: u64) -> Option { } } -/// Get the witness index from the input at `index`. -/// If the input's type is `Input::Coin` or `Input::Message`, -/// return the index as an `Some(u8)`. -/// Otherwise, returns `None`. +/// Gets the witness index from the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option] - The witness index of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`, else `None`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_witness_index; +/// +/// fn foo() { +/// let input_witness_index = input_witness_index(0); +/// assert(input_witness_index.is_some()); // Ensure the input has a witness index. +/// } +/// ``` pub fn input_witness_index(index: u64) -> Option { match input_type(index) { Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_WITNESS_INDEX)), @@ -173,10 +330,26 @@ pub fn input_witness_index(index: u64) -> Option { } } -/// Get the predicate length from the input at `index`. -/// If the input's type is `Input::Coin` or `Input::Message`, -/// return the length as an `Some(u16)`. -/// Otherwise, returns `None`. +/// Gets the predicate length from the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option] - The predicate length of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`, else `None`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_predicate_length; +/// +/// fn foo() { +/// let input_predicate_length = input_predicate_length(0); +/// assert(input_predicate_length.unwrap() != 0u16); +/// } +/// ``` pub fn input_predicate_length(index: u64) -> Option { match input_type(index) { Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_LENGTH)), @@ -185,10 +358,26 @@ pub fn input_predicate_length(index: u64) -> Option { } } -/// Get the predicate pointer from the input at `index`. -/// If the input's type is `Input::Coin` or `Input::Message`, -/// return the pointer as an `Some(ptr)`. -/// Otherwise, returns `None`. +/// Gets the predicate pointer from the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option] - The predicate pointer of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`, else `None`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_predicate_pointer; +/// +/// fn foo() { +/// let input_predicate_pointer = input_predicate_pointer(0); +/// assert(input_predicate_pointer.is_some()); +/// } +/// ``` pub fn input_predicate_pointer(index: u64) -> Option { match input_type(index) { Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE)), @@ -197,9 +386,30 @@ pub fn input_predicate_pointer(index: u64) -> Option { } } -/// Get the predicate from the input at `index`. -/// If the input's type is `Input::Coin` or `Input::Message`, -/// return the data, otherwise reverts. +/// Gets the predicate from the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Bytes] - The predicate bytecode of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`. +/// +/// # Reverts +/// +/// * When the input's type is not `Input::Coin` or `Input::Message`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_predicate; +/// +/// fn foo() { +/// let input_predicate = input_predicate(0); +/// assert(input_predicate.len() != 0); +/// } +/// ``` pub fn input_predicate(index: u64) -> Bytes { let wrapped = input_predicate_length(index); if wrapped.is_none() { @@ -217,10 +427,26 @@ pub fn input_predicate(index: u64) -> Bytes { } } -/// Get the predicate data length from the input at `index`. -/// If the input's type is `Input::Coin` or `Input::Message`, -/// return the data length as an `Some(u16)`. -/// Otherwise, returns `None`. +/// Gets the predicate data length from the input at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option] - The predicate data length of the input at `index`, if the input's type is `Input::Coin` or `Input::Message`, else `None`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_predicate_data_length; +/// +/// fn foo() { +/// let input_predicate_data_length = input_predicate_data_length(0); +/// assert(input_predicate_data_length.unwrap() != 0_u16); +/// } +/// ``` pub fn input_predicate_data_length(index: u64) -> Option { match input_type(index) { Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_PREDICATE_DATA_LENGTH)), @@ -230,11 +456,32 @@ pub fn input_predicate_data_length(index: u64) -> Option { } // Coin Inputs -// -/// Get the maturity from the input at `index`. -/// If the input's type is `Input::Coin`, -/// return the index as an `Some(u32)`. -/// Otherwise, returns `None`. + +/// Gets the maturity from the input at `index`. +/// +/// # Additional Information +/// +/// The matury of an input refers to the number of blocks that must pass before the input can be spent. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Option] - The maturity of the input at `index`, if the input's type is `Input::Coin`, else `None`. +/// +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_maturity; +/// +/// fn foo() { +/// let input_maturity = input_maturity(0); +/// assert(input_maturity.unwrap() == 0_u32); +/// } +/// ``` pub fn input_maturity(index: u64) -> Option { match input_type(index) { Input::Coin => Some(__gtf::(index, GTF_INPUT_COIN_MATURITY)), @@ -242,27 +489,127 @@ pub fn input_maturity(index: u64) -> Option { } } -/// Get the sender of the input message at `index`. +/// Gets the sender of the input message at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Address] - The sender of the input message at `index`, if the input's type is `Input::Message`. +/// +/// # Examples +/// +/// ```sway +/// use std::{constants::ZERO_B256, inputs::input_message_sender}; +/// +/// fn foo() { +/// let input_message_sender = input_message_sender(0); +/// assert(input_message_sender != Address::from(ZERO_B256)); +/// } +/// ``` pub fn input_message_sender(index: u64) -> Address { Address::from(__gtf::(index, GTF_INPUT_MESSAGE_SENDER)) } -/// Get the recipient of the input message at `index`. +/// Gets the recipient of the input message at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [Address] - The recipient of the input message at `index`, if the input's type is `Input::Message`. +/// +/// # Examples +/// +/// ```sway +/// use std::{constants::ZERO_B256, inputs::input_message_recipient}; +/// +/// fn foo() { +/// let input_message_recipient = input_message_recipient(0); +/// assert(input_message_recipient != Address::from(ZERO_B256)); +/// } +/// ``` pub fn input_message_recipient(index: u64) -> Address { Address::from(__gtf::(index, GTF_INPUT_MESSAGE_RECIPIENT)) } -/// Get the nonce of input message at `index`. +/// Gets the nonce of input message at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [b256] - The nonce of the input message at `index`, if the input's type is `Input::Message`. +/// +/// # Examples +/// +/// ```sway +/// use std::{constants::ZERO_B256, inputs::input_message_nonce}; +/// +/// fn foo() { +/// let input_message_nonce = input_message_nonce(0); +/// assert(input_message_nonce != b256::from(ZERO_B256)); +/// } +/// ``` pub fn input_message_nonce(index: u64) -> b256 { __gtf::(index, GTF_INPUT_MESSAGE_NONCE) } -/// Get the length of the input message at `index`. +/// Gets the length of the input message at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// +/// # Returns +/// +/// * [u16] - The length of the input message at `index`, if the input's type is `Input::Message`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_message_length; +/// +/// fn foo() { +/// let input_message_length = input_message_length(0); +/// assert(input_message_length != 0_u16); +/// } +/// ``` pub fn input_message_data_length(index: u64) -> u16 { __gtf::(index, GTF_INPUT_MESSAGE_DATA_LENGTH) } -/// Get the data of the input message at `index`. +/// Gets the data of the input message at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the input to check. +/// * `offset`: [u64] - The offset to start reading the data from. +/// +/// # Returns +/// +/// * [Bytes] - The data of the input message at `index`, if the input's type is `Input::Message`. +/// +/// # Reverts +/// +/// * When the input's type is not `Input::Message`. +/// +/// # Examples +/// +/// ```sway +/// use std::inputs::input_message_data; +/// +/// fn foo() { +/// let input_message_data = input_message_data(0, 0); +/// assert(input_message_data.len() != 0); +/// } +/// ``` pub fn input_message_data(index: u64, offset: u64) -> Bytes { assert(valid_input_type(index, Input::Message)); let data = __gtf::(index, GTF_INPUT_MESSAGE_DATA); diff --git a/sway-lib-std/src/intrinsics.sw b/sway-lib-std/src/intrinsics.sw index 35ac78bfeab..ca80a8ea2b1 100644 --- a/sway-lib-std/src/intrinsics.sw +++ b/sway-lib-std/src/intrinsics.sw @@ -2,16 +2,91 @@ library; /// Returns whether a generic type `T` is a reference type or not. +/// +/// # Returns +/// +/// * [bool] - `true` if `T` is a reference type, `false` otherwise. +/// +/// # Examples +/// +/// ```sway +/// use std::intrinsics::is_reference_type; +/// +/// fn foo() { +/// let a = 1; +/// assert(is_reference_type(a)) +/// } +/// ``` pub fn is_reference_type() -> bool { __is_reference_type::() } /// Returns the size of a generic type `T` in bytes. +/// +/// # Returns +/// +/// * [u64] - The size of `T` in bytes. +/// +/// # Examples +/// +/// ```sway +/// use std::intrinsics::size_of; +/// +/// fn foo() { +/// assert(size_of::() == 8); +/// } +/// ``` +/// +/// ```sway +/// use std::intrinsics::size_of; +/// +/// pub struct Foo { +/// a: u64, +/// b: u64, +/// } +/// +/// fn foo() { +/// assert(size_of::() == 16); +/// } +/// ``` pub fn size_of() -> u64 { __size_of::() } /// Returns the size of the type of a value in bytes. +/// +/// # Arguments +/// +/// * `val` - The value to get the size of. +/// +/// # Returns +/// +/// * [u64] - The size of the type of `val` in bytes. +/// +/// # Examples +/// +/// ```sway +/// use std::intrinsics::size_of_val; +/// +/// fn foo() { +/// let a = 1; +/// assert(size_of_val(a) == 8); +/// } +/// ``` +/// +/// ```sway +/// use std::intrinsics::size_of_val; +/// +/// pub struct Foo { +/// a: u64, +/// b: u64, +/// } +/// +/// fn foo() { +/// let a = Foo { a: 1, b: 2 }; +/// assert(size_of_val(a) == 16); +/// } +/// ``` pub fn size_of_val(val: T) -> u64 { __size_of_val::(val) } diff --git a/sway-lib-std/src/logging.sw b/sway-lib-std/src/logging.sw index ff88504e5cf..6d5dfcb6b38 100644 --- a/sway-lib-std/src/logging.sw +++ b/sway-lib-std/src/logging.sw @@ -2,8 +2,23 @@ library; /// Log any stack type. +/// +/// # Additional Information +/// /// If the type is a reference type, `log` is used. /// Otherwise `logd` is used.' +/// +/// # Arguments +/// +/// * `value`: [T] - The value to log. +/// +/// # Examples +/// +/// ```sway +/// fn foo() { +/// log("Fuel is blazingly fast"); +/// } +/// ``` pub fn log(value: T) { __log::(value); } diff --git a/sway-lib-std/src/low_level_call.sw b/sway-lib-std/src/low_level_call.sw index 4c4e0ebe901..2727d964ae5 100644 --- a/sway-lib-std/src/low_level_call.sw +++ b/sway-lib-std/src/low_level_call.sw @@ -11,13 +11,56 @@ use ::vec::Vec; /// A struct representing the call parameters of a function call. pub struct CallParams { + /// Amount of the asset to transfer. coins: u64, + /// AssetId of the asset to transfer. asset_id: AssetId, + /// Gas to forward. gas: u64, } // TODO : Replace with `from` when implemented /// Represent a contract ID as a `Bytes`, so it can be concatenated with a payload. +/// +/// # Additional Information +/// +/// It is recommended to use the `call_with_function_selector` function directly, unless you know what you are doing. +/// +/// # Arguments +/// +/// * `contract_id`: [ContractId] - The contract ID to be represented as a `Bytes`. +/// +/// # Returns +/// +/// * [Bytes] - The input ContractId represented as a `Bytes`. +/// +/// # Examples +/// +/// ```sway +/// use std::low_level_call::{contract_id_to_bytes, call_with_raw_payload, CallParams}; +/// +/// fn call_with_copy_type_arg(target: ContractId, function_selector: Bytes, calldata: Bytes, call_params: CallParams) { +/// let mut payload = Bytes::new(); +/// payload.append(contract_id_to_bytes(target)); +/// payload.append(function_selector); +/// payload.append(calldata); +/// +/// call_with_raw_payload(payload, call_params); +/// } +/// ``` +/// +/// ```sway +/// use std::low_level_call::{bytes::Bytes, contract_id_to_bytes, call_with_raw_payload, CallParams, ptr_as_bytes}; +/// +/// fn call_with_reference_type_arg(target: ContractId, function_selector: Bytes, calldata: Bytes, call_params: CallParams) { +/// let mut payload = Bytes::new(); +/// payload.append(contract_id_to_bytes(target)); +/// payload.append(function_selector); +/// payload.append(ptr_as_bytes(calldata.buf.ptr)); +/// +/// call_with_raw_payload(payload, call_params); +/// } +/// ``` fn contract_id_to_bytes(contract_id: ContractId) -> Bytes { let mut target_bytes = Bytes::with_capacity(32); target_bytes.len = 32; @@ -28,6 +71,33 @@ fn contract_id_to_bytes(contract_id: ContractId) -> Bytes { } /// Represent a raw pointer as a `Bytes`, so it can be concatenated with a payload. +/// +/// # Additional Information +/// +/// It is recommended to use the `call_with_function_selector` function directly, unless you know what you are doing. +/// +/// # Arguments +/// +/// * `ptr`: [raw_ptr] - The raw pointer to be represented as a `Bytes`. +/// +/// # Returns +/// +/// * [Bytes] - The input raw pointer represented as a `Bytes`. +/// +/// # Examples +/// +/// ```sway +/// use std::low_level_call::{bytes::Bytes, contract_id_to_bytes, call_with_raw_payload, CallParams, ptr_as_bytes}; +/// +/// fn call_with_reference_type_arg(target: ContractId, function_selector: Bytes, calldata: Bytes, call_params: CallParams) { +/// let mut payload = Bytes::new(); +/// payload.append(contract_id_to_bytes(target)); +/// payload.append(function_selector); +/// payload.append(ptr_as_bytes(calldata.buf.ptr)); +/// +/// call_with_raw_payload(payload, call_params); +/// } +/// ``` fn ptr_as_bytes(ptr: raw_ptr) -> Bytes { let mut bytes = Bytes::with_capacity(8); bytes.len = 8; @@ -41,7 +111,37 @@ fn ptr_as_bytes(ptr: raw_ptr) -> Bytes { } /// Call a target contract with an already-encoded payload. -/// `payload` : The encoded payload to be called. +/// +/// # Additional Information +/// +/// It is recommended to use the `call_with_function_selector` function directly, unless you know what you are doing. +/// +/// The payload needs to be encoded according to the [Fuel VM specification](https://github.com/FuelLabs/fuel-specs/blob/master/src/vm/instruction_set.md#call-call-contract): +/// +/// bytes type value description +/// 32 byte[32] to Contract ID to call. +/// 8 byte[8] param1 First parameter (function selector). +/// 8 byte[8] param2 Second parameter (abi-encoded calldata: value if value type, otherwise pointer to reference type). +/// +/// # Arguments +/// +/// * `payload` : [Bytes] - The encoded payload to be called. +/// * `call_params` : [CallParams] - The call parameters of the function call. +/// +/// # Examples +/// +/// ```sway +/// use std::low_level_call::{bytes::Bytes, contract_id_to_bytes, call_with_raw_payload, CallParams}; +/// +/// fn call_with_copy_type_arg(target: ContractId, function_selector: Bytes, calldata: Bytes, call_params: CallParams) { +/// let mut payload = Bytes::new(); +/// payload.append(contract_id_to_bytes(target)); +/// payload.append(function_selector); +/// payload.append(calldata); +/// +/// call_with_raw_payload(payload, call_params); +/// } +/// ``` fn call_with_raw_payload(payload: Bytes, call_params: CallParams) { asm(r1: payload.buf.ptr, r2: call_params.coins, r3: call_params.asset_id, r4: call_params.gas) { call r1 r2 r3 r4; @@ -49,6 +149,33 @@ fn call_with_raw_payload(payload: Bytes, call_params: CallParams) { } /// Encode a payload from the function selection and calldata. +/// +/// # Additional Information +/// +/// It is recommended to use the `call_with_function_selector` function directly, unless you know what you are doing. +/// +/// # Arguments +/// +/// * `target` : [ContractId] - The ContractId of the contract to be called. +/// * `function_selector` : [Bytes] - The function selector of the function to be called, i.e. the first 8 bytes of `sha256("my_func(u64)")`. +/// * `calldata` : [Bytes] - The encoded arguments with which to call the function. +/// * `single_value_type_arg` : [bool] - Whether the function being called takes a single value-type argument. +/// +/// # Returns +/// +/// * [Bytes] - The encoded payload. +/// +/// # Examples +/// +/// ```sway +/// use std::low_level_call::{bytes::Bytes, create_payload, call_with_raw_payload, CallParams}; +/// +/// fn call_contract(target: ContractId, function_selector: Bytes, calldata: Bytes, call_params: CallParams, single_value_type_arg: bool) { +/// let payload = create_payload(target, function_selector, calldata, single_value_type_arg); +/// +/// call_with_raw_payload(payload, call_params); +/// } +/// ``` fn create_payload( target: ContractId, function_selector: Bytes, @@ -80,11 +207,24 @@ fn create_payload( } /// Call a target contract with a function selector and calldata, provided as `Bytes`. -/// `target` : The contract ID of the contract to be called. -/// `function_selector` : The function selector of the function to be called, i.e. the first 8 bytes of `sha256("my_func(u64)")`. -/// `calldata` : The encoded arguments with which to call the function. -/// `single_value_type_arg`: Whether the function being called takes a single value-type argument. -/// `call_params` : The amount and color of coins to forward, and the gas to forward. +/// +/// # Arguments +/// +/// * `target` : [ContractId] - The ContractId of the contract to be called. +/// * `function_selector` : [Bytes] - The function selector of the function to be called, i.e. the first 8 bytes of `sha256("my_func(u64)")`. +/// * `calldata` : [Bytes] - The encoded arguments with which to call the function. +/// * `single_value_type_arg` : [bool] - Whether the function being called takes a single value-type argument. +/// * `call_params` : [CallParams] - The amount and color of coins to forward, and the gas to forward. +/// +/// # Examples +/// +/// ```sway +/// use std::low_level_call::{bytes::Bytes, call_with_function_selector, CallParams}; +/// +/// fn call_contract(target: ContractId, function_selector: Bytes, calldata: Bytes, call_params: CallParams, single_value_type_arg: bool) { +/// call_with_function_selector(target, function_selector, calldata, single_value_type_arg, call_params); +/// } +/// ``` pub fn call_with_function_selector( target: ContractId, function_selector: Bytes, @@ -98,6 +238,28 @@ pub fn call_with_function_selector( // TO DO: Deprecate when SDK supports Bytes /// Call a target contract with a function selector and calldata, provided as `Vec`. +/// +/// # Additional Information +/// +/// It is recommended to use the `call_with_function_selector` function as this function will be deprecated in the future. +/// +/// # Arguments +/// +/// * `target` : [ContractId] - The ContractId of the contract to be called. +/// * `function_selector` : [Vec] - The function selector of the function to be called, i.e. the first 8 bytes of `sha256("my_func(u64)")`. +/// * `calldata` : [Vec] - The encoded arguments with which to call the function. +/// * `single_value_type_arg` : [bool] - Whether the function being called takes a single value-type argument. +/// * `call_params` : [CallParams] - The amount and color of coins to forward, and the gas to forward. +/// +/// # Examples +/// +/// ```sway +/// use std::low_level_call::{call_with_function_selector_vec, CallParams}; +/// +/// fn call_contract(target: ContractId, function_selector: Vec, calldata: Vec, call_params: CallParams, single_value_type_arg: bool) { +/// call_with_function_selector_vec(target, function_selector, calldata, single_value_type_arg, call_params); +/// } +/// ``` pub fn call_with_function_selector_vec( target: ContractId, function_selector: Vec, diff --git a/sway-lib-std/src/message.sw b/sway-lib-std/src/message.sw index 1f979dcbc19..8fe365b7ed9 100644 --- a/sway-lib-std/src/message.sw +++ b/sway-lib-std/src/message.sw @@ -8,13 +8,28 @@ use ::revert::revert; /// Sends a message `msg_data` to `recipient` with a `coins` amount of the base asset. /// +/// # Additional Information +/// /// Use `send_typed_message` instead of `send_message` if the message needs to be indexed. /// -/// ### Arguments +/// # Arguments +/// +/// * `recipient`: [b256] - The address of the message recipient. +/// * `msg_data`: [Bytes] - Arbitrary length message data. +/// * `coins`: [u64] - Amount of base asset to send. +/// +/// # Examples /// -/// * `recipient` - The address of the message recipient. -/// * `msg_data` - Arbitrary length message data. -/// * `coins` - Amount of base asset to send. +/// ```sway +/// use std::{message::send_message, bytes::Bytes}; +/// +/// fn foo() { +/// let recipient = 0xee45573606c96c98ba970ff7cf9511f1b8b25e6bcd52ced30b89df1e4a9c4323; +/// let mut bytes = Bytes::new(); +/// bytes.push(5u8); +/// send_message(recipient, bytes, 50); +/// } +/// ``` pub fn send_message(recipient: b256, msg_data: Bytes, coins: u64) { let recipient_pointer = __addr_of(recipient); let mut size = 0; @@ -33,13 +48,26 @@ pub fn send_message(recipient: b256, msg_data: Bytes, coins: u64) { /// Sends a message `msg_data` of type `T` to `recipient` with a `coins` amount of the base asset. /// +/// # Additional Information +/// /// Use `send_typed_message` instead of `send_message` if the message needs to be indexed. /// -/// ### Arguments +/// # Arguments +/// +/// * `recipient`: [b256] - The address of the message recipient. +/// * `msg_data`: [T] - Message data of arbitrary type `T`. +/// * `coins`: [u64] - Amount of base asset to send. +/// +/// # Examples /// -/// * `recipient` - The address of the message recipient. -/// * `msg_data` - Message data of arbitrary type `T`. -/// * `coins` - Amount of base asset to send. +/// ```sway +/// use std::message::send_typed_message; +/// +/// fn foo() { +/// let recipient = 0xee45573606c96c98ba970ff7cf9511f1b8b25e6bcd52ced30b89df1e4a9c4323; +/// send_message(recipient, "Fuel is blazingly fast", 50); +/// } +/// ``` pub fn send_typed_message(recipient: b256, msg_data: T, coins: u64) { __smo(recipient, msg_data, coins); } diff --git a/sway-lib-std/src/option.sw b/sway-lib-std/src/option.sw index 411ba160133..d6e865e3071 100644 --- a/sway-lib-std/src/option.sw +++ b/sway-lib-std/src/option.sw @@ -37,12 +37,12 @@ //! } //! ``` //! -//! ### Method overview +//! # Method overview //! //! In addition to working with pattern matching, `Option` provides a wide //! variety of different methods. //! -//! ### Querying the variant +//! # Querying the variant //! //! The `is_some` and `is_none` methods return `true` if the `Option` //! is `Some` or `None`, respectively. @@ -50,7 +50,7 @@ //! `is_none`: `Option::is_none` //! `is_some`: `Option::is_some` //! -//! ### Extracting the contained value +//! # Extracting the contained value //! //! These methods extract the contained value in an `Option` when it //! is the `Some` variant. If the `Option` is `None`: @@ -61,7 +61,7 @@ //! `unwrap` : `Option::unwrap` //! `unwrap_or`: `Option::unwrap_or` //! -//! ### Transforming contained values +//! # Transforming contained values //! //! These methods transform `Option` to `Result`: //! @@ -92,16 +92,22 @@ pub enum Option { impl Option { // Querying the contained values // - /// Returns `true` if the option is a `Some` value. + /// Returns whether the option is the `Some` variant. /// - /// ### Examples + /// # Returns /// - /// ``` - /// let x: Option = Some(2); - /// assert(x.is_some()); + /// * [bool] - Returns `true` if the option is `Some`, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: Option = Some(2); + /// assert(x.is_some()); /// - /// let x: Option = None; - /// assert(!x.is_some()); + /// let x: Option = None; + /// assert(!x.is_some()); + /// } /// ``` pub fn is_some(self) -> bool { match self { @@ -110,16 +116,22 @@ impl Option { } } - /// Returns `true` if the option is a `None` value. + /// Returns whether the option is the `None` variant. /// - /// ### Examples + /// # Returns /// - /// ``` - /// let x: Option = Some(2); - /// assert(!x.is_none()); + /// * [bool] - Returns `true` if the option is `None`, otherwise `false`. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x: Option = Some(2); + /// assert(!x.is_none()); /// - /// let x: Option = None; - /// assert(x.is_none()); + /// let x: Option = None; + /// assert(x.is_none()); + /// } /// ``` pub fn is_none(self) -> bool { match self { @@ -132,26 +144,34 @@ impl Option { // /// Returns the contained `Some` value, consuming the `self` value. /// + /// # Additional Information + /// /// Because this function may revert, its use is generally discouraged. /// Instead, use pattern matching and handle the `None` /// case explicitly, or call `unwrap_or`. /// - /// `unwrap_or`: `Option::unwrap_or` + /// # Returns /// - /// ### Reverts + /// * [T] - The value contained by the option. /// - /// Reverts if the self value equals `None`. + /// # Reverts /// - /// ### Examples + /// * Reverts if the `Option` is the `None` variant. /// - /// ``` - /// let x = Some(42); - /// assert(x.unwrap() == 42); - /// ``` + /// # Examples /// + /// ```sway + /// fn foo() { + /// let x = Some(42); + /// assert(x.unwrap() == 42); + /// } /// ``` - /// let x: Option = None; - /// assert(x.unwrap() == 42); // fails + /// + /// ```sway + /// fn foo() { + /// let x: Option = None; + /// let value = x.unwrap(); // reverts + /// } /// ``` pub fn unwrap(self) -> T { match self { @@ -162,13 +182,21 @@ impl Option { /// Returns the contained `Some` value or a provided default. /// - /// `unwrap_or`: `Option::unwrap_or` + /// # Arguments /// - /// ### Examples + /// * `default`: [T] - The default value the function will revert to. /// - /// ``` - /// assert(Some(42).unwrap_or(69) == 42); - /// assert(None::().unwrap_or(69) == 69); + /// # Returns + /// + /// * [T] - The contained value or the default value. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// assert(Some(42).unwrap_or(69) == 42); + /// assert(None::().unwrap_or(69) == 69); + /// } /// ``` pub fn unwrap_or(self, default: T) -> T { match self { @@ -182,24 +210,36 @@ impl Option { /// Transforms the `Option` into a `Result`, mapping `Some(v)` to /// `Ok(v)` and `None` to `Err(e)`. /// + /// # Additional Information + /// /// `Ok(v)` : `Result::Ok` /// `Err(e)` : `Result::Err` /// `Some(v)`: `Option::Some` /// `ok_or` : `Option::ok_or` /// - /// ### Examples + /// # Arguments + /// + /// * `err`: [E] - The error value if the option is `None`. /// - /// ``` - /// let x = Some(42); - /// match x.ok_or(0) { - /// Result::Ok(inner) => assert(inner == 42), - /// Result::Err => revert(0), - /// } + /// # Returns + /// + /// * [Result] - The result containing the value or the error. + /// + /// # Examples + /// + /// ```sway + /// fn foo() { + /// let x = Some(42); + /// match x.ok_or(0) { + /// Result::Ok(inner) => assert(inner == 42), + /// Result::Err => revert(0), + /// } /// - /// let x:Option = None; - /// match x.ok_or(0) { - /// Result::Ok(_) => revert(0), - /// Result::Err(e) => assert(e == 0), + /// let x: Option = None; + /// match x.ok_or(0) { + /// Result::Ok(_) => revert(0), + /// Result::Err(e) => assert(e == 0), + /// } /// } /// ``` pub fn ok_or(self, err: E) -> Result { diff --git a/sway-lib-std/src/outputs.sw b/sway-lib-std/src/outputs.sw index c5ccbb9346b..faa3361bf83 100644 --- a/sway-lib-std/src/outputs.sw +++ b/sway-lib-std/src/outputs.sw @@ -29,13 +29,45 @@ pub const GTF_OUTPUT_COIN_ASSET_ID = 0x204; /// The output type for a transaction. pub enum Output { + /// A coin output. Coin: (), + /// A contract output. Contract: (), + /// Remaining "change" from spending of a coin. Change: (), + /// A variable output. Variable: (), } /// Get the type of an output at `index`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the output to get the type of. +/// +/// # Returns +/// +/// * [Output] - The type of the output at `index`. +/// +/// # Reverts +/// +/// * When the output type is unrecognized. This should never happen. +/// +/// # Examples +/// +/// ```sway +/// use std::outputs::output_type; +/// +/// fn foo() { +/// let output_type = output_type(0); +/// match output_type { +/// Output::Coin => { log("The output is a coin") }, +/// Output::Contract => { log("The output is a contract") }, +/// Output::Change => { log("The output is change") }, +/// Output::Variable => { log("The output is a variable") }, +/// }; +/// } +/// ``` pub fn output_type(index: u64) -> Output { match __gtf::(index, GTF_OUTPUT_TYPE) { 0u8 => Output::Coin, @@ -48,6 +80,29 @@ pub fn output_type(index: u64) -> Output { /// Get a pointer to the output at `index` /// for either `tx_type` (transaction-script or transaction-create). +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the output to get the pointer to. +/// +/// # Returns +/// +/// * [u64] - A pointer to the output at `index`. +/// +/// # Reverts +/// +/// * When the output type is unrecognized. This should never happen. +/// +/// # Examples +/// +/// ```sway +/// use std::outputs::output_pointer; +/// +/// fn foo() { +/// let output_pointer = output_pointer(0); +/// log(output_pointer); +/// } +/// ``` pub fn output_pointer(index: u64) -> u64 { match tx_type() { Transaction::Script => __gtf::(index, GTF_SCRIPT_OUTPUT_AT_INDEX), @@ -57,6 +112,25 @@ pub fn output_pointer(index: u64) -> u64 { /// Get the transaction outputs count for either `tx_type` /// (transaction-script or transaction-create). +/// +/// # Returns +/// +/// * [u64] - The transaction outputs count. +/// +/// # Reverts +/// +/// * When the output type is unrecognized. This should never happen. +/// +/// # Examples +/// +/// ```sway +/// use std::outputs::output_count; +/// +/// fn foo() { +/// let output_count = output_count(); +/// log(output_count); +/// } +/// ``` pub fn output_count() -> u64 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_OUTPUTS_COUNT), @@ -64,9 +138,39 @@ pub fn output_count() -> u64 { } } -/// Get the amount of coins to send for the output at `index`. +/// The amount of coins to send to the output at `index`. +/// +/// # Additional Information +/// /// This method is only meaningful if the `Output` type has the `amount` field, /// specifically: `Output::Coin`, `Output::Change` & `Output::Variable`. +/// +/// For now, output changes are always guaranteed to have an amount of +/// zero since they're only set after execution terminates. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the output to get the amount of. +/// +/// # Returns +/// +/// * [u64] - The amount of coins to send to the output at `index`. +/// +/// # Reverts +/// +/// * When the output type is `Output::Contract`. +/// * When the output type is unrecognized. This should never happen. +/// +/// # Examples +/// +/// ```sway +/// use std::outputs::output_amount; +/// +/// fn foo() { +/// let output_amount = output_amount(0); +/// log(output_amount); +/// } +/// ``` pub fn output_amount(index: u64) -> u64 { match output_type(index) { Output::Coin => __gtf::(index, GTF_OUTPUT_COIN_AMOUNT), @@ -91,8 +195,30 @@ pub fn output_amount(index: u64) -> u64 { } } -/// If the output's type is `Output::Coin` return the asset ID as an `Some(id)`. -/// Otherwise, returns `None`. +/// Gets the AssetId of the output if it is a `Output::Coin`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the output to get the AssetId of. +/// +/// # Returns +/// +/// * [Option] - The AssetId of the output if it is a `Output::Coin`. None otherwise. +/// +/// # Reverts +/// +/// * When the output type is unrecognized. This should never happen. +/// +/// # Examples +/// +/// ```sway +/// use std::outputs::output_asset_id; +/// +/// fn foo() { +/// let output_asset_id = output_asset_id(0); +/// log(output_asset_id); +/// } +/// ``` pub fn output_asset_id(index: u64) -> Option { match output_type(index) { Output::Coin => Option::Some(__gtf::(index, GTF_OUTPUT_COIN_ASSET_ID)), @@ -100,9 +226,31 @@ pub fn output_asset_id(index: u64) -> Option { } } -/// If the output's type is `Output::Coin` return the b256 as `Some(to)`. -/// Otherwise, returns `None`. -/// TODO: Update to `Identity` when https://github.com/FuelLabs/sway/issues/4569 is resolved +// TODO: Update to `Identity` when https://github.com/FuelLabs/sway/issues/4569 is resolved +/// Returns the reciever of the output if it is a `Output::Coin`. Represents the reciever as a `b256`. +/// +/// # Arguments +/// +/// * `index`: [u64] - The index of the output to get the reciever of. +/// +/// # Returns +/// +/// * [Option] - The reciever of the output if it is a `Output::Coin`. None otherwise. +/// +/// # Reverts +/// +/// * When the output type is unrecognized. This should never happen. +/// +/// # Examples +/// +/// ```sway +/// use std::outputs::output_asset_to; +/// +/// fn foo() { +/// let output_reciever = output_asset_to(0); +/// log(output_reciever); +/// } +/// ``` pub fn output_asset_to(index: u64) -> Option { match output_type(index) { Output::Coin => Option::Some(__gtf::(index, GTF_OUTPUT_COIN_TO)), diff --git a/sway-lib-std/src/registers.sw b/sway-lib-std/src/registers.sw index b8589654642..6431654714b 100644 --- a/sway-lib-std/src/registers.sw +++ b/sway-lib-std/src/registers.sw @@ -3,71 +3,315 @@ library; /// Contains overflow & underflow of addition, subtraction, and multiplication. +/// +/// # Addtional Information +/// +/// In order to use this function, panic on overflow must be disabled. +/// +/// # Returns +/// +/// * [u64] - The overflow or underflow remaining value. +/// +/// # Examples +/// +/// ```sway +/// use std::{registers::overflow, flags::{disable_panic_on_overflow, enable_panic_on_overflow}}; +/// +/// fn foo() { +/// disable_panic_on_overflow(); +/// let max = u64::max(); +/// let result = max + 1; +/// let overflow_val = overflow(); +/// +/// assert(result == 0); +/// assert(overflow_val == 1); +/// enable_panic_on_overflow(); +/// } +/// ``` pub fn overflow() -> u64 { asm() { of } } /// The program counter. Memory address of the current instruction. +/// +/// # Returns +/// +/// * [raw_ptr] - The location in memory of the current instruction. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::program_counter; +/// +/// fn foo() { +/// let pc = program_counter(); +/// assert(!pc.is_null()); +/// } +/// ``` pub fn program_counter() -> raw_ptr { asm() { pc: raw_ptr } } /// Memory address of bottom of current writable stack area. +/// +/// # Returns +/// +/// * [raw_ptr] - The location in memory of the bottom of the stack. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::stack_start_ptr; +/// +/// fn foo() { +/// let ssp = stack_start_ptr(); +/// assert(!ssp.is_null()); +/// } +/// ``` pub fn stack_start_ptr() -> raw_ptr { asm() { ssp: raw_ptr } } /// Memory address on top of current writable stack area (points to free memory). +/// +/// # Returns +/// +/// * [raw_ptr] - The location in memory of the top of the stack. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::stack_ptr; +/// +/// fn foo() { +/// let sp = stack_ptr(); +/// assert(!sp.is_null()); +/// } +/// ``` pub fn stack_ptr() -> raw_ptr { asm() { sp: raw_ptr } } /// Memory address of beginning of current call frame. +/// +/// # Returns +/// +/// * [raw_ptr] - The location in memory of the start of the call frame. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::frame_ptr; +/// +/// fn foo() { +/// let fp = frame_ptr(); +/// assert(!fp.is_null()); +/// } +/// ``` pub fn frame_ptr() -> raw_ptr { asm() { fp: raw_ptr } } /// Memory address below the current bottom of the heap (points to free memory). +/// +/// # Returns +/// +/// * [raw_ptr] - The location in memory of the bottom of the heap. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::heap_ptr; +/// +/// fn foo() { +/// let hp = heap_ptr(); +/// assert(!hp.is_null()); +/// } +/// ``` pub fn heap_ptr() -> raw_ptr { asm() { hp: raw_ptr } } /// Error codes for particular operations. +/// +/// # Additional Information +/// +/// Normally, if the result of an ALU operation is mathematically undefined (e.g. dividing by zero), the VM Reverts. +/// However, if the `F_UNSAFEMATH` flag is set, $err is set to `true` and execution continues. +/// +/// # Returns +/// +/// * [u64] - A VM error code. +/// +/// # Examples +/// +/// ```sway +/// use std::{registers::error, flags::{disable_panic_on_unsafe_math, enable_panic_on_unsafe_math}}; +/// +/// fn foo() { +/// disable_panic_on_unsafe_math(); +/// let bar = 1 / 0; +/// assert(error() == 1); +/// enable_panic_on_unsafe_math(); +/// } +/// ``` pub fn error() -> u64 { asm() { err } } /// Remaining gas globally. +/// +/// # Returns +/// +/// * [u64] - The remaining gas. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::global_gas; +/// +/// fn foo() { +/// let gas = global_gas(); +/// assert(gas != 0); +/// bar(); +/// +/// let gas_2 = global_gas(); +/// assert(gas_2 < gas); +/// } +/// +/// fn bar() { +/// let val = 0; +/// } +/// ``` pub fn global_gas() -> u64 { asm() { ggas } } /// Remaining gas in the context. +/// +/// # Returns +/// +/// * [u64] - The remaining gas for the curren context. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::context_gas; +/// +/// fn foo() { +/// let gas = context_gas(); +/// let gas_2 = bar(); +/// assert(gas_2 < gas); +/// } +/// +/// fn bar() -> u64 { +/// context_gas(); +/// } +/// ``` pub fn context_gas() -> u64 { asm() { cgas } } /// Get the amount of units of `call_frames::msg_asset_id()` being sent. +/// +/// # Returns +/// +/// * [u64] - The forwarded coins in the context. +/// +/// # Examples +/// ```sway +/// use std::register::balance; +/// +/// fn foo() { +/// let bal = balance(); +/// assert(bal == 0); +/// } +/// ``` pub fn balance() -> u64 { asm() { bal } } /// Pointer to the start of the currently-executing code. +/// +/// # Returns +/// +/// * [raw_ptr] - The memory location of the start of the currently-executing code. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::instrs_start; +/// +/// fn foo() { +/// let is = instrs_start(); +/// assert(!is.is_null()); +/// } +/// ``` pub fn instrs_start() -> raw_ptr { asm() { is: raw_ptr } } /// Return value or pointer. +/// +/// # Returns +/// +/// * [u64] - The value or pointer stored in the return register of the VM for the current context. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::return_value; +/// +/// fn foo() { +/// let ret = return_value(); +/// assert(ret == 0); +/// } +/// ``` pub fn return_value() -> u64 { asm() { ret } } /// Return value length in bytes. +/// +/// # Returns +/// +/// * [u64] - The length in bytes of the value stored in the return register of the VM for the current context. +/// +/// # Examples +/// +/// ```sway +/// use std::registers::return_length; +/// +/// fn foo() { +/// let ret = return_length(); +/// assert(ret == 0); +/// } +/// ``` pub fn return_length() -> u64 { asm() { retl } } /// Flags register. +/// +/// # Returns +/// +/// * [u64] - The current flags set within the VM. +/// +/// # Examples +/// +/// ```sway +/// use std::{registers::flags, flags::disable_panic_on_overflow}; +/// +/// const F_WRAPPING_DISABLE_MASK: u64 = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010; +/// +/// fn foo() { +/// let flag = flags(); +/// assert(flag == 0); +/// disable_panic_on_overflow(); +/// let flag_2 = flags(); +/// assert(flag_2 == F_WRAPPING_DISABLE_MASK); +/// } +/// ``` pub fn flags() -> u64 { asm() { flag } } diff --git a/sway-lib-std/src/result.sw b/sway-lib-std/src/result.sw index 90bde3bb967..3b1c9a4909c 100644 --- a/sway-lib-std/src/result.sw +++ b/sway-lib-std/src/result.sw @@ -73,21 +73,27 @@ pub enum Result { impl Result { // Querying the contained values // - /// Returns `true` if the result is `Ok`. + /// Returns whether a result contains a success value. /// - /// ### Examples + /// # Returns /// - /// ``` + /// * [bool] - Returns `true` if the result is `Ok`. + /// + /// # Examples + /// + /// ```sway /// enum Error { /// NotFound, /// Invalid, /// } /// - /// let x: Result = Result::Ok(42); - /// assert(x.is_ok()); + /// fn foo() { + /// let x: Result = Result::Ok(42); + /// assert(x.is_ok()); /// - /// let y: Result = Result::Err(Error::NotFound)); - /// assert(!x.is_ok()); + /// let y: Result = Result::Err(Error::NotFound)); + /// assert(!y.is_ok()); + /// } /// ``` pub fn is_ok(self) -> bool { match self { @@ -96,21 +102,27 @@ impl Result { } } - /// Returns `true` if the result is `Err`. + /// Returns whether a result contains an error value. /// - /// ### Examples + /// # Returns /// - /// ``` + /// * [bool] - Returns `true` if the result is `Err`. + /// + /// # Examples + /// + /// ```sway /// enum Error { /// NotFound, /// Invalid, /// } /// - /// let x: Result = Result::Ok(42); - /// assert(!x.is_err()); + /// fn foo() { + /// let x: Result = Result::Ok(42); + /// assert(!x.is_err()); /// - /// let y: Result = Result::Err(Error::NotFound)); - /// assert(x.is_err()); + /// let y: Result = Result::Err(Error::NotFound)); + /// assert(y.is_err()); + /// } /// ``` pub fn is_err(self) -> bool { match self { @@ -121,27 +133,35 @@ impl Result { /// Returns the contained `Ok` value, consuming the `self` value. /// + /// # Additional Information + /// /// Because this function may revert, its use is generally discouraged. /// Instead, prefer to use pattern matching and handle the `Err` /// case explicitly. /// - /// ### Reverts + /// # Returns /// - /// Reverts if the self value is `Err`. + /// * [T] - The value contained by the result. /// - /// ### Examples + /// # Reverts /// - /// ``` + /// * Reverts if the `Result` is the `Err` variant. + /// + /// # Examples + /// + /// ```sway /// enum Error { /// NotFound, /// Invalid, /// } /// - /// let x: Result = Result::Ok(42); - /// assert(x.unwrap() == 42); + /// fn foo() { + /// let x: Result = Result::Ok(42); + /// assert(x.unwrap() == 42); /// - /// let y: Result = Result::Err(Error::NotFound)); - /// assert(x.unwrap() == 42); // reverts + /// let y: Result = Result::Err(Error::NotFound)); + /// let val = y.unwrap(); // reverts + /// } /// ``` pub fn unwrap(self) -> T { match self { @@ -152,19 +172,29 @@ impl Result { /// Returns the contained `Ok` value or a provided default. /// - /// ### Examples + /// # Arguments /// - /// ``` + /// * `default`: [T] - The value that is the default. + /// + /// # Returns + /// + /// * [T] - The value of the result or the default. + /// + /// # Examples + /// + /// ```sway /// enum Error { /// NotFound, /// Invalid, /// } /// - /// let x: Result = Result::Ok(42); - /// assert(x.unwrap_or(69) == 42); + /// fn foo() { + /// let x: Result = Result::Ok(42); + /// assert(x.unwrap_or(69) == 42); /// - /// let y: Result = Result::Err(Error::NotFound)); - /// assert(x.unwrap_or(69) == 69); + /// let y: Result = Result::Err(Error::NotFound)); + /// assert(y.unwrap_or(69) == 69); + /// } /// ``` pub fn unwrap_or(self, default: T) -> T { match self { diff --git a/sway-lib-std/src/revert.sw b/sway-lib-std/src/revert.sw index 962cf9008a1..a64a9a0acba 100644 --- a/sway-lib-std/src/revert.sw +++ b/sway-lib-std/src/revert.sw @@ -5,22 +5,21 @@ use ::logging::log; use ::error_signals::FAILED_REQUIRE_SIGNAL; /// Will either panic or revert with a given number depending on the context. -/// If used in a predicate, it will panic. -/// If used in a contract, it will revert. /// -/// ### Arguments +/// # Additional Information /// -/// * `code` - The code with which to revert the program. +/// If used in a predicate, it will panic. +/// If used in a contract, it will revert. /// -/// ### Reverts +/// # Arguments /// -/// Reverts when called in a contract. +/// * `code`: [u64] - The code with which to revert the program. /// -/// ### Panics +/// # Reverts /// -/// Panics when called in a predicate. +/// * Reverts unconditionally. /// -/// ### Examples +/// # Examples /// /// ```sway /// fn foo(should_revert: bool) { @@ -36,16 +35,16 @@ pub fn revert(code: u64) { /// Checks if the given `condition` is `true` and if not, logs `value` and reverts. /// -/// ### Arguments +/// # Arguments /// -/// * `condition` - The condition upon which to decide whether to revert or not. -/// * `value` - The value which will be logged in case `condition` is `false`. +/// * `condition`: [bool] - The condition upon which to decide whether to revert or not. +/// * `value`: [T] - The value which will be logged in case `condition` is `false`. /// -/// ### Reverts +/// # Reverts /// -/// Reverts when `condition` is `false`. +/// * Reverts when `condition` is `false`. /// -/// ### Examples +/// # Examples /// /// ```sway /// fn foo(a: u64, b: u64) { diff --git a/sway-lib-std/src/storage/storable_slice.sw b/sway-lib-std/src/storage/storable_slice.sw index 157354297d7..a1f9dd16ed6 100644 --- a/sway-lib-std/src/storage/storable_slice.sw +++ b/sway-lib-std/src/storage/storable_slice.sw @@ -7,21 +7,27 @@ use ::storage::storage_api::*; /// Store a raw_slice from the heap into storage. /// -/// ### Arguments +/// # Arguments /// -/// * `key` - The storage slot at which the variable will be stored. -/// * `slice` - The raw_slice to be stored. +/// * `key`: [b256] - The storage slot at which the variable will be stored. +/// * `slice`: [raw_slice] - The raw_slice to be stored. +/// +/// # Number of Storage Accesses /// -/// ### Examples +/// * Writes: `2` +/// +/// # Examples /// /// ```sway /// use std::{alloc::alloc_bytes, storage::{write_slice, read_slice}, constants::ZERO_B256}; /// -/// let slice = asm(ptr: (alloc_bytes(1), 1)) { ptr: raw_slice }; -/// assert(read_slice(ZERO_B256).is_none()); -/// write_slice(ZERO_B256, slice); -/// let stored_slice = read_slice(ZERO_B256).unwrap(); -/// assert(slice == stored_slice); +/// fn foo() { +/// let slice = asm(ptr: (alloc_bytes(1), 1)) { ptr: raw_slice }; +/// assert(read_slice(ZERO_B256).is_none()); +/// write_slice(ZERO_B256, slice); +/// let stored_slice = read_slice(ZERO_B256).unwrap(); +/// assert(slice == stored_slice); +/// } /// ``` #[storage(read, write)] pub fn write_slice(key: b256, slice: raw_slice) { @@ -43,23 +49,31 @@ pub fn write_slice(key: b256, slice: raw_slice) { /// Load a raw_slice from storage. /// -/// If no value was previously stored at `key`, `None` is returned. Otherwise, -/// `Some(value)` is returned, where `value` is the value stored at `key`. +/// # Arguments /// -/// ### Arguments +/// * `key`: [b256] - The storage slot to load the value from. +/// +/// # Returns +/// +/// - [Option] - If no value was previously stored at `key`, `None` is returned. Otherwise, +/// `Some(value)` is returned, where `value` is the value stored at `key`. /// -/// * `key` - The storage slot to load the value from. +/// # Number of Storage Accesses /// -/// ### Examples +/// * Reads: `2` +/// +/// # Examples /// /// ```sway /// use std::{alloc::alloc_bytes, storage::{write_slice, read_slice}, constants::ZERO_B256}; /// -/// let slice = asm(ptr: (alloc_bytes(1), 1)) { ptr: raw_slice }; -/// assert(read_slice(ZERO_B256).is_none()); -/// write_slice(ZERO_B256, slice); -/// let stored_slice = read_slice(ZERO_B256).unwrap(); -/// assert(slice == stored_slice); +/// fn foo { +/// let slice = asm(ptr: (alloc_bytes(1), 1)) { ptr: raw_slice }; +/// assert(read_slice(ZERO_B256).is_none()); +/// write_slice(ZERO_B256, slice); +/// let stored_slice = read_slice(ZERO_B256).unwrap(); +/// assert(slice == stored_slice); +/// } /// ``` #[storage(read)] pub fn read_slice(key: b256) -> Option { @@ -77,24 +91,34 @@ pub fn read_slice(key: b256) -> Option { } } -/// Clear a sequence of storage slots starting at a some key. Returns a Boolean -/// indicating whether all of the storage slots cleared were previously set. +/// Clear a sequence of storage slots starting at a some key. +/// +/// # Arguments +/// +/// * `key`: [b256] - The key of the first storage slot that will be cleared +/// +/// # Returns /// -/// ### Arguments +/// * [bool] - Indicates whether all of the storage slots cleared were previously set. +/// +/// # Number of Storage Accesses /// -/// * `key` - The key of the first storage slot that will be cleared +/// * Reads: `1` +/// * Clears: `2` /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{alloc::alloc_bytes, storage::{clear_slice, write_slice, read_slice}, constants::ZERO_B256}; /// -/// let slice = asm(ptr: (alloc_bytes(1), 1)) { ptr: raw_slice }; -/// write_slice(ZERO_B256, slice); -/// assert(read_slice(ZERO_B256).is_some()); -/// let cleared = clear_slice(ZERO_B256); -/// assert(cleared); -/// assert(read_slice(ZERO_B256).is_none()); +/// fn foo() { +/// let slice = asm(ptr: (alloc_bytes(1), 1)) { ptr: raw_slice }; +/// write_slice(ZERO_B256, slice); +/// assert(read_slice(ZERO_B256).is_some()); +/// let cleared = clear_slice(ZERO_B256); +/// assert(cleared); +/// assert(read_slice(ZERO_B256).is_none()); +/// } /// ``` #[storage(read, write)] pub fn clear_slice(key: b256) -> bool { diff --git a/sway-lib-std/src/storage/storage_api.sw b/sway-lib-std/src/storage/storage_api.sw index e4e70aa8437..099cf83a754 100644 --- a/sway-lib-std/src/storage/storage_api.sw +++ b/sway-lib-std/src/storage/storage_api.sw @@ -5,20 +5,28 @@ use ::option::Option::{self, *}; /// Store a stack value in storage. Will not work for heap values. /// -/// ### Arguments +/// # Arguments /// -/// * `slot` - The storage slot at which the variable will be stored. -/// * `value` - The value to be stored. -/// * `offset` - An offset, in words, from the beginning of `slot`, at which `value` should be -/// stored. +/// * `slot`: [b256] - The storage slot at which the variable will be stored. +/// * `offset`: [u64] - An offset starting at the beginning of `slot` at which `value` should be stored. +/// * `value`: [T] - The value to be stored. /// -/// ### Examples +/// # Number of Storage Accesses +/// +/// * Reads: `1` +/// * Writes: `1` +/// +/// # Examples /// /// ```sway -/// let five = 5_u64; -/// write(ZERO_B256, 2, five); -/// let stored_five = read::(ZERO_B256, 2).unwrap(); -/// assert(five == stored_five); +/// use std::{storage::storage_api::{read, write}, constants::ZERO_B256}; +/// +/// fn foo() { +/// let five = 5_u64; +/// write(ZERO_B256, 2, five); +/// let stored_five = read::(ZERO_B256, 2).unwrap(); +/// assert(five == stored_five); +/// } /// ``` #[storage(read, write)] pub fn write(slot: b256, offset: u64, value: T) { @@ -51,21 +59,31 @@ pub fn write(slot: b256, offset: u64, value: T) { /// Reads a value of type `T` starting at the location specified by `slot` and `offset`. If the /// value crosses the boundary of a storage slot, reading continues at the following slot. /// -/// Returns `Option(value)` if the storage slots read were valid and contain `value`. Otherwise, -/// return `None`. +/// # Arguments +/// +/// * `slot`: [b256] - The storage slot to load the value from. +/// * `offset`: [u64] - An offset, in words, from the start of `slot`, from which the value should be read. /// -/// ### Arguments +/// # Returns /// -/// * `slot` - The storage slot to load the value from. -/// * `offset` - An offset, in words, from the start of `slot`, from which the value should be read. +/// * [Option] - `Option(value)` if the storage slots read were valid and contain `value`. Otherwise, +/// returns `None`. /// -/// ### Examples +/// # Number of Storage Accesses +/// +/// * Reads: `1` +/// +/// # Examples /// /// ```sway -/// let five = 5_u64; -/// write(ZERO_B256, 2, five); -/// let stored_five = read::(ZERO_B256, 2); -/// assert(five == stored_five); +/// use std::{storage::storage_api::{read, write}, constants::ZERO_B256}; +/// +/// fn foo() { +/// let five = 5_u64; +/// write(ZERO_B256, 2, five); +/// let stored_five = read::(ZERO_B256, 2); +/// assert(five == stored_five.unwrap()); +/// } /// ``` #[storage(read)] pub fn read(slot: b256, offset: u64) -> Option { @@ -91,21 +109,32 @@ pub fn read(slot: b256, offset: u64) -> Option { } } -/// Clear a sequence of consecutive storage slots starting at a some slot. Returns a Boolean -/// indicating whether all of the storage slots cleared were previously set. +/// Clear a sequence of consecutive storage slots starting at a some slot. /// -/// ### Arguments +/// # Arguments /// -/// * `slot` - The key of the first storage slot that will be cleared +/// * `slot`: [b256] - The key of the first storage slot that will be cleared /// -/// ### Examples +/// # Returns +/// +/// * [bool] - Indicates whether all of the storage slots cleared were previously set. +/// +/// # Number of Storage Accesses +/// +/// * Clears: `1` +/// +/// # Examples /// /// ```sway -/// let five = 5_u64; -/// write(ZERO_B256, 0, five); -/// let cleared = clear::(ZERO_B256); -/// assert(cleared); -/// assert(read::(ZERO_B256, 0).is_none()); +/// use std::{storage::storage_api::{read, write, clear}, constants::ZERO_B256}; +/// +/// fn foo() { +/// let five = 5_u64; +/// write(ZERO_B256, 0, five); +/// let cleared = clear::(ZERO_B256); +/// assert(cleared); +/// assert(read::(ZERO_B256, 0).is_none()); +/// } /// ``` #[storage(write)] pub fn clear(slot: b256) -> bool { diff --git a/sway-lib-std/src/storage/storage_bytes.sw b/sway-lib-std/src/storage/storage_bytes.sw index bc09d630b34..14a00e3c770 100644 --- a/sway-lib-std/src/storage/storage_bytes.sw +++ b/sway-lib-std/src/storage/storage_bytes.sw @@ -11,17 +11,19 @@ pub struct StorageBytes {} impl StorableSlice for StorageKey { /// Takes a `Bytes` type and stores the underlying collection of tightly packed bytes. /// - /// ### Arguments + /// # Arguments /// - /// * `bytes` - The bytes which will be stored. + /// * `bytes`: [Bytes] - The bytes which will be stored. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// /// * Writes: `2` /// - /// ### Examples + /// # Examples /// /// ```sway + /// use std::{storage::storage_bytes::StorageBytes, bytes::Bytes}; + /// /// storage { /// stored_bytes: StorageBytes = StorageBytes {} /// } @@ -42,13 +44,19 @@ impl StorableSlice for StorageKey { /// Constructs a `Bytes` type from a collection of tightly packed bytes in storage. /// - /// ### Number of Storage Accesses + /// # Returns + /// + /// * [Option] - The valid `Bytes` stored, otherwise `None`. + /// + /// # Number of Storage Accesses /// /// * Reads: `2` /// - /// ### Examples + /// # Examples /// /// ```sway + /// use std::{storage::storage_bytes::StorageBytes, bytes::Bytes}; + /// /// storage { /// stored_bytes: StorageBytes = StorageBytes {} /// } @@ -77,14 +85,20 @@ impl StorableSlice for StorageKey { /// Clears a collection of tightly packed bytes in storage. /// - /// ### Number of Storage Accesses + /// # Returns + /// + /// * [bool] - Indicates whether all of the storage slots cleared were previously set. + /// + /// # Number of Storage Accesses /// /// * Reads: `1` /// * Clears: `2` /// - /// ### Examples + /// # Examples /// /// ```sway + /// use std::{storage::storage_bytes::StorageBytes, bytes::Bytes}; + /// /// storage { /// stored_bytes: StorageBytes = StorageBytes {} /// } @@ -110,13 +124,19 @@ impl StorableSlice for StorageKey { /// Returns the length of tightly packed bytes in storage. /// - /// ### Number of Storage Accesses + /// # Returns + /// + /// * [u64] - The length of the bytes in storage. + /// + /// # Number of Storage Accesses /// /// * Reads: `1` /// - /// ### Examples + /// # Examples /// /// ```sway + /// use std::{storage::storage_bytes::StorageBytes, bytes::Bytes}; + /// /// storage { /// stored_bytes: StorageBytes = StorageBytes {} /// } diff --git a/sway-lib-std/src/storage/storage_key.sw b/sway-lib-std/src/storage/storage_key.sw index c1d6f04feca..49bcb6aa660 100644 --- a/sway-lib-std/src/storage/storage_key.sw +++ b/sway-lib-std/src/storage/storage_key.sw @@ -7,14 +7,16 @@ impl StorageKey { /// Reads a value of type `T` starting at the location specified by `self`. If the value /// crosses the boundary of a storage slot, reading continues at the following slot. /// - /// Returns the value previously stored if a the storage slots read were - /// valid and contain `value`. Panics otherwise. + /// # Returns /// - /// ### Arguments + /// * [T] - Returns the value previously stored if a the storage slots read were + /// valid and contain `value`. Reverts otherwise. /// - /// None + /// # Number of Storage Accesses /// - /// ### Examples + /// * Reads: `1` + /// + /// # Examples /// /// ```sway /// fn foo() { @@ -36,14 +38,16 @@ impl StorageKey { /// Reads a value of type `T` starting at the location specified by `self`. If the value /// crosses the boundary of a storage slot, reading continues at the following slot. /// - /// Returns `Some(value)` if a the storage slots read were valid and contain `value`. + /// # Returns + /// + /// * [Option] - Returns `Some(value)` if a the storage slots read were valid and contain `value`. /// Otherwise, return `None`. /// - /// ### Arguments + /// # Number of Storage Accesses /// - /// None + /// * Reads: `1` /// - /// ### Examples + /// # Examples /// /// ```sway /// fn foo() { @@ -65,11 +69,17 @@ impl StorageKey { /// Writes a value of type `T` starting at the location specified by `self`. If the value /// crosses the boundary of a storage slot, writing continues at the following slot. /// - /// ### Arguments + /// # Arguments + /// + /// * `value`: [T] - The value of type `T` to write. /// - /// * value: the value of type `T` to write /// - /// ### Examples + /// # Number of Storage Accesses + /// + /// * Reads: `1` + /// * Writes: `1` + /// + /// # Examples /// /// ```sway /// fn foo() { @@ -78,7 +88,9 @@ impl StorageKey { /// offset: 2, /// field_id: 0x0000000000000000000000000000000000000000000000000000000000000000, /// }; - /// let x = r.write(42); // Writes 42 at the third word of storage slot with key 0x000...0 + /// + /// // Writes 42 at the third word of storage slot with key 0x000...0 + /// let x = r.write(42); /// } /// ``` #[storage(read, write)] diff --git a/sway-lib-std/src/storage/storage_map.sw b/sway-lib-std/src/storage/storage_map.sw index 9215f957d4b..69afc857d6b 100644 --- a/sway-lib-std/src/storage/storage_map.sw +++ b/sway-lib-std/src/storage/storage_map.sw @@ -10,12 +10,17 @@ pub struct StorageMap where K: Hash {} impl StorageKey> where K: Hash { /// Inserts a key-value pair into the map. /// - /// ### Arguments + /// # Arguments /// - /// * `key` - The key to which the value is paired. - /// * `value` - The value to be stored. + /// * `key`: [K] - The key to which the value is paired. + /// * `value`: [V] - The value to be stored. /// - /// ### Examples + /// # Number of Storage Accesses + /// + /// * Reads: `1` + /// * Writes: `1` + /// + /// # Examples /// /// ```sway /// storage { @@ -39,11 +44,15 @@ impl StorageKey> where K: Hash { /// Retrieves the `StorageKey` that describes the raw location in storage of the value /// stored at `key`, regardless of whether a value is actually stored at that location or not. /// - /// ### Arguments + /// # Arguments + /// + /// * `key`: [K] - The key to which the value is paired. + /// + /// # Returns /// - /// * `key` - The key to which the value is paired. + /// * [StorageKey] - Describes the raw location in storage of the value stored at `key`. /// - /// ### Examples + /// # Examples /// /// ```sway /// storage { @@ -68,13 +77,19 @@ impl StorageKey> where K: Hash { /// Clears a value previously stored using a key /// - /// Return a Boolean indicating whether there was a value previously stored at `key`. + /// # Arguments + /// + /// * `key`: [K] - The key to which the value is paired. + /// + /// # Returns + /// + /// * [bool] - Indicates whether there was a value previously stored at `key`. /// - /// ### Arguments + /// # Number of Storage Accesses /// - /// * `key` - The key to which the value is paired + /// * Clears: `1` /// - /// ### Examples + /// # Examples /// /// ```sway /// storage { diff --git a/sway-lib-std/src/storage/storage_string.sw b/sway-lib-std/src/storage/storage_string.sw index 78923c45df1..8128e58a422 100644 --- a/sway-lib-std/src/storage/storage_string.sw +++ b/sway-lib-std/src/storage/storage_string.sw @@ -11,17 +11,19 @@ pub struct StorageString {} impl StorableSlice for StorageKey { /// Takes a `String` type and saves the underlying data in storage. /// - /// ### Arguments + /// # Arguments /// - /// * `string` - The string which will be stored. + /// * `string`: [String] - The string which will be stored. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// /// * Writes: `2` /// - /// ### Examples + /// # Examples /// /// ```sway + /// use std::{storage::storage_string::StorageString, bytes::Bytes, string::String}; + /// /// storage { /// stored_string: StorageString = StorageString {} /// } @@ -43,13 +45,19 @@ impl StorableSlice for StorageKey { /// Constructs a `String` type from storage. /// - /// ### Number of Storage Accesses + /// # Returns + /// + /// * [Option] - The valid `String` stored, otherwise `None`. + /// + /// # Number of Storage Accesses /// /// * Reads: `2` /// - /// ### Examples + /// # Examples /// /// ```sway + /// use std::{storage::storage_string::StorageString, bytes::Bytes, string::String}; + /// /// storage { /// stored_string: StorageString = StorageString {} /// } @@ -79,14 +87,20 @@ impl StorableSlice for StorageKey { /// Clears a stored `String` in storage. /// - /// ### Number of Storage Accesses + /// # Returns + /// + /// * [bool] - Indicates whether all of the storage slots cleared were previously set. + /// + /// # Number of Storage Accesses /// /// * Reads: `1` /// * Clears: `2` /// - /// ### Examples + /// # Examples /// /// ```sway + /// use std::{storage::storage_string::StorageString, bytes::Bytes, string::String}; + /// /// storage { /// stored_string: StorageString = StorageString {} /// } @@ -114,13 +128,19 @@ impl StorableSlice for StorageKey { /// Returns the length of `String` in storage. /// - /// ### Number of Storage Accesses + /// # Returns + /// + /// * [u64] - The length of the bytes in storage. + /// + /// # Number of Storage Accesses /// /// * Reads: `1` /// - /// ### Examples + /// # Examples /// /// ```sway + /// use std::{storage::storage_string::StorageString, bytes::Bytes, string::String}; + /// /// storage { /// stored_string: StorageString = StorageString {} /// } diff --git a/sway-lib-std/src/storage/storage_vec.sw b/sway-lib-std/src/storage/storage_vec.sw index 484ea61b327..44437a86ef4 100644 --- a/sway-lib-std/src/storage/storage_vec.sw +++ b/sway-lib-std/src/storage/storage_vec.sw @@ -13,16 +13,16 @@ pub struct StorageVec {} impl StorageKey> { /// Appends the value to the end of the vector. /// - /// ### Arguments + /// # Arguments /// - /// * `value` - The item being added to the end of the vector. + /// * `value`: [V] - The item being added to the end of the vector. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// - /// * Reads: `1` + /// * Reads: `3` /// * Writes: `2` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -51,12 +51,16 @@ impl StorageKey> { /// Removes the last element of the vector and returns it, `None` if empty. /// - /// ### Number of Storage Accesses + /// # Returns /// - /// * Reads: `2` + /// * [Option] - The last element `V` or `None`. + /// + /// # Number of Storage Accesses + /// + /// * Reads: `3` /// * Writes: `1` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -92,15 +96,20 @@ impl StorageKey> { /// Gets the value in the given index, `None` if index is out of bounds. /// - /// ### Arguments + /// # Arguments /// - /// * `index` - The index of the vec to retrieve the item from. + /// * `index`: [u64] - The index of the vec to retrieve the item from. /// - /// ### Number of Storage Accesses + /// # Returns /// - /// * Reads: `2` + /// * [Option>] - Describes the raw location in storage of the value stored at + /// `key` or `None` if out of bounds. /// - /// ### Examples + /// # Number of Storage Accesses + /// + /// * Reads: `1` + /// + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -135,22 +144,28 @@ impl StorageKey> { /// Removes the element in the given index and moves all the elements in the following indexes /// down one index. Also returns the element. /// - /// > **_WARNING:_** Expensive for larger vecs. + /// # Additional Information + /// + /// **_WARNING:_** Expensive for larger vecs. + /// + /// # Arguments /// - /// ### Arguments + /// * `index`: [u64] - The index of the vec to remove the item from. + /// + /// # Returns /// - /// * `index` - The index of the vec to remove the item from. + /// * [V] - The element that has been removed at the index. /// - /// ### Reverts + /// # Reverts /// - /// Reverts if index is larger or equal to length of the vec. + /// * Reverts if index is larger or equal to length of the vec. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// - /// * Reads: `2 + self.len() - index` + /// * Reads: `3 + (2 * (self.len() - index))` /// * Writes: `self.len() - index` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -199,20 +214,24 @@ impl StorageKey> { /// Removes the element at the specified index and fills it with the last element. /// This does not preserve ordering and returns the element. /// - /// ### Arguments + /// # Arguments /// - /// * `index` - The index of the vec to remove the item from. + /// * `index`: [u64] - The index of the vec to remove the item from. /// - /// ### Reverts + /// # Returns /// - /// Reverts if index is larger or equal to length of the vec. + /// * [V] - The element that has been removed at the index. /// - /// ### Number of Storage Accesses + /// # Reverts /// - /// * Reads: `3` + /// * Reverts if index is larger or equal to length of the vec. + /// + /// # Number of Storage Accesses + /// + /// * Reads: `5` /// * Writes: `2` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -253,21 +272,21 @@ impl StorageKey> { /// Sets or mutates the value at the given index. /// - /// ### Arguments + /// # Arguments /// - /// * `index` - The index of the vec to set the value at - /// * `value` - The value to be set + /// * `index`: [u64] - The index of the vec to set the value at + /// * `value`: [V] - The value to be set /// - /// ### Reverts + /// # Reverts /// - /// Reverts if index is larger than or equal to the length of the vec. + /// * Reverts if index is larger than or equal to the length of the vec. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// - /// * Reads: `1` + /// * Reads: `2` /// * Writes: `1` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -300,23 +319,25 @@ impl StorageKey> { /// Inserts the value at the given index, moving the current index's value /// as well as the following index's value up by one index. /// + /// # Additional Information + /// /// > **_WARNING:_** Expensive for larger vecs. /// - /// ### Arguments + /// # Arguments /// - /// * `index` - The index of the vec to insert the item into. - /// * `value` - The value to insert into the vec. + /// * `index`: [u64] - The index of the vec to insert the item into. + /// * `value`: [V] - The value to insert into the vec. /// - /// ### Reverts + /// # Reverts /// - /// Reverts if index is larger than the length of the vec. + /// * Reverts if index is larger than the length of the vec. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// - /// * Reads: `if self.len() == index { 1 } else { 1 + self.len() - index }` + /// * Reads: `if self.len() == index { 3 } else { 5 + (2 * (self.len() - index)) }` /// * Writes: `if self.len() == index { 2 } else { 2 + self.len() - index }` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -377,11 +398,15 @@ impl StorageKey> { /// Returns the length of the vector. /// - /// ### Number of Storage Accesses + /// # Returns + /// + /// * [u64] - The stored length of the vector. + /// + /// # Number of Storage Accesses /// /// * Reads: `1` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -405,11 +430,15 @@ impl StorageKey> { /// Checks whether the len is zero or not. /// - /// ### Number of Storage Accesses + /// # Returns + /// + /// * [bool] - Indicates whether the vector is or is not empty. + /// + /// # Number of Storage Accesses /// /// * Reads: `1` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -437,11 +466,11 @@ impl StorageKey> { /// Sets the len to zero. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// /// * Clears: `1` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -465,21 +494,21 @@ impl StorageKey> { /// Swaps two elements. /// - /// ### Arguments + /// # Arguments /// - /// * element1_index - The index of the first element. - /// * element2_index - The index of the second element. + /// * `element1_index`: [u64] - The index of the first element. + /// * `element2_index`: [u64] - The index of the second element. /// - /// ### Reverts + /// # Reverts /// /// * If `element1_index` or `element2_index` is greater than the length of the vector. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// - /// * Reads: `3` + /// * Reads: `5` /// * Writes: `2` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::storage::storage_vec::*; @@ -518,11 +547,16 @@ impl StorageKey> { /// Returns the first element of the vector, or `None` if it is empty. /// - /// ### Number of Storage Accesses + /// # Returns /// - /// * Reads: `2` + /// * [Option>] - Describes the raw location in storage of the value stored at + /// the start of the vector or zero if the vector is empty. /// - /// ### Examples + /// # Number of Storage Accesses + /// + /// * Reads: `1` + /// + /// # Examples /// /// ```sway /// storage { @@ -551,11 +585,16 @@ impl StorageKey> { /// Returns the last element of the vector, or `None` if it is empty. /// - /// ### Number of Storage Accesses + /// # Returns /// - /// * Reads: `2` + /// * [Option>] - Describes the raw location in storage of the value stored at + /// the end of the vector or zero if the vector is empty. + /// + /// # Number of Storage Accesses /// - /// ### Examples + /// * Reads: `1` + /// + /// # Examples /// /// ```sway /// storage { @@ -585,12 +624,12 @@ impl StorageKey> { /// Reverses the order of elements in the vector, in place. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// - /// * Reads: `1 + (2 * (self.len() / 2))` + /// * Reads: `1 + (3 * (self.len() / 2))` /// * Writes: `2 * (self.len() / 2)` /// - /// ### Examples + /// # Examples /// /// ```sway /// storage { @@ -632,16 +671,16 @@ impl StorageKey> { /// Fills `self` with elements by cloning `value`. /// - /// ### Arguments + /// # Arguments /// - /// * value - Value to copy to each element of the vector. + /// * `value`: [V] - Value to copy to each element of the vector. /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// - /// * Reads: `1` + /// * Reads: `1 + self.len()` /// * Writes: `self.len()` /// - /// ### Examples + /// # Examples /// /// ```sway /// storage { @@ -672,21 +711,23 @@ impl StorageKey> { /// Resizes `self` in place so that `len` is equal to `new_len`. /// + /// # Additional Information + /// /// If `new_len` is greater than `len`, `self` is extended by the difference, with each /// additional slot being filled with `value`. If the `new_len` is less than `len`, `self` is /// simply truncated. /// - /// ### Arguments + /// # Arguments /// - /// * new_len - The new length to expand or truncate to - /// * value - The value to fill into new slots if the `new_len` is greater than the current length + /// * `new_len`: [u64] - The new length to expand or truncate to + /// * `value`: [V] - The value to fill into new slots if the `new_len` is greater than the current length /// - /// ### Number of Storage Accesses + /// # Number of Storage Accesses /// - /// * Reads - `1` + /// * Reads - `if new_len > self.len() { new_len - len + 2 } else { 2 }` /// * Writes - `if new_len > self.len() { new_len - len + 1 } else { 1 }` /// - /// ### Examples + /// # Examples /// /// ```sway /// storage { diff --git a/sway-lib-std/src/string.sw b/sway-lib-std/src/string.sw index 9b3df0b7e1b..7b88ccdfd52 100644 --- a/sway-lib-std/src/string.sw +++ b/sway-lib-std/src/string.sw @@ -5,38 +5,112 @@ use ::convert::From; use ::option::Option; use ::assert::assert; -/// A UTF-8 encoded growable string -/// + +/// A UTF-8 encoded growable string. +/// +/// # Additional Information +/// /// WARNING: As this type is meant to be forward compatible with UTF-8, do *not* /// add any mutation functionality or unicode input of any kind until `char` is /// implemented, codepoints are *not* guaranteed to fall on byte boundaries pub struct String { + /// The bytes representing the characters of the string. bytes: Bytes, } impl String { /// Returns `Bytes` giving a UTF-8 representation of the string. + /// + /// # Returns + /// + /// * [Bytes] - A UTF-8 representation of the string. + /// + /// # Examples + /// + /// ```sway + /// use std::string::String; + /// + /// fn foo() { + /// let mut string = String::new(); + /// string.push(0u8); + /// let bytes = string.as_bytes(); + /// assert(bytes.len() == 1); + /// assert(bytes.get(0).unwrap() == 0u8); + /// } + /// ``` pub fn as_bytes(self) -> Bytes { self.bytes } /// Gets the amount of memory on the heap allocated to the `String`. + /// + /// # Returns + /// + /// * `u64` - The number of characters the `String` can hold without reallocating. + /// + /// # Examples + /// + /// ```sway + /// use std::string::String; + /// + /// fn foo() { + /// let mut string = String::new(); + /// assert(string.capacity() == 0); + /// string.push(0u8); + /// assert(string.capacity() == 1); + /// string.push(1u8); + /// assert(string.capacity() == 2); + /// } + /// ``` pub fn capacity(self) -> u64 { self.bytes.capacity() } /// Truncates this `String` to a length of zero, clearing all content. + /// + /// # Examples + /// + /// ```sway + /// use std::string::String; + /// + /// fn foo() { + /// let mut string = String::new(); + /// string.push(0u8); + /// assert(!string.is_empty()); + /// string.clear(); + /// assert(string.is_empty()); + /// } + /// ``` pub fn clear(ref mut self) { self.bytes.clear() } /// Converts a vector of ASCII encoded bytes to a `String`. /// + /// # Additional Information + /// /// Each byte represents a single character, this supports ASCII but it does **not** support Unicode. /// /// # Arguments /// /// * `bytes` - ASCII bytes which will be converted into a `String`. + /// + /// # Returns + /// + /// * [String] - A `String` containing the ASCII encoded bytes. + /// + /// # Examples + /// + /// ```sway + /// use std::string::String; + /// + /// fn foo() { + /// let mut bytes = Bytes::new(); + /// bytes.push(0u8); + /// bytes.push(1u8); + /// let string = String::from_ascii(bytes); + /// } + /// ``` pub fn from_ascii(bytes: Bytes) -> Self { Self { bytes, @@ -45,7 +119,31 @@ impl String { /// Converts a string literal containing ASCII encoded bytes to a `String` /// - /// WARNING: this is a temporary convenience before dynamically sized types are implemented + /// # Additional Information + /// + /// This is a temporary convenience before dynamically sized types are implemented + /// + /// # Arguments + /// + /// * `s` - A string literal containing ASCII encoded bytes. + /// + /// # Returns + /// + /// * [String] - A `String` containing the ASCII encoded bytes. + /// + /// # Reverts + /// + /// * When `s` is not a string literal. + /// + /// # Examples + /// + /// ```sway + /// use std::string::String; + /// + /// fn foo() { + /// let string = String::from_ascii_str("ABCDEF"); + /// } + /// ``` pub fn from_ascii_str(s: S) -> Self { assert(__is_str_type::()); let len = __size_of_str::(); @@ -58,12 +156,44 @@ impl String { } } - /// Returns `true` if the string is empty (contains no bytes). + /// Returns a `bool` indicating whether the `String` is empty. + /// + /// # Returns + /// + /// * [bool] - `true` if the `String` is empty, `false` otherwise. + /// + /// # Examples + /// + /// ```sway + /// use std::string::String; + /// + /// fn foo() { + /// let mut string = String::new(); + /// assert(string.is_empty()); + /// string.push(0u8); + /// assert(!string.is_empty()); + /// } + /// ``` pub fn is_empty(self) -> bool { self.bytes.is_empty() } /// Constructs a new instance of the `String` type. + /// + /// # Returns + /// + /// * [String] - A new empty instance of the `String` type. + /// + /// # Examples + /// + /// ```sway + /// use std::string::String; + /// + /// fn foo() { + /// let string = String::new(); + /// string.push(0u8); + /// } + /// ``` pub fn new() -> Self { Self { bytes: Bytes::new(), @@ -74,7 +204,23 @@ impl String { /// /// # Arguments /// - /// * `capacity` - The specified amount of memory on the heap to be allocated for the `String`. + /// * `capacity`: [u64] - The specified amount of bytes on the heap to be allocated for the `String`. + /// + /// # Returns + /// + /// * [String] - A new empty instance of the `String` type with the specified capacity. + /// + /// # Examples + /// + /// ```sway + /// use std::string::String; + /// + /// fn foo() { + /// let string = String::with_capacity(1); + /// string.push(0u8); // This will not reallocate + /// string.push(1u8); // This will reallocate + /// } + /// ``` pub fn with_capacity(capacity: u64) -> Self { Self { bytes: Bytes::with_capacity(capacity), @@ -114,7 +260,6 @@ impl From for String { } // Tests -// #[test] fn string_test_as_bytes() { diff --git a/sway-lib-std/src/token.sw b/sway-lib-std/src/token.sw index 4d5de1ae86a..f0618cc5065 100644 --- a/sway-lib-std/src/token.sw +++ b/sway-lib-std/src/token.sw @@ -15,28 +15,29 @@ use ::outputs::{Output, output_amount, output_count, output_type}; /// to `to` by calling either `force_transfer_to_contract` or /// `transfer_to_address`, depending on the type of `Identity`. /// -/// > **_WARNING:_** -/// > -/// > If the `to` Identity is a contract, this will transfer coins to the contract even with no way to retrieve them -/// > (i.e: no withdrawal functionality on the receiving contract), possibly leading to -/// > the **_PERMANENT LOSS OF COINS_** if not used with care. +/// # Additional Information +/// +/// If the `to` Identity is a contract, this will transfer coins to the contract even with no way to retrieve them +/// (i.e: no withdrawal functionality on the receiving contract), possibly leading to +/// the **_PERMANENT LOSS OF COINS_** if not used with care. /// -/// ### Arguments +/// # Arguments /// -/// * `to` - The `Identity` to which to send the tokens. -/// * `sub_id` - The sub identfier of the asset which to mint. -/// * `amount` - The amount of tokens to mint. +/// * `to`: [Identity] - The recipient identity. +/// * `sub_id`: [SubId] - The sub identfier of the asset which to mint. +/// * `amount`: [u64] - The amount of tokens to mint. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{constants::ZERO_B256, token::mint_to}; /// -/// // replace the zero Address/ContractId with your desired Address/ContractId -/// let to_address = Identity::Address(Address::from(ZERO_B256)); -/// let to_contract_id = Identity::ContractId(ContractId::from(ZERO_B256)); -/// mint_to(to_address, ZERO_B256, 500); -/// mint_to(to_contract_id, ZERO_B256, 500); +/// fn foo() { +/// let to_address = Identity::Address(Address::from(ZERO_B256)); +/// let to_contract_id = Identity::ContractId(ContractId::from(ZERO_B256)); +/// mint_to(to_address, ZERO_B256, 500); +/// mint_to(to_contract_id, ZERO_B256, 500); +/// } /// ``` pub fn mint_to(to: Identity, sub_id: SubId, amount: u64) { mint(sub_id, amount); @@ -46,26 +47,27 @@ pub fn mint_to(to: Identity, sub_id: SubId, amount: u64) { /// Mint `amount` coins of the current contract's `asset_id` and send them /// UNCONDITIONALLY to the contract at `to`. /// -/// > **_WARNING:_** -/// > -/// > This will transfer coins to a contract even with no way to retrieve them -/// > (i.e: no withdrawal functionality on the receiving contract), possibly leading to -/// > the **_PERMANENT LOSS OF COINS_** if not used with care. +/// # Additional Information +/// +/// This will transfer coins to a contract even with no way to retrieve them +/// (i.e: no withdrawal functionality on the receiving contract), possibly leading to +/// the **_PERMANENT LOSS OF COINS_** if not used with care. /// -/// ### Arguments +/// # Arguments /// -/// * `to` - The `ContractId` to which to send the tokens. -/// * `sub_id` - The sub identfier of the asset which to mint. -/// * `amount` - The amount of tokens to mint. +/// * `to`: [ContractId] - The recipient contract. +/// * `sub_id`: [SubId] - The sub identfier of the asset which to mint. +/// * `amount`: [u64] - The amount of tokens to mint. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{constants::ZERO_B256, token::mint_to_contract}; /// -/// // replace the zero ContractId with your desired ContractId -/// let to = ContractId::from(ZERO_B256); -/// mint_to_contract(to, ZERO_B256, 500); +/// fn foo() { +/// let to = ContractId::from(ZERO_B256); +/// mint_to_contract(to, ZERO_B256, 500); +/// } /// ``` pub fn mint_to_contract(to: ContractId, sub_id: SubId, amount: u64) { mint(sub_id, amount); @@ -75,20 +77,21 @@ pub fn mint_to_contract(to: ContractId, sub_id: SubId, amount: u64) { /// Mint `amount` coins of the current contract's `asset_id` and send them to /// the Address `to`. /// -/// ### Arguments +/// # Arguments /// -/// * `to` - The `Address` to which to send the tokens. -/// * `sub_id` - The sub identfier of the asset which to mint. -/// * `amount` - The amount of tokens to mint. +/// * `to`: [Address] - The recipient address. +/// * `sub_id`: [SubId] - The sub identfier of the asset which to mint. +/// * `amount`: [u64] - The amount of tokens to mint. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{constants::ZERO_B256, token::mint_to_address}; /// -/// // replace the zero Address with your desired Address -/// let to = Address::from(ZERO_B256); -/// mint_to_address(to, ZERO_B256, 500); +/// fn foo() { +/// let to = Address::from(ZERO_B256); +/// mint_to_address(to, ZERO_B256, 500); +/// } /// ``` pub fn mint_to_address(to: Address, sub_id: SubId, amount: u64) { mint(sub_id, amount); @@ -97,17 +100,19 @@ pub fn mint_to_address(to: Address, sub_id: SubId, amount: u64) { /// Mint `amount` coins of the current contract's `sub_id`. The newly minted tokens are owned by the current contract. /// -/// ### Arguments +/// # Arguments /// -/// * `sub_id` - The sub identfier of the asset which to mint. -/// * `amount` - The amount of tokens to mint. +/// * `sub_id`: [SubId] - The sub identfier of the asset which to mint. +/// * `amount`: [u64] - The amount of tokens to mint. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{constants::ZERO_B256, token::mint}; /// -/// mint(ZERO_B256, 500); +/// fn foo() { +/// mint(ZERO_B256, 500); +/// } /// ``` pub fn mint(sub_id: SubId, amount: u64) { asm(r1: amount, r2: sub_id) { @@ -117,21 +122,23 @@ pub fn mint(sub_id: SubId, amount: u64) { /// Burn `amount` coins of the current contract's `sub_id`. Burns them from the balance of the current contract. /// -/// ### Arguments +/// # Arguments /// -/// * `sub_id` - The sub identfier of the asset which to burn. -/// * `amount` - The amount of tokens to burn. +/// * `sub_id`: [SubId] - The sub identfier of the asset which to burn. +/// * `amount`: [u64] - The amount of tokens to burn. /// -/// ### Reverts +/// # Reverts /// -/// Reverts if the contract balance is less than `amount`. +/// * When the contract balance is less than `amount`. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{constants::ZERO_B256, token::burn}; /// -/// burn(ZERO_B256, 500); +/// fn foo() { +/// burn(ZERO_B256, 500); +/// } /// ``` pub fn burn(sub_id: SubId, amount: u64) { asm(r1: amount, r2: sub_id) { @@ -143,34 +150,35 @@ pub fn burn(sub_id: SubId, amount: u64) { /// to `to` by calling either `force_transfer_to_contract` or /// `transfer_to_address`, depending on the type of `Identity`. /// -/// > **_WARNING:_** -/// > -/// > If the `to` Identity is a contract this may transfer coins to the contract even with no way to retrieve them -/// > (i.e. no withdrawal functionality on receiving contract), possibly leading -/// > to the **_PERMANENT LOSS OF COINS_** if not used with care. +/// # Additional Information +/// +/// If the `to` Identity is a contract this may transfer coins to the contract even with no way to retrieve them +/// (i.e. no withdrawal functionality on receiving contract), possibly leading +/// to the **_PERMANENT LOSS OF COINS_** if not used with care. /// -/// ### Arguments +/// # Arguments /// -/// * `to` - The `Identity` of the recipient. -/// * `asset_id` - The `AssetId` of the token to transfer. -/// * `amount` - The amount of tokens to transfer. +/// * `to`: [Identity] - The recipient identity. +/// * `asset_id`: [AssetId] - The token to transfer. +/// * `amount`: [u64] - The amount of tokens to transfer. /// -/// ### Reverts +/// # Reverts /// -/// * If `amount` is greater than the contract balance for `asset_id`. -/// * If `amount` is equal to zero. -/// * If there are no free variable outputs when transferring to an `Address`. +/// * When `amount` is greater than the contract balance for `asset_id`. +/// * When `amount` is equal to zero. +/// * When there are no free variable outputs when transferring to an `Address`. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{constants::{BASE_ASSET_ID, ZERO_B256}, token::transfer}; /// -/// // replace the zero Address/ContractId with your desired Address/ContractId -/// let to_address = Identity::Address(Address::from(ZERO_B256)); -/// let to_contract_id = Identity::ContractId(ContractId::from(ZERO_B256)); -/// transfer(to_address, BASE_ASSET_ID, 500); -/// transfer(to_contract_id, BASE_ASSET_ID, 500); +/// fn foo() { +/// let to_address = Identity::Address(Address::from(ZERO_B256)); +/// let to_contract_id = Identity::ContractId(ContractId::from(ZERO_B256)); +/// transfer(to_address, BASE_ASSET_ID, 500); +/// transfer(to_contract_id, BASE_ASSET_ID, 500); +/// } /// ``` pub fn transfer(to: Identity, asset_id: AssetId, amount: u64) { match to { @@ -182,31 +190,32 @@ pub fn transfer(to: Identity, asset_id: AssetId, amount: u64) { /// UNCONDITIONAL transfer of `amount` coins of type `asset_id` to /// the contract at `to`. /// -/// > **_WARNING:_** -/// > -/// > This will transfer coins to a contract even with no way to retrieve them -/// > (i.e. no withdrawal functionality on receiving contract), possibly leading -/// > to the **_PERMANENT LOSS OF COINS_** if not used with care. +/// # Additional Information +/// +/// This will transfer coins to a contract even with no way to retrieve them +/// (i.e. no withdrawal functionality on receiving contract), possibly leading +/// to the **_PERMANENT LOSS OF COINS_** if not used with care. /// -/// ### Arguments +/// # Arguments /// -/// * `to` - The `ContractId` of the recipient contract. -/// * `asset_id` - The `AssetId` of the token to transfer. -/// * `amount` - The amount of tokens to transfer. +/// * `to`: [ContractId] - The recipient contract. +/// * `asset_id`: [AssetId] - The token to transfer. +/// * `amount`: [u64] - The amount of tokens to transfer. /// -/// ### Reverts +/// # Reverts /// -/// * If `amount` is greater than the contract balance for `asset_id`. -/// * If `amount` is equal to zero. +/// * When `amount` is greater than the contract balance for `asset_id`. +/// * When `amount` is equal to zero. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{constants::{BASE_ASSET_ID, ZERO_B256}, token::force_transfer_to_contract}; /// -/// // replace the zero ContractId with your desired ContractId -/// let to_contract_id = ContractId::from(ZERO_B256); -/// force_transfer_to_contract(to_contract_id, BASE_ASSET_ID, 500); +/// fn foo() { +/// let to_contract_id = ContractId::from(ZERO_B256); +/// force_transfer_to_contract(to_contract_id, BASE_ASSET_ID, 500); +/// } /// ``` pub fn force_transfer_to_contract(to: ContractId, asset_id: AssetId, amount: u64) { asm(r1: amount, r2: asset_id, r3: to.value) { @@ -217,26 +226,27 @@ pub fn force_transfer_to_contract(to: ContractId, asset_id: AssetId, amount: u64 /// Transfer `amount` coins of type `asset_id` and send them to /// the address `to`. /// -/// ### Arguments +/// # Arguments /// -/// * `to` - The `Address` of the recipient user. -/// * `asset_id` - The `AssetId` of the token to transfer. -/// * `amount` - The amount of tokens to transfer. +/// * `to`: [Address] - The recipient address. +/// * `asset_id`: [AssetId] - The token to transfer. +/// * `amount`: [u64] - The amount of tokens to transfer. /// -/// ### Reverts +/// # Reverts /// -/// * If `amount` is greater than the contract balance for `asset_id`. -/// * If `amount` is equal to zero. -/// * If there are no free variable outputs. +/// * When `amount` is greater than the contract balance for `asset_id`. +/// * When `amount` is equal to zero. +/// * When there are no free variable outputs. /// -/// ### Examples +/// # Examples /// /// ```sway /// use std::{constants::{BASE_ASSET_ID, ZERO_B256}, token::transfer_to_address}; /// -/// // replace the zero Address with your desired Address -/// let to_address = Address::from(ZERO_B256); -/// transfer_to_address(to_address, BASE_ASSET_ID, 500); +/// fn foo() { +/// let to_address = Address::from(ZERO_B256); +/// transfer_to_address(to_address, BASE_ASSET_ID, 500); +/// } /// ``` pub fn transfer_to_address(to: Address, asset_id: AssetId, amount: u64) { // maintain a manual index as we only have `while` loops in sway atm: diff --git a/sway-lib-std/src/tx.sw b/sway-lib-std/src/tx.sw index 0d5795373d9..c13d0a47d67 100644 --- a/sway-lib-std/src/tx.sw +++ b/sway-lib-std/src/tx.sw @@ -42,12 +42,40 @@ pub const GTF_WITNESS_DATA = 0x302; /// A transaction type. pub enum Transaction { + /// A standard transaction, where execution is defined by a script. Script: (), + /// A contract deployment transaction. Create: (), } /// Get the type of the current transaction. -/// Either `0` (transaction-script) or `1` (transaction-create). +/// Either `Transaction::Script` or `Transaction::Create`. +/// +/// # Returns +/// +/// * [Transaction] - The type of the current transaction. +/// +/// # Reverts +/// +/// * When the transaction type is unrecognized. This should never happen. +/// +/// # Example +/// +/// ```sway +/// use std::tx::tx_type; +/// +/// fn foo() { +/// let tx_type = tx_type(); +/// match tx_type { +/// Transaction::Script => { +/// log("Regular script transaction"); +/// }, +/// Transaction::Create => { +/// log("Contract deployment transaction"); +/// }, +/// } +/// } +/// ``` pub fn tx_type() -> Transaction { match __gtf::(0, GTF_TYPE) { 0u8 => Transaction::Script, @@ -56,8 +84,22 @@ pub fn tx_type() -> Transaction { } } -/// Get the transaction gas price for either `tx_type` -/// (transaction-script or transaction-create). +/// Get the transaction gas price for the transaction. +/// +/// # Returns +/// +/// * [u64] - The gas price for the transaction. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_gas_price; +/// +/// fn foo() { +/// let gas_price = tx_gas_price(); +/// log(gas_price); +/// } +/// ``` pub fn tx_gas_price() -> u64 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_GAS_PRICE), @@ -65,8 +107,22 @@ pub fn tx_gas_price() -> u64 { } } -/// Get the transaction-script gas limit for either `tx_type` -/// (transaction-script or transaction-create). +/// Get the transaction-script gas limit for the transaction. +/// +/// # Returns +/// +/// * [u64] - The gas limit for the transaction. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_gas_limit; +/// +/// fn foo() { +/// let gas_limit = tx_gas_limit(); +/// log(gas_limit); +/// } +/// ``` pub fn tx_gas_limit() -> u64 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_GAS_LIMIT), @@ -74,8 +130,22 @@ pub fn tx_gas_limit() -> u64 { } } -/// Get the transaction maturity for either `tx_type` -/// (transaction-script or transaction-create). +/// Get the transaction maturity for the transaction. +/// +/// # Returns +/// +/// * [u32] - The maturity for the transaction. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_maturity; +/// +/// fn foo() { +/// let maturity = tx_maturity(); +/// log(maturity); +/// } +/// ``` pub fn tx_maturity() -> u32 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_MATURITY), @@ -83,8 +153,26 @@ pub fn tx_maturity() -> u32 { } } -/// Get the transaction-script script length. -/// Reverts if not a transaction-script. +/// Get the length of the script for the transaction. +/// +/// # Returns +/// +/// * [u64] - The script length for the transaction. +/// +/// # Reverts +/// +/// * When the transaction type is of type `Transaction::Create`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_script_length; +/// +/// fn foo() { +/// let script_length = tx_script_length(); +/// assert(script_length > 0); +/// } +/// ``` pub fn tx_script_length() -> u64 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_SCRIPT_LENGTH), @@ -92,8 +180,26 @@ pub fn tx_script_length() -> u64 { } } -/// Get the transaction script data length. -/// Reverts if not a transaction-script. +/// Get the script data length for the transaction. +/// +/// # Returns +/// +/// * [u64] - The script data length for the transaction. +/// +/// # Reverts +/// +/// * When the transaction type is of type `Transaction::Create`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_script_data_length; +/// +/// fn foo() { +/// let script_data_length = tx_script_data_length(); +/// assert(script_data_length > 0); +/// } +/// ``` pub fn tx_script_data_length() -> u64 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_SCRIPT_DATA_LENGTH), @@ -101,8 +207,22 @@ pub fn tx_script_data_length() -> u64 { } } -/// Get the transaction witnesses count for either `tx_type` -/// (transaction-script or transaction-create). +/// Get the transaction witnesses count for the transaction. +/// +/// # Returns +/// +/// * [u64] - The witnesses count for the transaction. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_witnesses_count; +/// +/// fn foo() { +/// let witnesses_count = tx_witnesses_count(); +/// log(witnesses_count); +/// } +/// ``` pub fn tx_witnesses_count() -> u64 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_WITNESSES_COUNT), @@ -110,8 +230,26 @@ pub fn tx_witnesses_count() -> u64 { } } -/// Get a pointer to the witness at index `index` for either `tx_type` -/// (transaction-script or transaction-create). +/// Get a pointer to the witness at index `index` for the transaction. +/// +/// # Arguments +/// +/// * `index` - The index of the witness to get the pointer for. +/// +/// # Returns +/// +/// * [u64] - The pointer to the witness at index `index`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_witness_pointer; +/// +/// fn foo() { +/// let witness_pointer = tx_witness_pointer(0); +/// log(witness_pointer); +/// } +/// ``` pub fn tx_witness_pointer(index: u64) -> u64 { match tx_type() { Transaction::Script => __gtf::(index, GTF_SCRIPT_WITNESS_AT_INDEX), @@ -120,17 +258,73 @@ pub fn tx_witness_pointer(index: u64) -> u64 { } /// Get the length of the witness data at `index`. +/// +/// # Arguments +/// +/// * `index` - The index of the witness to get the data length for. +/// +/// # Returns +/// +/// * [u64] - The length of the witness data at `index`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_witness_data_length; +/// +/// fn foo() { +/// let witness_data_length = tx_witness_data_length(0); +/// log(witness_data_length); +/// } +/// ``` pub fn tx_witness_data_length(index: u64) -> u64 { __gtf::(index, GTF_WITNESS_DATA_LENGTH) } /// Get the witness data at `index`. +/// +/// # Arguments +/// +/// * `index` - The index of the witness to get the data for. +/// +/// # Returns +/// +/// * [T] - The witness data at `index`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_witness_data; +/// +/// fn foo() { +/// let witness_data: u64 = tx_witness_data(0); +/// log(witness_data); +/// } +/// ``` pub fn tx_witness_data(index: u64) -> T { __gtf::(index, GTF_WITNESS_DATA).read::() } /// Get the transaction receipts root. -/// Reverts if not a transaction-script. +/// +/// # Returns +/// +/// * [b256] - The transaction receipts root. +/// +/// # Reverts +/// +/// * When the transaction type is of type `Transaction::Create`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_receipts_root; +/// +/// fn foo() { +/// let receipts_root = tx_receipts_root(); +/// log(receipts_root); +/// } +/// ``` pub fn tx_receipts_root() -> b256 { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_RECEIPTS_ROOT).read::(), @@ -139,7 +333,25 @@ pub fn tx_receipts_root() -> b256 { } /// Get the transaction script start pointer. -/// Reverts if not a transaction-script. +/// +/// # Returns +/// +/// * [raw_ptr] - The transaction script start pointer. +/// +/// # Reverts +/// +/// * When the transaction type is of type `Transaction::Create`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_script_start_pointer; +/// +/// fn foo() { +/// let script_start_pointer = tx_script_start_pointer(); +/// log(script_start_pointer); +/// } +/// ``` pub fn tx_script_start_pointer() -> raw_ptr { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_SCRIPT), @@ -148,8 +360,25 @@ pub fn tx_script_start_pointer() -> raw_ptr { } /// Get the transaction script data start pointer. -/// Reverts if not a transaction-script -/// (transaction-create has no script data length). +/// +/// # Returns +/// +/// * [raw_ptr] - The transaction script data start pointer. +/// +/// # Reverts +/// +/// * When the transaction type is of type `Transaction::Create`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_script_data_start_pointer; +/// +/// fn foo() { +/// let script_data_start_pointer = tx_script_data_start_pointer(); +/// log(script_data_start_pointer); +/// } +/// ``` pub fn tx_script_data_start_pointer() -> raw_ptr { match tx_type() { Transaction::Script => __gtf::(0, GTF_SCRIPT_SCRIPT_DATA), @@ -160,7 +389,31 @@ pub fn tx_script_data_start_pointer() -> raw_ptr { } } -/// Get the script data, typed. **Unsafe.** +/// Get the script data, typed. +/// +/// # Additional Information +/// +/// **Unsafe.** +/// **Assumes the type is correct.** +/// +/// # Returns +/// +/// * [T] - The script data, typed. +/// +/// # Reverts +/// +/// * When the transaction type is of type `Transaction::Create`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_script_data; +/// +/// fn foo() { +/// let script_data: u64 = tx_script_data(); +/// log(script_data); +/// } +/// ``` pub fn tx_script_data() -> T { let ptr = tx_script_data_start_pointer(); // TODO some safety checks on the input data? We are going to assume it is the right type for now. @@ -168,14 +421,55 @@ pub fn tx_script_data() -> T { } /// Get the script bytecode. +/// +/// # Additional Information +/// /// Must be cast to a `u64` array, with sufficient length to contain the bytecode. /// Bytecode will be padded to next whole word. +/// +/// # Returns +/// +/// * [T] - The script bytecode. +/// +/// # Reverts +/// +/// * When the transaction type is of type `Transaction::Create`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_script_bytecode; +/// +/// fn foo() { +/// let script_bytecode: [u64; 64] = tx_script_bytecode(); +/// log(script_bytecode); +/// } +/// ``` pub fn tx_script_bytecode() -> T { tx_script_start_pointer().read::() } /// Get the hash of the script bytecode. /// Reverts if not a transaction-script. +/// +/// # Returns +/// +/// * [b256] - The hash of the script bytecode. +/// +/// # Reverts +/// +/// * When the transaction type is of type `Transaction::Create`. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_script_bytecode_hash; +/// +/// fn foo() { +/// let script_bytecode_hash: b256 = tx_script_bytecode_hash(); +/// assert(script_bytecode_hash == 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef); +/// } +/// ``` pub fn tx_script_bytecode_hash() -> b256 { match tx_type() { Transaction::Script => { @@ -196,7 +490,22 @@ pub fn tx_script_bytecode_hash() -> b256 { const TX_ID_OFFSET = 0; -/// Get the ID of the current transaction. +/// Get the Transaction ID of the current transaction. +/// +/// # Returns +/// +/// * [b256] - The Transaction ID of the current transaction. +/// +/// # Examples +/// +/// ```sway +/// use std::tx::tx_id; +/// +/// fn foo() { +/// let tx_id: b256 = tx_id(); +/// log(tx_id); +/// } +/// ``` pub fn tx_id() -> b256 { asm(ptr: TX_ID_OFFSET) { ptr: raw_ptr }.read() } diff --git a/sway-lib-std/src/u128.sw b/sway-lib-std/src/u128.sw index b7aea44da89..020445a79ed 100644 --- a/sway-lib-std/src/u128.sw +++ b/sway-lib-std/src/u128.sw @@ -8,14 +8,20 @@ use ::math::*; use ::result::Result::{self, *}; /// The 128-bit unsigned integer type. +/// +/// # Additional Information +/// /// Represented as two 64-bit components: `(upper, lower)`, where `value = (upper << 64) + lower`. pub struct U128 { + /// The most significant 64 bits of the `U128`. upper: u64, + /// The least significant 64 bits of the `U128`. lower: u64, } -/// The error type used for `u128` type errors. +/// The error type used for `U128` type errors. pub enum U128Error { + /// This error occurs when a `U128` is attempted to be downcast to a `u64` and the conversion would result in a loss of precision. LossOfPrecision: (), } @@ -52,6 +58,33 @@ impl core::ops::Ord for U128 { // impl core::ops::OrdEq for U128 { // } impl u64 { + /// Performs addition between two `u64` values, returning a `U128`. + /// + /// # Additional Information + /// + /// Allows for addition between two `u64` values that would otherwise overflow. + /// + /// # Arguments + /// + /// * `right`: [u64] - The right-hand side of the addition. + /// + /// # Returns + /// + /// * [U128] - The result of the addition. + /// + /// # Examples + /// + /// ```sway + /// use std::u128::U128; + /// + /// fn foo() { + /// let x = u64::max(); + /// let y = u64::max(); + /// let z = x.overflowing_add(y); + /// + /// assert(z == U128 { upper: 1, lower: 18446744073709551614 }); + /// } + /// ``` pub fn overflowing_add(self, right: Self) -> U128 { let prior_flags = disable_panic_on_overflow(); @@ -77,6 +110,33 @@ impl u64 { result } + /// Performs multiplication between two `u64` values, returning a `U128`. + /// + /// # Additional Information + /// + /// Allows for multiplication between two `u64` values that would otherwise overflow. + /// + /// # Arguments + /// + /// * `right`: [u64] - The right-hand side of the multiplication. + /// + /// # Returns + /// + /// * [U128] - The result of the multiplication. + /// + /// # Examples + /// + /// ```sway + /// use std::u128::U128; + /// + /// fn foo() { + /// let x = u64::max(); + /// let y = u64::max(); + /// let z = x.overflowing_mul(y); + /// + /// assert(z == U128 { upper: 18446744073709551615, lower: 1 }); + /// } + /// ``` pub fn overflowing_mul(self, right: Self) -> U128 { let prior_flags = disable_panic_on_overflow(); @@ -106,15 +166,21 @@ impl u64 { impl U128 { /// Initializes a new, zeroed `U128`. /// - /// ### Examples + /// # Returns + /// + /// * [U128] - A new, zero value `U128`. + /// + /// # Examples /// /// ```sway /// use std::u128::U128; /// - /// let new_u128 = U128::new(); - /// let zero_u128 = U128 { upper: 0, lower: 0 }; - /// - /// assert(new_u128 == zero_u128); + /// fn foo() { + /// let new_u128 = U128::new(); + /// let zero_u128 = U128 { upper: 0, lower: 0 }; + /// + /// assert(new_u128 == zero_u128); + /// } /// ``` pub fn new() -> Self { Self { @@ -124,22 +190,31 @@ impl U128 { } /// Safely downcast to `u64` without loss of precision. - /// Returns `Err` if the `number > u64::max()`. /// - /// ### Examples + /// # Additional Information /// - /// ```sway - /// use std::u128::{U128, U128Error}; + /// If the `U128` is larger than `u64::max()`, an error is returned. + /// + /// # Returns /// - /// let zero_u128 = U128 { upper: 0, lower: 0 }; - /// let zero_u64 = zero_u128.as_u64().unwrap(); + /// * [Result] - The result of the downcast. /// - /// assert(zero_u64 == 0); + /// # Examples /// - /// let max_u128 = U128::max(); - /// let result = max_u128.as_u64(); + /// ```sway + /// use std::u128::{U128, U128Error}; /// - /// assert(result.is_err())); + /// fn foo() { + /// let zero_u128 = U128 { upper: 0, lower: 0 }; + /// let zero_u64 = zero_u128.as_u64().unwrap(); + /// + /// assert(zero_u64 == 0); + /// + /// let max_u128 = U128::max(); + /// let result = max_u128.as_u64(); + /// + /// assert(result.is_err())); + /// } /// ``` pub fn as_u64(self) -> Result { match self.upper { @@ -149,17 +224,22 @@ impl U128 { } /// The smallest value that can be represented by this integer type. - /// Initializes a new, zeroed `U128`. /// - /// ### Examples + /// # Returns + /// + /// * [U128] - The smallest value that can be represented by this integer type, `0`. + /// + /// # Examples /// /// ```sway /// use std::u128::U128; /// - /// let min_u128 = U128::min(); - /// let zero_u128 = U128 { upper: 0, lower: 0 }; - /// - /// assert(min_u128 == zero_u128); + /// fn foo() { + /// let min_u128 = U128::min(); + /// let zero_u128 = U128 { upper: 0, lower: 0 }; + /// + /// assert(min_u128 == zero_u128); + /// } /// ``` pub fn min() -> Self { Self { @@ -169,17 +249,22 @@ impl U128 { } /// The largest value that can be represented by this type, - /// `2128 - 1`. /// - /// ### Examples + /// # Returns + /// + /// * [U128] - The largest value that can be represented by this type, `2128 - 1`. + /// + /// # Examples /// /// ```sway /// use std::u128::U128; /// - /// let max_u128 = U128::max(); - /// let maxed_u128 = U128 { upper: u64::max(), lower: u64::max() }; - /// - /// assert(max_u128 == maxed_u128); + /// fn foo() { + /// let max_u128 = U128::max(); + /// let maxed_u128 = U128 { upper: u64::max(), lower: u64::max() }; + /// + /// assert(max_u128 == maxed_u128); + /// } /// ``` pub fn max() -> Self { Self { @@ -190,14 +275,20 @@ impl U128 { /// The size of this type in bits. /// - /// ### Examples + /// # Returns + /// + /// * [u32] - The size of this type in bits, `128`. + /// + /// # Examples /// /// ```sway /// use std::u128::U128; /// - /// let bits = U128::bits(); + /// fn foo() { + /// let bits = U128::bits(); /// - /// assert(bits == 128); + /// assert(bits == 128); + /// } /// ``` pub fn bits() -> u32 { 128 @@ -276,7 +367,7 @@ impl core::ops::Not for U128 { } impl core::ops::Add for U128 { - /// Add a `U128` to a `U128`. Panics on overflow. + /// Add a `U128` to a `U128`. Reverts on overflow. fn add(self, other: Self) -> Self { let mut upper_128 = self.upper.overflowing_add(other.upper); @@ -301,7 +392,7 @@ impl core::ops::Add for U128 { } impl core::ops::Subtract for U128 { - /// Subtract a `U128` from a `U128`. Panics of overflow. + /// Subtract a `U128` from a `U128`. Reverts of overflow. fn subtract(self, other: Self) -> Self { // If trying to subtract a larger number, panic. assert(!(self < other)); @@ -321,7 +412,7 @@ impl core::ops::Subtract for U128 { } } impl core::ops::Multiply for U128 { - /// Multiply a `U128` with a `U128`. Panics of overflow. + /// Multiply a `U128` with a `U128`. Reverts of overflow. fn multiply(self, other: Self) -> Self { // in case both of the `U128` upper parts are bigger than zero, // it automatically means overflow, as any `U128` value @@ -342,7 +433,7 @@ impl core::ops::Multiply for U128 { } impl core::ops::Divide for U128 { - /// Divide a `U128` by a `U128`. Panics if divisor is zero. + /// Divide a `U128` by a `U128`. Reverts if divisor is zero. fn divide(self, divisor: Self) -> Self { let zero = Self::from((0, 0)); diff --git a/sway-lib-std/src/u256.sw b/sway-lib-std/src/u256.sw index 60196d97cd8..14f1ef24c6c 100644 --- a/sway-lib-std/src/u256.sw +++ b/sway-lib-std/src/u256.sw @@ -23,16 +23,24 @@ fn rsh_with_carry(word: u64, shift_amount: u64) -> (u64, u64) { } /// The 256-bit unsigned integer type. +/// +/// # Additional Information +/// /// Represented as four 64-bit components: `(a, b, c, d)`, where `value = (a << 192) + (b << 128) + (c << 64) + d`. pub struct U256 { + /// The most significant 64 bits of the `U256`. a: u64, + /// The 65-128th most significant bits of the `U256`. b: u64, + /// The 129-192nd most significant bits of the `U256`. c: u64, + /// The 193-256th most significant bits of the `U256`. d: u64, } -/// The error type used for `u256` type errors. +/// The error type used for `U256` type errors. pub enum U256Error { + /// This error occurs when a `U256` is attempted to be downcast to a `u64` or `u128` and the conversion would result in a loss of precision. LossOfPrecision: (), } @@ -62,15 +70,21 @@ impl core::ops::Eq for U256 { impl U256 { /// Initializes a new, zeroed `U256`. /// - /// ### Examples + /// # Returns + /// + /// * [U256] - A new, zero value `U256`. + /// + /// # Examples /// /// ```sway /// use std::u256::U256; /// - /// let new_u256 = U256::new(); - /// let zero_u256 = U256 { a: 0, b: 0, c: 0, d: 0 }; + /// fn foo() { + /// let new_u256 = U256::new(); + /// let zero_u256 = U256 { a: 0, b: 0, c: 0, d: 0 }; /// - /// assert(new_u256 == zero_u256); + /// assert(new_u256 == zero_u256); + /// } /// ``` pub fn new() -> Self { Self { @@ -82,22 +96,31 @@ impl U256 { } /// Safely downcast to `u64` without loss of precision. - /// Returns `Err` if the `number > u64::max()`. /// - /// ### Examples + /// # Additional Information /// - /// ```sway - /// use std::u256::{U256, U256Error}; + /// If the `U256` is larger than `u64::max()`, an error will be returned. + /// + /// # Returns /// - /// let zero_u256 = U256 { a: 0, b: 0, c: 0, d: 0 }; - /// let zero_u64 = zero_u256.as_u64().unwrap(); + /// * [Result] - The `U256` as a `u64` or an error if the conversion would result in a loss of precision. /// - /// assert(zero_u64 == 0); + /// # Examples /// - /// let max_u256 = U256::max(); - /// let result = U256.as_u64(); + /// ```sway + /// use std::u256::{U256, U256Error}; /// - /// assert(result.is_err())) + /// fn foo() { + /// let zero_u256 = U256 { a: 0, b: 0, c: 0, d: 0 }; + /// let zero_u64 = zero_u256.as_u64().unwrap(); + /// + /// assert(zero_u64 == 0); + /// + /// let max_u256 = U256::max(); + /// let result = U256.as_u64(); + /// + /// assert(result.is_err())) + /// } /// ``` pub fn as_u64(self) -> Result { if self.a == 0 && self.b == 0 && self.c == 0 { @@ -107,23 +130,32 @@ impl U256 { } } - /// Safely downcast to `u128` without loss of precision. - /// Returns `Err` if `self > U128::max()`. + /// Safely downcast to `U128` without loss of precision. /// - /// ### Examples + /// # Additional Information /// - /// ```sway - /// use std::{u128::U128, u256::{U256, U256Error}}; + /// If the `U256` is larger than `U128::max()`, an error will be returned. + /// + /// # Returns /// - /// let zero_u256 = U256 { a: 0, b: 0, c: 0, d: 0 }; - /// let zero_u128 = zero_u256.as_u128().unwrap(); + /// * [Result] - The `U256` as a `U128` or an error if the conversion would result in a loss of precision. /// - /// assert(zero_u128 == U128 { upper: 0, lower: 0 }); + /// # Examples /// - /// let max_u256 = U256::max(); - /// let result = U256.as_u64(); + /// ```sway + /// use std::{u128::U128, u256::{U256, U256Error}}; /// - /// assert(result.is_err())) + /// fn foo() { + /// let zero_u256 = U256 { a: 0, b: 0, c: 0, d: 0 }; + /// let zero_u128 = zero_u256.as_u128().unwrap(); + /// + /// assert(zero_u128 == U128 { upper: 0, lower: 0 }); + /// + /// let max_u256 = U256::max(); + /// let result = U256.as_u64(); + /// + /// assert(result.is_err())) + /// } /// ``` pub fn as_u128(self) -> Result { if self.a == 0 && self.b == 0 { @@ -135,15 +167,21 @@ impl U256 { /// The smallest value that can be represented by this integer type. /// - /// ### Examples + /// # Returns + /// + /// * [U256] - The smallest value that can be represented by this integer type, `0`. + /// + /// # Examples /// /// ```sway /// use std::u256::U256; /// - /// let min_u256 = U256::min(); - /// let zero_u256 = U256 { a: 0, b: 0, c: 0, d: 0 }; - /// - /// assert(min_u256 == zero_u256); + /// fn foo() { + /// let min_u256 = U256::min(); + /// let zero_u256 = U256 { a: 0, b: 0, c: 0, d: 0 }; + /// + /// assert(min_u256 == zero_u256); + /// } /// ``` pub fn min() -> Self { Self { @@ -154,18 +192,23 @@ impl U256 { } } - /// The largest value that can be represented by this type, - /// `2256 - 1`. + /// The largest value that can be represented by this type. /// - /// ### Examples + /// # Returns + /// + /// * [U256] - The largest value that can be represented by this type, `2256 - 1`. + /// + /// # Examples /// /// ```sway /// use std::u256::U256; /// - /// let max_u256 = U256::max(); - /// let maxed_u256 = U256 { a: u64::max(), b: u64::max(), c: u64::max(), d: u64::max() }; - /// - /// assert(max_u256 == maxed_u256); + /// fn foo() { + /// let max_u256 = U256::max(); + /// let maxed_u256 = U256 { a: u64::max(), b: u64::max(), c: u64::max(), d: u64::max() }; + /// + /// assert(max_u256 == maxed_u256); + /// } /// ``` pub fn max() -> Self { Self { @@ -178,7 +221,11 @@ impl U256 { /// The size of this type in bits. /// - /// ### Examples + /// # Returns + /// + /// * [u32] - The size of this type in bits, `256`. + /// + /// # Examples /// /// ```sway /// use std::u256::U256; @@ -340,7 +387,7 @@ impl core::ops::Not for U256 { } impl core::ops::Add for U256 { - /// Add a `U256` to a `U256`. Panics on overflow. + /// Add a `U256` to a `U256`. Reverts on overflow. fn add(self, other: Self) -> Self { let (word_1, word_2, word_3, word_4) = self.into(); let (other_word_1, other_word_2, other_word_3, other_word_4) = other.into(); @@ -367,7 +414,7 @@ impl core::ops::Add for U256 { } impl core::ops::Subtract for U256 { - /// Subtract a `U256` from a `U256`. Panics of overflow. + /// Subtract a `U256` from a `U256`. Reverts of overflow. fn subtract(self, other: Self) -> Self { if self == other { return Self::min(); @@ -431,7 +478,7 @@ impl core::ops::Subtract for U256 { } impl core::ops::Multiply for U256 { - /// Multiply a `U256` with a `U256`. Panics on overflow. + /// Multiply a `U256` with a `U256`. Reverts on overflow. fn multiply(self, other: Self) -> Self { // Both upper words cannot be non-zero simultaneously. Otherwise, overflow is guaranteed. assert(self.a == 0 || other.a == 0); @@ -527,7 +574,7 @@ impl core::ops::Multiply for U256 { } impl core::ops::Divide for U256 { - /// Divide a `U256` by a `U256`. Panics if divisor is zero. + /// Divide a `U256` by a `U256`. Reverts if divisor is zero. fn divide(self, divisor: Self) -> Self { let zero = Self::from((0, 0, 0, 0)); let one = Self::from((0, 0, 0, 1)); diff --git a/sway-lib-std/src/vec.sw b/sway-lib-std/src/vec.sw index f9f5fc40f1d..7595eafa605 100644 --- a/sway-lib-std/src/vec.sw +++ b/sway-lib-std/src/vec.sw @@ -13,6 +13,20 @@ struct RawVec { impl RawVec { /// Create a new `RawVec` with zero capacity. + /// + /// # Returns + /// + /// * [RawVec] - A new `RawVec` with zero capacity. + /// + /// # Examples + /// + /// ```sway + /// use std::vec::RawVec; + /// + /// fn foo() { + /// let vec = RawVec::new(); + /// } + /// ``` pub fn new() -> Self { Self { ptr: alloc::(0), @@ -23,6 +37,24 @@ impl RawVec { /// Creates a `RawVec` (on the heap) with exactly the capacity for a /// `[T; capacity]`. This is equivalent to calling `RawVec::new` when /// `capacity` is zero. + /// + /// # Arguments + /// + /// * `capacity`: [u64] - The capacity of the `RawVec`. + /// + /// # Returns + /// + /// * [RawVec] - A new `RawVec` with zero capacity. + /// + /// # Examples + /// + /// ```sway + /// use std::vec::RawVec; + /// + /// fn foo() { + /// let vec = RawVec::with_capacity(5); + /// } + /// ``` pub fn with_capacity(capacity: u64) -> Self { Self { ptr: alloc::(capacity), @@ -31,11 +63,43 @@ impl RawVec { } /// Gets the pointer of the allocation. + /// + /// # Returns + /// + /// * [raw_ptr] - The pointer of the allocation. + /// + /// # Examples + /// + /// ```sway + /// use std::vec::RawVec; + /// + /// fn foo() { + /// let vec = RawVec::new(); + /// let ptr = vec.ptr(); + /// let end = ptr.add::(0); + /// end.write(5); + /// assert(end.read::() == 5); + /// } pub fn ptr(self) -> raw_ptr { self.ptr } /// Gets the capacity of the allocation. + /// + /// # Returns + /// + /// * [u64] - The capacity of the allocation. + /// + /// # Examples + /// + /// ```sway + /// use std::vec::RawVec; + /// + /// fn foo() { + /// let vec = RawVec::with_capacity(5); + /// let cap = vec.capacity(); + /// assert(cap == 5); + /// } pub fn capacity(self) -> u64 { self.cap } @@ -43,6 +107,19 @@ impl RawVec { /// Grow the capacity of the vector by doubling its current capacity. The /// `realloc` function allocates memory on the heap and copies the data /// from the old allocation to the new allocation. + /// + /// # Examples + /// + /// ```sway + /// use std::vec::RawVec; + /// + /// fn foo() { + /// let mut vec = RawVec::new(); + /// vec.grow(); + /// assert(vec.capacity() == 1); + /// vec.grow(); + /// assert(vec.capacity() == 2); + /// } pub fn grow(ref mut self) { let new_cap = if self.cap == 0 { 1 } else { 2 * self.cap }; @@ -60,16 +137,24 @@ pub struct Vec { impl Vec { /// Constructs a new, empty `Vec`. /// + /// # Additional Information + /// /// The vector will not allocate until elements are pushed onto it. /// - /// ### Examples + /// # Returns + /// + /// * [Vec] - A new, empty `Vec`. + /// + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// // allocates when an element is pushed - /// vec.push(5); + /// fn foo() { + /// let vec = Vec::new(); + /// // allocates when an element is pushed + /// vec.push(5); + /// } /// ``` pub fn new() -> Self { Self { @@ -80,22 +165,36 @@ impl Vec { /// Constructs a new, empty `Vec` with the specified capacity. /// + /// # Additional Information + /// /// The vector will be able to hold exactly `capacity` elements without /// reallocating. If `capacity` is zero, the vector will not allocate. /// /// It is important to note that although the returned vector has the /// *capacity* specified, the vector will have a zero *length*. /// - /// ### Examples + /// # Arguments + /// + /// * `capacity`: [u64] - The capacity of the `Vec`. + /// + /// # Returns + /// + /// * [Vec] - A new, empty `Vec` with the specified capacity. + /// + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::with_capacity(2); - /// // does not allocate - /// vec.push(5); - /// // does not re-allocate - /// vec.push(10); + /// fn foo() { + /// let vec = Vec::with_capacity(2); + /// // does not allocate + /// vec.push(5); + /// // does not re-allocate + /// vec.push(10); + /// // allocates + /// vec.push(15); + /// } /// ``` pub fn with_capacity(capacity: u64) -> Self { Self { @@ -104,18 +203,24 @@ impl Vec { } } - /// Appends an element to the back of a collection. + /// Appends an element at the end of the collection. + /// + /// # Arguments + /// + /// * `value`: [T] - The value to be pushed onto the end of the collection. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// vec.push(5); - /// let last_element = vec.pop().unwrap(); - /// assert(last_element == 5); - /// ``` + /// fn foo() { + /// let vec = Vec::new(); + /// vec.push(5); + /// let last_element = vec.pop().unwrap(); + /// assert(last_element == 5); + /// } + ///``` pub fn push(ref mut self, value: T) { // If there is insufficient capacity, grow the buffer. if self.len == self.buf.capacity() { @@ -135,14 +240,20 @@ impl Vec { /// Gets the capacity of the allocation. /// - /// ### Examples + /// # Returns + /// + /// * [u64] - The capacity of the allocation. + /// + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::with_capacity(5); - /// let cap = vec.capacity(); - /// assert(cap == 5); + /// fn foo() { + /// let vec = Vec::with_capacity(5); + /// let cap = vec.capacity(); + /// assert(cap == 5); + /// } /// ``` pub fn capacity(self) -> u64 { self.buf.cap @@ -153,36 +264,47 @@ impl Vec { /// Note that this method has no effect on the allocated capacity /// of the vector. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// vec.push(5); - /// vec.clear() - /// assert(vec.is_empty()); + /// fn foo() { + /// let vec = Vec::new(); + /// vec.push(5); + /// vec.clear() + /// assert(vec.is_empty()); + /// } /// ``` pub fn clear(ref mut self) { self.len = 0; } - /// Returns a vector element at `index`, or `None` if `index` is out of - /// bounds. + /// Fetches the element stored at `index` /// - /// ### Examples + /// # Arguments + /// + /// * `index`: [u64] - The index of the element to be fetched. + /// + /// # Returns + /// + /// * [Option] - The element stored at `index`, or `None` if `index` is out of bounds. + /// + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// vec.push(5); - /// vec.push(10); - /// vec.push(15); - /// let item = vec.get(1).unwrap(); - /// assert(item == 10); - /// let res = vec.get(10); - /// assert(res.is_none()); // index out of bounds + /// fn foo() { + /// let vec = Vec::new(); + /// vec.push(5); + /// vec.push(10); + /// vec.push(15); + /// let item = vec.get(1).unwrap(); + /// assert(item == 10); + /// let res = vec.get(10); + /// assert(res.is_none()); // index out of bounds + /// } /// ``` pub fn get(self, index: u64) -> Option { // First check that index is within bounds. @@ -200,34 +322,44 @@ impl Vec { /// Returns the number of elements in the vector, also referred to /// as its `length`. /// - /// ### Examples + /// # Returns + /// + /// * [u64] - The length of the vector. + /// + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// vec.push(5); - /// assert(vec.len() == 1); - /// vec.push(10); - /// assert(vec.len() == 2); + /// fn foo() { + /// let vec = Vec::new(); + /// vec.push(5); + /// assert(vec.len() == 1); + /// vec.push(10); + /// assert(vec.len() == 2); + /// } /// ``` pub fn len(self) -> u64 { self.len } - /// Returns `true` if the vector contains no elements. + /// Returns whether the vector is empty. + /// + /// # Returns /// - /// ### Examples + /// * [bool] - `true` if the vector is empty, `false` otherwise. + /// + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// assert(vec.is_empty()); - /// vec.push(5); - /// assert(!vec.is_empty()); - /// vec.clear() - /// assert(vec.is_empty()); + /// fn foo() { + /// let vec = Vec::new(); + /// assert(vec.is_empty()); + /// vec.push(5); + /// assert(!vec.is_empty()); + /// } /// ``` pub fn is_empty(self) -> bool { self.len == 0 @@ -236,24 +368,34 @@ impl Vec { /// Removes and returns the element at position `index` within the vector, /// shifting all elements after it to the left. /// - /// ### Reverts + /// # Arguments + /// + /// * `index`: [u64] - The index of the element to be removed. + /// + /// # Returns + /// + /// * [T] - The element that was removed. + /// + /// # Reverts /// /// * If `index >= self.len` /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// vec.push(5); - /// vec.push(10); - /// vec.push(15); - /// let item = vec.remove(1); - /// assert(item == 10); - /// assert(vec.get(0).unwrap() == 5); - /// assert(vec.get(1).unwrap() == 15); - /// assert(vec.get(2).is_none()); + /// fn foo() { + /// let vec = Vec::new(); + /// vec.push(5); + /// vec.push(10); + /// vec.push(15); + /// let item = vec.remove(1); + /// assert(item == 10); + /// assert(vec.get(0).unwrap() == 5); + /// assert(vec.get(1).unwrap() == 15); + /// assert(vec.get(2).is_none()); + /// } /// ``` pub fn remove(ref mut self, index: u64) -> T { assert(index < self.len); @@ -281,22 +423,33 @@ impl Vec { /// Inserts an element at position `index` within the vector, shifting all /// elements after it to the right. - /// Panics if `index > len`. /// - /// ### Examples + /// # Arguments + /// + /// * `index`: [u64] - The index at which to insert the element. + /// + /// * `element`: [T] - The element to be inserted. + /// + /// # Reverts + /// + /// * If `index > self.len` + /// + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// vec.push(5); - /// vec.push(10); + /// fn foo() { + /// let vec = Vec::new(); + /// vec.push(5); + /// vec.push(10); /// - /// vec.insert(1, 15); + /// vec.insert(1, 15); /// - /// assert(vec.get(0).unwrap() == 5); - /// assert(vec.get(0).unwrap() == 15); - /// assert(vec.get(0).unwrap() == 10); + /// assert(vec.get(0).unwrap() == 5); + /// assert(vec.get(1).unwrap() == 15); + /// assert(vec.get(2).unwrap() == 10); + /// } /// ``` pub fn insert(ref mut self, index: u64, element: T) { assert(index <= self.len); @@ -326,23 +479,28 @@ impl Vec { self.len += 1; } - /// Removes the last element from a vector and returns it, or `None` if it - /// is empty. + /// Removes the last element from a vector and returns it. /// - /// ### Examples + /// # Returns /// - /// ```sway - /// use std::vec::Vec; + /// * [Option] - The last element of the vector, or `None` if the vector is empty. /// - /// let vec = Vec::new(); + /// # Examples /// - /// let res = vec.pop(); - /// assert(res.is_none()); + /// ```sway + /// use std::vec::Vec; /// - /// vec.push(5); - /// let res = vec.pop(); - /// assert(res.unwrap() == 5); - /// assert(vec.is_empty()); + /// fn foo() { + /// let vec = Vec::new(); + /// + /// let res = vec.pop(); + /// assert(res.is_none()); + /// + /// vec.push(5); + /// let res = vec.pop(); + /// assert(res.unwrap() == 5); + /// assert(vec.is_empty()); + /// } /// ``` pub fn pop(ref mut self) -> Option { if self.len == 0 { @@ -354,28 +512,30 @@ impl Vec { /// Swaps two elements. /// - /// ### Arguments + /// # Arguments /// - /// * element1_index - The index of the first element. - /// * element2_index - The index of the second element. + /// * `element1_index`: [u64] - The index of the first element. + /// * `element2_index`: [u64] - The index of the second element. /// - /// ### Reverts + /// # Reverts /// /// * If `element1_index` or `element2_index` is greater than or equal to the length of vector. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// vec.push(5); - /// vec.push(10); + /// fn foo() { + /// let vec = Vec::new(); + /// vec.push(5); + /// vec.push(10); /// - /// vec.swap(0, 1); + /// vec.swap(0, 1); /// - /// assert(vec.get(0).unwrap() == 10); - /// assert(vec.get(1).unwrap() == 5); + /// assert(vec.get(0).unwrap() == 10); + /// assert(vec.get(1).unwrap() == 5); + /// } /// ``` pub fn swap(ref mut self, element1_index: u64, element2_index: u64) { assert(element1_index < self.len); @@ -395,28 +555,30 @@ impl Vec { /// Updates an element at position `index` with a new element `value`. /// - /// ### Arguments + /// # Arguments /// - /// * index - The index of the element to be set. - /// * value - The value of the element to be set. + /// * `index`: [u64] - The index of the element to be set. + /// * `value`: [T] - The value of the element to be set. /// - /// ### Reverts + /// # Reverts /// /// * If `index` is greater than or equal to the length of vector. /// - /// ### Examples + /// # Examples /// /// ```sway /// use std::vec::Vec; /// - /// let vec = Vec::new(); - /// vec.push(5); - /// vec.push(10); + /// fn foo() { + /// let vec = Vec::new(); + /// vec.push(5); + /// vec.push(10); /// - /// vec.set(0, 15); + /// vec.set(0, 15); /// - /// assert(vec.get(0).unwrap() == 15); - /// assert(vec.get(1).unwrap() == 10); + /// assert(vec.get(0).unwrap() == 15); + /// assert(vec.get(1).unwrap() == 10); + /// } /// ``` pub fn set(ref mut self, index: u64, value: T) { assert(index < self.len); @@ -428,7 +590,6 @@ impl Vec { } impl AsRawSlice for Vec { - /// Returns a raw slice to all of the elements in the vector. fn as_raw_slice(self) -> raw_slice { raw_slice::from_parts::(self.buf.ptr(), self.len) } diff --git a/sway-lib-std/src/vm/evm/ecr.sw b/sway-lib-std/src/vm/evm/ecr.sw index b3d703cb3b1..2a1bb375afa 100644 --- a/sway-lib-std/src/vm/evm/ecr.sw +++ b/sway-lib-std/src/vm/evm/ecr.sw @@ -10,6 +10,32 @@ use ::vm::evm::evm_address::EvmAddress; /// Recover the EVM address derived from the private key used to sign a message. /// Returns a `Result` to let the caller choose an error handling strategy. +/// +/// # Arguments +/// +/// * `signature`: [B512] - The signature generated by signing a message hash. +/// * `msg_hash`: [b256] - The signed data. +/// +/// # Returns +/// +/// * [Result] - The recovered evm address or an error. +/// +/// # Examples +/// +/// ```sway +/// use std::{vm::evm::{evm_address::EvmAddress, ecr::ec_recover_evm_address}, b512::B512}; +/// +/// fn foo() { +/// let hi = 0xbd0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c; +/// let lo = 0x44ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d; +/// let msg_hash = 0xee45573606c96c98ba970ff7cf9511f1b8b25e6bcd52ced30b89df1e4a9c4323; +/// let evm_address = EvmAddress::from(0x7AAE2D980BE4C3275C72CE5B527FA23FFB97B766966559DD062E2B78FD9D3766); +/// let signature: B512 = B512::from((hi, lo)); +/// // A recovered evm address. +/// let result_address = ec_recover_evm_address(signature, msg_hash).unwrap(); +/// assert(result_address == evm_address); +/// } +/// ``` pub fn ec_recover_evm_address( signature: B512, msg_hash: b256, diff --git a/sway-lib-std/src/vm/evm/evm_address.sw b/sway-lib-std/src/vm/evm/evm_address.sw index c8369baab44..da01bba6edd 100644 --- a/sway-lib-std/src/vm/evm/evm_address.sw +++ b/sway-lib-std/src/vm/evm/evm_address.sw @@ -6,6 +6,7 @@ use ::convert::From; /// The `EvmAddress` type, a struct wrapper around the inner `b256` value. pub struct EvmAddress { + /// The underlying evm address data. value: b256, } diff --git a/sway-lsp/tests/lib.rs b/sway-lsp/tests/lib.rs index a8b72a1bf1b..9836c628be0 100644 --- a/sway-lsp/tests/lib.rs +++ b/sway-lsp/tests/lib.rs @@ -722,7 +722,7 @@ async fn go_to_definition_for_paths() { req_uri: &uri, req_line: 24, req_char: 31, - def_line: 9, + def_line: 33, def_start_char: 10, def_end_char: 19, def_path: "sway-lib-std/src/constants.sw", @@ -747,7 +747,7 @@ async fn go_to_definition_for_paths() { req_uri: &uri, req_line: 13, req_char: 17, - def_line: 74, + def_line: 230, def_start_char: 5, def_end_char: 9, def_path: "sway-lib-core/src/primitives.sw", @@ -906,7 +906,7 @@ async fn go_to_definition_for_consts() { req_uri: &uri, req_line: 9, req_char: 24, - def_line: 19, + def_line: 20, def_start_char: 5, def_end_char: 9, def_path: "sway-lib-std/src/contract_id.sw", @@ -914,7 +914,7 @@ async fn go_to_definition_for_consts() { lsp::definition_check(&server, &contract_go_to); contract_go_to.req_char = 34; - contract_go_to.def_line = 20; + contract_go_to.def_line = 40; contract_go_to.def_start_char = 7; contract_go_to.def_end_char = 11; lsp::definition_check(&server, &contract_go_to);