diff --git a/crates/sui-framework/docs/move-stdlib/ascii.md b/crates/sui-framework/docs/move-stdlib/ascii.md index f7640e0139703..1026a9537d877 100644 --- a/crates/sui-framework/docs/move-stdlib/ascii.md +++ b/crates/sui-framework/docs/move-stdlib/ascii.md @@ -508,7 +508,7 @@ Returns false otherwise.
public fun is_printable_char(byte: u8): bool {
     byte >= 0x20 && // Disallow metacharacters
-    byte <= 0x7E // Don't allow DEL metacharacter
+        byte <= 0x7E // Don't allow DEL metacharacter
 }
 
diff --git a/crates/sui-framework/docs/move-stdlib/bcs.md b/crates/sui-framework/docs/move-stdlib/bcs.md index 4a02c8bfa35b7..633d619dd44c7 100644 --- a/crates/sui-framework/docs/move-stdlib/bcs.md +++ b/crates/sui-framework/docs/move-stdlib/bcs.md @@ -31,7 +31,7 @@ Return the binary representation of v in BCS (Binary Canonical Seri Implementation -
native public fun to_bytes<MoveValue>(v: &MoveValue): vector<u8>;
+
public native fun to_bytes<MoveValue>(v: &MoveValue): vector<u8>;
 
diff --git a/crates/sui-framework/docs/move-stdlib/option.md b/crates/sui-framework/docs/move-stdlib/option.md index bffabbe535ca2..bbc74e2ee87b7 100644 --- a/crates/sui-framework/docs/move-stdlib/option.md +++ b/crates/sui-framework/docs/move-stdlib/option.md @@ -285,10 +285,7 @@ Return default if t does not hold a value Implementation -
public fun get_with_default<Element: copy + drop>(
-    t: &Option<Element>,
-    default: Element,
-): Element {
+
public fun get_with_default<Element: copy + drop>(t: &Option<Element>, default: Element): Element {
     let vec_ref = &t.vec;
     if (vec_ref.is_empty()) default
     else vec_ref[0]
@@ -432,7 +429,7 @@ Different from swap(), swap_or_fill() allows for t not holding a va
 
public fun swap_or_fill<Element>(t: &mut Option<Element>, e: Element): Option<Element> {
     let vec_ref = &mut t.vec;
     let old_value = if (vec_ref.is_empty()) none()
-        else some(vec_ref.pop_back());
+    else some(vec_ref.pop_back());
     vec_ref.push_back(e);
     old_value
 }
diff --git a/crates/sui-framework/docs/move-stdlib/string.md b/crates/sui-framework/docs/move-stdlib/string.md
index 420d672321165..16a0f2cb1b5c6 100644
--- a/crates/sui-framework/docs/move-stdlib/string.md
+++ b/crates/sui-framework/docs/move-stdlib/string.md
@@ -365,10 +365,7 @@ must be at a valid utf8 char boundary.
 
 
public fun insert(s: &mut String, at: u64, o: String) {
     let bytes = &s.bytes;
-    assert!(
-        at <= bytes.length() && internal_is_char_boundary(bytes, at),
-        EInvalidIndex,
-    );
+    assert!(at <= bytes.length() && internal_is_char_boundary(bytes, at), EInvalidIndex);
     let l = s.length();
     let mut front = s.substring(0, at);
     let end = s.substring(at, l);
@@ -406,9 +403,9 @@ guaranteeing that the result is valid utf8.
     let l = bytes.length();
     assert!(
         j <= l &&
-        i <= j &&
-        internal_is_char_boundary(bytes, i) &&
-        internal_is_char_boundary(bytes, j),
+            i <= j &&
+            internal_is_char_boundary(bytes, i) &&
+            internal_is_char_boundary(bytes, j),
         EInvalidIndex,
     );
     String { bytes: internal_sub_string(bytes, i, j) }
diff --git a/crates/sui-framework/docs/move-stdlib/type_name.md b/crates/sui-framework/docs/move-stdlib/type_name.md
index 3b0bf0df95028..b2ae36229709b 100644
--- a/crates/sui-framework/docs/move-stdlib/type_name.md
+++ b/crates/sui-framework/docs/move-stdlib/type_name.md
@@ -213,22 +213,22 @@ u8, u16, u32, u64, u128, u256, bool, address, vector.
 
public fun is_primitive(self: &TypeName): bool {
     let bytes = self.name.as_bytes();
     bytes == &b"bool" ||
-    bytes == &b"u8" ||
-    bytes == &b"u16" ||
-    bytes == &b"u32" ||
-    bytes == &b"u64" ||
-    bytes == &b"u128" ||
-    bytes == &b"u256" ||
-    bytes == &b"address" ||
-    (
-        bytes.length() >= 6 &&
-        bytes[0] == ASCII_V &&
-        bytes[1] == ASCII_E &&
-        bytes[2] == ASCII_C &&
-        bytes[3] == ASCII_T &&
-        bytes[4] == ASCII_O &&
-        bytes[5] == ASCII_R,
-    )
+        bytes == &b"u8" ||
+        bytes == &b"u16" ||
+        bytes == &b"u32" ||
+        bytes == &b"u64" ||
+        bytes == &b"u128" ||
+        bytes == &b"u256" ||
+        bytes == &b"address" ||
+        (
+            bytes.length() >= 6 &&
+            bytes[0] == ASCII_V &&
+            bytes[1] == ASCII_E &&
+            bytes[2] == ASCII_C &&
+            bytes[3] == ASCII_T &&
+            bytes[4] == ASCII_O &&
+            bytes[5] == ASCII_R,
+        )
 }
 
diff --git a/crates/sui-framework/docs/move-stdlib/vector.md b/crates/sui-framework/docs/move-stdlib/vector.md index 7f9d3d1f48877..0832eebeb7d27 100644 --- a/crates/sui-framework/docs/move-stdlib/vector.md +++ b/crates/sui-framework/docs/move-stdlib/vector.md @@ -436,7 +436,10 @@ Aborts if i is out of bounds. if (i >= len) abort EINDEX_OUT_OF_BOUNDS; len = len - 1; - while (i < len) v.swap(i, { i = i + 1; i }); + while (i < len) v.swap(i, { + i = i + 1; + i + }); v.pop_back() }
diff --git a/crates/sui-framework/packages/move-stdlib/sources/address.move b/crates/sui-framework/packages/move-stdlib/sources/address.move index ec1416b4473bf..e33c9e5429c81 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/address.move +++ b/crates/sui-framework/packages/move-stdlib/sources/address.move @@ -3,10 +3,10 @@ /// Provides a way to get address length since it's a /// platform-specific parameter. -module std::address { - /// Should be converted to a native function. - /// Current implementation only works for Sui. - public fun length(): u64 { - 32 - } +module std::address; + +/// Should be converted to a native function. +/// Current implementation only works for Sui. +public fun length(): u64 { + 32 } diff --git a/crates/sui-framework/packages/move-stdlib/sources/ascii.move b/crates/sui-framework/packages/move-stdlib/sources/ascii.move index 60564b49893a1..5c6ffaf7e3655 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/ascii.move +++ b/crates/sui-framework/packages/move-stdlib/sources/ascii.move @@ -3,164 +3,164 @@ /// The `ASCII` module defines basic string and char newtypes in Move that verify /// that characters are valid ASCII, and that strings consist of only valid ASCII characters. -module std::ascii { - // Allows calling `.to_string()` to convert an `ascii::String` into as `string::String` - public use fun std::string::from_ascii as String.to_string; - - /// An invalid ASCII character was encountered when creating an ASCII string. - const EInvalidASCIICharacter: u64 = 0x10000; - /// An invalid index was encountered when creating a substring. - const EInvalidIndex: u64 = 0x10001; - - /// The `String` struct holds a vector of bytes that all represent - /// valid ASCII characters. Note that these ASCII characters may not all - /// be printable. To determine if a `String` contains only "printable" - /// characters you should use the `all_characters_printable` predicate - /// defined in this module. - public struct String has copy, drop, store { - bytes: vector, - } - - /// An ASCII character. - public struct Char has copy, drop, store { - byte: u8, - } - - /// Convert a `byte` into a `Char` that is checked to make sure it is valid ASCII. - public fun char(byte: u8): Char { - assert!(is_valid_char(byte), EInvalidASCIICharacter); - Char { byte } - } - - /// Convert a vector of bytes `bytes` into an `String`. Aborts if - /// `bytes` contains non-ASCII characters. - public fun string(bytes: vector): String { - let x = try_string(bytes); - assert!(x.is_some(), EInvalidASCIICharacter); - x.destroy_some() - } - - /// Convert a vector of bytes `bytes` into an `String`. Returns - /// `Some()` if the `bytes` contains all valid ASCII - /// characters. Otherwise returns `None`. - public fun try_string(bytes: vector): Option { - let is_valid = bytes.all!(|byte| is_valid_char(*byte)); - if (is_valid) option::some(String { bytes }) - else option::none() - } - - /// Returns `true` if all characters in `string` are printable characters - /// Returns `false` otherwise. Not all `String`s are printable strings. - public fun all_characters_printable(string: &String): bool { - string.bytes.all!(|byte| is_printable_char(*byte)) - } - - /// Push a `Char` to the end of the `string`. - public fun push_char(string: &mut String, char: Char) { - string.bytes.push_back(char.byte); - } - - /// Pop a `Char` from the end of the `string`. - public fun pop_char(string: &mut String): Char { - Char { byte: string.bytes.pop_back() } - } - - /// Returns the length of the `string` in bytes. - public fun length(string: &String): u64 { - string.as_bytes().length() - } - - /// Append the `other` string to the end of `string`. - public fun append(string: &mut String, other: String) { - string.bytes.append(other.into_bytes()) - } - - /// Insert the `other` string at the `at` index of `string`. - public fun insert(s: &mut String, at: u64, o: String) { - assert!(at <= s.length(), EInvalidIndex); - o.into_bytes().destroy!(|e| s.bytes.insert(e, at)); - } - - /// Copy the slice of the `string` from `i` to `j` into a new `String`. - public fun substring(string: &String, i: u64, j: u64): String { - assert!(i <= j && j <= string.length(), EInvalidIndex); - let mut bytes = vector[]; - i.range_do!(j, |i| bytes.push_back(string.bytes[i])); - String { bytes } - } - - /// Get the inner bytes of the `string` as a reference - public fun as_bytes(string: &String): &vector { - &string.bytes - } - - /// Unpack the `string` to get its backing bytes - public fun into_bytes(string: String): vector { - let String { bytes } = string; - bytes - } - - /// Unpack the `char` into its underlying bytes. - public fun byte(char: Char): u8 { - let Char { byte } = char; - byte - } - - /// Returns `true` if `b` is a valid ASCII character. - /// Returns `false` otherwise. - public fun is_valid_char(b: u8): bool { - b <= 0x7F - } - - /// Returns `true` if `byte` is an printable ASCII character. - /// Returns `false` otherwise. - public fun is_printable_char(byte: u8): bool { - byte >= 0x20 && // Disallow metacharacters +module std::ascii; + +// Allows calling `.to_string()` to convert an `ascii::String` into as `string::String` +public use fun std::string::from_ascii as String.to_string; + +/// An invalid ASCII character was encountered when creating an ASCII string. +const EInvalidASCIICharacter: u64 = 0x10000; +/// An invalid index was encountered when creating a substring. +const EInvalidIndex: u64 = 0x10001; + +/// The `String` struct holds a vector of bytes that all represent +/// valid ASCII characters. Note that these ASCII characters may not all +/// be printable. To determine if a `String` contains only "printable" +/// characters you should use the `all_characters_printable` predicate +/// defined in this module. +public struct String has copy, drop, store { + bytes: vector, +} + +/// An ASCII character. +public struct Char has copy, drop, store { + byte: u8, +} + +/// Convert a `byte` into a `Char` that is checked to make sure it is valid ASCII. +public fun char(byte: u8): Char { + assert!(is_valid_char(byte), EInvalidASCIICharacter); + Char { byte } +} + +/// Convert a vector of bytes `bytes` into an `String`. Aborts if +/// `bytes` contains non-ASCII characters. +public fun string(bytes: vector): String { + let x = try_string(bytes); + assert!(x.is_some(), EInvalidASCIICharacter); + x.destroy_some() +} + +/// Convert a vector of bytes `bytes` into an `String`. Returns +/// `Some()` if the `bytes` contains all valid ASCII +/// characters. Otherwise returns `None`. +public fun try_string(bytes: vector): Option { + let is_valid = bytes.all!(|byte| is_valid_char(*byte)); + if (is_valid) option::some(String { bytes }) + else option::none() +} + +/// Returns `true` if all characters in `string` are printable characters +/// Returns `false` otherwise. Not all `String`s are printable strings. +public fun all_characters_printable(string: &String): bool { + string.bytes.all!(|byte| is_printable_char(*byte)) +} + +/// Push a `Char` to the end of the `string`. +public fun push_char(string: &mut String, char: Char) { + string.bytes.push_back(char.byte); +} + +/// Pop a `Char` from the end of the `string`. +public fun pop_char(string: &mut String): Char { + Char { byte: string.bytes.pop_back() } +} + +/// Returns the length of the `string` in bytes. +public fun length(string: &String): u64 { + string.as_bytes().length() +} + +/// Append the `other` string to the end of `string`. +public fun append(string: &mut String, other: String) { + string.bytes.append(other.into_bytes()) +} + +/// Insert the `other` string at the `at` index of `string`. +public fun insert(s: &mut String, at: u64, o: String) { + assert!(at <= s.length(), EInvalidIndex); + o.into_bytes().destroy!(|e| s.bytes.insert(e, at)); +} + +/// Copy the slice of the `string` from `i` to `j` into a new `String`. +public fun substring(string: &String, i: u64, j: u64): String { + assert!(i <= j && j <= string.length(), EInvalidIndex); + let mut bytes = vector[]; + i.range_do!(j, |i| bytes.push_back(string.bytes[i])); + String { bytes } +} + +/// Get the inner bytes of the `string` as a reference +public fun as_bytes(string: &String): &vector { + &string.bytes +} + +/// Unpack the `string` to get its backing bytes +public fun into_bytes(string: String): vector { + let String { bytes } = string; + bytes +} + +/// Unpack the `char` into its underlying bytes. +public fun byte(char: Char): u8 { + let Char { byte } = char; + byte +} + +/// Returns `true` if `b` is a valid ASCII character. +/// Returns `false` otherwise. +public fun is_valid_char(b: u8): bool { + b <= 0x7F +} + +/// Returns `true` if `byte` is an printable ASCII character. +/// Returns `false` otherwise. +public fun is_printable_char(byte: u8): bool { + byte >= 0x20 && // Disallow metacharacters byte <= 0x7E // Don't allow DEL metacharacter - } - - /// Returns `true` if `string` is empty. - public fun is_empty(string: &String): bool { - string.bytes.is_empty() - } - - /// Convert a `string` to its uppercase equivalent. - public fun to_uppercase(string: &String): String { - let bytes = string.as_bytes().map_ref!(|byte| char_to_uppercase(*byte)); - String { bytes } - } - - /// Convert a `string` to its lowercase equivalent. - public fun to_lowercase(string: &String): String { - let bytes = string.as_bytes().map_ref!(|byte| char_to_lowercase(*byte)); - String { bytes } - } - - /// Computes the index of the first occurrence of the `substr` in the `string`. - /// Returns the length of the `string` if the `substr` is not found. - /// Returns 0 if the `substr` is empty. - public fun index_of(string: &String, substr: &String): u64 { - let mut i = 0; - let (n, m) = (string.length(), substr.length()); - if (n < m) return n; - while (i <= n - m) { - let mut j = 0; - while (j < m && string.bytes[i + j] == substr.bytes[j]) j = j + 1; - if (j == m) return i; - i = i + 1; - }; - n - } - - /// Convert a `char` to its lowercase equivalent. - fun char_to_uppercase(byte: u8): u8 { - if (byte >= 0x61 && byte <= 0x7A) byte - 0x20 - else byte - } - - /// Convert a `char` to its lowercase equivalent. - fun char_to_lowercase(byte: u8): u8 { - if (byte >= 0x41 && byte <= 0x5A) byte + 0x20 - else byte - } +} + +/// Returns `true` if `string` is empty. +public fun is_empty(string: &String): bool { + string.bytes.is_empty() +} + +/// Convert a `string` to its uppercase equivalent. +public fun to_uppercase(string: &String): String { + let bytes = string.as_bytes().map_ref!(|byte| char_to_uppercase(*byte)); + String { bytes } +} + +/// Convert a `string` to its lowercase equivalent. +public fun to_lowercase(string: &String): String { + let bytes = string.as_bytes().map_ref!(|byte| char_to_lowercase(*byte)); + String { bytes } +} + +/// Computes the index of the first occurrence of the `substr` in the `string`. +/// Returns the length of the `string` if the `substr` is not found. +/// Returns 0 if the `substr` is empty. +public fun index_of(string: &String, substr: &String): u64 { + let mut i = 0; + let (n, m) = (string.length(), substr.length()); + if (n < m) return n; + while (i <= n - m) { + let mut j = 0; + while (j < m && string.bytes[i + j] == substr.bytes[j]) j = j + 1; + if (j == m) return i; + i = i + 1; + }; + n +} + +/// Convert a `char` to its lowercase equivalent. +fun char_to_uppercase(byte: u8): u8 { + if (byte >= 0x61 && byte <= 0x7A) byte - 0x20 + else byte +} + +/// Convert a `char` to its lowercase equivalent. +fun char_to_lowercase(byte: u8): u8 { + if (byte >= 0x41 && byte <= 0x5A) byte + 0x20 + else byte } diff --git a/crates/sui-framework/packages/move-stdlib/sources/bcs.move b/crates/sui-framework/packages/move-stdlib/sources/bcs.move index 8e07273cf1ee5..7e0cec97d2a6d 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/bcs.move +++ b/crates/sui-framework/packages/move-stdlib/sources/bcs.move @@ -5,7 +5,7 @@ /// Serialization). BCS is the binary encoding for Move resources and other non-module values /// published on-chain. See https://github.com/diem/bcs#binary-canonical-serialization-bcs for more /// details on BCS. -module std::bcs { - /// Return the binary representation of `v` in BCS (Binary Canonical Serialization) format - native public fun to_bytes(v: &MoveValue): vector; -} +module std::bcs; + +/// Return the binary representation of `v` in BCS (Binary Canonical Serialization) format +public native fun to_bytes(v: &MoveValue): vector; diff --git a/crates/sui-framework/packages/move-stdlib/sources/bit_vector.move b/crates/sui-framework/packages/move-stdlib/sources/bit_vector.move index 354b72c492872..0e834f0d89d31 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/bit_vector.move +++ b/crates/sui-framework/packages/move-stdlib/sources/bit_vector.move @@ -1,111 +1,111 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 -module std::bit_vector { - /// The provided index is out of bounds - const EINDEX: u64 = 0x20000; - /// An invalid length of bitvector was given - const ELENGTH: u64 = 0x20001; - - #[allow(unused_const)] - const WORD_SIZE: u64 = 1; - /// The maximum allowed bitvector size - const MAX_SIZE: u64 = 1024; - - public struct BitVector has copy, drop, store { - length: u64, - bit_field: vector, - } +module std::bit_vector; - public fun new(length: u64): BitVector { - assert!(length > 0, ELENGTH); - assert!(length < MAX_SIZE, ELENGTH); - let mut counter = 0; - let mut bit_field = vector::empty(); - while (counter < length) { - bit_field.push_back(false); - counter = counter + 1; - }; +/// The provided index is out of bounds +const EINDEX: u64 = 0x20000; +/// An invalid length of bitvector was given +const ELENGTH: u64 = 0x20001; - BitVector { - length, - bit_field, - } - } +#[allow(unused_const)] +const WORD_SIZE: u64 = 1; +/// The maximum allowed bitvector size +const MAX_SIZE: u64 = 1024; - /// Set the bit at `bit_index` in the `bitvector` regardless of its previous state. - public fun set(bitvector: &mut BitVector, bit_index: u64) { - assert!(bit_index < bitvector.bit_field.length(), EINDEX); - let x = &mut bitvector.bit_field[bit_index]; - *x = true; - } +public struct BitVector has copy, drop, store { + length: u64, + bit_field: vector, +} - /// Unset the bit at `bit_index` in the `bitvector` regardless of its previous state. - public fun unset(bitvector: &mut BitVector, bit_index: u64) { - assert!(bit_index < bitvector.bit_field.length(), EINDEX); - let x = &mut bitvector.bit_field[bit_index]; - *x = false; +public fun new(length: u64): BitVector { + assert!(length > 0, ELENGTH); + assert!(length < MAX_SIZE, ELENGTH); + let mut counter = 0; + let mut bit_field = vector::empty(); + while (counter < length) { + bit_field.push_back(false); + counter = counter + 1; + }; + + BitVector { + length, + bit_field, } +} - /// Shift the `bitvector` left by `amount`. If `amount` is greater than the - /// bitvector's length the bitvector will be zeroed out. - public fun shift_left(bitvector: &mut BitVector, amount: u64) { - if (amount >= bitvector.length) { - let len = bitvector.bit_field.length(); - let mut i = 0; - while (i < len) { - let elem = &mut bitvector.bit_field[i]; - *elem = false; - i = i + 1; - }; - } else { - let mut i = amount; - - while (i < bitvector.length) { - if (bitvector.is_index_set(i)) bitvector.set(i - amount) - else bitvector.unset(i - amount); - i = i + 1; - }; - - i = bitvector.length - amount; - - while (i < bitvector.length) { - unset(bitvector, i); - i = i + 1; - }; - } - } +/// Set the bit at `bit_index` in the `bitvector` regardless of its previous state. +public fun set(bitvector: &mut BitVector, bit_index: u64) { + assert!(bit_index < bitvector.bit_field.length(), EINDEX); + let x = &mut bitvector.bit_field[bit_index]; + *x = true; +} - /// Return the value of the bit at `bit_index` in the `bitvector`. `true` - /// represents "1" and `false` represents a 0 - public fun is_index_set(bitvector: &BitVector, bit_index: u64): bool { - assert!(bit_index < bitvector.bit_field.length(), EINDEX); - bitvector.bit_field[bit_index] - } +/// Unset the bit at `bit_index` in the `bitvector` regardless of its previous state. +public fun unset(bitvector: &mut BitVector, bit_index: u64) { + assert!(bit_index < bitvector.bit_field.length(), EINDEX); + let x = &mut bitvector.bit_field[bit_index]; + *x = false; +} - /// Return the length (number of usable bits) of this bitvector - public fun length(bitvector: &BitVector): u64 { - bitvector.bit_field.length() - } +/// Shift the `bitvector` left by `amount`. If `amount` is greater than the +/// bitvector's length the bitvector will be zeroed out. +public fun shift_left(bitvector: &mut BitVector, amount: u64) { + if (amount >= bitvector.length) { + let len = bitvector.bit_field.length(); + let mut i = 0; + while (i < len) { + let elem = &mut bitvector.bit_field[i]; + *elem = false; + i = i + 1; + }; + } else { + let mut i = amount; - /// Returns the length of the longest sequence of set bits starting at (and - /// including) `start_index` in the `bitvector`. If there is no such - /// sequence, then `0` is returned. - public fun longest_set_sequence_starting_at(bitvector: &BitVector, start_index: u64): u64 { - assert!(start_index < bitvector.length, EINDEX); - let mut index = start_index; - - // Find the greatest index in the vector such that all indices less than it are set. - while (index < bitvector.length) { - if (!bitvector.is_index_set(index)) break; - index = index + 1; + while (i < bitvector.length) { + if (bitvector.is_index_set(i)) bitvector.set(i - amount) + else bitvector.unset(i - amount); + i = i + 1; }; - index - start_index - } + i = bitvector.length - amount; - #[test_only] - public fun word_size(): u64 { - WORD_SIZE + while (i < bitvector.length) { + unset(bitvector, i); + i = i + 1; + }; } } + +/// Return the value of the bit at `bit_index` in the `bitvector`. `true` +/// represents "1" and `false` represents a 0 +public fun is_index_set(bitvector: &BitVector, bit_index: u64): bool { + assert!(bit_index < bitvector.bit_field.length(), EINDEX); + bitvector.bit_field[bit_index] +} + +/// Return the length (number of usable bits) of this bitvector +public fun length(bitvector: &BitVector): u64 { + bitvector.bit_field.length() +} + +/// Returns the length of the longest sequence of set bits starting at (and +/// including) `start_index` in the `bitvector`. If there is no such +/// sequence, then `0` is returned. +public fun longest_set_sequence_starting_at(bitvector: &BitVector, start_index: u64): u64 { + assert!(start_index < bitvector.length, EINDEX); + let mut index = start_index; + + // Find the greatest index in the vector such that all indices less than it are set. + while (index < bitvector.length) { + if (!bitvector.is_index_set(index)) break; + index = index + 1; + }; + + index - start_index +} + +#[test_only] +public fun word_size(): u64 { + WORD_SIZE +} diff --git a/crates/sui-framework/packages/move-stdlib/sources/debug.move b/crates/sui-framework/packages/move-stdlib/sources/debug.move index dc9d236a8d07d..b14064b250243 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/debug.move +++ b/crates/sui-framework/packages/move-stdlib/sources/debug.move @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 /// Module providing debug functionality. -module std::debug { - native public fun print(x: &T); +module std::debug; - native public fun print_stack_trace(); -} +public native fun print(x: &T); + +public native fun print_stack_trace(); diff --git a/crates/sui-framework/packages/move-stdlib/sources/fixed_point32.move b/crates/sui-framework/packages/move-stdlib/sources/fixed_point32.move index d25eb58ed3b1c..557400e813d40 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/fixed_point32.move +++ b/crates/sui-framework/packages/move-stdlib/sources/fixed_point32.move @@ -4,106 +4,105 @@ /// Defines a fixed-point numeric type with a 32-bit integer part and /// a 32-bit fractional part. -module std::fixed_point32 { +module std::fixed_point32; - /// Define a fixed-point numeric type with 32 fractional bits. - /// This is just a u64 integer but it is wrapped in a struct to - /// make a unique type. This is a binary representation, so decimal - /// values may not be exactly representable, but it provides more - /// than 9 decimal digits of precision both before and after the - /// decimal point (18 digits total). For comparison, double precision - /// floating-point has less than 16 decimal digits of precision, so - /// be careful about using floating-point to convert these values to - /// decimal. - public struct FixedPoint32 has copy, drop, store { value: u64 } +/// Define a fixed-point numeric type with 32 fractional bits. +/// This is just a u64 integer but it is wrapped in a struct to +/// make a unique type. This is a binary representation, so decimal +/// values may not be exactly representable, but it provides more +/// than 9 decimal digits of precision both before and after the +/// decimal point (18 digits total). For comparison, double precision +/// floating-point has less than 16 decimal digits of precision, so +/// be careful about using floating-point to convert these values to +/// decimal. +public struct FixedPoint32 has copy, drop, store { value: u64 } - ///> TODO: This is a basic constant and should be provided somewhere centrally in the framework. - const MAX_U64: u128 = 18446744073709551615; +///> TODO: This is a basic constant and should be provided somewhere centrally in the framework. +const MAX_U64: u128 = 18446744073709551615; - /// The denominator provided was zero - const EDENOMINATOR: u64 = 0x10001; - /// The quotient value would be too large to be held in a `u64` - const EDIVISION: u64 = 0x20002; - /// The multiplied value would be too large to be held in a `u64` - const EMULTIPLICATION: u64 = 0x20003; - /// A division by zero was encountered - const EDIVISION_BY_ZERO: u64 = 0x10004; - /// The computed ratio when converting to a `FixedPoint32` would be unrepresentable - const ERATIO_OUT_OF_RANGE: u64 = 0x20005; +/// The denominator provided was zero +const EDENOMINATOR: u64 = 0x10001; +/// The quotient value would be too large to be held in a `u64` +const EDIVISION: u64 = 0x20002; +/// The multiplied value would be too large to be held in a `u64` +const EMULTIPLICATION: u64 = 0x20003; +/// A division by zero was encountered +const EDIVISION_BY_ZERO: u64 = 0x10004; +/// The computed ratio when converting to a `FixedPoint32` would be unrepresentable +const ERATIO_OUT_OF_RANGE: u64 = 0x20005; - /// Multiply a u64 integer by a fixed-point number, truncating any - /// fractional part of the product. This will abort if the product - /// overflows. - public fun multiply_u64(val: u64, multiplier: FixedPoint32): u64 { - // The product of two 64 bit values has 128 bits, so perform the - // multiplication with u128 types and keep the full 128 bit product - // to avoid losing accuracy. - let unscaled_product = val as u128 * (multiplier.value as u128); - // The unscaled product has 32 fractional bits (from the multiplier) - // so rescale it by shifting away the low bits. - let product = unscaled_product >> 32; - // Check whether the value is too large. - assert!(product <= MAX_U64, EMULTIPLICATION); - product as u64 - } +/// Multiply a u64 integer by a fixed-point number, truncating any +/// fractional part of the product. This will abort if the product +/// overflows. +public fun multiply_u64(val: u64, multiplier: FixedPoint32): u64 { + // The product of two 64 bit values has 128 bits, so perform the + // multiplication with u128 types and keep the full 128 bit product + // to avoid losing accuracy. + let unscaled_product = val as u128 * (multiplier.value as u128); + // The unscaled product has 32 fractional bits (from the multiplier) + // so rescale it by shifting away the low bits. + let product = unscaled_product >> 32; + // Check whether the value is too large. + assert!(product <= MAX_U64, EMULTIPLICATION); + product as u64 +} - /// Divide a u64 integer by a fixed-point number, truncating any - /// fractional part of the quotient. This will abort if the divisor - /// is zero or if the quotient overflows. - public fun divide_u64(val: u64, divisor: FixedPoint32): u64 { - // Check for division by zero. - assert!(divisor.value != 0, EDIVISION_BY_ZERO); - // First convert to 128 bits and then shift left to - // add 32 fractional zero bits to the dividend. - let scaled_value = val as u128 << 32; - let quotient = scaled_value / (divisor.value as u128); - // Check whether the value is too large. - assert!(quotient <= MAX_U64, EDIVISION); - // the value may be too large, which will cause the cast to fail - // with an arithmetic error. - quotient as u64 - } +/// Divide a u64 integer by a fixed-point number, truncating any +/// fractional part of the quotient. This will abort if the divisor +/// is zero or if the quotient overflows. +public fun divide_u64(val: u64, divisor: FixedPoint32): u64 { + // Check for division by zero. + assert!(divisor.value != 0, EDIVISION_BY_ZERO); + // First convert to 128 bits and then shift left to + // add 32 fractional zero bits to the dividend. + let scaled_value = val as u128 << 32; + let quotient = scaled_value / (divisor.value as u128); + // Check whether the value is too large. + assert!(quotient <= MAX_U64, EDIVISION); + // the value may be too large, which will cause the cast to fail + // with an arithmetic error. + quotient as u64 +} - /// Create a fixed-point value from a rational number specified by its - /// numerator and denominator. Calling this function should be preferred - /// for using `Self::create_from_raw_value` which is also available. - /// This will abort if the denominator is zero. It will also - /// abort if the numerator is nonzero and the ratio is not in the range - /// 2^-32 .. 2^32-1. When specifying decimal fractions, be careful about - /// rounding errors: if you round to display N digits after the decimal - /// point, you can use a denominator of 10^N to avoid numbers where the - /// very small imprecision in the binary representation could change the - /// rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013. - public fun create_from_rational(numerator: u64, denominator: u64): FixedPoint32 { - // If the denominator is zero, this will abort. - // Scale the numerator to have 64 fractional bits and the denominator - // to have 32 fractional bits, so that the quotient will have 32 - // fractional bits. - let scaled_numerator = numerator as u128 << 64; - let scaled_denominator = denominator as u128 << 32; - assert!(scaled_denominator != 0, EDENOMINATOR); - let quotient = scaled_numerator / scaled_denominator; - assert!(quotient != 0 || numerator == 0, ERATIO_OUT_OF_RANGE); - // Return the quotient as a fixed-point number. We first need to check whether the cast - // can succeed. - assert!(quotient <= MAX_U64, ERATIO_OUT_OF_RANGE); - FixedPoint32 { value: quotient as u64 } - } +/// Create a fixed-point value from a rational number specified by its +/// numerator and denominator. Calling this function should be preferred +/// for using `Self::create_from_raw_value` which is also available. +/// This will abort if the denominator is zero. It will also +/// abort if the numerator is nonzero and the ratio is not in the range +/// 2^-32 .. 2^32-1. When specifying decimal fractions, be careful about +/// rounding errors: if you round to display N digits after the decimal +/// point, you can use a denominator of 10^N to avoid numbers where the +/// very small imprecision in the binary representation could change the +/// rounding, e.g., 0.0125 will round down to 0.012 instead of up to 0.013. +public fun create_from_rational(numerator: u64, denominator: u64): FixedPoint32 { + // If the denominator is zero, this will abort. + // Scale the numerator to have 64 fractional bits and the denominator + // to have 32 fractional bits, so that the quotient will have 32 + // fractional bits. + let scaled_numerator = numerator as u128 << 64; + let scaled_denominator = denominator as u128 << 32; + assert!(scaled_denominator != 0, EDENOMINATOR); + let quotient = scaled_numerator / scaled_denominator; + assert!(quotient != 0 || numerator == 0, ERATIO_OUT_OF_RANGE); + // Return the quotient as a fixed-point number. We first need to check whether the cast + // can succeed. + assert!(quotient <= MAX_U64, ERATIO_OUT_OF_RANGE); + FixedPoint32 { value: quotient as u64 } +} - /// Create a fixedpoint value from a raw value. - public fun create_from_raw_value(value: u64): FixedPoint32 { - FixedPoint32 { value } - } +/// Create a fixedpoint value from a raw value. +public fun create_from_raw_value(value: u64): FixedPoint32 { + FixedPoint32 { value } +} - /// Accessor for the raw u64 value. Other less common operations, such as - /// adding or subtracting FixedPoint32 values, can be done using the raw - /// values directly. - public fun get_raw_value(num: FixedPoint32): u64 { - num.value - } +/// Accessor for the raw u64 value. Other less common operations, such as +/// adding or subtracting FixedPoint32 values, can be done using the raw +/// values directly. +public fun get_raw_value(num: FixedPoint32): u64 { + num.value +} - /// Returns true if the ratio is zero. - public fun is_zero(num: FixedPoint32): bool { - num.value == 0 - } +/// Returns true if the ratio is zero. +public fun is_zero(num: FixedPoint32): bool { + num.value == 0 } diff --git a/crates/sui-framework/packages/move-stdlib/sources/hash.move b/crates/sui-framework/packages/move-stdlib/sources/hash.move index ed84f18a9a7fc..8ea9483da019d 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/hash.move +++ b/crates/sui-framework/packages/move-stdlib/sources/hash.move @@ -5,7 +5,7 @@ /// /// The functions in this module are natively declared both in the Move runtime /// as in the Move prover's prelude. -module std::hash { - native public fun sha2_256(data: vector): vector; - native public fun sha3_256(data: vector): vector; -} +module std::hash; + +public native fun sha2_256(data: vector): vector; +public native fun sha3_256(data: vector): vector; diff --git a/crates/sui-framework/packages/move-stdlib/sources/macros.move b/crates/sui-framework/packages/move-stdlib/sources/macros.move index f1713a984d61d..39083993f3896 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/macros.move +++ b/crates/sui-framework/packages/move-stdlib/sources/macros.move @@ -2,148 +2,146 @@ // SPDX-License-Identifier: Apache-2.0 /// This module holds shared implementation of macros used in `std` -module std::macros { - use std::string::String; - - public macro fun num_max($x: _, $y: _): _ { - let x = $x; - let y = $y; - if (x > y) x - else y - } +module std::macros; - public macro fun num_min($x: _, $y: _): _ { - let x = $x; - let y = $y; - if (x < y) x - else y - } +use std::string::String; - public macro fun num_diff($x: _, $y: _): _ { - let x = $x; - let y = $y; - if (x > y) x - y - else y - x - } - - public macro fun num_divide_and_round_up($x: _, $y: _): _ { - let x = $x; - let y = $y; - if (x % y == 0) x / y - else x / y + 1 - } +public macro fun num_max($x: _, $y: _): _ { + let x = $x; + let y = $y; + if (x > y) x + else y +} +public macro fun num_min($x: _, $y: _): _ { + let x = $x; + let y = $y; + if (x < y) x + else y +} - public macro fun num_pow($base: _, $exponent: u8): _ { - let mut base = $base; - let mut exponent = $exponent; - let mut res = 1; - while (exponent >= 1) { - if (exponent % 2 == 0) { - base = base * base; - exponent = exponent / 2; - } else { - res = res * base; - exponent = exponent - 1; - } - }; +public macro fun num_diff($x: _, $y: _): _ { + let x = $x; + let y = $y; + if (x > y) x - y + else y - x +} - res - } +public macro fun num_divide_and_round_up($x: _, $y: _): _ { + let x = $x; + let y = $y; + if (x % y == 0) x / y + else x / y + 1 +} - public macro fun num_sqrt<$T, $U>($x: $T, $bitsize: u8): $T { - let x = $x; - let mut bit = (1: $U) << $bitsize; - let mut res = (0: $U); - let mut x = x as $U; - - while (bit != 0) { - if (x >= res + bit) { - x = x - (res + bit); - res = (res >> 1) + bit; - } else { - res = res >> 1; - }; - bit = bit >> 2; - }; +public macro fun num_pow($base: _, $exponent: u8): _ { + let mut base = $base; + let mut exponent = $exponent; + let mut res = 1; + while (exponent >= 1) { + if (exponent % 2 == 0) { + base = base * base; + exponent = exponent / 2; + } else { + res = res * base; + exponent = exponent - 1; + } + }; - res as $T - } + res +} - public macro fun num_to_string($x: _): String { - let mut x = $x; - if (x == 0) { - return b"0".to_string() +public macro fun num_sqrt<$T, $U>($x: $T, $bitsize: u8): $T { + let x = $x; + let mut bit = (1: $U) << $bitsize; + let mut res = (0: $U); + let mut x = x as $U; + + while (bit != 0) { + if (x >= res + bit) { + x = x - (res + bit); + res = (res >> 1) + bit; + } else { + res = res >> 1; }; - let mut buffer = vector[]; - while (x != 0) { - buffer.push_back(((48 + x % 10) as u8)); - x = x / 10; - }; - buffer.reverse(); - buffer.to_string() - } + bit = bit >> 2; + }; - public macro fun range_do($start: _, $stop: _, $f: |_|) { - let mut i = $start; - let stop = $stop; - while (i < stop) { - $f(i); - i = i + 1; - } - } + res as $T +} - public macro fun range_do_eq($start: _, $stop: _, $f: |_|) { - let mut i = $start; - let stop = $stop; - // we check `i >= stop` inside the loop instead of `i <= stop` as `while` condition to avoid - // incrementing `i` past the MAX integer value. - // Because of this, we need to check if `i > stop` and return early--instead of letting the - // loop bound handle it, like in the `range_do` macro. - if (i > stop) return; - loop { - $f(i); - if (i >= stop) break; - i = i + 1; - } - } +public macro fun num_to_string($x: _): String { + let mut x = $x; + if (x == 0) { + return b"0".to_string() + }; + let mut buffer = vector[]; + while (x != 0) { + buffer.push_back(((48 + x % 10) as u8)); + x = x / 10; + }; + buffer.reverse(); + buffer.to_string() +} - public macro fun do($stop: _, $f: |_|) { - range_do!(0, $stop, $f) +public macro fun range_do($start: _, $stop: _, $f: |_|) { + let mut i = $start; + let stop = $stop; + while (i < stop) { + $f(i); + i = i + 1; } +} - public macro fun do_eq($stop: _, $f: |_|) { - range_do_eq!(0, $stop, $f) +public macro fun range_do_eq($start: _, $stop: _, $f: |_|) { + let mut i = $start; + let stop = $stop; + // we check `i >= stop` inside the loop instead of `i <= stop` as `while` condition to avoid + // incrementing `i` past the MAX integer value. + // Because of this, we need to check if `i > stop` and return early--instead of letting the + // loop bound handle it, like in the `range_do` macro. + if (i > stop) return; + loop { + $f(i); + if (i >= stop) break; + i = i + 1; } +} - public macro fun try_as_u8($x: _): Option { - let x = $x; - if (x > 0xFF) option::none() - else option::some(x as u8) - } +public macro fun do($stop: _, $f: |_|) { + range_do!(0, $stop, $f) +} - public macro fun try_as_u16($x: _): Option { - let x = $x; - if (x > 0xFFFF) option::none() - else option::some(x as u16) - } +public macro fun do_eq($stop: _, $f: |_|) { + range_do_eq!(0, $stop, $f) +} - public macro fun try_as_u32($x: _): Option { - let x = $x; - if (x > 0xFFFF_FFFF) option::none() - else option::some(x as u32) - } +public macro fun try_as_u8($x: _): Option { + let x = $x; + if (x > 0xFF) option::none() + else option::some(x as u8) +} - public macro fun try_as_u64($x: _): Option { - let x = $x; - if (x > 0xFFFF_FFFF_FFFF_FFFF) option::none() - else option::some(x as u64) - } +public macro fun try_as_u16($x: _): Option { + let x = $x; + if (x > 0xFFFF) option::none() + else option::some(x as u16) +} - public macro fun try_as_u128($x: _): Option { - let x = $x; - if (x > 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF) option::none() - else option::some(x as u128) - } +public macro fun try_as_u32($x: _): Option { + let x = $x; + if (x > 0xFFFF_FFFF) option::none() + else option::some(x as u32) +} + +public macro fun try_as_u64($x: _): Option { + let x = $x; + if (x > 0xFFFF_FFFF_FFFF_FFFF) option::none() + else option::some(x as u64) +} +public macro fun try_as_u128($x: _): Option { + let x = $x; + if (x > 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF) option::none() + else option::some(x as u128) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/option.move b/crates/sui-framework/packages/move-stdlib/sources/option.move index 00d5b9a20686f..857e76ae0d2bb 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/option.move +++ b/crates/sui-framework/packages/move-stdlib/sources/option.move @@ -2,252 +2,250 @@ // SPDX-License-Identifier: Apache-2.0 /// This module defines the Option type and its methods to represent and handle an optional value. -module std::option { - /// Abstraction of a value that may or may not be present. Implemented with a vector of size - /// zero or one because Move bytecode does not have ADTs. - public struct Option has copy, drop, store { - vec: vector - } +module std::option; - /// The `Option` is in an invalid state for the operation attempted. - /// The `Option` is `Some` while it should be `None`. - const EOPTION_IS_SET: u64 = 0x40000; - /// The `Option` is in an invalid state for the operation attempted. - /// The `Option` is `None` while it should be `Some`. - const EOPTION_NOT_SET: u64 = 0x40001; +/// Abstraction of a value that may or may not be present. Implemented with a vector of size +/// zero or one because Move bytecode does not have ADTs. +public struct Option has copy, drop, store { + vec: vector, +} - /// Return an empty `Option` - public fun none(): Option { - Option { vec: vector::empty() } - } +/// The `Option` is in an invalid state for the operation attempted. +/// The `Option` is `Some` while it should be `None`. +const EOPTION_IS_SET: u64 = 0x40000; +/// The `Option` is in an invalid state for the operation attempted. +/// The `Option` is `None` while it should be `Some`. +const EOPTION_NOT_SET: u64 = 0x40001; - /// Return an `Option` containing `e` - public fun some(e: Element): Option { - Option { vec: vector::singleton(e) } - } +/// Return an empty `Option` +public fun none(): Option { + Option { vec: vector::empty() } +} - /// Return true if `t` does not hold a value - public fun is_none(t: &Option): bool { - t.vec.is_empty() - } +/// Return an `Option` containing `e` +public fun some(e: Element): Option { + Option { vec: vector::singleton(e) } +} - /// Return true if `t` holds a value - public fun is_some(t: &Option): bool { - !t.vec.is_empty() - } +/// Return true if `t` does not hold a value +public fun is_none(t: &Option): bool { + t.vec.is_empty() +} - /// Return true if the value in `t` is equal to `e_ref` - /// Always returns `false` if `t` does not hold a value - public fun contains(t: &Option, e_ref: &Element): bool { - t.vec.contains(e_ref) - } +/// Return true if `t` holds a value +public fun is_some(t: &Option): bool { + !t.vec.is_empty() +} - /// Return an immutable reference to the value inside `t` - /// Aborts if `t` does not hold a value - public fun borrow(t: &Option): &Element { - assert!(t.is_some(), EOPTION_NOT_SET); - &t.vec[0] - } +/// Return true if the value in `t` is equal to `e_ref` +/// Always returns `false` if `t` does not hold a value +public fun contains(t: &Option, e_ref: &Element): bool { + t.vec.contains(e_ref) +} - /// Return a reference to the value inside `t` if it holds one - /// Return `default_ref` if `t` does not hold a value - public fun borrow_with_default(t: &Option, default_ref: &Element): &Element { - let vec_ref = &t.vec; - if (vec_ref.is_empty()) default_ref - else &vec_ref[0] - } +/// Return an immutable reference to the value inside `t` +/// Aborts if `t` does not hold a value +public fun borrow(t: &Option): &Element { + assert!(t.is_some(), EOPTION_NOT_SET); + &t.vec[0] +} - /// Return the value inside `t` if it holds one - /// Return `default` if `t` does not hold a value - public fun get_with_default( - t: &Option, - default: Element, - ): Element { - let vec_ref = &t.vec; - if (vec_ref.is_empty()) default - else vec_ref[0] - } +/// Return a reference to the value inside `t` if it holds one +/// Return `default_ref` if `t` does not hold a value +public fun borrow_with_default(t: &Option, default_ref: &Element): &Element { + let vec_ref = &t.vec; + if (vec_ref.is_empty()) default_ref + else &vec_ref[0] +} - /// Convert the none option `t` to a some option by adding `e`. - /// Aborts if `t` already holds a value - public fun fill(t: &mut Option, e: Element) { - let vec_ref = &mut t.vec; - if (vec_ref.is_empty()) vec_ref.push_back(e) - else abort EOPTION_IS_SET - } +/// Return the value inside `t` if it holds one +/// Return `default` if `t` does not hold a value +public fun get_with_default(t: &Option, default: Element): Element { + let vec_ref = &t.vec; + if (vec_ref.is_empty()) default + else vec_ref[0] +} - /// Convert a `some` option to a `none` by removing and returning the value stored inside `t` - /// Aborts if `t` does not hold a value - public fun extract(t: &mut Option): Element { - assert!(t.is_some(), EOPTION_NOT_SET); - t.vec.pop_back() - } +/// Convert the none option `t` to a some option by adding `e`. +/// Aborts if `t` already holds a value +public fun fill(t: &mut Option, e: Element) { + let vec_ref = &mut t.vec; + if (vec_ref.is_empty()) vec_ref.push_back(e) + else abort EOPTION_IS_SET +} - /// Return a mutable reference to the value inside `t` - /// Aborts if `t` does not hold a value - public fun borrow_mut(t: &mut Option): &mut Element { - assert!(t.is_some(), EOPTION_NOT_SET); - &mut t.vec[0] - } +/// Convert a `some` option to a `none` by removing and returning the value stored inside `t` +/// Aborts if `t` does not hold a value +public fun extract(t: &mut Option): Element { + assert!(t.is_some(), EOPTION_NOT_SET); + t.vec.pop_back() +} - /// Swap the old value inside `t` with `e` and return the old value - /// Aborts if `t` does not hold a value - public fun swap(t: &mut Option, e: Element): Element { - assert!(t.is_some(), EOPTION_NOT_SET); - let vec_ref = &mut t.vec; - let old_value = vec_ref.pop_back(); - vec_ref.push_back(e); - old_value - } +/// Return a mutable reference to the value inside `t` +/// Aborts if `t` does not hold a value +public fun borrow_mut(t: &mut Option): &mut Element { + assert!(t.is_some(), EOPTION_NOT_SET); + &mut t.vec[0] +} - /// Swap the old value inside `t` with `e` and return the old value; - /// or if there is no old value, fill it with `e`. - /// Different from swap(), swap_or_fill() allows for `t` not holding a value. - public fun swap_or_fill(t: &mut Option, e: Element): Option { - let vec_ref = &mut t.vec; - let old_value = if (vec_ref.is_empty()) none() - else some(vec_ref.pop_back()); - vec_ref.push_back(e); - old_value - } +/// Swap the old value inside `t` with `e` and return the old value +/// Aborts if `t` does not hold a value +public fun swap(t: &mut Option, e: Element): Element { + assert!(t.is_some(), EOPTION_NOT_SET); + let vec_ref = &mut t.vec; + let old_value = vec_ref.pop_back(); + vec_ref.push_back(e); + old_value +} - /// Destroys `t.` If `t` holds a value, return it. Returns `default` otherwise - public fun destroy_with_default(t: Option, default: Element): Element { - let Option { mut vec } = t; - if (vec.is_empty()) default - else vec.pop_back() - } +/// Swap the old value inside `t` with `e` and return the old value; +/// or if there is no old value, fill it with `e`. +/// Different from swap(), swap_or_fill() allows for `t` not holding a value. +public fun swap_or_fill(t: &mut Option, e: Element): Option { + let vec_ref = &mut t.vec; + let old_value = if (vec_ref.is_empty()) none() + else some(vec_ref.pop_back()); + vec_ref.push_back(e); + old_value +} - /// Unpack `t` and return its contents - /// Aborts if `t` does not hold a value - public fun destroy_some(t: Option): Element { - assert!(t.is_some(), EOPTION_NOT_SET); - let Option { mut vec } = t; - let elem = vec.pop_back(); - vec.destroy_empty(); - elem - } +/// Destroys `t.` If `t` holds a value, return it. Returns `default` otherwise +public fun destroy_with_default(t: Option, default: Element): Element { + let Option { mut vec } = t; + if (vec.is_empty()) default + else vec.pop_back() +} - /// Unpack `t` - /// Aborts if `t` holds a value - public fun destroy_none(t: Option) { - assert!(t.is_none(), EOPTION_IS_SET); - let Option { vec } = t; - vec.destroy_empty() - } - /// Convert `t` into a vector of length 1 if it is `Some`, - /// and an empty vector otherwise - public fun to_vec(t: Option): vector { - let Option { vec } = t; - vec - } +/// Unpack `t` and return its contents +/// Aborts if `t` does not hold a value +public fun destroy_some(t: Option): Element { + assert!(t.is_some(), EOPTION_NOT_SET); + let Option { mut vec } = t; + let elem = vec.pop_back(); + vec.destroy_empty(); + elem +} - // === Macro Functions === +/// Unpack `t` +/// Aborts if `t` holds a value +public fun destroy_none(t: Option) { + assert!(t.is_none(), EOPTION_IS_SET); + let Option { vec } = t; + vec.destroy_empty() +} - /// Destroy `Option` and call the closure `f` on the value inside if it holds one. - public macro fun destroy<$T>($o: Option<$T>, $f: |$T|) { - let o = $o; - o.do!($f); - } +/// Convert `t` into a vector of length 1 if it is `Some`, +/// and an empty vector otherwise +public fun to_vec(t: Option): vector { + let Option { vec } = t; + vec +} - /// Destroy `Option` and call the closure `f` on the value inside if it holds one. - public macro fun do<$T>($o: Option<$T>, $f: |$T|) { - let o = $o; - if (o.is_some()) $f(o.destroy_some()) - else o.destroy_none() - } +// === Macro Functions === - /// Execute a closure on the value inside `t` if it holds one. - public macro fun do_ref<$T>($o: &Option<$T>, $f: |&$T|) { - let o = $o; - if (o.is_some()) $f(o.borrow()); - } +/// Destroy `Option` and call the closure `f` on the value inside if it holds one. +public macro fun destroy<$T>($o: Option<$T>, $f: |$T|) { + let o = $o; + o.do!($f); +} - /// Execute a closure on the mutable reference to the value inside `t` if it holds one. - public macro fun do_mut<$T>($o: &mut Option<$T>, $f: |&mut $T|) { - let o = $o; - if (o.is_some()) $f(o.borrow_mut()); - } +/// Destroy `Option` and call the closure `f` on the value inside if it holds one. +public macro fun do<$T>($o: Option<$T>, $f: |$T|) { + let o = $o; + if (o.is_some()) $f(o.destroy_some()) + else o.destroy_none() +} - /// Select the first `Some` value from the two options, or `None` if both are `None`. - /// Equivalent to Rust's `a.or(b)`. - public macro fun or<$T>($o: Option<$T>, $default: Option<$T>): Option<$T> { - let o = $o; - if (o.is_some()) { - o - } else { - o.destroy_none(); - $default - } - } +/// Execute a closure on the value inside `t` if it holds one. +public macro fun do_ref<$T>($o: &Option<$T>, $f: |&$T|) { + let o = $o; + if (o.is_some()) $f(o.borrow()); +} - /// If the value is `Some`, call the closure `f` on it. Otherwise, return `None`. - /// Equivalent to Rust's `t.and_then(f)`. - public macro fun and<$T, $U>($o: Option<$T>, $f: |$T| -> Option<$U>): Option<$U> { - let o = $o; - if (o.is_some()) { - $f(o.destroy_some()) - } else { - o.destroy_none(); - none() - } - } +/// Execute a closure on the mutable reference to the value inside `t` if it holds one. +public macro fun do_mut<$T>($o: &mut Option<$T>, $f: |&mut $T|) { + let o = $o; + if (o.is_some()) $f(o.borrow_mut()); +} - /// If the value is `Some`, call the closure `f` on it. Otherwise, return `None`. - /// Equivalent to Rust's `t.and_then(f)`. - public macro fun and_ref<$T, $U>($o: &Option<$T>, $f: |&$T| -> Option<$U>): Option<$U> { - let o = $o; - if (o.is_some()) $f(o.borrow()) - else none() +/// Select the first `Some` value from the two options, or `None` if both are `None`. +/// Equivalent to Rust's `a.or(b)`. +public macro fun or<$T>($o: Option<$T>, $default: Option<$T>): Option<$T> { + let o = $o; + if (o.is_some()) { + o + } else { + o.destroy_none(); + $default } +} - /// Map an `Option` to `Option` by applying a function to a contained value. - /// Equivalent to Rust's `t.map(f)`. - public macro fun map<$T, $U>($o: Option<$T>, $f: |$T| -> $U): Option<$U> { - let o = $o; - if (o.is_some()) { - some($f(o.destroy_some())) - } else { - o.destroy_none(); - none() - } +/// If the value is `Some`, call the closure `f` on it. Otherwise, return `None`. +/// Equivalent to Rust's `t.and_then(f)`. +public macro fun and<$T, $U>($o: Option<$T>, $f: |$T| -> Option<$U>): Option<$U> { + let o = $o; + if (o.is_some()) { + $f(o.destroy_some()) + } else { + o.destroy_none(); + none() } +} - /// Map an `Option` value to `Option` by applying a function to a contained value by reference. - /// Original `Option` is preserved. - /// Equivalent to Rust's `t.map(f)`. - public macro fun map_ref<$T, $U>($o: &Option<$T>, $f: |&$T| -> $U): Option<$U> { - let o = $o; - if (o.is_some()) some($f(o.borrow())) - else none() - } +/// If the value is `Some`, call the closure `f` on it. Otherwise, return `None`. +/// Equivalent to Rust's `t.and_then(f)`. +public macro fun and_ref<$T, $U>($o: &Option<$T>, $f: |&$T| -> Option<$U>): Option<$U> { + let o = $o; + if (o.is_some()) $f(o.borrow()) + else none() +} - /// Return `None` if the value is `None`, otherwise return `Option` if the predicate `f` returns true. - public macro fun filter<$T: drop>($o: Option<$T>, $f: |&$T| -> bool): Option<$T> { - let o = $o; - if (o.is_some() && $f(o.borrow())) o - else none() +/// Map an `Option` to `Option` by applying a function to a contained value. +/// Equivalent to Rust's `t.map(f)`. +public macro fun map<$T, $U>($o: Option<$T>, $f: |$T| -> $U): Option<$U> { + let o = $o; + if (o.is_some()) { + some($f(o.destroy_some())) + } else { + o.destroy_none(); + none() } +} - /// Return `false` if the value is `None`, otherwise return the result of the predicate `f`. - public macro fun is_some_and<$T>($o: &Option<$T>, $f: |&$T| -> bool): bool { - let o = $o; - o.is_some() && $f(o.borrow()) - } +/// Map an `Option` value to `Option` by applying a function to a contained value by reference. +/// Original `Option` is preserved. +/// Equivalent to Rust's `t.map(f)`. +public macro fun map_ref<$T, $U>($o: &Option<$T>, $f: |&$T| -> $U): Option<$U> { + let o = $o; + if (o.is_some()) some($f(o.borrow())) + else none() +} + +/// Return `None` if the value is `None`, otherwise return `Option` if the predicate `f` returns true. +public macro fun filter<$T: drop>($o: Option<$T>, $f: |&$T| -> bool): Option<$T> { + let o = $o; + if (o.is_some() && $f(o.borrow())) o + else none() +} + +/// Return `false` if the value is `None`, otherwise return the result of the predicate `f`. +public macro fun is_some_and<$T>($o: &Option<$T>, $f: |&$T| -> bool): bool { + let o = $o; + o.is_some() && $f(o.borrow()) +} - /// Destroy `Option` and return the value inside if it holds one, or `default` otherwise. - /// Equivalent to Rust's `t.unwrap_or(default)`. - /// - /// Note: this function is a more efficient version of `destroy_with_default`, as it does not - /// evaluate the default value unless necessary. The `destroy_with_default` function should be - /// deprecated in favor of this function. - public macro fun destroy_or<$T>($o: Option<$T>, $default: $T): $T { - let o = $o; - if (o.is_some()) { - o.destroy_some() - } else { - o.destroy_none(); - $default - } +/// Destroy `Option` and return the value inside if it holds one, or `default` otherwise. +/// Equivalent to Rust's `t.unwrap_or(default)`. +/// +/// Note: this function is a more efficient version of `destroy_with_default`, as it does not +/// evaluate the default value unless necessary. The `destroy_with_default` function should be +/// deprecated in favor of this function. +public macro fun destroy_or<$T>($o: Option<$T>, $default: $T): $T { + let o = $o; + if (o.is_some()) { + o.destroy_some() + } else { + o.destroy_none(); + $default } } diff --git a/crates/sui-framework/packages/move-stdlib/sources/string.move b/crates/sui-framework/packages/move-stdlib/sources/string.move index 8914fa36856b1..3538c8285966a 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/string.move +++ b/crates/sui-framework/packages/move-stdlib/sources/string.move @@ -3,130 +3,127 @@ /// The `string` module defines the `String` type which represents UTF8 encoded /// strings. -module std::string { - use std::ascii; - - /// An invalid UTF8 encoding. - const EInvalidUTF8: u64 = 1; - - /// Index out of range. - const EInvalidIndex: u64 = 2; - - /// A `String` holds a sequence of bytes which is guaranteed to be in utf8 - /// format. - public struct String has copy, drop, store { - bytes: vector, - } - - /// Creates a new string from a sequence of bytes. Aborts if the bytes do - /// not represent valid utf8. - public fun utf8(bytes: vector): String { - assert!(internal_check_utf8(&bytes), EInvalidUTF8); - String { bytes } - } - - /// Convert an ASCII string to a UTF8 string - public fun from_ascii(s: ascii::String): String { - String { bytes: s.into_bytes() } - } - - /// Convert an UTF8 string to an ASCII string. - /// Aborts if `s` is not valid ASCII - public fun to_ascii(s: String): ascii::String { - let String { bytes } = s; - bytes.to_ascii_string() - } - - /// Tries to create a new string from a sequence of bytes. - public fun try_utf8(bytes: vector): Option { - if (internal_check_utf8(&bytes)) option::some(String { bytes }) - else option::none() - } - - /// Returns a reference to the underlying byte vector. - public fun as_bytes(s: &String): &vector { - &s.bytes - } - - /// Unpack the `string` to get its underlying bytes. - public fun into_bytes(s: String): vector { - let String { bytes } = s; - bytes - } - - /// Checks whether this string is empty. - public fun is_empty(s: &String): bool { - s.bytes.is_empty() - } - - /// Returns the length of this string, in bytes. - public fun length(s: &String): u64 { - s.bytes.length() - } - - /// Appends a string. - public fun append(s: &mut String, r: String) { - s.bytes.append(r.bytes) - } - - /// Appends bytes which must be in valid utf8 format. - public fun append_utf8(s: &mut String, bytes: vector) { - s.append(utf8(bytes)) - } - - /// Insert the other string at the byte index in given string. The index - /// must be at a valid utf8 char boundary. - public fun insert(s: &mut String, at: u64, o: String) { - let bytes = &s.bytes; - assert!( - at <= bytes.length() && internal_is_char_boundary(bytes, at), - EInvalidIndex, - ); - let l = s.length(); - let mut front = s.substring(0, at); - let end = s.substring(at, l); - front.append(o); - front.append(end); - *s = front; - } - - /// Returns a sub-string using the given byte indices, where `i` is the first - /// byte position and `j` is the start of the first byte not included (or the - /// length of the string). The indices must be at valid utf8 char boundaries, - /// guaranteeing that the result is valid utf8. - public fun substring(s: &String, i: u64, j: u64): String { - let bytes = &s.bytes; - let l = bytes.length(); - assert!( - j <= l && +module std::string; + +use std::ascii; + +/// An invalid UTF8 encoding. +const EInvalidUTF8: u64 = 1; + +/// Index out of range. +const EInvalidIndex: u64 = 2; + +/// A `String` holds a sequence of bytes which is guaranteed to be in utf8 +/// format. +public struct String has copy, drop, store { + bytes: vector, +} + +/// Creates a new string from a sequence of bytes. Aborts if the bytes do +/// not represent valid utf8. +public fun utf8(bytes: vector): String { + assert!(internal_check_utf8(&bytes), EInvalidUTF8); + String { bytes } +} + +/// Convert an ASCII string to a UTF8 string +public fun from_ascii(s: ascii::String): String { + String { bytes: s.into_bytes() } +} + +/// Convert an UTF8 string to an ASCII string. +/// Aborts if `s` is not valid ASCII +public fun to_ascii(s: String): ascii::String { + let String { bytes } = s; + bytes.to_ascii_string() +} + +/// Tries to create a new string from a sequence of bytes. +public fun try_utf8(bytes: vector): Option { + if (internal_check_utf8(&bytes)) option::some(String { bytes }) + else option::none() +} + +/// Returns a reference to the underlying byte vector. +public fun as_bytes(s: &String): &vector { + &s.bytes +} + +/// Unpack the `string` to get its underlying bytes. +public fun into_bytes(s: String): vector { + let String { bytes } = s; + bytes +} + +/// Checks whether this string is empty. +public fun is_empty(s: &String): bool { + s.bytes.is_empty() +} + +/// Returns the length of this string, in bytes. +public fun length(s: &String): u64 { + s.bytes.length() +} + +/// Appends a string. +public fun append(s: &mut String, r: String) { + s.bytes.append(r.bytes) +} + +/// Appends bytes which must be in valid utf8 format. +public fun append_utf8(s: &mut String, bytes: vector) { + s.append(utf8(bytes)) +} + +/// Insert the other string at the byte index in given string. The index +/// must be at a valid utf8 char boundary. +public fun insert(s: &mut String, at: u64, o: String) { + let bytes = &s.bytes; + assert!(at <= bytes.length() && internal_is_char_boundary(bytes, at), EInvalidIndex); + let l = s.length(); + let mut front = s.substring(0, at); + let end = s.substring(at, l); + front.append(o); + front.append(end); + *s = front; +} + +/// Returns a sub-string using the given byte indices, where `i` is the first +/// byte position and `j` is the start of the first byte not included (or the +/// length of the string). The indices must be at valid utf8 char boundaries, +/// guaranteeing that the result is valid utf8. +public fun substring(s: &String, i: u64, j: u64): String { + let bytes = &s.bytes; + let l = bytes.length(); + assert!( + j <= l && i <= j && internal_is_char_boundary(bytes, i) && internal_is_char_boundary(bytes, j), - EInvalidIndex, - ); - String { bytes: internal_sub_string(bytes, i, j) } - } + EInvalidIndex, + ); + String { bytes: internal_sub_string(bytes, i, j) } +} - /// Computes the index of the first occurrence of a string. Returns `s.length()` - /// if no occurrence found. - public fun index_of(s: &String, r: &String): u64 { - internal_index_of(&s.bytes, &r.bytes) - } +/// Computes the index of the first occurrence of a string. Returns `s.length()` +/// if no occurrence found. +public fun index_of(s: &String, r: &String): u64 { + internal_index_of(&s.bytes, &r.bytes) +} - // Native API +// Native API - native fun internal_check_utf8(v: &vector): bool; - native fun internal_is_char_boundary(v: &vector, i: u64): bool; - native fun internal_sub_string(v: &vector, i: u64, j: u64): vector; - native fun internal_index_of(v: &vector, r: &vector): u64; +native fun internal_check_utf8(v: &vector): bool; +native fun internal_is_char_boundary(v: &vector, i: u64): bool; +native fun internal_sub_string(v: &vector, i: u64, j: u64): vector; +native fun internal_index_of(v: &vector, r: &vector): u64; - // === Deprecated === +// === Deprecated === - #[deprecated(note = b"Use `std::string::as_bytes` instead.")] - public fun bytes(s: &String): &vector { s.as_bytes() } +#[deprecated(note = b"Use `std::string::as_bytes` instead.")] +public fun bytes(s: &String): &vector { s.as_bytes() } - #[deprecated(note = b"Use `std::string::substring` instead.")] - public fun sub_string(s: &String, i: u64, j: u64): String { - s.substring(i, j) - } +#[deprecated(note = b"Use `std::string::substring` instead.")] +public fun sub_string(s: &String, i: u64, j: u64): String { + s.substring(i, j) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/type_name.move b/crates/sui-framework/packages/move-stdlib/sources/type_name.move index 70cc4407a8c5c..9b330c1c66179 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/type_name.move +++ b/crates/sui-framework/packages/move-stdlib/sources/type_name.move @@ -2,58 +2,59 @@ // SPDX-License-Identifier: Apache-2.0 /// Functionality for converting Move types into values. Use with care! -module std::type_name { - use std::ascii::{Self, String}; - use std::address; - - /// ASCII Character code for the `:` (colon) symbol. - const ASCII_COLON: u8 = 58; - - /// ASCII Character code for the `v` (lowercase v) symbol. - const ASCII_V: u8 = 118; - /// ASCII Character code for the `e` (lowercase e) symbol. - const ASCII_E: u8 = 101; - /// ASCII Character code for the `c` (lowercase c) symbol. - const ASCII_C: u8 = 99; - /// ASCII Character code for the `t` (lowercase t) symbol. - const ASCII_T: u8 = 116; - /// ASCII Character code for the `o` (lowercase o) symbol. - const ASCII_O: u8 = 111; - /// ASCII Character code for the `r` (lowercase r) symbol. - const ASCII_R: u8 = 114; - - /// The type is not from a package/module. It is a primitive type. - const ENonModuleType: u64 = 0; - - public struct TypeName has copy, drop, store { - /// String representation of the type. All types are represented - /// using their source syntax: - /// "u8", "u64", "bool", "address", "vector", and so on for primitive types. - /// Struct types are represented as fully qualified type names; e.g. - /// `00000000000000000000000000000001::string::String` or - /// `0000000000000000000000000000000a::module_name1::type_name1<0000000000000000000000000000000a::module_name2::type_name2>` - /// Addresses are hex-encoded lowercase values of length ADDRESS_LENGTH (16, 20, or 32 depending on the Move platform) - name: String, - } - - /// Return a value representation of the type `T`. Package IDs - /// that appear in fully qualified type names in the output from - /// this function are defining IDs (the ID of the package in - /// storage that first introduced the type). - public native fun get(): TypeName; - - /// Return a value representation of the type `T`. Package IDs - /// that appear in fully qualified type names in the output from - /// this function are original IDs (the ID of the first version of - /// the package, even if the type in question was introduced in a - /// later upgrade). - public native fun get_with_original_ids(): TypeName; - - /// Returns true iff the TypeName represents a primitive type, i.e. one of - /// u8, u16, u32, u64, u128, u256, bool, address, vector. - public fun is_primitive(self: &TypeName): bool { - let bytes = self.name.as_bytes(); - bytes == &b"bool" || +module std::type_name; + +use std::address; +use std::ascii::{Self, String}; + +/// ASCII Character code for the `:` (colon) symbol. +const ASCII_COLON: u8 = 58; + +/// ASCII Character code for the `v` (lowercase v) symbol. +const ASCII_V: u8 = 118; +/// ASCII Character code for the `e` (lowercase e) symbol. +const ASCII_E: u8 = 101; +/// ASCII Character code for the `c` (lowercase c) symbol. +const ASCII_C: u8 = 99; +/// ASCII Character code for the `t` (lowercase t) symbol. +const ASCII_T: u8 = 116; +/// ASCII Character code for the `o` (lowercase o) symbol. +const ASCII_O: u8 = 111; +/// ASCII Character code for the `r` (lowercase r) symbol. +const ASCII_R: u8 = 114; + +/// The type is not from a package/module. It is a primitive type. +const ENonModuleType: u64 = 0; + +public struct TypeName has copy, drop, store { + /// String representation of the type. All types are represented + /// using their source syntax: + /// "u8", "u64", "bool", "address", "vector", and so on for primitive types. + /// Struct types are represented as fully qualified type names; e.g. + /// `00000000000000000000000000000001::string::String` or + /// `0000000000000000000000000000000a::module_name1::type_name1<0000000000000000000000000000000a::module_name2::type_name2>` + /// Addresses are hex-encoded lowercase values of length ADDRESS_LENGTH (16, 20, or 32 depending on the Move platform) + name: String, +} + +/// Return a value representation of the type `T`. Package IDs +/// that appear in fully qualified type names in the output from +/// this function are defining IDs (the ID of the package in +/// storage that first introduced the type). +public native fun get(): TypeName; + +/// Return a value representation of the type `T`. Package IDs +/// that appear in fully qualified type names in the output from +/// this function are original IDs (the ID of the first version of +/// the package, even if the type in question was introduced in a +/// later upgrade). +public native fun get_with_original_ids(): TypeName; + +/// Returns true iff the TypeName represents a primitive type, i.e. one of +/// u8, u16, u32, u64, u128, u256, bool, address, vector. +public fun is_primitive(self: &TypeName): bool { + let bytes = self.name.as_bytes(); + bytes == &b"bool" || bytes == &b"u8" || bytes == &b"u16" || bytes == &b"u32" || @@ -70,58 +71,57 @@ module std::type_name { bytes[4] == ASCII_O && bytes[5] == ASCII_R, ) - } - - /// Get the String representation of `self` - public fun borrow_string(self: &TypeName): &String { - &self.name - } - - /// Get Address string (Base16 encoded), first part of the TypeName. - /// Aborts if given a primitive type. - public fun get_address(self: &TypeName): String { - assert!(!self.is_primitive(), ENonModuleType); - - // Base16 (string) representation of an address has 2 symbols per byte. - let len = address::length() * 2; - let str_bytes = self.name.as_bytes(); - let mut addr_bytes = vector[]; - let mut i = 0; - - // Read `len` bytes from the type name and push them to addr_bytes. - while (i < len) { - addr_bytes.push_back(str_bytes[i]); +} + +/// Get the String representation of `self` +public fun borrow_string(self: &TypeName): &String { + &self.name +} + +/// Get Address string (Base16 encoded), first part of the TypeName. +/// Aborts if given a primitive type. +public fun get_address(self: &TypeName): String { + assert!(!self.is_primitive(), ENonModuleType); + + // Base16 (string) representation of an address has 2 symbols per byte. + let len = address::length() * 2; + let str_bytes = self.name.as_bytes(); + let mut addr_bytes = vector[]; + let mut i = 0; + + // Read `len` bytes from the type name and push them to addr_bytes. + while (i < len) { + addr_bytes.push_back(str_bytes[i]); + i = i + 1; + }; + + ascii::string(addr_bytes) +} + +/// Get name of the module. +/// Aborts if given a primitive type. +public fun get_module(self: &TypeName): String { + assert!(!self.is_primitive(), ENonModuleType); + + // Starts after address and a double colon: `::` + let mut i = address::length() * 2 + 2; + let str_bytes = self.name.as_bytes(); + let mut module_name = vector[]; + let colon = ASCII_COLON; + loop { + let char = &str_bytes[i]; + if (char != &colon) { + module_name.push_back(*char); i = i + 1; - }; - - ascii::string(addr_bytes) - } - - /// Get name of the module. - /// Aborts if given a primitive type. - public fun get_module(self: &TypeName): String { - assert!(!self.is_primitive(), ENonModuleType); - - // Starts after address and a double colon: `::` - let mut i = address::length() * 2 + 2; - let str_bytes = self.name.as_bytes(); - let mut module_name = vector[]; - let colon = ASCII_COLON; - loop { - let char = &str_bytes[i]; - if (char != &colon) { - module_name.push_back(*char); - i = i + 1; - } else { - break - } - }; - - ascii::string(module_name) - } - - /// Convert `self` into its inner String - public fun into_string(self: TypeName): String { - self.name - } + } else { + break + } + }; + + ascii::string(module_name) +} + +/// Convert `self` into its inner String +public fun into_string(self: TypeName): String { + self.name } diff --git a/crates/sui-framework/packages/move-stdlib/sources/u128.move b/crates/sui-framework/packages/move-stdlib/sources/u128.move index d197db1b72cf7..1e3c129daad7b 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/u128.move +++ b/crates/sui-framework/packages/move-stdlib/sources/u128.move @@ -2,115 +2,115 @@ // SPDX-License-Identifier: Apache-2.0 #[defines_primitive(u128)] -module std::u128 { - use std::string::String; - - /// Returns the bitwise not of the value. - /// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. - public fun bitwise_not(x: u128): u128 { - x ^ max_value!() - } - - /// Return the larger of `x` and `y` - public fun max(x: u128, y: u128): u128 { - std::macros::num_max!(x, y) - } - - /// Return the smaller of `x` and `y` - public fun min(x: u128, y: u128): u128 { - std::macros::num_min!(x, y) - } - - /// Return the absolute value of x - y - public fun diff(x: u128, y: u128): u128 { - std::macros::num_diff!(x, y) - } - - /// Calculate x / y, but round up the result. - public fun divide_and_round_up(x: u128, y: u128): u128 { - std::macros::num_divide_and_round_up!(x, y) - } - - /// Return the value of a base raised to a power - public fun pow(base: u128, exponent: u8): u128 { - std::macros::num_pow!(base, exponent) - } - - /// Get a nearest lower integer Square Root for `x`. Given that this - /// function can only operate with integers, it is impossible - /// to get perfect (or precise) integer square root for some numbers. - /// - /// Example: - /// ``` - /// math::sqrt(9) => 3 - /// math::sqrt(8) => 2 // the nearest lower square root is 4; - /// ``` - /// - /// In integer math, one of the possible ways to get results with more - /// precision is to use higher values or temporarily multiply the - /// value by some bigger number. Ideally if this is a square of 10 or 100. - /// - /// Example: - /// ``` - /// math::sqrt(8) => 2; - /// math::sqrt(8 * 10000) => 282; - /// // now we can use this value as if it was 2.82; - /// // but to get the actual result, this value needs - /// // to be divided by 100 (because sqrt(10000)). - /// - /// - /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) - /// ``` - public fun sqrt(x: u128): u128 { - std::macros::num_sqrt!(x, 128) - } - - /// Try to convert a `u128` to a `u8`. Returns `None` if the value is too large. - public fun try_as_u8(x: u128): Option { - std::macros::try_as_u8!(x) - } - - /// Try to convert a `u128` to a `u16`. Returns `None` if the value is too large. - public fun try_as_u16(x: u128): Option { - std::macros::try_as_u16!(x) - } - - /// Try to convert a `u128` to a `u32`. Returns `None` if the value is too large. - public fun try_as_u32(x: u128): Option { - std::macros::try_as_u32!(x) - } - - /// Try to convert a `u128` to a `u64`. Returns `None` if the value is too large. - public fun try_as_u64(x: u128): Option { - std::macros::try_as_u64!(x) - } - - public fun to_string(x: u128): String { - std::macros::num_to_string!(x) - } - - /// Maximum value for a `u128` - public macro fun max_value(): u128 { - 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u128, $stop: u128, $f: |u128|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u128, $stop: u128, $f: |u128|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u128, $f: |u128|) { - std::macros::do!($stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u128, $f: |u128|) { - std::macros::do_eq!($stop, $f) - } +module std::u128; + +use std::string::String; + +/// Returns the bitwise not of the value. +/// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. +public fun bitwise_not(x: u128): u128 { + x ^ max_value!() +} + +/// Return the larger of `x` and `y` +public fun max(x: u128, y: u128): u128 { + std::macros::num_max!(x, y) +} + +/// Return the smaller of `x` and `y` +public fun min(x: u128, y: u128): u128 { + std::macros::num_min!(x, y) +} + +/// Return the absolute value of x - y +public fun diff(x: u128, y: u128): u128 { + std::macros::num_diff!(x, y) +} + +/// Calculate x / y, but round up the result. +public fun divide_and_round_up(x: u128, y: u128): u128 { + std::macros::num_divide_and_round_up!(x, y) +} + +/// Return the value of a base raised to a power +public fun pow(base: u128, exponent: u8): u128 { + std::macros::num_pow!(base, exponent) +} + +/// Get a nearest lower integer Square Root for `x`. Given that this +/// function can only operate with integers, it is impossible +/// to get perfect (or precise) integer square root for some numbers. +/// +/// Example: +/// ``` +/// math::sqrt(9) => 3 +/// math::sqrt(8) => 2 // the nearest lower square root is 4; +/// ``` +/// +/// In integer math, one of the possible ways to get results with more +/// precision is to use higher values or temporarily multiply the +/// value by some bigger number. Ideally if this is a square of 10 or 100. +/// +/// Example: +/// ``` +/// math::sqrt(8) => 2; +/// math::sqrt(8 * 10000) => 282; +/// // now we can use this value as if it was 2.82; +/// // but to get the actual result, this value needs +/// // to be divided by 100 (because sqrt(10000)). +/// +/// +/// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) +/// ``` +public fun sqrt(x: u128): u128 { + std::macros::num_sqrt!(x, 128) +} + +/// Try to convert a `u128` to a `u8`. Returns `None` if the value is too large. +public fun try_as_u8(x: u128): Option { + std::macros::try_as_u8!(x) +} + +/// Try to convert a `u128` to a `u16`. Returns `None` if the value is too large. +public fun try_as_u16(x: u128): Option { + std::macros::try_as_u16!(x) +} + +/// Try to convert a `u128` to a `u32`. Returns `None` if the value is too large. +public fun try_as_u32(x: u128): Option { + std::macros::try_as_u32!(x) +} + +/// Try to convert a `u128` to a `u64`. Returns `None` if the value is too large. +public fun try_as_u64(x: u128): Option { + std::macros::try_as_u64!(x) +} + +public fun to_string(x: u128): String { + std::macros::num_to_string!(x) +} + +/// Maximum value for a `u128` +public macro fun max_value(): u128 { + 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) +public macro fun range_do($start: u128, $stop: u128, $f: |u128|) { + std::macros::range_do!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) +public macro fun range_do_eq($start: u128, $stop: u128, $f: |u128|) { + std::macros::range_do_eq!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (exclusive) +public macro fun do($stop: u128, $f: |u128|) { + std::macros::do!($stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (inclusive) +public macro fun do_eq($stop: u128, $f: |u128|) { + std::macros::do_eq!($stop, $f) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/u16.move b/crates/sui-framework/packages/move-stdlib/sources/u16.move index 2a8182aa633d8..fffe7440d5502 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/u16.move +++ b/crates/sui-framework/packages/move-stdlib/sources/u16.move @@ -2,100 +2,100 @@ // SPDX-License-Identifier: Apache-2.0 #[defines_primitive(u16)] -module std::u16 { - use std::string::String; - - /// Returns the bitwise not of the value. - /// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. - public fun bitwise_not(x: u16): u16 { - x ^ max_value!() - } - - /// Return the larger of `x` and `y` - public fun max(x: u16, y: u16): u16 { - std::macros::num_max!(x, y) - } - - /// Return the smaller of `x` and `y` - public fun min(x: u16, y: u16): u16 { - std::macros::num_min!(x, y) - } - - /// Return the absolute value of x - y - public fun diff(x: u16, y: u16): u16 { - std::macros::num_diff!(x, y) - } - - /// Calculate x / y, but round up the result. - public fun divide_and_round_up(x: u16, y: u16): u16 { - std::macros::num_divide_and_round_up!(x, y) - } - - /// Return the value of a base raised to a power - public fun pow(base: u16, exponent: u8): u16 { - std::macros::num_pow!(base, exponent) - } - - /// Get a nearest lower integer Square Root for `x`. Given that this - /// function can only operate with integers, it is impossible - /// to get perfect (or precise) integer square root for some numbers. - /// - /// Example: - /// ``` - /// math::sqrt(9) => 3 - /// math::sqrt(8) => 2 // the nearest lower square root is 4; - /// ``` - /// - /// In integer math, one of the possible ways to get results with more - /// precision is to use higher values or temporarily multiply the - /// value by some bigger number. Ideally if this is a square of 10 or 100. - /// - /// Example: - /// ``` - /// math::sqrt(8) => 2; - /// math::sqrt(8 * 10000) => 282; - /// // now we can use this value as if it was 2.82; - /// // but to get the actual result, this value needs - /// // to be divided by 100 (because sqrt(10000)). - /// - /// - /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) - /// ``` - public fun sqrt(x: u16): u16 { - std::macros::num_sqrt!(x, 16) - } - - /// Try to convert a `u16` to a `u8`. Returns `None` if the value is too large. - public fun try_as_u8(x: u16): Option { - std::macros::try_as_u8!(x) - } - - public fun to_string(x: u16): String { - std::macros::num_to_string!(x) - } - - /// Maximum value for a `u16` - public macro fun max_value(): u16 { - 0xFFFF - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u16, $stop: u16, $f: |u16|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u16, $stop: u16, $f: |u16|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u16, $f: |u16|) { - std::macros::do!($stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u16, $f: |u16|) { - std::macros::do_eq!($stop, $f) - } +module std::u16; + +use std::string::String; + +/// Returns the bitwise not of the value. +/// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. +public fun bitwise_not(x: u16): u16 { + x ^ max_value!() +} + +/// Return the larger of `x` and `y` +public fun max(x: u16, y: u16): u16 { + std::macros::num_max!(x, y) +} + +/// Return the smaller of `x` and `y` +public fun min(x: u16, y: u16): u16 { + std::macros::num_min!(x, y) +} + +/// Return the absolute value of x - y +public fun diff(x: u16, y: u16): u16 { + std::macros::num_diff!(x, y) +} + +/// Calculate x / y, but round up the result. +public fun divide_and_round_up(x: u16, y: u16): u16 { + std::macros::num_divide_and_round_up!(x, y) +} + +/// Return the value of a base raised to a power +public fun pow(base: u16, exponent: u8): u16 { + std::macros::num_pow!(base, exponent) +} + +/// Get a nearest lower integer Square Root for `x`. Given that this +/// function can only operate with integers, it is impossible +/// to get perfect (or precise) integer square root for some numbers. +/// +/// Example: +/// ``` +/// math::sqrt(9) => 3 +/// math::sqrt(8) => 2 // the nearest lower square root is 4; +/// ``` +/// +/// In integer math, one of the possible ways to get results with more +/// precision is to use higher values or temporarily multiply the +/// value by some bigger number. Ideally if this is a square of 10 or 100. +/// +/// Example: +/// ``` +/// math::sqrt(8) => 2; +/// math::sqrt(8 * 10000) => 282; +/// // now we can use this value as if it was 2.82; +/// // but to get the actual result, this value needs +/// // to be divided by 100 (because sqrt(10000)). +/// +/// +/// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) +/// ``` +public fun sqrt(x: u16): u16 { + std::macros::num_sqrt!(x, 16) +} + +/// Try to convert a `u16` to a `u8`. Returns `None` if the value is too large. +public fun try_as_u8(x: u16): Option { + std::macros::try_as_u8!(x) +} + +public fun to_string(x: u16): String { + std::macros::num_to_string!(x) +} + +/// Maximum value for a `u16` +public macro fun max_value(): u16 { + 0xFFFF +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) +public macro fun range_do($start: u16, $stop: u16, $f: |u16|) { + std::macros::range_do!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) +public macro fun range_do_eq($start: u16, $stop: u16, $f: |u16|) { + std::macros::range_do_eq!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (exclusive) +public macro fun do($stop: u16, $f: |u16|) { + std::macros::do!($stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (inclusive) +public macro fun do_eq($stop: u16, $f: |u16|) { + std::macros::do_eq!($stop, $f) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/u256.move b/crates/sui-framework/packages/move-stdlib/sources/u256.move index 572ca4df503b1..c708d4d603809 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/u256.move +++ b/crates/sui-framework/packages/move-stdlib/sources/u256.move @@ -2,91 +2,91 @@ // SPDX-License-Identifier: Apache-2.0 #[defines_primitive(u256)] -module std::u256 { - use std::string::String; - - /// Returns the bitwise not of the value. - /// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. - public fun bitwise_not(x: u256): u256 { - x ^ max_value!() - } - - /// Return the larger of `x` and `y` - public fun max(x: u256, y: u256): u256 { - std::macros::num_max!(x, y) - } - - /// Return the smaller of `x` and `y` - public fun min(x: u256, y: u256): u256 { - std::macros::num_min!(x, y) - } - - /// Return the absolute value of x - y - public fun diff(x: u256, y: u256): u256 { - std::macros::num_diff!(x, y) - } - - /// Calculate x / y, but round up the result. - public fun divide_and_round_up(x: u256, y: u256): u256 { - std::macros::num_divide_and_round_up!(x, y) - } - - /// Return the value of a base raised to a power - public fun pow(base: u256, exponent: u8): u256 { - std::macros::num_pow!(base, exponent) - } - - /// Try to convert a `u256` to a `u8`. Returns `None` if the value is too large. - public fun try_as_u8(x: u256): Option { - std::macros::try_as_u8!(x) - } - - /// Try to convert a `u256` to a `u16`. Returns `None` if the value is too large. - public fun try_as_u16(x: u256): Option { - std::macros::try_as_u16!(x) - } - - /// Try to convert a `u256` to a `u32`. Returns `None` if the value is too large. - public fun try_as_u32(x: u256): Option { - std::macros::try_as_u32!(x) - } - - /// Try to convert a `u256` to a `u64`. Returns `None` if the value is too large. - public fun try_as_u64(x: u256): Option { - std::macros::try_as_u64!(x) - } - - /// Try to convert a `u256` to a `u128`. Returns `None` if the value is too large. - public fun try_as_u128(x: u256): Option { - std::macros::try_as_u128!(x) - } - - public fun to_string(x: u256): String { - std::macros::num_to_string!(x) - } - - /// Maximum value for a `u256` - public macro fun max_value(): u256 { - 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u256, $stop: u256, $f: |u256|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u256, $stop: u256, $f: |u256|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u256, $f: |u256|) { - std::macros::do!($stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u256, $f: |u256|) { - std::macros::do_eq!($stop, $f) - } +module std::u256; + +use std::string::String; + +/// Returns the bitwise not of the value. +/// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. +public fun bitwise_not(x: u256): u256 { + x ^ max_value!() +} + +/// Return the larger of `x` and `y` +public fun max(x: u256, y: u256): u256 { + std::macros::num_max!(x, y) +} + +/// Return the smaller of `x` and `y` +public fun min(x: u256, y: u256): u256 { + std::macros::num_min!(x, y) +} + +/// Return the absolute value of x - y +public fun diff(x: u256, y: u256): u256 { + std::macros::num_diff!(x, y) +} + +/// Calculate x / y, but round up the result. +public fun divide_and_round_up(x: u256, y: u256): u256 { + std::macros::num_divide_and_round_up!(x, y) +} + +/// Return the value of a base raised to a power +public fun pow(base: u256, exponent: u8): u256 { + std::macros::num_pow!(base, exponent) +} + +/// Try to convert a `u256` to a `u8`. Returns `None` if the value is too large. +public fun try_as_u8(x: u256): Option { + std::macros::try_as_u8!(x) +} + +/// Try to convert a `u256` to a `u16`. Returns `None` if the value is too large. +public fun try_as_u16(x: u256): Option { + std::macros::try_as_u16!(x) +} + +/// Try to convert a `u256` to a `u32`. Returns `None` if the value is too large. +public fun try_as_u32(x: u256): Option { + std::macros::try_as_u32!(x) +} + +/// Try to convert a `u256` to a `u64`. Returns `None` if the value is too large. +public fun try_as_u64(x: u256): Option { + std::macros::try_as_u64!(x) +} + +/// Try to convert a `u256` to a `u128`. Returns `None` if the value is too large. +public fun try_as_u128(x: u256): Option { + std::macros::try_as_u128!(x) +} + +public fun to_string(x: u256): String { + std::macros::num_to_string!(x) +} + +/// Maximum value for a `u256` +public macro fun max_value(): u256 { + 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) +public macro fun range_do($start: u256, $stop: u256, $f: |u256|) { + std::macros::range_do!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) +public macro fun range_do_eq($start: u256, $stop: u256, $f: |u256|) { + std::macros::range_do_eq!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (exclusive) +public macro fun do($stop: u256, $f: |u256|) { + std::macros::do!($stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (inclusive) +public macro fun do_eq($stop: u256, $f: |u256|) { + std::macros::do_eq!($stop, $f) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/u32.move b/crates/sui-framework/packages/move-stdlib/sources/u32.move index e969c20c1038a..eab1cadf0804c 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/u32.move +++ b/crates/sui-framework/packages/move-stdlib/sources/u32.move @@ -2,105 +2,105 @@ // SPDX-License-Identifier: Apache-2.0 #[defines_primitive(u32)] -module std::u32 { - use std::string::String; - - /// Returns the bitwise not of the value. - /// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. - public fun bitwise_not(x: u32): u32 { - x ^ max_value!() - } - - /// Return the larger of `x` and `y` - public fun max(x: u32, y: u32): u32 { - std::macros::num_max!(x, y) - } - - /// Return the smaller of `x` and `y` - public fun min(x: u32, y: u32): u32 { - std::macros::num_min!(x, y) - } - - /// Return the absolute value of x - y - public fun diff(x: u32, y: u32): u32 { - std::macros::num_diff!(x, y) - } - - /// Calculate x / y, but round up the result. - public fun divide_and_round_up(x: u32, y: u32): u32 { - std::macros::num_divide_and_round_up!(x, y) - } - - /// Return the value of a base raised to a power - public fun pow(base: u32, exponent: u8): u32 { - std::macros::num_pow!(base, exponent) - } - - /// Get a nearest lower integer Square Root for `x`. Given that this - /// function can only operate with integers, it is impossible - /// to get perfect (or precise) integer square root for some numbers. - /// - /// Example: - /// ``` - /// math::sqrt(9) => 3 - /// math::sqrt(8) => 2 // the nearest lower square root is 4; - /// ``` - /// - /// In integer math, one of the possible ways to get results with more - /// precision is to use higher values or temporarily multiply the - /// value by some bigger number. Ideally if this is a square of 10 or 100. - /// - /// Example: - /// ``` - /// math::sqrt(8) => 2; - /// math::sqrt(8 * 10000) => 282; - /// // now we can use this value as if it was 2.82; - /// // but to get the actual result, this value needs - /// // to be divided by 100 (because sqrt(10000)). - /// - /// - /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) - /// ``` - public fun sqrt(x: u32): u32 { - std::macros::num_sqrt!(x, 32) - } - - /// Try to convert a `u32` to a `u8`. Returns `None` if the value is too large. - public fun try_as_u8(x: u32): Option { - std::macros::try_as_u8!(x) - } - - /// Try to convert a `u32` to a `u16`. Returns `None` if the value is too large. - public fun try_as_u16(x: u32): Option { - std::macros::try_as_u16!(x) - } - - public fun to_string(x: u32): String { - std::macros::num_to_string!(x) - } - - /// Maximum value for a `u32` - public macro fun max_value(): u32 { - 0xFFFF_FFFF - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u32, $stop: u32, $f: |u32|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u32, $stop: u32, $f: |u32|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u32, $f: |u32|) { - std::macros::do!($stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u32, $f: |u32|) { - std::macros::do_eq!($stop, $f) - } +module std::u32; + +use std::string::String; + +/// Returns the bitwise not of the value. +/// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. +public fun bitwise_not(x: u32): u32 { + x ^ max_value!() +} + +/// Return the larger of `x` and `y` +public fun max(x: u32, y: u32): u32 { + std::macros::num_max!(x, y) +} + +/// Return the smaller of `x` and `y` +public fun min(x: u32, y: u32): u32 { + std::macros::num_min!(x, y) +} + +/// Return the absolute value of x - y +public fun diff(x: u32, y: u32): u32 { + std::macros::num_diff!(x, y) +} + +/// Calculate x / y, but round up the result. +public fun divide_and_round_up(x: u32, y: u32): u32 { + std::macros::num_divide_and_round_up!(x, y) +} + +/// Return the value of a base raised to a power +public fun pow(base: u32, exponent: u8): u32 { + std::macros::num_pow!(base, exponent) +} + +/// Get a nearest lower integer Square Root for `x`. Given that this +/// function can only operate with integers, it is impossible +/// to get perfect (or precise) integer square root for some numbers. +/// +/// Example: +/// ``` +/// math::sqrt(9) => 3 +/// math::sqrt(8) => 2 // the nearest lower square root is 4; +/// ``` +/// +/// In integer math, one of the possible ways to get results with more +/// precision is to use higher values or temporarily multiply the +/// value by some bigger number. Ideally if this is a square of 10 or 100. +/// +/// Example: +/// ``` +/// math::sqrt(8) => 2; +/// math::sqrt(8 * 10000) => 282; +/// // now we can use this value as if it was 2.82; +/// // but to get the actual result, this value needs +/// // to be divided by 100 (because sqrt(10000)). +/// +/// +/// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) +/// ``` +public fun sqrt(x: u32): u32 { + std::macros::num_sqrt!(x, 32) +} + +/// Try to convert a `u32` to a `u8`. Returns `None` if the value is too large. +public fun try_as_u8(x: u32): Option { + std::macros::try_as_u8!(x) +} + +/// Try to convert a `u32` to a `u16`. Returns `None` if the value is too large. +public fun try_as_u16(x: u32): Option { + std::macros::try_as_u16!(x) +} + +public fun to_string(x: u32): String { + std::macros::num_to_string!(x) +} + +/// Maximum value for a `u32` +public macro fun max_value(): u32 { + 0xFFFF_FFFF +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) +public macro fun range_do($start: u32, $stop: u32, $f: |u32|) { + std::macros::range_do!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) +public macro fun range_do_eq($start: u32, $stop: u32, $f: |u32|) { + std::macros::range_do_eq!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (exclusive) +public macro fun do($stop: u32, $f: |u32|) { + std::macros::do!($stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (inclusive) +public macro fun do_eq($stop: u32, $f: |u32|) { + std::macros::do_eq!($stop, $f) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/u64.move b/crates/sui-framework/packages/move-stdlib/sources/u64.move index c532958dc3803..e3bc76cc45f92 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/u64.move +++ b/crates/sui-framework/packages/move-stdlib/sources/u64.move @@ -2,110 +2,110 @@ // SPDX-License-Identifier: Apache-2.0 #[defines_primitive(u64)] -module std::u64 { - use std::string::String; - - /// Returns the bitwise not of the value. - /// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. - public fun bitwise_not(x: u64): u64 { - x ^ max_value!() - } - - /// Return the larger of `x` and `y` - public fun max(x: u64, y: u64): u64 { - std::macros::num_max!(x, y) - } - - /// Return the smaller of `x` and `y` - public fun min(x: u64, y: u64): u64 { - std::macros::num_min!(x, y) - } - - /// Return the absolute value of x - y - public fun diff(x: u64, y: u64): u64 { - std::macros::num_diff!(x, y) - } - - /// Calculate x / y, but round up the result. - public fun divide_and_round_up(x: u64, y: u64): u64 { - std::macros::num_divide_and_round_up!(x, y) - } - - /// Return the value of a base raised to a power - public fun pow(base: u64, exponent: u8): u64 { - std::macros::num_pow!(base, exponent) - } - - /// Get a nearest lower integer Square Root for `x`. Given that this - /// function can only operate with integers, it is impossible - /// to get perfect (or precise) integer square root for some numbers. - /// - /// Example: - /// ``` - /// math::sqrt(9) => 3 - /// math::sqrt(8) => 2 // the nearest lower square root is 4; - /// ``` - /// - /// In integer math, one of the possible ways to get results with more - /// precision is to use higher values or temporarily multiply the - /// value by some bigger number. Ideally if this is a square of 10 or 100. - /// - /// Example: - /// ``` - /// math::sqrt(8) => 2; - /// math::sqrt(8 * 10000) => 282; - /// // now we can use this value as if it was 2.82; - /// // but to get the actual result, this value needs - /// // to be divided by 100 (because sqrt(10000)). - /// - /// - /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) - /// ``` - public fun sqrt(x: u64): u64 { - std::macros::num_sqrt!(x, 64) - } - - /// Try to convert a `u64` to a `u8`. Returns `None` if the value is too large. - public fun try_as_u8(x: u64): Option { - std::macros::try_as_u8!(x) - } - - /// Try to convert a `u64` to a `u16`. Returns `None` if the value is too large. - public fun try_as_u16(x: u64): Option { - std::macros::try_as_u16!(x) - } - - /// Try to convert a `u64` to a `u32`. Returns `None` if the value is too large. - public fun try_as_u32(x: u64): Option { - std::macros::try_as_u32!(x) - } - - public fun to_string(x: u64): String { - std::macros::num_to_string!(x) - } - - /// Maximum value for a `u64` - public macro fun max_value(): u64 { - 0xFFFF_FFFF_FFFF_FFFF - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u64, $stop: u64, $f: |u64|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u64, $stop: u64, $f: |u64|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u64, $f: |u64|) { - std::macros::do!($stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u64, $f: |u64|) { - std::macros::do_eq!($stop, $f) - } +module std::u64; + +use std::string::String; + +/// Returns the bitwise not of the value. +/// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. +public fun bitwise_not(x: u64): u64 { + x ^ max_value!() +} + +/// Return the larger of `x` and `y` +public fun max(x: u64, y: u64): u64 { + std::macros::num_max!(x, y) +} + +/// Return the smaller of `x` and `y` +public fun min(x: u64, y: u64): u64 { + std::macros::num_min!(x, y) +} + +/// Return the absolute value of x - y +public fun diff(x: u64, y: u64): u64 { + std::macros::num_diff!(x, y) +} + +/// Calculate x / y, but round up the result. +public fun divide_and_round_up(x: u64, y: u64): u64 { + std::macros::num_divide_and_round_up!(x, y) +} + +/// Return the value of a base raised to a power +public fun pow(base: u64, exponent: u8): u64 { + std::macros::num_pow!(base, exponent) +} + +/// Get a nearest lower integer Square Root for `x`. Given that this +/// function can only operate with integers, it is impossible +/// to get perfect (or precise) integer square root for some numbers. +/// +/// Example: +/// ``` +/// math::sqrt(9) => 3 +/// math::sqrt(8) => 2 // the nearest lower square root is 4; +/// ``` +/// +/// In integer math, one of the possible ways to get results with more +/// precision is to use higher values or temporarily multiply the +/// value by some bigger number. Ideally if this is a square of 10 or 100. +/// +/// Example: +/// ``` +/// math::sqrt(8) => 2; +/// math::sqrt(8 * 10000) => 282; +/// // now we can use this value as if it was 2.82; +/// // but to get the actual result, this value needs +/// // to be divided by 100 (because sqrt(10000)). +/// +/// +/// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) +/// ``` +public fun sqrt(x: u64): u64 { + std::macros::num_sqrt!(x, 64) +} + +/// Try to convert a `u64` to a `u8`. Returns `None` if the value is too large. +public fun try_as_u8(x: u64): Option { + std::macros::try_as_u8!(x) +} + +/// Try to convert a `u64` to a `u16`. Returns `None` if the value is too large. +public fun try_as_u16(x: u64): Option { + std::macros::try_as_u16!(x) +} + +/// Try to convert a `u64` to a `u32`. Returns `None` if the value is too large. +public fun try_as_u32(x: u64): Option { + std::macros::try_as_u32!(x) +} + +public fun to_string(x: u64): String { + std::macros::num_to_string!(x) +} + +/// Maximum value for a `u64` +public macro fun max_value(): u64 { + 0xFFFF_FFFF_FFFF_FFFF +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) +public macro fun range_do($start: u64, $stop: u64, $f: |u64|) { + std::macros::range_do!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) +public macro fun range_do_eq($start: u64, $stop: u64, $f: |u64|) { + std::macros::range_do_eq!($start, $stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (exclusive) +public macro fun do($stop: u64, $f: |u64|) { + std::macros::do!($stop, $f) +} + +/// Loops applying `$f` to each number from `0` to `$stop` (inclusive) +public macro fun do_eq($stop: u64, $f: |u64|) { + std::macros::do_eq!($stop, $f) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/u8.move b/crates/sui-framework/packages/move-stdlib/sources/u8.move index 8bb4e58139017..f0a99d690f58a 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/u8.move +++ b/crates/sui-framework/packages/move-stdlib/sources/u8.move @@ -2,95 +2,95 @@ // SPDX-License-Identifier: Apache-2.0 #[defines_primitive(u8)] -module std::u8 { - use std::string::String; +module std::u8; - /// Returns the bitwise not of the value. - /// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. - public fun bitwise_not(x: u8): u8 { - x ^ max_value!() - } +use std::string::String; - /// Return the larger of `x` and `y` - public fun max(x: u8, y: u8): u8 { - std::macros::num_max!(x, y) - } +/// Returns the bitwise not of the value. +/// Each bit that is 1 becomes 0. Each bit that is 0 becomes 1. +public fun bitwise_not(x: u8): u8 { + x ^ max_value!() +} - /// Return the smaller of `x` and `y` - public fun min(x: u8, y: u8): u8 { - std::macros::num_min!(x, y) - } +/// Return the larger of `x` and `y` +public fun max(x: u8, y: u8): u8 { + std::macros::num_max!(x, y) +} - /// Return the absolute value of x - y - public fun diff(x: u8, y: u8): u8 { - std::macros::num_diff!(x, y) - } +/// Return the smaller of `x` and `y` +public fun min(x: u8, y: u8): u8 { + std::macros::num_min!(x, y) +} - /// Calculate x / y, but round up the result. - public fun divide_and_round_up(x: u8, y: u8): u8 { - std::macros::num_divide_and_round_up!(x, y) - } +/// Return the absolute value of x - y +public fun diff(x: u8, y: u8): u8 { + std::macros::num_diff!(x, y) +} - /// Return the value of a base raised to a power - public fun pow(base: u8, exponent: u8): u8 { - std::macros::num_pow!(base, exponent) - } +/// Calculate x / y, but round up the result. +public fun divide_and_round_up(x: u8, y: u8): u8 { + std::macros::num_divide_and_round_up!(x, y) +} - /// Get a nearest lower integer Square Root for `x`. Given that this - /// function can only operate with integers, it is impossible - /// to get perfect (or precise) integer square root for some numbers. - /// - /// Example: - /// ``` - /// math::sqrt(9) => 3 - /// math::sqrt(8) => 2 // the nearest lower square root is 4; - /// ``` - /// - /// In integer math, one of the possible ways to get results with more - /// precision is to use higher values or temporarily multiply the - /// value by some bigger number. Ideally if this is a square of 10 or 100. - /// - /// Example: - /// ``` - /// math::sqrt(8) => 2; - /// math::sqrt(8 * 10000) => 282; - /// // now we can use this value as if it was 2.82; - /// // but to get the actual result, this value needs - /// // to be divided by 100 (because sqrt(10000)). - /// - /// - /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) - /// ``` - public fun sqrt(x: u8): u8 { - std::macros::num_sqrt!(x, 8) - } +/// Return the value of a base raised to a power +public fun pow(base: u8, exponent: u8): u8 { + std::macros::num_pow!(base, exponent) +} - public fun to_string(x: u8): String { - std::macros::num_to_string!(x) - } +/// Get a nearest lower integer Square Root for `x`. Given that this +/// function can only operate with integers, it is impossible +/// to get perfect (or precise) integer square root for some numbers. +/// +/// Example: +/// ``` +/// math::sqrt(9) => 3 +/// math::sqrt(8) => 2 // the nearest lower square root is 4; +/// ``` +/// +/// In integer math, one of the possible ways to get results with more +/// precision is to use higher values or temporarily multiply the +/// value by some bigger number. Ideally if this is a square of 10 or 100. +/// +/// Example: +/// ``` +/// math::sqrt(8) => 2; +/// math::sqrt(8 * 10000) => 282; +/// // now we can use this value as if it was 2.82; +/// // but to get the actual result, this value needs +/// // to be divided by 100 (because sqrt(10000)). +/// +/// +/// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) +/// ``` +public fun sqrt(x: u8): u8 { + std::macros::num_sqrt!(x, 8) +} - /// Maximum value for a `u8` - public macro fun max_value(): u8 { - 0xFF - } +public fun to_string(x: u8): String { + std::macros::num_to_string!(x) +} + +/// Maximum value for a `u8` +public macro fun max_value(): u8 { + 0xFF +} - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u8, $stop: u8, $f: |u8|) { - std::macros::range_do!($start, $stop, $f) - } +/// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) +public macro fun range_do($start: u8, $stop: u8, $f: |u8|) { + std::macros::range_do!($start, $stop, $f) +} - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u8, $stop: u8, $f: |u8|) { - std::macros::range_do_eq!($start, $stop, $f) - } +/// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) +public macro fun range_do_eq($start: u8, $stop: u8, $f: |u8|) { + std::macros::range_do_eq!($start, $stop, $f) +} - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u8, $f: |u8|) { - std::macros::do!($stop, $f) - } +/// Loops applying `$f` to each number from `0` to `$stop` (exclusive) +public macro fun do($stop: u8, $f: |u8|) { + std::macros::do!($stop, $f) +} - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u8, $f: |u8|) { - std::macros::do_eq!($stop, $f) - } +/// Loops applying `$f` to each number from `0` to `$stop` (inclusive) +public macro fun do_eq($stop: u8, $f: |u8|) { + std::macros::do_eq!($stop, $f) } diff --git a/crates/sui-framework/packages/move-stdlib/sources/unit_test.move b/crates/sui-framework/packages/move-stdlib/sources/unit_test.move index 1deb6a70c0529..7672eb3f54416 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/unit_test.move +++ b/crates/sui-framework/packages/move-stdlib/sources/unit_test.move @@ -3,32 +3,31 @@ #[test_only] /// Module providing testing functionality. Only included for tests. -module std::unit_test { +module std::unit_test; - /// DEPRECATED - native public fun create_signers_for_testing(num_signers: u64): vector; +/// DEPRECATED +public native fun create_signers_for_testing(num_signers: u64): vector; - /// This function is used to poison modules compiled in `test` mode. - /// This will cause a linking failure if an attempt is made to publish a - /// test module in a VM that isn't in unit test mode. - native public fun poison(); +/// This function is used to poison modules compiled in `test` mode. +/// This will cause a linking failure if an attempt is made to publish a +/// test module in a VM that isn't in unit test mode. +public native fun poison(); - public macro fun assert_eq<$T: drop>($t1: $T, $t2: $T) { - let t1 = $t1; - let t2 = $t2; - assert_ref_eq!(&t1, &t2) - } +public macro fun assert_eq<$T: drop>($t1: $T, $t2: $T) { + let t1 = $t1; + let t2 = $t2; + assert_ref_eq!(&t1, &t2) +} - public macro fun assert_ref_eq<$T>($t1: &$T, $t2: &$T) { - let t1 = $t1; - let t2 = $t2; - let res = t1 == t2; - if (!res) { - std::debug::print(&b"Assertion failed:"); - std::debug::print(t1); - std::debug::print(&b"!="); - std::debug::print(t2); - assert!(false); - } +public macro fun assert_ref_eq<$T>($t1: &$T, $t2: &$T) { + let t1 = $t1; + let t2 = $t2; + let res = t1 == t2; + if (!res) { + std::debug::print(&b"Assertion failed:"); + std::debug::print(t1); + std::debug::print(&b"!="); + std::debug::print(t2); + assert!(false); } } diff --git a/crates/sui-framework/packages/move-stdlib/sources/vector.move b/crates/sui-framework/packages/move-stdlib/sources/vector.move index 6d7d0e37fe458..96a2567855501 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/vector.move +++ b/crates/sui-framework/packages/move-stdlib/sources/vector.move @@ -4,368 +4,371 @@ #[defines_primitive(vector)] /// A variable-sized container that can hold any type. Indexing is 0-based, and /// vectors are growable. This module has many native functions. -module std::vector { - /// Allows calling `.to_string()` on a vector of `u8` to get a utf8 `String`. - public use fun std::string::utf8 as vector.to_string; - - /// Allows calling `.try_to_string()` on a vector of `u8` to get a utf8 `String`. - /// This will return `None` if the vector is not valid utf8. - public use fun std::string::try_utf8 as vector.try_to_string; - - /// Allows calling `.to_ascii_string()` on a vector of `u8` to get an `ascii::String`. - public use fun std::ascii::string as vector.to_ascii_string; - - /// Allows calling `.try_to_ascii_string()` on a vector of `u8` to get an - /// `ascii::String`. This will return `None` if the vector is not valid ascii. - public use fun std::ascii::try_string as vector.try_to_ascii_string; - - /// The index into the vector is out of bounds - const EINDEX_OUT_OF_BOUNDS: u64 = 0x20000; - - #[bytecode_instruction] - /// Create an empty vector. - public native fun empty(): vector; - - #[bytecode_instruction] - /// Return the length of the vector. - public native fun length(v: &vector): u64; - - #[syntax(index)] - #[bytecode_instruction] - /// Acquire an immutable reference to the `i`th element of the vector `v`. - /// Aborts if `i` is out of bounds. - public native fun borrow(v: &vector, i: u64): ∈ - - #[bytecode_instruction] - /// Add element `e` to the end of the vector `v`. - public native fun push_back(v: &mut vector, e: Element); - - #[syntax(index)] - #[bytecode_instruction] - /// Return a mutable reference to the `i`th element in the vector `v`. - /// Aborts if `i` is out of bounds. - public native fun borrow_mut(v: &mut vector, i: u64): &mut Element; - - #[bytecode_instruction] - /// Pop an element from the end of vector `v`. - /// Aborts if `v` is empty. - public native fun pop_back(v: &mut vector): Element; - - #[bytecode_instruction] - /// Destroy the vector `v`. - /// Aborts if `v` is not empty. - public native fun destroy_empty(v: vector); - - #[bytecode_instruction] - /// Swaps the elements at the `i`th and `j`th indices in the vector `v`. - /// Aborts if `i` or `j` is out of bounds. - public native fun swap(v: &mut vector, i: u64, j: u64); - - /// Return an vector of size one containing element `e`. - public fun singleton(e: Element): vector { - let mut v = empty(); - v.push_back(e); - v - } +module std::vector; + +/// Allows calling `.to_string()` on a vector of `u8` to get a utf8 `String`. +public use fun std::string::utf8 as vector.to_string; + +/// Allows calling `.try_to_string()` on a vector of `u8` to get a utf8 `String`. +/// This will return `None` if the vector is not valid utf8. +public use fun std::string::try_utf8 as vector.try_to_string; + +/// Allows calling `.to_ascii_string()` on a vector of `u8` to get an `ascii::String`. +public use fun std::ascii::string as vector.to_ascii_string; + +/// Allows calling `.try_to_ascii_string()` on a vector of `u8` to get an +/// `ascii::String`. This will return `None` if the vector is not valid ascii. +public use fun std::ascii::try_string as vector.try_to_ascii_string; + +/// The index into the vector is out of bounds +const EINDEX_OUT_OF_BOUNDS: u64 = 0x20000; + +#[bytecode_instruction] +/// Create an empty vector. +public native fun empty(): vector; + +#[bytecode_instruction] +/// Return the length of the vector. +public native fun length(v: &vector): u64; + +#[syntax(index)] +#[bytecode_instruction] +/// Acquire an immutable reference to the `i`th element of the vector `v`. +/// Aborts if `i` is out of bounds. +public native fun borrow(v: &vector, i: u64): ∈ + +#[bytecode_instruction] +/// Add element `e` to the end of the vector `v`. +public native fun push_back(v: &mut vector, e: Element); + +#[syntax(index)] +#[bytecode_instruction] +/// Return a mutable reference to the `i`th element in the vector `v`. +/// Aborts if `i` is out of bounds. +public native fun borrow_mut(v: &mut vector, i: u64): &mut Element; + +#[bytecode_instruction] +/// Pop an element from the end of vector `v`. +/// Aborts if `v` is empty. +public native fun pop_back(v: &mut vector): Element; + +#[bytecode_instruction] +/// Destroy the vector `v`. +/// Aborts if `v` is not empty. +public native fun destroy_empty(v: vector); + +#[bytecode_instruction] +/// Swaps the elements at the `i`th and `j`th indices in the vector `v`. +/// Aborts if `i` or `j` is out of bounds. +public native fun swap(v: &mut vector, i: u64, j: u64); + +/// Return an vector of size one containing element `e`. +public fun singleton(e: Element): vector { + let mut v = empty(); + v.push_back(e); + v +} - /// Reverses the order of the elements in the vector `v` in place. - public fun reverse(v: &mut vector) { - let len = v.length(); - if (len == 0) return (); - - let mut front_index = 0; - let mut back_index = len - 1; - while (front_index < back_index) { - v.swap(front_index, back_index); - front_index = front_index + 1; - back_index = back_index - 1; - } +/// Reverses the order of the elements in the vector `v` in place. +public fun reverse(v: &mut vector) { + let len = v.length(); + if (len == 0) return (); + + let mut front_index = 0; + let mut back_index = len - 1; + while (front_index < back_index) { + v.swap(front_index, back_index); + front_index = front_index + 1; + back_index = back_index - 1; } +} - /// Pushes all of the elements of the `other` vector into the `lhs` vector. - public fun append(lhs: &mut vector, mut other: vector) { - other.reverse(); - while (!other.is_empty()) lhs.push_back(other.pop_back()); - other.destroy_empty(); - } +/// Pushes all of the elements of the `other` vector into the `lhs` vector. +public fun append(lhs: &mut vector, mut other: vector) { + other.reverse(); + while (!other.is_empty()) lhs.push_back(other.pop_back()); + other.destroy_empty(); +} - /// Return `true` if the vector `v` has no elements and `false` otherwise. - public fun is_empty(v: &vector): bool { - v.length() == 0 - } +/// Return `true` if the vector `v` has no elements and `false` otherwise. +public fun is_empty(v: &vector): bool { + v.length() == 0 +} - /// Return true if `e` is in the vector `v`. - /// Otherwise, returns false. - public fun contains(v: &vector, e: &Element): bool { - let mut i = 0; - let len = v.length(); - while (i < len) { - if (&v[i] == e) return true; - i = i + 1; - }; - false - } +/// Return true if `e` is in the vector `v`. +/// Otherwise, returns false. +public fun contains(v: &vector, e: &Element): bool { + let mut i = 0; + let len = v.length(); + while (i < len) { + if (&v[i] == e) return true; + i = i + 1; + }; + false +} - /// Return `(true, i)` if `e` is in the vector `v` at index `i`. - /// Otherwise, returns `(false, 0)`. - public fun index_of(v: &vector, e: &Element): (bool, u64) { - let mut i = 0; - let len = v.length(); - while (i < len) { - if (&v[i] == e) return (true, i); - i = i + 1; - }; - (false, 0) - } +/// Return `(true, i)` if `e` is in the vector `v` at index `i`. +/// Otherwise, returns `(false, 0)`. +public fun index_of(v: &vector, e: &Element): (bool, u64) { + let mut i = 0; + let len = v.length(); + while (i < len) { + if (&v[i] == e) return (true, i); + i = i + 1; + }; + (false, 0) +} - /// Remove the `i`th element of the vector `v`, shifting all subsequent elements. - /// This is O(n) and preserves ordering of elements in the vector. - /// Aborts if `i` is out of bounds. - public fun remove(v: &mut vector, mut i: u64): Element { - let mut len = v.length(); - // i out of bounds; abort - if (i >= len) abort EINDEX_OUT_OF_BOUNDS; - - len = len - 1; - while (i < len) v.swap(i, { i = i + 1; i }); - v.pop_back() - } +/// Remove the `i`th element of the vector `v`, shifting all subsequent elements. +/// This is O(n) and preserves ordering of elements in the vector. +/// Aborts if `i` is out of bounds. +public fun remove(v: &mut vector, mut i: u64): Element { + let mut len = v.length(); + // i out of bounds; abort + if (i >= len) abort EINDEX_OUT_OF_BOUNDS; + + len = len - 1; + while (i < len) v.swap(i, { + i = i + 1; + i + }); + v.pop_back() +} - /// Insert `e` at position `i` in the vector `v`. - /// If `i` is in bounds, this shifts the old `v[i]` and all subsequent elements to the right. - /// If `i == v.length()`, this adds `e` to the end of the vector. - /// This is O(n) and preserves ordering of elements in the vector. - /// Aborts if `i > v.length()` - public fun insert(v: &mut vector, e: Element, mut i: u64) { - let len = v.length(); - // i too big abort - if (i > len) abort EINDEX_OUT_OF_BOUNDS; - - v.push_back(e); - while (i < len) { - v.swap(i, len); - i = i + 1 - } +/// Insert `e` at position `i` in the vector `v`. +/// If `i` is in bounds, this shifts the old `v[i]` and all subsequent elements to the right. +/// If `i == v.length()`, this adds `e` to the end of the vector. +/// This is O(n) and preserves ordering of elements in the vector. +/// Aborts if `i > v.length()` +public fun insert(v: &mut vector, e: Element, mut i: u64) { + let len = v.length(); + // i too big abort + if (i > len) abort EINDEX_OUT_OF_BOUNDS; + + v.push_back(e); + while (i < len) { + v.swap(i, len); + i = i + 1 } +} - /// Swap the `i`th element of the vector `v` with the last element and then pop the vector. - /// This is O(1), but does not preserve ordering of elements in the vector. - /// Aborts if `i` is out of bounds. - public fun swap_remove(v: &mut vector, i: u64): Element { - assert!(!v.is_empty(), EINDEX_OUT_OF_BOUNDS); - let last_idx = v.length() - 1; - v.swap(i, last_idx); - v.pop_back() - } +/// Swap the `i`th element of the vector `v` with the last element and then pop the vector. +/// This is O(1), but does not preserve ordering of elements in the vector. +/// Aborts if `i` is out of bounds. +public fun swap_remove(v: &mut vector, i: u64): Element { + assert!(!v.is_empty(), EINDEX_OUT_OF_BOUNDS); + let last_idx = v.length() - 1; + v.swap(i, last_idx); + v.pop_back() +} - // === Macros === +// === Macros === - /// Create a vector of length `n` by calling the function `f` on each index. - public macro fun tabulate<$T>($n: u64, $f: |u64| -> $T): vector<$T> { - let mut v = vector[]; - let n = $n; - n.do!(|i| v.push_back($f(i))); - v - } +/// Create a vector of length `n` by calling the function `f` on each index. +public macro fun tabulate<$T>($n: u64, $f: |u64| -> $T): vector<$T> { + let mut v = vector[]; + let n = $n; + n.do!(|i| v.push_back($f(i))); + v +} - /// Destroy the vector `v` by calling `f` on each element and then destroying the vector. - /// Does not preserve the order of elements in the vector (starts from the end of the vector). - public macro fun destroy<$T>($v: vector<$T>, $f: |$T|) { - let mut v = $v; - while (!v.is_empty()) $f(v.pop_back()); - v.destroy_empty(); - } +/// Destroy the vector `v` by calling `f` on each element and then destroying the vector. +/// Does not preserve the order of elements in the vector (starts from the end of the vector). +public macro fun destroy<$T>($v: vector<$T>, $f: |$T|) { + let mut v = $v; + while (!v.is_empty()) $f(v.pop_back()); + v.destroy_empty(); +} - /// Destroy the vector `v` by calling `f` on each element and then destroying the vector. - /// Preserves the order of elements in the vector. - public macro fun do<$T>($v: vector<$T>, $f: |$T|) { - let mut v = $v; - v.reverse(); - while (!v.is_empty()) $f(v.pop_back()); - v.destroy_empty(); - } +/// Destroy the vector `v` by calling `f` on each element and then destroying the vector. +/// Preserves the order of elements in the vector. +public macro fun do<$T>($v: vector<$T>, $f: |$T|) { + let mut v = $v; + v.reverse(); + while (!v.is_empty()) $f(v.pop_back()); + v.destroy_empty(); +} - /// Perform an action `f` on each element of the vector `v`. The vector is not modified. - public macro fun do_ref<$T>($v: &vector<$T>, $f: |&$T|) { - let v = $v; - v.length().do!(|i| $f(&v[i])) - } +/// Perform an action `f` on each element of the vector `v`. The vector is not modified. +public macro fun do_ref<$T>($v: &vector<$T>, $f: |&$T|) { + let v = $v; + v.length().do!(|i| $f(&v[i])) +} - /// Perform an action `f` on each element of the vector `v`. - /// The function `f` takes a mutable reference to the element. - public macro fun do_mut<$T>($v: &mut vector<$T>, $f: |&mut $T|) { - let v = $v; - v.length().do!(|i| $f(&mut v[i])) - } +/// Perform an action `f` on each element of the vector `v`. +/// The function `f` takes a mutable reference to the element. +public macro fun do_mut<$T>($v: &mut vector<$T>, $f: |&mut $T|) { + let v = $v; + v.length().do!(|i| $f(&mut v[i])) +} - /// Map the vector `v` to a new vector by applying the function `f` to each element. - /// Preserves the order of elements in the vector, first is called first. - public macro fun map<$T, $U>($v: vector<$T>, $f: |$T| -> $U): vector<$U> { - let v = $v; - let mut r = vector[]; - v.do!(|e| r.push_back($f(e))); - r - } +/// Map the vector `v` to a new vector by applying the function `f` to each element. +/// Preserves the order of elements in the vector, first is called first. +public macro fun map<$T, $U>($v: vector<$T>, $f: |$T| -> $U): vector<$U> { + let v = $v; + let mut r = vector[]; + v.do!(|e| r.push_back($f(e))); + r +} - /// Map the vector `v` to a new vector by applying the function `f` to each element. - /// Preserves the order of elements in the vector, first is called first. - public macro fun map_ref<$T, $U>($v: &vector<$T>, $f: |&$T| -> $U): vector<$U> { - let v = $v; - let mut r = vector[]; - v.do_ref!(|e| r.push_back($f(e))); - r - } +/// Map the vector `v` to a new vector by applying the function `f` to each element. +/// Preserves the order of elements in the vector, first is called first. +public macro fun map_ref<$T, $U>($v: &vector<$T>, $f: |&$T| -> $U): vector<$U> { + let v = $v; + let mut r = vector[]; + v.do_ref!(|e| r.push_back($f(e))); + r +} - /// Filter the vector `v` by applying the function `f` to each element. - /// Return a new vector containing only the elements for which `f` returns `true`. - public macro fun filter<$T: drop>($v: vector<$T>, $f: |&$T| -> bool): vector<$T> { - let v = $v; - let mut r = vector[]; - v.do!(|e| if ($f(&e)) r.push_back(e)); - r - } +/// Filter the vector `v` by applying the function `f` to each element. +/// Return a new vector containing only the elements for which `f` returns `true`. +public macro fun filter<$T: drop>($v: vector<$T>, $f: |&$T| -> bool): vector<$T> { + let v = $v; + let mut r = vector[]; + v.do!(|e| if ($f(&e)) r.push_back(e)); + r +} - /// Split the vector `v` into two vectors by applying the function `f` to each element. - /// Return a tuple containing two vectors: the first containing the elements for which `f` returns `true`, - /// and the second containing the elements for which `f` returns `false`. - public macro fun partition<$T>($v: vector<$T>, $f: |&$T| -> bool): (vector<$T>, vector<$T>) { - let v = $v; - let mut r1 = vector[]; - let mut r2 = vector[]; - v.do!(|e| if ($f(&e)) r1.push_back(e) else r2.push_back(e)); - (r1, r2) - } +/// Split the vector `v` into two vectors by applying the function `f` to each element. +/// Return a tuple containing two vectors: the first containing the elements for which `f` returns `true`, +/// and the second containing the elements for which `f` returns `false`. +public macro fun partition<$T>($v: vector<$T>, $f: |&$T| -> bool): (vector<$T>, vector<$T>) { + let v = $v; + let mut r1 = vector[]; + let mut r2 = vector[]; + v.do!(|e| if ($f(&e)) r1.push_back(e) else r2.push_back(e)); + (r1, r2) +} - /// Finds the index of first element in the vector `v` that satisfies the predicate `f`. - /// Returns `some(index)` if such an element is found, otherwise `none()`. - public macro fun find_index<$T>($v: &vector<$T>, $f: |&$T| -> bool): Option { - let v = $v; - 'find_index: { - v.length().do!(|i| if ($f(&v[i])) return 'find_index option::some(i)); - option::none() - } +/// Finds the index of first element in the vector `v` that satisfies the predicate `f`. +/// Returns `some(index)` if such an element is found, otherwise `none()`. +public macro fun find_index<$T>($v: &vector<$T>, $f: |&$T| -> bool): Option { + let v = $v; + 'find_index: { + v.length().do!(|i| if ($f(&v[i])) return 'find_index option::some(i)); + option::none() } +} - /// Count how many elements in the vector `v` satisfy the predicate `f`. - public macro fun count<$T>($v: &vector<$T>, $f: |&$T| -> bool): u64 { - let v = $v; - let mut count = 0; - v.do_ref!(|e| if ($f(e)) count = count + 1); - count - } +/// Count how many elements in the vector `v` satisfy the predicate `f`. +public macro fun count<$T>($v: &vector<$T>, $f: |&$T| -> bool): u64 { + let v = $v; + let mut count = 0; + v.do_ref!(|e| if ($f(e)) count = count + 1); + count +} - /// Reduce the vector `v` to a single value by applying the function `f` to each element. - /// Similar to `fold_left` in Rust and `reduce` in Python and JavaScript. - public macro fun fold<$T, $Acc>($v: vector<$T>, $init: $Acc, $f: |$Acc, $T| -> $Acc): $Acc { - let v = $v; - let mut acc = $init; - v.do!(|e| acc = $f(acc, e)); - acc - } +/// Reduce the vector `v` to a single value by applying the function `f` to each element. +/// Similar to `fold_left` in Rust and `reduce` in Python and JavaScript. +public macro fun fold<$T, $Acc>($v: vector<$T>, $init: $Acc, $f: |$Acc, $T| -> $Acc): $Acc { + let v = $v; + let mut acc = $init; + v.do!(|e| acc = $f(acc, e)); + acc +} - /// Concatenate the vectors of `v` into a single vector, keeping the order of the elements. - public fun flatten(v: vector>): vector { - let mut r = vector[]; - v.do!(|u| r.append(u)); - r - } +/// Concatenate the vectors of `v` into a single vector, keeping the order of the elements. +public fun flatten(v: vector>): vector { + let mut r = vector[]; + v.do!(|u| r.append(u)); + r +} - /// Whether any element in the vector `v` satisfies the predicate `f`. - /// If the vector is empty, returns `false`. - public macro fun any<$T>($v: &vector<$T>, $f: |&$T| -> bool): bool { - let v = $v; - 'any: { - v.do_ref!(|e| if ($f(e)) return 'any true); - false - } +/// Whether any element in the vector `v` satisfies the predicate `f`. +/// If the vector is empty, returns `false`. +public macro fun any<$T>($v: &vector<$T>, $f: |&$T| -> bool): bool { + let v = $v; + 'any: { + v.do_ref!(|e| if ($f(e)) return 'any true); + false } +} - /// Whether all elements in the vector `v` satisfy the predicate `f`. - /// If the vector is empty, returns `true`. - public macro fun all<$T>($v: &vector<$T>, $f: |&$T| -> bool): bool { - let v = $v; - 'all: { - v.do_ref!(|e| if (!$f(e)) return 'all false); - true - } +/// Whether all elements in the vector `v` satisfy the predicate `f`. +/// If the vector is empty, returns `true`. +public macro fun all<$T>($v: &vector<$T>, $f: |&$T| -> bool): bool { + let v = $v; + 'all: { + v.do_ref!(|e| if (!$f(e)) return 'all false); + true } +} - /// Destroys two vectors `v1` and `v2` by calling `f` to each pair of elements. - /// Aborts if the vectors are not of the same length. - /// The order of elements in the vectors is preserved. - public macro fun zip_do<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f: |$T1, $T2|) { - let v1 = $v1; - let mut v2 = $v2; - v2.reverse(); - let len = v1.length(); - assert!(len == v2.length()); - v1.do!(|el1| $f(el1, v2.pop_back())); - } +/// Destroys two vectors `v1` and `v2` by calling `f` to each pair of elements. +/// Aborts if the vectors are not of the same length. +/// The order of elements in the vectors is preserved. +public macro fun zip_do<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f: |$T1, $T2|) { + let v1 = $v1; + let mut v2 = $v2; + v2.reverse(); + let len = v1.length(); + assert!(len == v2.length()); + v1.do!(|el1| $f(el1, v2.pop_back())); +} - /// Destroys two vectors `v1` and `v2` by calling `f` to each pair of elements. - /// Aborts if the vectors are not of the same length. - /// Starts from the end of the vectors. - public macro fun zip_do_reverse<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f: |$T1, $T2|) { - let v1 = $v1; - let mut v2 = $v2; - let len = v1.length(); - assert!(len == v2.length()); - v1.destroy!(|el1| $f(el1, v2.pop_back())); - } +/// Destroys two vectors `v1` and `v2` by calling `f` to each pair of elements. +/// Aborts if the vectors are not of the same length. +/// Starts from the end of the vectors. +public macro fun zip_do_reverse<$T1, $T2>($v1: vector<$T1>, $v2: vector<$T2>, $f: |$T1, $T2|) { + let v1 = $v1; + let mut v2 = $v2; + let len = v1.length(); + assert!(len == v2.length()); + v1.destroy!(|el1| $f(el1, v2.pop_back())); +} - /// Iterate through `v1` and `v2` and apply the function `f` to references of each pair of - /// elements. The vectors are not modified. - /// Aborts if the vectors are not of the same length. - /// The order of elements in the vectors is preserved. - public macro fun zip_do_ref<$T1, $T2>($v1: &vector<$T1>, $v2: &vector<$T2>, $f: |&$T1, &$T2|) { - let v1 = $v1; - let v2 = $v2; - let len = v1.length(); - assert!(len == v2.length()); - len.do!(|i| $f(&v1[i], &v2[i])); - } +/// Iterate through `v1` and `v2` and apply the function `f` to references of each pair of +/// elements. The vectors are not modified. +/// Aborts if the vectors are not of the same length. +/// The order of elements in the vectors is preserved. +public macro fun zip_do_ref<$T1, $T2>($v1: &vector<$T1>, $v2: &vector<$T2>, $f: |&$T1, &$T2|) { + let v1 = $v1; + let v2 = $v2; + let len = v1.length(); + assert!(len == v2.length()); + len.do!(|i| $f(&v1[i], &v2[i])); +} - /// Iterate through `v1` and `v2` and apply the function `f` to mutable references of each pair - /// of elements. The vectors may be modified. - /// Aborts if the vectors are not of the same length. - /// The order of elements in the vectors is preserved. - public macro fun zip_do_mut<$T1, $T2>( - $v1: &mut vector<$T1>, - $v2: &mut vector<$T2>, - $f: |&mut $T1, &mut $T2|, - ) { - let v1 = $v1; - let v2 = $v2; - let len = v1.length(); - assert!(len == v2.length()); - len.do!(|i| $f(&mut v1[i], &mut v2[i])); - } +/// Iterate through `v1` and `v2` and apply the function `f` to mutable references of each pair +/// of elements. The vectors may be modified. +/// Aborts if the vectors are not of the same length. +/// The order of elements in the vectors is preserved. +public macro fun zip_do_mut<$T1, $T2>( + $v1: &mut vector<$T1>, + $v2: &mut vector<$T2>, + $f: |&mut $T1, &mut $T2|, +) { + let v1 = $v1; + let v2 = $v2; + let len = v1.length(); + assert!(len == v2.length()); + len.do!(|i| $f(&mut v1[i], &mut v2[i])); +} - /// Destroys two vectors `v1` and `v2` by applying the function `f` to each pair of elements. - /// The returned values are collected into a new vector. - /// Aborts if the vectors are not of the same length. - /// The order of elements in the vectors is preserved. - public macro fun zip_map<$T1, $T2, $U>( - $v1: vector<$T1>, - $v2: vector<$T2>, - $f: |$T1, $T2| -> $U, - ): vector<$U> { - let mut r = vector[]; - zip_do!($v1, $v2, |el1, el2| r.push_back($f(el1, el2))); - r - } +/// Destroys two vectors `v1` and `v2` by applying the function `f` to each pair of elements. +/// The returned values are collected into a new vector. +/// Aborts if the vectors are not of the same length. +/// The order of elements in the vectors is preserved. +public macro fun zip_map<$T1, $T2, $U>( + $v1: vector<$T1>, + $v2: vector<$T2>, + $f: |$T1, $T2| -> $U, +): vector<$U> { + let mut r = vector[]; + zip_do!($v1, $v2, |el1, el2| r.push_back($f(el1, el2))); + r +} - /// Iterate through `v1` and `v2` and apply the function `f` to references of each pair of - /// elements. The returned values are collected into a new vector. - /// Aborts if the vectors are not of the same length. - /// The order of elements in the vectors is preserved. - public macro fun zip_map_ref<$T1, $T2, $U>( - $v1: &vector<$T1>, - $v2: &vector<$T2>, - $f: |&$T1, &$T2| -> $U, - ): vector<$U> { - let mut r = vector[]; - zip_do_ref!($v1, $v2, |el1, el2| r.push_back($f(el1, el2))); - r - } +/// Iterate through `v1` and `v2` and apply the function `f` to references of each pair of +/// elements. The returned values are collected into a new vector. +/// Aborts if the vectors are not of the same length. +/// The order of elements in the vectors is preserved. +public macro fun zip_map_ref<$T1, $T2, $U>( + $v1: &vector<$T1>, + $v2: &vector<$T2>, + $f: |&$T1, &$T2| -> $U, +): vector<$U> { + let mut r = vector[]; + zip_do_ref!($v1, $v2, |el1, el2| r.push_back($f(el1, el2))); + r }