//! A UTF-8 encoded growable string.
library;
use ::assert::assert_eq;
use ::bytes::*;
use ::convert::*;
use ::hash::{Hash, Hasher};
use ::option::Option;
use ::codec::*;
use ::debug::*;
use ::ops::*;
use ::raw_slice::AsRawSlice;
use ::clone::Clone;
/// A UTF-8 encoded growable string, that has ownership of its buffer.
///
/// # Additional Information
///
/// WARNING: As this type is meant to be forward compatible with UTF-8, do *not*
/// add any mutation functionality or unicode input of any kind until `char` is
/// implemented. Currently, codepoints are *not* guaranteed to fall on byte boundaries.
pub struct String {
/// The bytes representing the characters of the string.
bytes: Bytes,
}
impl String {
/// Returns `Bytes` giving a UTF-8 representation of the string.
///
/// # Additional Information
///
/// The returned `Bytes` contains a copy of the underlying string bytes.
/// To get string bytes without creating a copy of the underlying bytes,
/// use `String::as_raw_slice`.
///
/// # Returns
///
/// * [Bytes] - A UTF-8 representation of the string.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let string = String::from_ascii_str("Fuel");
/// let bytes = string.as_bytes();
/// assert_eq(bytes.len(), 4);
/// assert_eq(bytes.get(0).unwrap(), 70u8); // "F"
/// assert(bytes.ptr() != string.ptr()); // A copy is returned.
/// }
/// ```
pub fn as_bytes(self) -> Bytes {
self.bytes.clone()
}
/// Gets the amount of memory on the heap allocated to the `String`.
///
/// # Returns
///
/// * `u64` - The number of characters the `String` can hold without reallocating.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let string = String::new();
/// assert_eq(string.capacity(), 0);
/// let mut string = String::from_ascii_str("Fuel");
/// assert_eq(string.capacity(), 4);
/// string.clear();
/// assert_eq(string.capacity(), 4); // Clearing does not change the capacity.
/// }
/// ```
pub fn capacity(self) -> u64 {
self.bytes.capacity()
}
/// Truncates this `String` to a length of zero, clearing all content.
///
/// Note that this method has no effect on the allocated capacity
/// of the `String`.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let mut string = String::from_ascii_str("Fuel");
/// assert(!string.is_empty());
/// assert_eq(string.capacity(), 4);
/// string.clear();
/// assert(string.is_empty());
/// assert_eq(string.capacity(), 4); // Clearing does not change the capacity.
/// }
/// ```
pub fn clear(ref mut self) {
self.bytes.clear()
}
/// Converts a vector of ASCII encoded bytes to a `String`.
///
/// # Additional Information
///
/// Each byte represents a single character, this supports ASCII but it does **not** support Unicode.
///
/// The content of `bytes` gets copied into the newly created `String`.
/// To take the ownership of the `bytes` and move them into the newly
/// created `String` without copying the content, use `String::from_moved_ascii`.
///
/// # Arguments
///
/// * `bytes` - ASCII bytes which will be converted into a `String`.
///
/// # Returns
///
/// * [String] - A `String` containing the ASCII encoded bytes.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let mut bytes = Bytes::new();
/// bytes.push(70u8); // "F"
/// bytes.push(117u8); // "u"
/// bytes.push(101u8); // "e"
/// bytes.push(108u8); // "l"
/// let string = String::from_ascii(bytes);
/// assert_eq(string.len(), 4);
/// }
/// ```
pub fn from_ascii(bytes: Bytes) -> Self {
Self {
bytes: bytes.clone(),
}
}
/// Converts a vector of ASCII encoded bytes to a `String`, taking the
/// ownership of the `bytes`.
///
/// # Additional Information
///
/// Each byte represents a single character, this supports ASCII but it does **not** support Unicode.
///
/// `bytes` **must not be used after the ownership is transferred to the
/// newly created `String`**. Violating this restriction results in an undefined behavior.
///
/// To convert the `bytes` to a `String` by copying its content, and without
/// taking the ownership, use `String::from_ascii`.
///
/// # Arguments
///
/// * `bytes` - ASCII bytes which will be moved into a `String`.
///
/// # Returns
///
/// * [String] - A `String` containing the ASCII encoded bytes.
///
/// # Examples
///
/// ```sway
/// use std::{bytes::Bytes, string::String};
///
/// fn foo() {
/// let mut bytes = Bytes::new();
/// bytes.push(70u8); // "F"
/// bytes.push(117u8); // "u"
/// bytes.push(101u8); // "e"
/// bytes.push(108u8); // "l"
/// let string = String::from_moved_ascii(bytes);
///
/// // ** `bytes` must not be used after this point. **
///
/// assert_eq(string.len(), 4);
/// }
/// ```
pub fn from_moved_ascii(bytes: Bytes) -> Self {
Self { bytes }
}
/// Converts a string slice containing ASCII encoded bytes to a `String`.
///
/// # Arguments
///
/// * `s` - A string slice containing ASCII encoded bytes.
///
/// # Returns
///
/// * [String] - A `String` containing the ASCII encoded bytes.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let string = String::from_ascii_str("ABCDEF");
/// assert_eq(string.len(), 6);
/// }
/// ```
pub fn from_ascii_str(s: str) -> Self {
Self {
bytes: Bytes::from(__transmute::<str, raw_slice>(s)),
}
}
/// Converts a string array containing ASCII encoded bytes to a `String`.
///
/// # Arguments
///
/// * `s` - A string array containing ASCII encoded bytes.
///
/// # Returns
///
/// * [String] - A `String` containing the ASCII encoded bytes.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let string = String::from_ascii_str_array(__to_str_array("ABCDEF"));
/// assert_eq(string.len(), 6);
/// }
/// ```
pub fn from_ascii_str_array<const N: u64>(s: str[N]) -> Self {
Self {
bytes: Bytes::from(__transmute::<(raw_ptr, u64), raw_slice>((__addr_of(s), N))),
}
}
/// Constructs a new `String` that takes the ownership of the `slice`.
///
/// # Additional Information
///
/// `slice` **must point to a heap-allocated memory** and, together with its
/// owner, **must not be used after the ownership is transferred to the newly
/// created `String`**. Violating these restrictions results in an undefined behavior.
///
/// To create a new `String` from a `raw_slice` that copies the slice content
/// and does not take the ownership, use `String::from(raw_slice)`.
///
/// # Arguments
///
/// * `slice`: [raw_slice] - The heap-allocated slice whose ownership is transferred to the `String`.
///
/// # Returns
///
/// * [String] - A new `String` whose content is the original content of the `slice`.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let source = String::from_ascii_str("Fuel");
/// let string = String::from_moved_raw_slice(source.as_raw_slice());
///
/// // ** `source` must not be used after this point. **
///
/// assert_eq(string.len(), 4);
/// }
/// ```
pub fn from_moved_raw_slice(slice: raw_slice) -> Self {
Self {
bytes: Bytes::from_moved_raw_slice(slice),
}
}
/// Returns a `bool` indicating whether the `String` is empty.
///
/// # Returns
///
/// * [bool] - `true` if the `String` is empty, `false` otherwise.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let mut string = String::from_ascii_str("Fuel");
/// assert(!string.is_empty());
/// string.clear();
/// assert(string.is_empty());
///
/// assert(String::new().is_empty());
/// }
/// ```
pub fn is_empty(self) -> bool {
self.bytes.is_empty()
}
/// Constructs a new empty instance of the `String` type.
///
/// # Returns
///
/// * [String] - A new empty instance of the `String` type.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let string = String::new();
/// assert(string.is_empty());
/// }
/// ```
pub fn new() -> Self {
Self {
bytes: Bytes::new(),
}
}
/// Constructs a new instance of the `String` type with the specified `capacity`.
///
/// # Arguments
///
/// * `capacity`: [u64] - The specified amount of bytes on the heap to be allocated for the `String`.
///
/// # Returns
///
/// * [String] - A new empty instance of the `String` type with the specified `capacity`.
///
/// # Examples
///
/// ```sway
/// use std::string::String;
///
/// fn foo() {
/// let string = String::with_capacity(1);
/// assert_eq(string.capacity(), 1);
/// }
/// ```
pub fn with_capacity(capacity: u64) -> Self {
Self {
bytes: Bytes::with_capacity(capacity),
}
}
/// Gets the pointer of the allocation.
///
/// # Returns
///
/// [raw_ptr] - The location in memory that the allocated string lives.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let string = String::new();
/// assert(!string.ptr().is_null());
/// }
/// ```
pub fn ptr(self) -> raw_ptr {
self.bytes.ptr()
}
/// Gets the length of the `String` in bytes, not chars or graphemes.
/// In other words, it might not be what a human considers the length of the string.
///
/// # Returns
///
/// * [u64] - The length of the `String` in bytes, not chars or graphemes.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let string = String::from_ascii_str("Fuel");
/// assert_eq(string.len(), 4);
/// }
/// ```
pub fn len(self) -> u64 {
self.bytes.len()
}
/// Converts the `String` into a string slice.
///
/// # Returns
///
/// [str] - The `String` as a string slice.
///
/// # Examples
///
/// ```sway
/// fn foo() {
/// let string = String::from_ascii_str("Fuel");
/// assert(string.as_str() == "Fuel");
/// }
/// ```
pub fn as_str(self) -> str {
let ptr = self.bytes.ptr();
let str_size = self.bytes.len();
__transmute::<(raw_ptr, u64), str>((ptr, str_size))
}
}
impl From<Bytes> for String {
fn from(b: Bytes) -> Self {
Self {
bytes: b.clone(),
}
}
}
impl From<String> for Bytes {
fn from(s: String) -> Bytes {
s.as_bytes()
}
}
impl From<str> for String {
fn from(s: str) -> String {
String::from_ascii_str(s)
}
}
impl From<String> for str {
fn from(s: String) -> str {
s.as_str()
}
}
impl AsRawSlice for String {
/// Returns a raw slice to all of the elements in the string.
fn as_raw_slice(self) -> raw_slice {
self.bytes.as_raw_slice()
}
}
impl From<raw_slice> for String {
/// Converts a `raw_slice` to a `String`.
///
/// # Additional Information
///
/// The content of the `slice` gets copied into the newly created `String`
/// which allocates its own buffer.
///
/// To take the ownership of the `slice` and move it into the newly created
/// `String` without copying the content, use `String::from_moved_raw_slice`.
///
/// # Arguments
///
/// * `slice`: [raw_slice] - The `raw_slice` to convert to a `String`.
///
/// # Returns
///
/// * [String] - The newly created `String`.
///
/// # Examples
///
/// ```sway
/// use std::{alloc::alloc, string::*};
///
/// fn foo() {
/// let ptr = alloc::<u64>(1);
/// let slice = raw_slice::from_parts::<u64>(ptr, 1);
/// let string: String = String::from(slice);
/// }
/// ```
fn from(slice: raw_slice) -> Self {
Self {
bytes: Bytes::from(slice),
}
}
}
impl From<String> for raw_slice {
/// Converts a `String` to a `raw_slice`.
///
/// # Additional Information
///
/// **NOTE:** To import, use the glob operator i.e. `use std::string::*;`
///
/// # Arguments
///
/// * `s`: [String] - The `String` to convert to a `raw_slice`.
///
/// # Returns
///
/// * [raw_slice] - The newly created `raw_slice`.
///
/// # Examples
///
/// ```sway
/// use std::string::*;
///
/// fn foo() {
/// let string = String::from_ascii_str("Fuel");
/// let string_slice: raw_slice = string.into();
/// }
/// ```
fn from(s: String) -> raw_slice {
s.bytes.as_raw_slice()
}
}
impl PartialEq for String {
fn eq(self, other: Self) -> bool {
self.bytes == other.as_bytes()
}
}
impl Eq for String {}
impl Hash for String {
fn is_hash_trivial() -> bool {
false
}
fn hash(self, ref mut state: Hasher) {
self.bytes.hash(state);
}
}
impl AbiEncode for String {
fn is_encode_trivial() -> bool {
false
}
fn abi_encode(self, buffer: Buffer) -> Buffer {
self.bytes.abi_encode(buffer)
}
}
impl AbiDecode for String {
fn is_decode_trivial() -> bool {
false
}
fn abi_decode(ref mut buffer: BufferReader) -> Self {
String {
bytes: Bytes::abi_decode(buffer),
}
}
}
impl Clone for String {
fn clone(self) -> Self {
Self {
bytes: self.bytes.clone(),
}
}
}
impl Debug for String {
fn fmt(self, ref mut f: Formatter) {
let s = __transmute::<(raw_ptr, u64), str>((self.bytes.ptr(), self.bytes.len()));
f.print_string_quotes();
f.print_str(s);
f.print_string_quotes();
}
}