From 1f24c116cad40ff6da392d6dcd158d11b0a7b1c8 Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Wed, 28 Feb 2024 19:05:25 -0800 Subject: [PATCH 01/10] Method syntax and index annotations for move-stdlib --- .../packages/move-stdlib/Move.lock | 2 +- .../packages/move-stdlib/sources/ascii.move | 21 ++++---- .../move-stdlib/sources/bit_vector.move | 26 ++++----- .../packages/move-stdlib/sources/option.move | 54 +++++++++---------- .../packages/move-stdlib/sources/string.move | 38 +++++++------ .../move-stdlib/sources/type_name.move | 34 ++++++------ .../packages/move-stdlib/sources/vector.move | 48 +++++++++-------- 7 files changed, 114 insertions(+), 109 deletions(-) diff --git a/crates/sui-framework/packages/move-stdlib/Move.lock b/crates/sui-framework/packages/move-stdlib/Move.lock index 025b3162ca365..d75b1f6eb48fa 100644 --- a/crates/sui-framework/packages/move-stdlib/Move.lock +++ b/crates/sui-framework/packages/move-stdlib/Move.lock @@ -2,7 +2,7 @@ [move] version = 1 -manifest_digest = "0890647FF1B6D1A3ACBC9C56BE2A696623321284A8A0BB2705F11FBB5697CD39" +manifest_digest = "774F1883683AAACD2512A2B6C01188350E10E5A035E065A8CF110CE44A564509" deps_digest = "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855" [move.toolchain-version] diff --git a/crates/sui-framework/packages/move-stdlib/sources/ascii.move b/crates/sui-framework/packages/move-stdlib/sources/ascii.move index 638b18c9359a7..c4eef61173cf9 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/ascii.move +++ b/crates/sui-framework/packages/move-stdlib/sources/ascii.move @@ -7,6 +7,9 @@ module std::ascii { use std::vector; use std::option::{Self, Option}; + use fun is_valid_char as u8.is_valid_char; + use fun try_string as vector.try_string; + /// An invalid ASCII character was encountered when creating an ASCII string. const EINVALID_ASCII_CHARACTER: u64 = 0x10000; @@ -26,30 +29,30 @@ module std::ascii { /// 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), EINVALID_ASCII_CHARACTER); + assert!(byte.is_valid_char(), EINVALID_ASCII_CHARACTER); 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); + let x = bytes.try_string(); assert!( option::is_some(&x), EINVALID_ASCII_CHARACTER ); - option::destroy_some(x) + 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 len = vector::length(&bytes); + let len = bytes.length(); let mut i = 0; while (i < len) { - let possible_byte = *vector::borrow(&bytes, i); - if (!is_valid_char(possible_byte)) return option::none(); + let possible_byte = *bytes.borrow(i); + if (!possible_byte.is_valid_char()) return option::none(); i = i + 1; }; option::some(String { bytes }) @@ -69,15 +72,15 @@ module std::ascii { } public fun push_char(string: &mut String, char: Char) { - vector::push_back(&mut string.bytes, char.byte); + string.bytes.push_back(char.byte); } public fun pop_char(string: &mut String): Char { - Char { byte: vector::pop_back(&mut string.bytes) } + Char { byte: string.bytes.pop_back() } } public fun length(string: &String): u64 { - vector::length(as_bytes(string)) + string.as_bytes().length() } /// Get the inner bytes of the `string` as a reference 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 69ceccf3efffa..1a56b3d317136 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/bit_vector.move +++ b/crates/sui-framework/packages/move-stdlib/sources/bit_vector.move @@ -25,7 +25,7 @@ module std::bit_vector { let mut counter = 0; let mut bit_field = vector::empty(); while (counter < length) { - vector::push_back(&mut bit_field, false); + bit_field.push_back(false); counter = counter + 1; }; @@ -37,15 +37,15 @@ module std::bit_vector { /// 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 < vector::length(&bitvector.bit_field), EINDEX); - let x = vector::borrow_mut(&mut bitvector.bit_field, bit_index); + assert!(bit_index < bitvector.bit_field.length(), EINDEX); + let x = &mut bitvector.bit_field[bit_index]; *x = true; } /// 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 < vector::length(&bitvector.bit_field), EINDEX); - let x = vector::borrow_mut(&mut bitvector.bit_field, bit_index); + assert!(bit_index < bitvector.bit_field.length(), EINDEX); + let x = &mut bitvector.bit_field[bit_index]; *x = false; } @@ -53,10 +53,10 @@ module std::bit_vector { /// bitvector's length the bitvector will be zeroed out. public fun shift_left(bitvector: &mut BitVector, amount: u64) { if (amount >= bitvector.length) { - let len = vector::length(&bitvector.bit_field); + let len = bitvector.bit_field.length(); let mut i = 0; while (i < len) { - let elem = vector::borrow_mut(&mut bitvector.bit_field, i); + let elem = &mut bitvector.bit_field[i]; *elem = false; i = i + 1; }; @@ -64,8 +64,8 @@ module std::bit_vector { let mut i = amount; while (i < bitvector.length) { - if (is_index_set(bitvector, i)) set(bitvector, i - amount) - else unset(bitvector, i - amount); + if (bitvector.is_index_set(i)) bitvector.set(i - amount) + else bitvector.unset(i - amount); i = i + 1; }; @@ -81,13 +81,13 @@ module std::bit_vector { /// 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 < vector::length(&bitvector.bit_field), EINDEX); - *vector::borrow(&bitvector.bit_field, bit_index) + 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 { - vector::length(&bitvector.bit_field) + bitvector.bit_field.length() } /// Returns the length of the longest sequence of set bits starting at (and @@ -99,7 +99,7 @@ module std::bit_vector { // Find the greatest index in the vector such that all indices less than it are set. while (index < bitvector.length) { - if (!is_index_set(bitvector, index)) break; + if (!bitvector.is_index_set(index)) break; index = index + 1; }; diff --git a/crates/sui-framework/packages/move-stdlib/sources/option.move b/crates/sui-framework/packages/move-stdlib/sources/option.move index 1b5d82f7c9df2..609f6387f327c 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/option.move +++ b/crates/sui-framework/packages/move-stdlib/sources/option.move @@ -30,33 +30,33 @@ module std::option { /// Return true if `t` does not hold a value public fun is_none(t: &Option): bool { - vector::is_empty(&t.vec) + t.vec.is_empty() } /// Return true if `t` holds a value public fun is_some(t: &Option): bool { - !vector::is_empty(&t.vec) + !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 { - vector::contains(&t.vec, e_ref) + t.vec.contains(e_ref) } /// Return an immutable reference to the value inside `t` /// Aborts if `t` does not hold a value public fun borrow(t: &Option): &Element { - assert!(is_some(t), EOPTION_NOT_SET); - vector::borrow(&t.vec, 0) + assert!(t.is_some(), EOPTION_NOT_SET); + &t.vec[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 (vector::is_empty(vec_ref)) default_ref - else vector::borrow(vec_ref, 0) + if (vec_ref.is_empty()) default_ref + else &vec_ref[0] } /// Return the value inside `t` if it holds one @@ -66,39 +66,39 @@ module std::option { default: Element, ): Element { let vec_ref = &t.vec; - if (vector::is_empty(vec_ref)) default - else *vector::borrow(vec_ref, 0) + if (vec_ref.is_empty()) default + 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 (vector::is_empty(vec_ref)) vector::push_back(vec_ref, e) + if (vec_ref.is_empty()) vec_ref.push_back(e) else abort EOPTION_IS_SET } /// 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!(is_some(t), EOPTION_NOT_SET); - vector::pop_back(&mut t.vec) + assert!(t.is_some(), EOPTION_NOT_SET); + t.vec.pop_back() } /// 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!(is_some(t), EOPTION_NOT_SET); - vector::borrow_mut(&mut t.vec, 0) + assert!(t.is_some(), EOPTION_NOT_SET); + &mut t.vec[0] } /// 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!(is_some(t), EOPTION_NOT_SET); + assert!(t.is_some(), EOPTION_NOT_SET); let vec_ref = &mut t.vec; - let old_value = vector::pop_back(vec_ref); - vector::push_back(vec_ref, e); + let old_value = vec_ref.pop_back(); + vec_ref.push_back(e); old_value } @@ -107,35 +107,35 @@ module std::option { /// 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 (vector::is_empty(vec_ref)) none() - else some(vector::pop_back(vec_ref)); - vector::push_back(vec_ref, e); + let old_value = if (vec_ref.is_empty()) none() + else some(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 (vector::is_empty(&vec)) default - else vector::pop_back(&mut vec) + if (vec.is_empty()) default + else vec.pop_back() } /// Unpack `t` and return its contents /// Aborts if `t` does not hold a value public fun destroy_some(t: Option): Element { - assert!(is_some(&t), EOPTION_NOT_SET); + assert!(t.is_some(), EOPTION_NOT_SET); let Option { mut vec } = t; - let elem = vector::pop_back(&mut vec); - vector::destroy_empty(vec); + let elem = vec.pop_back(); + vec.destroy_empty(); elem } /// Unpack `t` /// Aborts if `t` holds a value public fun destroy_none(t: Option) { - assert!(is_none(&t), EOPTION_IS_SET); + assert!(t.is_none(), EOPTION_IS_SET); let Option { vec } = t; - vector::destroy_empty(vec) + vec.destroy_empty() } /// Convert `t` into a vector of length 1 if it is `Some`, /// and an empty vector otherwise diff --git a/crates/sui-framework/packages/move-stdlib/sources/string.move b/crates/sui-framework/packages/move-stdlib/sources/string.move index 8d1b46c994bbe..9c38e1ce43816 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/string.move +++ b/crates/sui-framework/packages/move-stdlib/sources/string.move @@ -4,9 +4,13 @@ /// The `string` module defines the `String` type which represents UTF8 encoded strings. module std::string { use std::ascii; - use std::vector; use std::option::{Self, Option}; + use fun internal_check_utf8 as vector.internal_check_utf8; + use fun internal_is_char_boundary as vector.internal_is_char_boundary; + use fun internal_sub_string as vector.internal_sub_string; + use fun internal_index_of as vector.internal_index_of; + /// An invalid UTF8 encoding. const EINVALID_UTF8: u64 = 1; @@ -20,7 +24,7 @@ module std::string { /// 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), EINVALID_UTF8); + assert!(bytes.internal_check_utf8(), EINVALID_UTF8); String{bytes} } @@ -38,7 +42,7 @@ module std::string { /// Tries to create a new string from a sequence of bytes. public fun try_utf8(bytes: vector): Option { - if (internal_check_utf8(&bytes)) { + if (bytes.internal_check_utf8()) { option::some(String{bytes}) } else { option::none() @@ -52,34 +56,34 @@ module std::string { /// Checks whether this string is empty. public fun is_empty(s: &String): bool { - vector::is_empty(&s.bytes) + s.bytes.is_empty() } /// Returns the length of this string, in bytes. public fun length(s: &String): u64 { - vector::length(&s.bytes) + s.bytes.length() } /// Appends a string. public fun append(s: &mut String, r: String) { - vector::append(&mut s.bytes, r.bytes) + s.bytes.append(r.bytes) } /// Appends bytes which must be in valid utf8 format. public fun append_utf8(s: &mut String, bytes: vector) { - append(s, utf8(bytes)) + 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 <= vector::length(bytes) && internal_is_char_boundary(bytes, at), EINVALID_INDEX); - let l = length(s); - let mut front = sub_string(s, 0, at); - let end = sub_string(s, at, l); - append(&mut front, o); - append(&mut front, end); + assert!(at <= bytes.length() && bytes.internal_is_char_boundary(at), EINVALID_INDEX); + let l = s.length(); + let mut front = s.sub_string(0, at); + let end = s.sub_string(at, l); + front.append(o); + front.append(end); *s = front; } @@ -88,17 +92,17 @@ module std::string { /// guaranteeing that the result is valid utf8. public fun sub_string(s: &String, i: u64, j: u64): String { let bytes = &s.bytes; - let l = vector::length(bytes); + let l = bytes.length(); assert!( - j <= l && i <= j && internal_is_char_boundary(bytes, i) && internal_is_char_boundary(bytes, j), + j <= l && i <= j && bytes.internal_is_char_boundary(i) && bytes.internal_is_char_boundary(j), EINVALID_INDEX ); - String{bytes: internal_sub_string(bytes, i, j)} + String{bytes: bytes.internal_sub_string(i, j)} } /// Computes the index of the first occurrence of a string. Returns `length(s)` if no occurrence found. public fun index_of(s: &String, r: &String): u64 { - internal_index_of(&s.bytes, &r.bytes) + s.bytes.internal_index_of(&r.bytes) } 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 1c6b1bff0dc54..b204de5c802ee 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/type_name.move +++ b/crates/sui-framework/packages/move-stdlib/sources/type_name.move @@ -6,7 +6,6 @@ module std::type_name { use std::ascii::{Self, String}; use std::address; - use std::vector; /// ASCII Character code for the `:` (colon) symbol. const ASCII_COLON: u8 = 58; @@ -54,7 +53,7 @@ module std::type_name { /// 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 = ascii::as_bytes(&self.name); + let bytes = self.name.as_bytes(); bytes == &b"bool" || bytes == &b"u8" || bytes == &b"u16" || @@ -63,13 +62,13 @@ module std::type_name { bytes == &b"u128" || bytes == &b"u256" || bytes == &b"address" || - (vector::length(bytes) >= 6 && - *vector::borrow(bytes, 0) == ASCII_V && - *vector::borrow(bytes, 1) == ASCII_E && - *vector::borrow(bytes, 2) == ASCII_C && - *vector::borrow(bytes, 3) == ASCII_T && - *vector::borrow(bytes, 4) == ASCII_O && - *vector::borrow(bytes, 5) == ASCII_R) + (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) } @@ -81,20 +80,17 @@ module std::type_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!(!is_primitive(self), ENonModuleType); + assert!(!self.is_primitive(), ENonModuleType); // Base16 (string) representation of an address has 2 symbols per byte. let len = address::length() * 2; - let str_bytes = ascii::as_bytes(&self.name); + 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) { - vector::push_back( - &mut addr_bytes, - *vector::borrow(str_bytes, i) - ); + addr_bytes.push_back(str_bytes[i]); i = i + 1; }; @@ -104,17 +100,17 @@ module std::type_name { /// Get name of the module. /// Aborts if given a primitive type. public fun get_module(self: &TypeName): String { - assert!(!is_primitive(self), ENonModuleType); + assert!(!self.is_primitive(), ENonModuleType); // Starts after address and a double colon: `::` let mut i = address::length() * 2 + 2; - let str_bytes = ascii::as_bytes(&self.name); + let str_bytes = self.name.as_bytes(); let mut module_name = vector[]; loop { - let char = vector::borrow(str_bytes, i); + let char = &str_bytes[i]; if (char != &ASCII_COLON) { - vector::push_back(&mut module_name, *char); + module_name.push_back(*char); i = i + 1; } else { break diff --git a/crates/sui-framework/packages/move-stdlib/sources/vector.move b/crates/sui-framework/packages/move-stdlib/sources/vector.move index ae99104831d83..bff77b7981111 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/vector.move +++ b/crates/sui-framework/packages/move-stdlib/sources/vector.move @@ -17,6 +17,7 @@ module std::vector { /// Return the length of the vector. native public 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. @@ -26,6 +27,7 @@ module std::vector { /// Add element `e` to the end of the vector `v`. native public 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. @@ -49,19 +51,19 @@ module std::vector { /// Return an vector of size one containing element `e`. public fun singleton(e: Element): vector { let mut v = empty(); - push_back(&mut v, e); + 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 = length(v); + let len = v.length(); if (len == 0) return (); let mut front_index = 0; let mut back_index = len -1; while (front_index < back_index) { - swap(v, front_index, back_index); + v.swap(front_index, back_index); front_index = front_index + 1; back_index = back_index - 1; } @@ -69,23 +71,23 @@ module std::vector { /// Pushes all of the elements of the `other` vector into the `lhs` vector. public fun append(lhs: &mut vector, mut other: vector) { - reverse(&mut other); - while (!is_empty(&other)) push_back(lhs, pop_back(&mut other)); - destroy_empty(other); + 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 { - length(v) == 0 + 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 = length(v); + let len = v.length(); while (i < len) { - if (borrow(v, i) == e) return true; + if (&v[i] == e) return true; i = i + 1; }; false @@ -95,9 +97,9 @@ module std::vector { /// Otherwise, returns `(false, 0)`. public fun index_of(v: &vector, e: &Element): (bool, u64) { let mut i = 0; - let len = length(v); + let len = v.length(); while (i < len) { - if (borrow(v, i) == e) return (true, i); + if (&v[i] == e) return (true, i); i = i + 1; }; (false, 0) @@ -107,28 +109,28 @@ module std::vector { /// 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 = length(v); + let mut len = v.length(); // i out of bounds; abort if (i >= len) abort EINDEX_OUT_OF_BOUNDS; len = len - 1; - while (i < len) swap(v, i, { i = i + 1; i }); - pop_back(v) + 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 == length(v)`, this adds `e` to the end of the vector. + /// 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 > length(v)` + /// Aborts if `i > v.length()` public fun insert(v: &mut vector, e: Element, mut i: u64) { - let len = length(v); + let len = v.length(); // i too big abort if (i > len) abort EINDEX_OUT_OF_BOUNDS; - push_back(v, e); + v.push_back(e); while (i < len) { - swap(v, i, len); + v.swap(i, len); i = i + 1 } } @@ -137,9 +139,9 @@ module std::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!(!is_empty(v), EINDEX_OUT_OF_BOUNDS); - let last_idx = length(v) - 1; - swap(v, i, last_idx); - pop_back(v) + assert!(!v.is_empty(), EINDEX_OUT_OF_BOUNDS); + let last_idx = v.length() - 1; + v.swap(i, last_idx); + v.pop_back() } } From b252f05f6802b37e4d645e6b9e5dd5bc5150e724 Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Mon, 18 Mar 2024 10:51:23 -0700 Subject: [PATCH 02/10] A few missing --- .../packages/move-stdlib/sources/ascii.move | 7 ++----- .../packages/sui-framework/sources/address.move | 12 ++++++------ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/crates/sui-framework/packages/move-stdlib/sources/ascii.move b/crates/sui-framework/packages/move-stdlib/sources/ascii.move index c4eef61173cf9..362aa24e278d9 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/ascii.move +++ b/crates/sui-framework/packages/move-stdlib/sources/ascii.move @@ -37,10 +37,7 @@ module std::ascii { /// `bytes` contains non-ASCII characters. public fun string(bytes: vector): String { let x = bytes.try_string(); - assert!( - option::is_some(&x), - EINVALID_ASCII_CHARACTER - ); + assert!(x.is_some(), EINVALID_ASCII_CHARACTER); x.destroy_some() } @@ -61,7 +58,7 @@ module std::ascii { /// 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 { - let len = vector::length(&string.bytes); + let len = string.bytes.length(); let mut i = 0; while (i < len) { let byte = *vector::borrow(&string.bytes, i); diff --git a/crates/sui-framework/packages/sui-framework/sources/address.move b/crates/sui-framework/packages/sui-framework/sources/address.move index 89f9051757f82..2bcadca935dd2 100644 --- a/crates/sui-framework/packages/sui-framework/sources/address.move +++ b/crates/sui-framework/packages/sui-framework/sources/address.move @@ -42,7 +42,7 @@ module sui::address { /// Convert `a` to a hex-encoded ASCII string public fun to_string(a: address): string::String { - string::from_ascii(to_ascii_string(a)) + a.to_ascii_string().from_ascii() } /// Converts an ASCII string to an address, taking the numerical value for each character. The @@ -52,16 +52,16 @@ module sui::address { /// Aborts with `EAddressParseError` if the length of `s` is not 64, /// or if an invalid character is encountered. public fun from_ascii_bytes(bytes: &vector): address { - assert!(vector::length(bytes) == 64, EAddressParseError); + assert!(bytes.length() == 64, EAddressParseError); let mut hex_bytes = vector[]; let mut i = 0; while (i < 64) { - let hi = hex_char_value(*vector::borrow(bytes, i)); - let lo = hex_char_value(*vector::borrow(bytes, i + 1)); - vector::push_back(&mut hex_bytes, (hi << 4) | lo); + let hi = bytes[i].hex_char_value(); + let lo = bytes[i+1].hex_char_value(); + hex_bytes.push_back((hi << 4) | lo); i = i + 2; }; - from_bytes(hex_bytes) + hex_bytes.from_bytes() } fun hex_char_value(c: u8): u8 { From 1df46b177fcbba542a9dca77ec945e76c8c2e5ec Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Mon, 18 Mar 2024 10:51:59 -0700 Subject: [PATCH 03/10] Revert sui-framework change --- .../packages/sui-framework/sources/address.move | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/sui-framework/packages/sui-framework/sources/address.move b/crates/sui-framework/packages/sui-framework/sources/address.move index 2bcadca935dd2..e357c60e718b0 100644 --- a/crates/sui-framework/packages/sui-framework/sources/address.move +++ b/crates/sui-framework/packages/sui-framework/sources/address.move @@ -42,7 +42,7 @@ module sui::address { /// Convert `a` to a hex-encoded ASCII string public fun to_string(a: address): string::String { - a.to_ascii_string().from_ascii() + string::from_ascii(to_ascii_string(a)) } /// Converts an ASCII string to an address, taking the numerical value for each character. The @@ -52,16 +52,16 @@ module sui::address { /// Aborts with `EAddressParseError` if the length of `s` is not 64, /// or if an invalid character is encountered. public fun from_ascii_bytes(bytes: &vector): address { - assert!(bytes.length() == 64, EAddressParseError); - let mut hex_bytes = vector[]; - let mut i = 0; + assert!(vector::length(bytes) == 64, EAddressParseError); + let hex_bytes = vector[]; + let i = 0; while (i < 64) { - let hi = bytes[i].hex_char_value(); - let lo = bytes[i+1].hex_char_value(); - hex_bytes.push_back((hi << 4) | lo); + let hi = hex_char_value(*vector::borrow(bytes, i)); + let lo = hex_char_value(*vector::borrow(bytes, i + 1)); + vector::push_back(&mut hex_bytes, (hi << 4) | lo); i = i + 2; }; - hex_bytes.from_bytes() + from_bytes(hex_bytes) } fun hex_char_value(c: u8): u8 { From 414c87c639cf49dc0d51affdf34b37ae4ad7f042 Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Mon, 18 Mar 2024 11:32:31 -0700 Subject: [PATCH 04/10] More fixups --- crates/sui-framework/packages/move-stdlib/sources/ascii.move | 4 ++-- .../sui-framework/packages/sui-framework/sources/address.move | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/sui-framework/packages/move-stdlib/sources/ascii.move b/crates/sui-framework/packages/move-stdlib/sources/ascii.move index 362aa24e278d9..207ecde5675dd 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/ascii.move +++ b/crates/sui-framework/packages/move-stdlib/sources/ascii.move @@ -48,7 +48,7 @@ module std::ascii { let len = bytes.length(); let mut i = 0; while (i < len) { - let possible_byte = *bytes.borrow(i); + let possible_byte = bytes[i]; if (!possible_byte.is_valid_char()) return option::none(); i = i + 1; }; @@ -61,7 +61,7 @@ module std::ascii { let len = string.bytes.length(); let mut i = 0; while (i < len) { - let byte = *vector::borrow(&string.bytes, i); + let byte = string.bytes[i]; if (!is_printable_char(byte)) return false; i = i + 1; }; diff --git a/crates/sui-framework/packages/sui-framework/sources/address.move b/crates/sui-framework/packages/sui-framework/sources/address.move index e357c60e718b0..89f9051757f82 100644 --- a/crates/sui-framework/packages/sui-framework/sources/address.move +++ b/crates/sui-framework/packages/sui-framework/sources/address.move @@ -53,8 +53,8 @@ module sui::address { /// or if an invalid character is encountered. public fun from_ascii_bytes(bytes: &vector): address { assert!(vector::length(bytes) == 64, EAddressParseError); - let hex_bytes = vector[]; - let i = 0; + let mut hex_bytes = vector[]; + let mut i = 0; while (i < 64) { let hi = hex_char_value(*vector::borrow(bytes, i)); let lo = hex_char_value(*vector::borrow(bytes, i + 1)); From f45bf6f5b95b04ac94c9edfb6624305d51ed4795 Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Mon, 18 Mar 2024 14:37:03 -0700 Subject: [PATCH 05/10] string ops --- .../packages/move-stdlib/sources/vector.move | 14 ++++++++++++++ .../packages/move-stdlib/tests/vector_tests.move | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/crates/sui-framework/packages/move-stdlib/sources/vector.move b/crates/sui-framework/packages/move-stdlib/sources/vector.move index bff77b7981111..5805dfd6fcc03 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/vector.move +++ b/crates/sui-framework/packages/move-stdlib/sources/vector.move @@ -6,6 +6,20 @@ /// 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; diff --git a/crates/sui-framework/packages/move-stdlib/tests/vector_tests.move b/crates/sui-framework/packages/move-stdlib/tests/vector_tests.move index f8c8a4014124b..2e0e5a0a2cd37 100644 --- a/crates/sui-framework/packages/move-stdlib/tests/vector_tests.move +++ b/crates/sui-framework/packages/move-stdlib/tests/vector_tests.move @@ -571,4 +571,13 @@ module std::vector_tests { i = i + 1; }; } + + #[test] + fun test_string_aliases() { + assert!(b"hello_world".to_string().length() == 11, 0); + assert!(b"hello_world".try_to_string().is_some(), 1); + + assert!(b"hello_world".to_ascii_string().length() == 11, 2); + assert!(b"hello_world".try_to_ascii_string().is_some(), 3); + } } From f99d206270f545dfdbfcde84f443ee52b091b7b0 Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Mon, 18 Mar 2024 14:43:07 -0700 Subject: [PATCH 06/10] Remove non-public use funs, add public use funs for vec strings --- .../packages/move-stdlib/sources/ascii.move | 9 +++---- .../packages/move-stdlib/sources/string.move | 25 ++++++++----------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/crates/sui-framework/packages/move-stdlib/sources/ascii.move b/crates/sui-framework/packages/move-stdlib/sources/ascii.move index 207ecde5675dd..f36452b5fc0b3 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/ascii.move +++ b/crates/sui-framework/packages/move-stdlib/sources/ascii.move @@ -7,9 +7,6 @@ module std::ascii { use std::vector; use std::option::{Self, Option}; - use fun is_valid_char as u8.is_valid_char; - use fun try_string as vector.try_string; - /// An invalid ASCII character was encountered when creating an ASCII string. const EINVALID_ASCII_CHARACTER: u64 = 0x10000; @@ -29,14 +26,14 @@ module std::ascii { /// Convert a `byte` into a `Char` that is checked to make sure it is valid ASCII. public fun char(byte: u8): Char { - assert!(byte.is_valid_char(), EINVALID_ASCII_CHARACTER); + assert!(is_valid_char(byte), EINVALID_ASCII_CHARACTER); 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 = bytes.try_string(); + let x = try_string(bytes); assert!(x.is_some(), EINVALID_ASCII_CHARACTER); x.destroy_some() } @@ -49,7 +46,7 @@ module std::ascii { let mut i = 0; while (i < len) { let possible_byte = bytes[i]; - if (!possible_byte.is_valid_char()) return option::none(); + if (!is_valid_char(possible_byte)) return option::none(); i = i + 1; }; option::some(String { bytes }) diff --git a/crates/sui-framework/packages/move-stdlib/sources/string.move b/crates/sui-framework/packages/move-stdlib/sources/string.move index 9c38e1ce43816..27a02c99150c7 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/string.move +++ b/crates/sui-framework/packages/move-stdlib/sources/string.move @@ -6,11 +6,6 @@ module std::string { use std::ascii; use std::option::{Self, Option}; - use fun internal_check_utf8 as vector.internal_check_utf8; - use fun internal_is_char_boundary as vector.internal_is_char_boundary; - use fun internal_sub_string as vector.internal_sub_string; - use fun internal_index_of as vector.internal_index_of; - /// An invalid UTF8 encoding. const EINVALID_UTF8: u64 = 1; @@ -24,8 +19,8 @@ module std::string { /// 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!(bytes.internal_check_utf8(), EINVALID_UTF8); - String{bytes} + assert!(internal_check_utf8(bytes), EINVALID_UTF8); + String { bytes } } /// Convert an ASCII string to a UTF8 string @@ -42,8 +37,8 @@ module std::string { /// Tries to create a new string from a sequence of bytes. public fun try_utf8(bytes: vector): Option { - if (bytes.internal_check_utf8()) { - option::some(String{bytes}) + if (internal_check_utf8(bytes)) { + option::some(String { bytes }) } else { option::none() } @@ -71,14 +66,14 @@ module std::string { /// Appends bytes which must be in valid utf8 format. public fun append_utf8(s: &mut String, bytes: vector) { - s.append(utf8(bytes)) + s.append(bytes.utf8()) } /// 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() && bytes.internal_is_char_boundary(at), EINVALID_INDEX); + assert!(at <= bytes.length() && internal_is_char_boundary(bytes, at), EINVALID_INDEX); let l = s.length(); let mut front = s.sub_string(0, at); let end = s.sub_string(at, l); @@ -94,19 +89,19 @@ module std::string { let bytes = &s.bytes; let l = bytes.length(); assert!( - j <= l && i <= j && bytes.internal_is_char_boundary(i) && bytes.internal_is_char_boundary(j), + j <= l && i <= j && internal_is_char_boundary(bytes, i) && internal_is_char_boundary(bytes, j), EINVALID_INDEX ); - String{bytes: bytes.internal_sub_string(i, j)} + String{bytes: internal_sub_string(bytes, i, j)} } /// Computes the index of the first occurrence of a string. Returns `length(s)` if no occurrence found. public fun index_of(s: &String, r: &String): u64 { - s.bytes.internal_index_of(&r.bytes) + internal_index_of(s.bytes, &r.bytes) } - // 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; From 7246df0cc675b339ea7d61f3a2cc3de2486a5054 Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Mon, 18 Mar 2024 15:40:09 -0700 Subject: [PATCH 07/10] More public use funs plus test fixes --- .../sui-framework/packages/move-stdlib/sources/ascii.move | 4 +++- .../packages/move-stdlib/sources/string.move | 8 ++++---- .../packages/move-stdlib/tests/type_name_tests.move | 8 ++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/sui-framework/packages/move-stdlib/sources/ascii.move b/crates/sui-framework/packages/move-stdlib/sources/ascii.move index f36452b5fc0b3..d037e74b4cb0d 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/ascii.move +++ b/crates/sui-framework/packages/move-stdlib/sources/ascii.move @@ -4,9 +4,11 @@ /// 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 { - use std::vector; use std::option::{Self, Option}; + // 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 EINVALID_ASCII_CHARACTER: u64 = 0x10000; diff --git a/crates/sui-framework/packages/move-stdlib/sources/string.move b/crates/sui-framework/packages/move-stdlib/sources/string.move index 27a02c99150c7..ac6adb0e4a4db 100644 --- a/crates/sui-framework/packages/move-stdlib/sources/string.move +++ b/crates/sui-framework/packages/move-stdlib/sources/string.move @@ -19,7 +19,7 @@ module std::string { /// 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), EINVALID_UTF8); + assert!(internal_check_utf8(&bytes), EINVALID_UTF8); String { bytes } } @@ -37,7 +37,7 @@ module std::string { /// Tries to create a new string from a sequence of bytes. public fun try_utf8(bytes: vector): Option { - if (internal_check_utf8(bytes)) { + if (internal_check_utf8(&bytes)) { option::some(String { bytes }) } else { option::none() @@ -66,7 +66,7 @@ module std::string { /// Appends bytes which must be in valid utf8 format. public fun append_utf8(s: &mut String, bytes: vector) { - s.append(bytes.utf8()) + s.append(utf8(bytes)) } /// Insert the other string at the byte index in given string. The index must be at a valid utf8 char @@ -97,7 +97,7 @@ module std::string { /// Computes the index of the first occurrence of a string. Returns `length(s)` if no occurrence found. public fun index_of(s: &String, r: &String): u64 { - internal_index_of(s.bytes, &r.bytes) + internal_index_of(&s.bytes, &r.bytes) } // Native API diff --git a/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move b/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move index 8831c4fc3f1c7..912494fab983b 100644 --- a/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move +++ b/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move @@ -84,22 +84,22 @@ module 0xA::type_name_tests { assert!(get_address(&get>()) == string(b"type_name_tests"), 0); } - #[test, expected_failure = std::type_name::ENonModuleType] + #[test, expected_failure(abort_code = std::type_name::ENonModuleType)] fun test_get_address_aborts_with_primitive() { get_address(&get()); } - #[test, expected_failure = std::type_name::ENonModuleType] + #[test, expected_failure(abort_code = std::type_name::ENonModuleType)] fun test_get_module_aborts_with_primitive() { get_module(&get()); } - #[test, expected_failure = std::type_name::ENonModuleType] + #[test, expected_failure(abort_code = std::type_name::ENonModuleType)] fun test_get_address_aborts_with_primitive_generic() { get_address(&get>()); } - #[test, expected_failure = std::type_name::ENonModuleType] + #[test, expected_failure(abort_code = std::type_name::ENonModuleType)] fun test_get_module_aborts_with_primitive_generic() { get_module(&get>>()); } From 0eaa6fca6f7adf9ac4544dc39f426db0779494b4 Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Mon, 18 Mar 2024 15:43:38 -0700 Subject: [PATCH 08/10] Fixing some tests --- .../packages/move-stdlib/tests/type_name_tests.move | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move b/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move index 912494fab983b..d62e28e063137 100644 --- a/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move +++ b/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move @@ -23,9 +23,8 @@ module 0xA::type_name_tests { assert!(into_string(get()) == string(b"u32"), 0); assert!(into_string(get()) == string(b"u64"), 0); assert!(into_string(get()) == string(b"u128"), 0); - assert!(into_string(get()) == string(b"u256"), 0); + assert!(into_string(get()) == string(b"u256"), 0); assert!(into_string(get
()) == string(b"address"), 0); - assert!(into_string(get()) == string(b"signer"), 0); assert!(into_string(get>()) == string(b"vector"), 0); assert!(into_string(get>>()) == string(b"vector>"), 0); assert!(into_string(get>>()) == string(b"vector>"), 0); @@ -40,7 +39,6 @@ module 0xA::type_name_tests { assert!(is_primitive(&get()), 0); assert!(is_primitive(&get()), 0); assert!(is_primitive(&get
()), 0); - assert!(is_primitive(&get()), 0); assert!(is_primitive(&get>()), 0); assert!(is_primitive(&get>>()), 0); assert!(is_primitive(&get>>()), 0); From d6636fb5a269aaf7b6e73e2c5a62bf57802244dc Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Mon, 18 Mar 2024 15:46:01 -0700 Subject: [PATCH 09/10] Fix up stdlib tests --- .../sui-framework/packages/move-stdlib/tests/bcs_tests.move | 3 ++- .../packages/move-stdlib/tests/type_name_tests.move | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/sui-framework/packages/move-stdlib/tests/bcs_tests.move b/crates/sui-framework/packages/move-stdlib/tests/bcs_tests.move index 73d8aae546f27..04f3f1aa6762d 100644 --- a/crates/sui-framework/packages/move-stdlib/tests/bcs_tests.move +++ b/crates/sui-framework/packages/move-stdlib/tests/bcs_tests.move @@ -101,7 +101,8 @@ module std::bcs_tests { } #[test] - #[expected_failure(abort_code = 453, location = std::bcs)] + #[expected_failure] + // failes due to VM max value depth fun encode_129() { bcs::to_bytes(&Box { x: box127(true) }); } diff --git a/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move b/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move index d62e28e063137..c9215d2bf01e7 100644 --- a/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move +++ b/crates/sui-framework/packages/move-stdlib/tests/type_name_tests.move @@ -77,9 +77,9 @@ module 0xA::type_name_tests { #[test] fun test_get_module() { - assert!(get_address(&get()) == string(b"ascii"), 0); - assert!(get_address(&get()) == string(b"type_name_tests"), 0); - assert!(get_address(&get>()) == string(b"type_name_tests"), 0); + assert!(get_module(&get()) == string(b"ascii"), 0); + assert!(get_module(&get()) == string(b"type_name_tests"), 0); + assert!(get_module(&get>()) == string(b"type_name_tests"), 0); } #[test, expected_failure(abort_code = std::type_name::ENonModuleType)] From 0b720f161f71bbfb08516288dcf3f74312ae28e4 Mon Sep 17 00:00:00 2001 From: Cameron Swords Date: Wed, 20 Mar 2024 16:49:35 -0700 Subject: [PATCH 10/10] Update docs --- .../sui-framework/docs/move-stdlib/ascii.md | 21 ++++---- .../sui-framework/docs/move-stdlib/option.md | 54 +++++++++---------- .../sui-framework/docs/move-stdlib/string.md | 26 ++++----- .../docs/move-stdlib/type_name.md | 33 ++++++------ .../sui-framework/docs/move-stdlib/vector.md | 46 ++++++++-------- 5 files changed, 87 insertions(+), 93 deletions(-) diff --git a/crates/sui-framework/docs/move-stdlib/ascii.md b/crates/sui-framework/docs/move-stdlib/ascii.md index d0d3cb40eb770..f851124d6964c 100644 --- a/crates/sui-framework/docs/move-stdlib/ascii.md +++ b/crates/sui-framework/docs/move-stdlib/ascii.md @@ -149,11 +149,8 @@ Convert a vector of bytes bytes into an string(bytes: vector<u8>): String { let x = try_string(bytes); - assert!( - option::is_some(&x), - EINVALID_ASCII_CHARACTER - ); - option::destroy_some(x) + assert!(x.is_some(), EINVALID_ASCII_CHARACTER); + x.destroy_some() } @@ -180,10 +177,10 @@ characters. Otherwise returns None.
public fun try_string(bytes: vector<u8>): Option<String> {
-    let len = vector::length(&bytes);
+    let len = bytes.length();
     let mut i = 0;
     while (i < len) {
-        let possible_byte = *vector::borrow(&bytes, i);
+        let possible_byte = bytes[i];
         if (!is_valid_char(possible_byte)) return option::none();
         i = i + 1;
     };
@@ -213,10 +210,10 @@ Returns false otherwise. Not all all_characters_printable(string: &String): bool {
-    let len = vector::length(&string.bytes);
+    let len = string.bytes.length();
     let mut i = 0;
     while (i < len) {
-        let byte = *vector::borrow(&string.bytes, i);
+        let byte = string.bytes[i];
         if (!is_printable_char(byte)) return false;
         i = i + 1;
     };
@@ -244,7 +241,7 @@ Returns false otherwise. Not all push_char(string: &mut String, char: Char) {
-    vector::push_back(&mut string.bytes, char.byte);
+    string.bytes.push_back(char.byte);
 }
 
@@ -268,7 +265,7 @@ Returns false otherwise. Not all pop_char(string: &mut String): Char { - Char { byte: vector::pop_back(&mut string.bytes) } + Char { byte: string.bytes.pop_back() } } @@ -292,7 +289,7 @@ Returns false otherwise. Not all length(string: &String): u64 { - vector::length(as_bytes(string)) + string.as_bytes().length() } diff --git a/crates/sui-framework/docs/move-stdlib/option.md b/crates/sui-framework/docs/move-stdlib/option.md index ee41a47b4d4a8..3296c74970422 100644 --- a/crates/sui-framework/docs/move-stdlib/option.md +++ b/crates/sui-framework/docs/move-stdlib/option.md @@ -155,7 +155,7 @@ Return true if t does not hold a value
public fun is_none<Element>(t: &Option<Element>): bool {
-    vector::is_empty(&t.vec)
+    t.vec.is_empty()
 }
 
@@ -180,7 +180,7 @@ Return true if t holds a value
public fun is_some<Element>(t: &Option<Element>): bool {
-    !vector::is_empty(&t.vec)
+    !t.vec.is_empty()
 }
 
@@ -206,7 +206,7 @@ Always returns false if t does not hold a value
public fun contains<Element>(t: &Option<Element>, e_ref: &Element): bool {
-    vector::contains(&t.vec, e_ref)
+    t.vec.contains(e_ref)
 }
 
@@ -232,8 +232,8 @@ Aborts if t does not hold a value
public fun borrow<Element>(t: &Option<Element>): &Element {
-    assert!(is_some(t), EOPTION_NOT_SET);
-    vector::borrow(&t.vec, 0)
+    assert!(t.is_some(), EOPTION_NOT_SET);
+    &t.vec[0]
 }
 
@@ -260,8 +260,8 @@ Return default_ref if t does not hold a value
public fun borrow_with_default<Element>(t: &Option<Element>, default_ref: &Element): &Element {
     let vec_ref = &t.vec;
-    if (vector::is_empty(vec_ref)) default_ref
-    else vector::borrow(vec_ref, 0)
+    if (vec_ref.is_empty()) default_ref
+    else &vec_ref[0]
 }
 
@@ -291,8 +291,8 @@ Return default if t does not hold a value default: Element, ): Element { let vec_ref = &t.vec; - if (vector::is_empty(vec_ref)) default - else *vector::borrow(vec_ref, 0) + if (vec_ref.is_empty()) default + else vec_ref[0] }
@@ -319,7 +319,7 @@ Aborts if t already holds a value
public fun fill<Element>(t: &mut Option<Element>, e: Element) {
     let vec_ref = &mut t.vec;
-    if (vector::is_empty(vec_ref)) vector::push_back(vec_ref, e)
+    if (vec_ref.is_empty()) vec_ref.push_back(e)
     else abort EOPTION_IS_SET
 }
 
@@ -346,8 +346,8 @@ Aborts if t does not hold a value
public fun extract<Element>(t: &mut Option<Element>): Element {
-    assert!(is_some(t), EOPTION_NOT_SET);
-    vector::pop_back(&mut t.vec)
+    assert!(t.is_some(), EOPTION_NOT_SET);
+    t.vec.pop_back()
 }
 
@@ -373,8 +373,8 @@ Aborts if t does not hold a value
public fun borrow_mut<Element>(t: &mut Option<Element>): &mut Element {
-    assert!(is_some(t), EOPTION_NOT_SET);
-    vector::borrow_mut(&mut t.vec, 0)
+    assert!(t.is_some(), EOPTION_NOT_SET);
+    &mut t.vec[0]
 }
 
@@ -400,10 +400,10 @@ Aborts if t does not hold a value
public fun swap<Element>(t: &mut Option<Element>, e: Element): Element {
-    assert!(is_some(t), EOPTION_NOT_SET);
+    assert!(t.is_some(), EOPTION_NOT_SET);
     let vec_ref = &mut t.vec;
-    let old_value = vector::pop_back(vec_ref);
-    vector::push_back(vec_ref, e);
+    let old_value = vec_ref.pop_back();
+    vec_ref.push_back(e);
     old_value
 }
 
@@ -432,9 +432,9 @@ 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 (vector::is_empty(vec_ref)) none()
-        else some(vector::pop_back(vec_ref));
-    vector::push_back(vec_ref, e);
+    let old_value = if (vec_ref.is_empty()) none()
+        else some(vec_ref.pop_back());
+    vec_ref.push_back(e);
     old_value
 }
 
@@ -461,8 +461,8 @@ Destroys t. If t holds a value, return it. Returns public fun destroy_with_default<Element: drop>(t: Option<Element>, default: Element): Element { let Option { mut vec } = t; - if (vector::is_empty(&vec)) default - else vector::pop_back(&mut vec) + if (vec.is_empty()) default + else vec.pop_back() } @@ -488,10 +488,10 @@ Aborts if t does not hold a value
public fun destroy_some<Element>(t: Option<Element>): Element {
-    assert!(is_some(&t), EOPTION_NOT_SET);
+    assert!(t.is_some(), EOPTION_NOT_SET);
     let Option { mut vec } = t;
-    let elem = vector::pop_back(&mut vec);
-    vector::destroy_empty(vec);
+    let elem = vec.pop_back();
+    vec.destroy_empty();
     elem
 }
 
@@ -518,9 +518,9 @@ Aborts if t holds a value
public fun destroy_none<Element>(t: Option<Element>) {
-    assert!(is_none(&t), EOPTION_IS_SET);
+    assert!(t.is_none(), EOPTION_IS_SET);
     let Option { vec } = t;
-    vector::destroy_empty(vec)
+    vec.destroy_empty()
 }
 
diff --git a/crates/sui-framework/docs/move-stdlib/string.md b/crates/sui-framework/docs/move-stdlib/string.md index 652596b47c4b3..fb3d567e15d6d 100644 --- a/crates/sui-framework/docs/move-stdlib/string.md +++ b/crates/sui-framework/docs/move-stdlib/string.md @@ -104,7 +104,7 @@ Creates a new string from a sequence of bytes. Aborts if the bytes do not repres
public fun utf8(bytes: vector<u8>): String {
     assert!(internal_check_utf8(&bytes), EINVALID_UTF8);
-    String{bytes}
+    String { bytes }
 }
 
@@ -182,7 +182,7 @@ Tries to create a new string from a sequence of bytes.
public fun try_utf8(bytes: vector<u8>): Option<String> {
     if (internal_check_utf8(&bytes)) {
-        option::some(String{bytes})
+        option::some(String { bytes })
     } else {
         option::none()
     }
@@ -235,7 +235,7 @@ Checks whether this string is empty.
 
 
 
public fun is_empty(s: &String): bool {
-    vector::is_empty(&s.bytes)
+    s.bytes.is_empty()
 }
 
@@ -260,7 +260,7 @@ Returns the length of this string, in bytes.
public fun length(s: &String): u64 {
-    vector::length(&s.bytes)
+    s.bytes.length()
 }
 
@@ -285,7 +285,7 @@ Appends a string.
public fun append(s: &mut String, r: String) {
-    vector::append(&mut s.bytes, r.bytes)
+    s.bytes.append(r.bytes)
 }
 
@@ -310,7 +310,7 @@ Appends bytes which must be in valid utf8 format.
public fun append_utf8(s: &mut String, bytes: vector<u8>) {
-    append(s, utf8(bytes))
+    s.append(utf8(bytes))
 }
 
@@ -337,12 +337,12 @@ boundary.
public fun insert(s: &mut String, at: u64, o: String) {
     let bytes = &s.bytes;
-    assert!(at <= vector::length(bytes) && internal_is_char_boundary(bytes, at), EINVALID_INDEX);
-    let l = length(s);
-    let mut front = sub_string(s, 0, at);
-    let end = sub_string(s, at, l);
-    append(&mut front, o);
-    append(&mut front, end);
+    assert!(at <= bytes.length() && internal_is_char_boundary(bytes, at), EINVALID_INDEX);
+    let l = s.length();
+    let mut front = s.sub_string(0, at);
+    let end = s.sub_string(at, l);
+    front.append(o);
+    front.append(end);
     *s = front;
 }
 
@@ -371,7 +371,7 @@ guaranteeing that the result is valid utf8.
public fun sub_string(s: &String, i: u64, j: u64): String {
     let bytes = &s.bytes;
-    let l = vector::length(bytes);
+    let l = bytes.length();
     assert!(
         j <= l && i <= j && internal_is_char_boundary(bytes, i) && internal_is_char_boundary(bytes, j),
         EINVALID_INDEX
diff --git a/crates/sui-framework/docs/move-stdlib/type_name.md b/crates/sui-framework/docs/move-stdlib/type_name.md
index 307345d62aa4e..941007233799f 100644
--- a/crates/sui-framework/docs/move-stdlib/type_name.md
+++ b/crates/sui-framework/docs/move-stdlib/type_name.md
@@ -212,7 +212,7 @@ u8, u16, u32, u64, u128, u256, bool, address, vector.
 
 
 
public fun is_primitive(self: &TypeName): bool {
-    let bytes = ascii::as_bytes(&self.name);
+    let bytes = self.name.as_bytes();
     bytes == &b"bool" ||
     bytes == &b"u8" ||
     bytes == &b"u16" ||
@@ -221,13 +221,13 @@ u8, u16, u32, u64, u128, u256, bool, address, vector.
     bytes == &b"u128" ||
     bytes == &b"u256" ||
     bytes == &b"address" ||
-    (vector::length(bytes) >= 6 &&
-    *vector::borrow(bytes, 0) == ASCII_V &&
-    *vector::borrow(bytes, 1) == ASCII_E &&
-    *vector::borrow(bytes, 2) == ASCII_C &&
-    *vector::borrow(bytes, 3) == ASCII_T &&
-    *vector::borrow(bytes, 4) == ASCII_O &&
-    *vector::borrow(bytes, 5) == ASCII_R)
+    (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)
 
 }
 
@@ -279,20 +279,17 @@ Aborts if given a primitive type.
public fun get_address(self: &TypeName): String {
-    assert!(!is_primitive(self), ENonModuleType);
+    assert!(!self.is_primitive(), ENonModuleType);
 
     // Base16 (string) representation of an address has 2 symbols per byte.
     let len = address::length() * 2;
-    let str_bytes = ascii::as_bytes(&self.name);
+    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) {
-        vector::push_back(
-            &mut addr_bytes,
-            *vector::borrow(str_bytes, i)
-        );
+        addr_bytes.push_back(str_bytes[i]);
         i = i + 1;
     };
 
@@ -322,17 +319,17 @@ Aborts if given a primitive type.
 
 
 
public fun get_module(self: &TypeName): String {
-    assert!(!is_primitive(self), ENonModuleType);
+    assert!(!self.is_primitive(), ENonModuleType);
 
     // Starts after address and a double colon: `<addr as HEX>::`
     let mut i = address::length() * 2 + 2;
-    let str_bytes = ascii::as_bytes(&self.name);
+    let str_bytes = self.name.as_bytes();
     let mut module_name = vector[];
 
     loop {
-        let char = vector::borrow(str_bytes, i);
+        let char = &str_bytes[i];
         if (char != &ASCII_COLON) {
-            vector::push_back(&mut module_name, *char);
+            module_name.push_back(*char);
             i = i + 1;
         } else {
             break
diff --git a/crates/sui-framework/docs/move-stdlib/vector.md b/crates/sui-framework/docs/move-stdlib/vector.md
index 1a356fc5215c3..3efefe10e6016 100644
--- a/crates/sui-framework/docs/move-stdlib/vector.md
+++ b/crates/sui-framework/docs/move-stdlib/vector.md
@@ -253,7 +253,7 @@ Return an vector of size one containing element e.
 
 
public fun singleton<Element>(e: Element): vector<Element> {
     let mut v = empty();
-    push_back(&mut v, e);
+    v.push_back(e);
     v
 }
 
@@ -279,13 +279,13 @@ Reverses the order of the elements in the vector v in place.
public fun reverse<Element>(v: &mut vector<Element>) {
-    let len = length(v);
+    let len = v.length();
     if (len == 0) return ();
 
     let mut front_index = 0;
     let mut back_index = len -1;
     while (front_index < back_index) {
-        swap(v, front_index, back_index);
+        v.swap(front_index, back_index);
         front_index = front_index + 1;
         back_index = back_index - 1;
     }
@@ -313,9 +313,9 @@ Pushes all of the elements of the other vector into the lhspublic fun append<Element>(lhs: &mut vector<Element>, mut other: vector<Element>) {
-    reverse(&mut other);
-    while (!is_empty(&other)) push_back(lhs, pop_back(&mut other));
-    destroy_empty(other);
+    other.reverse();
+    while (!other.is_empty()) lhs.push_back(other.pop_back());
+    other.destroy_empty();
 }
 
@@ -340,7 +340,7 @@ Return true if the vector v has no elements and
public fun is_empty<Element>(v: &vector<Element>): bool {
-    length(v) == 0
+    v.length() == 0
 }
 
@@ -367,9 +367,9 @@ Otherwise, returns false.
public fun contains<Element>(v: &vector<Element>, e: &Element): bool {
     let mut i = 0;
-    let len = length(v);
+    let len = v.length();
     while (i < len) {
-        if (borrow(v, i) == e) return true;
+        if (&v[i] == e) return true;
         i = i + 1;
     };
     false
@@ -399,9 +399,9 @@ Otherwise, returns (false, 0).
 
 
public fun index_of<Element>(v: &vector<Element>, e: &Element): (bool, u64) {
     let mut i = 0;
-    let len = length(v);
+    let len = v.length();
     while (i < len) {
-        if (borrow(v, i) == e) return (true, i);
+        if (&v[i] == e) return (true, i);
         i = i + 1;
     };
     (false, 0)
@@ -431,13 +431,13 @@ Aborts if i is out of bounds.
 
 
 
public fun remove<Element>(v: &mut vector<Element>, mut i: u64): Element {
-    let mut len = length(v);
+    let mut len = v.length();
     // i out of bounds; abort
     if (i >= len) abort EINDEX_OUT_OF_BOUNDS;
 
     len = len - 1;
-    while (i < len) swap(v, i, { i = i + 1; i });
-    pop_back(v)
+    while (i < len) v.swap(i, { i = i + 1; i });
+    v.pop_back()
 }
 
@@ -451,9 +451,9 @@ Aborts if i is out of bounds. 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 == length(v), this adds e to the end of the vector. +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 > length(v) +Aborts if i > v.length()
public fun insert<Element>(v: &mut vector<Element>, e: Element, i: u64)
@@ -466,13 +466,13 @@ Aborts if i > leng
 
 
 
public fun insert<Element>(v: &mut vector<Element>, e: Element, mut i: u64) {
-    let len = length(v);
+    let len = v.length();
     // i too big abort
     if (i > len) abort EINDEX_OUT_OF_BOUNDS;
 
-    push_back(v, e);
+    v.push_back(e);
     while (i < len) {
-        swap(v, i, len);
+        v.swap(i, len);
         i = i + 1
     }
 }
@@ -501,10 +501,10 @@ Aborts if i is out of bounds.
 
 
 
public fun swap_remove<Element>(v: &mut vector<Element>, i: u64): Element {
-    assert!(!is_empty(v), EINDEX_OUT_OF_BOUNDS);
-    let last_idx = length(v) - 1;
-    swap(v, i, last_idx);
-    pop_back(v)
+    assert!(!v.is_empty(), EINDEX_OUT_OF_BOUNDS);
+    let last_idx = v.length() - 1;
+    v.swap(i, last_idx);
+    v.pop_back()
 }