Search results

There are no results.

std.string.String

Atomic
type pub builtin String

An UTF-8 encoded and immutable string type.

Static methods

from_pointer

Show source code
Hide source code
fn pub static from_pointer(pointer: Pointer[UInt8]) -> String {
  if pointer as Int == 0 { return '' }

  from_primitive(inko_string_from_pointer(pointer))
}
fn pub static from_pointer(pointer: Pointer[UInt8]) -> String

Returns a String created from the given NULL terminated pointer.

If pointer is NULL, an empty String is returned.

Safety

The purpose of this method is to allow creating a String from a pointer returned by C code. Do not use this method unless you have somehow verified that the pointer is a valid NULL terminated C string.

If the pointer points to invalid memory or isn't NULL terminated, the behavior is undefined and likely results in a crash.

Examples

String.from_pointer("hello".pointer) == "hello" # => true

join

Show source code
Hide source code
fn pub static join[T: ToString, I: Iter[T]](
  iter: move I,
  with: String,
) -> String {
  let buf = StringBuffer.new

  for (idx, val) in iter.with_index {
    if idx > 0 { buf.push(with) }

    buf.push(val.to_string)
  }

  buf.into_string
}
fn pub static join[T: ToString, I: Iter[T]](iter: move I, with: String) -> String

Return a String that contains the values of the iterator, separated by the value of the with argument.

Examples

let vals = [10, 20, 30].into_iter

String.join(vals, with: ',') => '10,20,30'

try_from_bytes

Show source code
Hide source code
fn pub static try_from_bytes[B: Bytes](bytes: ref B) -> Option[String] {
  let len = bytes.size

  if len == 0 { return Option.Some('') }

  let prim = inko_string_try_from_bytes(bytes.pointer, len)

  if prim.size > -1 {
    Option.Some(from_borrowed_primitive(prim))
  } else {
    Option.None
  }
}
fn pub static try_from_bytes[B: Bytes](bytes: ref B) -> Option[String]

Returns a new String created from the given Bytes.

If the bytes contain invalid UTF-8 sequences, an Option.None is returned.

Examples

String.try_from_bytes('abc'.to_byte_array)         # => Option.Some('abc')
String.try_from_bytes(ByteArray.from_array([255])) # => Option.None

Instance methods

!=

Show source code
Hide source code
fn pub !=(other: ref Self) -> Bool {
  !(self == other)
}
fn pub !=(other: ref Self) -> Bool

Returns true if self and the given object are not equal to each other.

+

Show source code
Hide source code
fn pub inline +(other: String) -> String {
  let tot = size + other.size
  let new = alloc.allocate(tot + 1)

  alloc.copy(from: pointer, to: new, size: size)
  alloc.copy(from: other.pointer, to: ptr.add(new, size), size: other.size)
  alloc.write(byte: 0, to: ptr.add(new, tot), size: 1)
  String(size: tot, ptr: new)
}
fn pub inline +(other: String) -> String

Concatenates self and the given String, returning a new String.

Examples

'hello ' + 'world' # => 'hello world'

<

Show source code
Hide source code
fn pub <(other: ref Self) -> Bool {
  match cmp(other) {
    case Less -> true
    case _ -> false
  }
}
fn pub <(other: ref Self) -> Bool

Returns true if self is lower than the given argument.

<=

Show source code
Hide source code
fn pub <=(other: ref Self) -> Bool {
  match cmp(other) {
    case Less or Equal -> true
    case _ -> false
  }
}
fn pub <=(other: ref Self) -> Bool

Returns true if self is lower than or equal to the given argument.

==

Show source code
Hide source code
fn pub ==(other: String) -> Bool {
  let lsize = self.size

  if lsize == other.size { ptr.equal(@ptr, other.ptr, lsize) } else { false }
}
fn pub ==(other: String) -> Bool

Returns true if the current String and other are equal to each other.

Examples

Returns true if two Strings are equal:

'foo' == 'foo' # => true

Returns false if two Strings are not equal:

'foo' == 'bar' # => false

>

Show source code
Hide source code
fn pub >(other: ref Self) -> Bool {
  match cmp(other) {
    case Greater -> true
    case _ -> false
  }
}
fn pub >(other: ref Self) -> Bool

Returns true if self is greater than the given argument.

>=

Show source code
Hide source code
fn pub >=(other: ref Self) -> Bool {
  match cmp(other) {
    case Greater or Equal -> true
    case _ -> false
  }
}
fn pub >=(other: ref Self) -> Bool

Returns true if self is equal to or greater than the given argument.

bytes

Show source code
Hide source code
fn pub bytes -> Iter[ref Self] {
  Iter(source: self, index: 0)
}
fn pub bytes -> Iter[ref Self]

Returns an iterator over the bytes in self.

Examples

let bytes = ByteArray.from_array([10, 20, 30])
let iter = bytes.bytes

iter.next # => Option.Some(10)

chars

Show source code
Hide source code
fn pub inline chars -> Chars {
  Chars(string: self, iter: inko_string_chars(to_primitive))
}
fn pub inline chars -> Chars

Returns an iterator over the characters (= extended grapheme clusters) in self.

Examples

'๐Ÿ˜€๐Ÿ˜ƒ'.chars.to_array # => ['๐Ÿ˜€', '๐Ÿ˜ƒ']

clone

Show source code
Hide source code
fn pub inline clone -> String {
  self
}
fn pub inline clone -> String

Creates a clone of self.

The returned value is an owned value that is the same type as the receiver of this method. For example, cloning a ref Array[Int] results in a Array[Int], not another ref Array[Int].

cmp

Show source code
Hide source code
fn pub cmp(other: String) -> Ordering {
  let mut max = min(size, other.size)
  let mut idx = 0

  while idx < max {
    match byte_unchecked(idx).cmp(other.byte_unchecked(idx)) {
      case Equal -> idx += 1
      case ord -> return ord
    }
  }

  size.cmp(other.size)
}
fn pub cmp(other: String) -> Ordering

Performs a byte-wise comparison of self with other.

This method does not perform lexicographic sorting, and thus produces unreliable results for multi-byte strings.

Examples

'aaa'.cmp('bbb') # => Ordering.Less 'aab'.cmp('aaa') # => Ordering.Greater

contains?

Show source code
Hide source code
fn pub contains?(value: String) -> Bool {
  contains_bytes?(value)
}
fn pub contains?(value: String) -> Bool

Returns true if self contains the given String.

If you instead want to use a ByteArray or Slice as the argument, use String.contains_bytes? instead.

Examples

'hello world'.contains?('hello') # => true

contains_bytes?

Show source code
Hide source code
fn pub contains_bytes?[B: Bytes](bytes: ref B) -> Bool {
  index_of(bytes, starting_at: 0).some?
}
fn pub contains_bytes?[B: Bytes](bytes: ref B) -> Bool

Returns true if self contains the given byte sequence.

Examples

'hello'.contains_bytes?('hello') # => true

empty?

Show source code
Hide source code
fn pub empty? -> Bool {
  size == 0
}
fn pub empty? -> Bool

Returns true if self is empty.

Examples

''.empty? # => true
'hello'.empty? # => false

ends_with?

Show source code
Hide source code
fn pub ends_with?[T: Bytes](suffix: ref T) -> Bool {
  ptr.ends_with?(pointer, size, suffix.pointer, suffix.size)
}
fn pub ends_with?[T: Bytes](suffix: ref T) -> Bool

Returns true if self ends with the given sequence of bytes.

Examples

'hello'.ends_with?('o'.to_byte_array) # => true
'hello'.ends_with?('o')               # => true

equals?

Show source code
Hide source code
fn pub equals?[O: Bytes](other: ref O) -> Bool {
  let len = size

  len == other.size and (len == 0 or ptr.equal(pointer, other.pointer, len))
}
fn pub equals?[O: Bytes](other: ref O) -> Bool

Returns true if self and other contain identical bytes.

This allows comparing of any Bytes type with any other Bytes type (e.g. comparing a String to a ByteArray). In contrast, methods such as String.== only support comparing against values of the same type.

Examples

'hello'.equals?('hello')               # => true
'hello'.equals?('hello'.to_byte_array) # => true

equals_while_ignoring_case?

Show source code
Hide source code
fn pub equals_while_ignoring_case?[O: Bytes](other: ref O) -> Bool {
  let len = size

  if len == 0 { return true }

  if len != other.size { return false }

  let lhs = pointer
  let rhs = other.pointer
  let mut idx = 0

  # Since we have to convert ASCII bytes to lowercase (when necessary) we
  # can't use a more efficient comparison and instead have to compare the data
  # byte by byte.
  while idx < len {
    let mut a = ptr.add(lhs, idx).0 as Int
    let mut b = ptr.add(rhs, idx).0 as Int

    if upper?(a) { a = to_lower(a) }

    if upper?(b) { b = to_lower(b) }

    if a != b { return false }

    idx += 1
  }

  true
}
fn pub equals_while_ignoring_case?[O: Bytes](other: ref O) -> Bool

Returns true if self and other contain identical bytes, using an ASCII case-insensitive comparison.

This method only performs case-insensitive matching for characters in the ASCII range, meaning that "foo" and "FOO" are considered identical but "รก" and "ร" are considered different.

Examples

'foo'.equals_while_ignoring_case?('foo') # => true
'foo'.equals_while_ignoring_case?('FOO') # => true
'abc'.equals_while_ignoring_case?('def') # => false
'รก'.equals_while_ignoring_case?('ร') # => false

escaped

Show source code
Hide source code
fn pub escaped -> String {
  # If the String doesn't contain any special characters then we can/should
  # avoid the allocations that take place below.
  if !escape? { return self }

  let buff = ByteArray.new
  let mut i = 0

  while i < size {
    let byte = byte_unchecked(i := i + 1)

    match ESCAPE_TABLE.get(byte) {
      case Ok(-1) or Error(_) -> buff.push(byte)
      case Ok(byte) -> {
        buff.push(BSLASH)
        buff.push(byte)
      }
    }
  }

  buff.into_string
}
fn pub escaped -> String

Returns a copy of self with all special characters escaped.

The following characters are escaped:

  1. Double quotes
  2. Tabs
  3. Newlines
  4. Carriage returns
  5. Backspace
  6. Form feed
  7. Backslash

Examples

"hello\nworld" # => 'hello\nworld'
"hello\\world" # => 'hello\\world'

fmt

Show source code
Hide source code
fn pub fmt(formatter: mut Formatter) {
  formatter.write('"')
  formatter.write(escaped)
  formatter.write('"')
}
fn pub fmt(formatter: mut Formatter)

Formats self in a human-readable format for debugging purposes.

get

Show source code
Hide source code
fn pub inline get(index: Int) -> Result[Int, OutOfBounds] {
  try check_bounds(index, size)
  Result.Ok(byte_unchecked(index))
}
fn pub inline get(index: Int) -> Result[Int, OutOfBounds]

Returns the byte at the given index.

If the index is out of bounds, a std.bounds.OutOfBounds error is returned.

Examples

'abc'.get(0)  # => Result.Ok(97)
'abc'.get(10) # => Result.Error(OutOfBounds(...))

hash

Show source code
Hide source code
fn pub hash[H: mut + Hasher](hasher: mut H) {
  hash_bytes(self, hasher)
}
fn pub hash[H: mut + Hasher](hasher: mut H: mut)

Writes the hash for self into the given Hasher.

index_of

Show source code
Hide source code
fn pub index_of[B: Bytes](value: ref B, starting_at: Int) -> Option[Int] {
  # This is a naive string searching algorithm (see
  # https://en.wikipedia.org/wiki/String-searching_algorithm) for more details
  # on the various algorithms.
  #
  # We're using the naive algorithm because:
  #
  # 1. It's easy to implement
  # 2. It doesn't require any pre-processing
  # 3. At the time of writing there was no need for something more performant
  let find_size = value.size

  if find_size == 0 or size == 0 or find_size > size { return Option.None }

  let mut a = starting_at
  let max = size - find_size

  while a <= max {
    let mut b = 0

    while b < find_size and get(a + b) == value.get(b) { b += 1 }

    if b == find_size { return Option.Some(a) }

    a += 1
  }

  Option.None
}
fn pub index_of[B: Bytes](value: ref B, starting_at: Int) -> Option[Int]

Returns the byte index of the first occurrence of the given sequence of bytes, starting at the given byte index.

Examples

'hello'.index_of('h', starting_at: 0) # => Option.Some(0)
'hello'.index_of('l', starting_at: 0) # => Option.Some(2)
'hello'.index_of('l', starting_at: 3) # => Option.Some(3)
'hello'.index_of('x', starting_at: 0) # => Option.None

into_byte_array

Show source code
Hide source code
fn pub inline move into_byte_array -> ByteArray {
  to_byte_array
}
fn pub inline move into_byte_array -> ByteArray

into_string

Show source code
Hide source code
fn pub inline move into_string -> String {
  self
}
fn pub inline move into_string -> String

Moves self into a String.

pad_end

Show source code
Hide source code
fn pub pad_end(with: String, chars: Int) -> String {
  self + padding(with, chars: self.chars.count, pad_to: chars)
}
fn pub pad_end(with: String, chars: Int) -> String

Returns a new String that is padded with another String until the given number of characters is reached.

The padding is applied at the end of the new String.

Examples

'hello'.pad_end(with: ' ', chars: 7) # => 'hello  '
'hello'.pad_end(with: ' ', chars: 5) # => 'hello'

pad_start

Show source code
Hide source code
fn pub pad_start(with: String, chars: Int) -> String {
  padding(with, chars: self.chars.count, pad_to: chars) + self
}
fn pub pad_start(with: String, chars: Int) -> String

Returns a new String that is padded with another String until the given number of characters is reached.

The padding is applied at the start of the new String.

Examples

'hello'.pad_start(with: ' ', chars: 7) # => '  hello'
'hello'.pad_start(with: ' ', chars: 5) # => 'hello'

pointer

Show source code
Hide source code
fn pub inline pointer -> Pointer[UInt8] {
  @ptr
}
fn pub inline pointer -> Pointer[UInt8]

Returns a raw pointer to the bytes of self.

This method is meant to be used when passing strings to foreign functions (i.e. *char arguments). You should avoid using it for anything else.

repeat

Show source code
Hide source code
fn pub repeat(times: Int) -> String {
  match times {
    case 0 -> ''
    case 1 -> self
    case _ -> {
      let buf = StringBuffer.new

      times.times(fn (_) { buf.push(clone) })
      buf.into_string
    }
  }
}
fn pub repeat(times: Int) -> String

Returns a new String that contains self multiple times.

Examples

'a'.repeat(4) # => 'aaaa'

replace

Show source code
Hide source code
fn pub replace(string: String, with: String) -> String {
  # Different languages handle the pattern being empty differently. For
  # example, Javascript and Node only match the start of the string if the
  # pattern is empty. Other languages such as Ruby and Python appear to inject
  # the replacement in between every character, such that
  # `'AB'.replace('', ',')` results in `,A,B,`.
  #
  # We make the decision to just _not_ do any replacements in this case, as
  # replacing an empty string is nonsensical to begin with.
  if string.size == 0 { return self }

  let buf = ByteArray.new
  let mut start = 0
  let mut last = 0

  loop {
    match index_of(string, start) {
      case Some(i) -> {
        if i > last { buf.append(slice(start: last, end: i)) }

        buf.append(with.slice(start: 0, end: with.size))
        start = i + string.size
        last = start
      }
      case _ -> {
        if start < size { buf.append(slice(start: start, end: size)) }

        break
      }
    }
  }

  buf.into_string
}
fn pub replace(string: String, with: String) -> String

Replaces all occurrences of string with the value in with, returning the result as a new String.

If the string argument is an empty String, this method doesn't perform any replacements and instead returns a copy of self.

Examples

'foo foo'.replace('foo', with: 'bar') # => 'bar bar'

scalars

Show source code
Hide source code
fn pub inline scalars -> Scalars[Self] {
  Scalars.new(self)
}
fn pub inline scalars -> Scalars[String]

Returns an iterator over the UTF-8 scalars in self.

Examples

'foo'.scalars.to_array # => [102, 111, 111]
'๐Ÿคฆ๐Ÿผโ€โ™‚๏ธ'.scalars.to_array  # => [129318, 127996, 8205, 9794, 65039]

size

Show source code
Hide source code
fn pub inline size -> Int {
  @size
}
fn pub inline size -> Int

Returns the size of the String in bytes.

Examples

Getting the byte size of a String:

'foo'.size # => 3
'๐Ÿ˜€'.size  # => 4

slice

Show source code
Hide source code
fn pub slice(start: Int, end: Int) -> Slice[Self] {
  Slice.checked(self, start, end)
}
fn pub slice(start: Int, end: Int) -> Slice[String]

Slices self into a slice of bytes using a byte range from start until (but excluding) end.

Both the start and end arguments are byte indexes.

The start index is allowed to be equal to the size of self, but only if end is the same as start. Thus given a String with a size of 4, string.slice(4, 4) is valid.

Panics

This method panics if start or end is out of bounds.

Examples

'๐Ÿ˜Š'.slice(start: 0, end: 4).to_string # => '๐Ÿ˜Š'
'๐Ÿ˜Š'.slice(start: 0, end: 3).to_string # => "\u{FFFD}"

split

Show source code
Hide source code
fn pub split(separator: String) -> Stream[Slice[String]] {
  Slice.new(self, 0, size).split(separator)
}
fn pub split(separator: String) -> Stream[Slice[String]]

Splits self into an iterator of slices of the data in self, each separated by the given separator.

Examples

Splitting a String using a single character as the separator:

let iter = 'foo/bar/baz'.split('/')

iter.next.get.to_string # => 'foo'
iter.next.get.to_string # => 'bar'

Splitting a String using multiple characters as the separator:

let iter = 'foo::bar::baz'.split('::')

iter.next.get.to_string # => 'foo'
iter.next.get.to_string # => 'bar'

split_once

Show source code
Hide source code
fn pub split_once(
  separator: String,
) -> Option[(Slice[String], Slice[String])] {
  Slice.new(self, 0, size).split_once(separator)
}
fn pub split_once(separator: String) -> Option[(Slice[String], Slice[String])]

Splits self on the first occurrence of separator.

Refer to the documentation of Slice.split_once for more details.

Examples

let left_right = 'key=value'.split_once('=').get

left_right.0.to_string # => 'key'
left_right.1.to_string # => 'value'

starts_with?

Show source code
Hide source code
fn pub starts_with?[T: Bytes](prefix: ref T) -> Bool {
  ptr.starts_with?(pointer, size, prefix.pointer, prefix.size)
}
fn pub starts_with?[T: Bytes](prefix: ref T) -> Bool

Returns true if self starts with the given sequence of bytes.

Examples

'hello'.starts_with?('h'.to_byte_array) # => true
'hello'.starts_with?('h')               # => true

strip_prefix

Show source code
Hide source code
fn pub strip_prefix(prefix: String) -> Option[String] {
  if !starts_with?(prefix) { return Option.None }

  if size == prefix.size {
    Option.Some('')
  } else {
    Option.Some(slice(start: prefix.size, end: size).to_string)
  }
}
fn pub strip_prefix(prefix: String) -> Option[String]

Returns a new String without the given prefix.

If self starts with the prefix, a Option.Some is returned containing the substring after the prefix. If self doesn't start with the prefix, an Option.None is returned.

Examples

'xhellox'.strip_prefix('x') # => Option.Some('hellox')
'xhellox'.strip_prefix('y') # => Option.None

strip_suffix

Show source code
Hide source code
fn pub strip_suffix(suffix: String) -> Option[String] {
  if !ends_with?(suffix) { return Option.None }

  Option.Some(slice(start: 0, end: size - suffix.size).to_string)
}
fn pub strip_suffix(suffix: String) -> Option[String]

Returns a new String without the given suffix.

If self ends with the suffix, a Option.Some is returned containing the substring before the prefix. If self doesn't end with the suffix, an Option.None is returned.

Examples

'xhellox'.strip_suffix('x') # => Option.Some('xhello')
'xhellox'.strip_suffix('y') # => Option.None

substring

Show source code
Hide source code
fn pub substring(start: Int, end: Int) -> String {
  let buff = StringBuffer.new

  for (index, char) in self.chars.with_index {
    if index >= end { break } else if index >= start { buff.push(char) }
  }

  buff.into_string
}
fn pub substring(start: Int, end: Int) -> String

Slices self into a substring using a character range from start until (but excluding) end.

Both the start and end arguments are character indexes, not byte indexes. If start is less than zero, it's treated as if it were set to zero. If end is zero or start is greater than or equal to end, the returned value is always an empty String.

Slicing a String into a substring is not a constant-time operation, instead it's O(n) where n is the number of characters in the String.

Examples

'hello_world'.substring(start: 0, end: 5)  # => 'hello'
'hello_world'.substring(start: 0, end: 50) # => 'hello'
'๐Ÿ˜Š'.substring(start: 0, end: 1)           # => '๐Ÿ˜Š'

to_byte_array

Show source code
Hide source code
fn pub inline to_byte_array -> ByteArray {
  let bytes = ByteArray.new
  let _ = bytes.append(self)

  bytes
}
fn pub inline to_byte_array -> ByteArray

to_lower

Show source code
Hide source code
fn pub inline to_lower -> String {
  String.from_primitive(inko_string_to_lower(to_primitive))
}
fn pub inline to_lower -> String

Returns the lowercase equivalent of the current String.

Examples

Converting a String containing only ASCII symbols:

'HELLO'.to_lower # => 'hello'

Converting a String containing Unicode symbols:

'ร„'.to_lower # => 'รค'

Converting a String containing both ASCII and Unicode symbols:

'Aร„'.to_lower # => 'aรค'

to_path

Show source code
Hide source code
fn pub inline to_path -> Path {
  Path.new(self)
}
fn pub inline to_path -> Path

Converts self to a Path

Examples

'/tmp/test.txt'.to_path # => Path.new('/tmp/test.txt')

to_slice

Show source code
Hide source code
fn pub to_slice -> Slice[Self] {
  Slice.new(self, 0, size)
}
fn pub to_slice -> Slice[String]

Returns a Slice that covers all of self.

to_string

Show source code
Hide source code
fn pub inline to_string -> String {
  clone
}
fn pub inline to_string -> String

Converts self to a String.

to_upper

Show source code
Hide source code
fn pub inline to_upper -> String {
  String.from_primitive(inko_string_to_upper(to_primitive))
}
fn pub inline to_upper -> String

Returns the uppercase equivalent of the current String.

Examples

Converting a String containing only ASCII symbols:

'hello'.to_upper # => 'HELLO'

Converting a String containing Unicode symbols:

'รค'.to_upper # => 'ร„'

Converting a String containing both ASCII and Unicode symbols:

'aรค'.to_upper # => 'Aร„'

trim

Show source code
Hide source code
fn pub trim -> String {
  Slice.new(self, 0, size).trim.to_string
}
fn pub trim -> String

Returns a new String with both leading and trailing whitespace removed.

Examples

' hello '.trim  # => 'hello'
" hello\t".trim # => 'hello'

trim_end

Show source code
Hide source code
fn pub trim_end -> String {
  Slice.new(self, 0, size).trim_end.to_string
}
fn pub trim_end -> String

Returns a new String without any trailing whitespace.

Examples

'hello '.trim_end  # => 'hello'
"hello\t".trim_end # => 'hello'

trim_start

Show source code
Hide source code
fn pub trim_start -> String {
  Slice.new(self, 0, size).trim_start.to_string
}
fn pub trim_start -> String

Returns a new String without any leading whitespace.

Examples

' hello'.trim_start  # => 'hello'
"\thello".trim_start # => 'hello'

Implemented traits

std.bytes.

Bytes

impl Bytes for String
std.bytes.

IntoByteArray

impl IntoByteArray for String
std.bytes.

ToByteArray

impl ToByteArray for String
std.bytes.

ToSlice

impl ToSlice[String] for String
std.clone.

Clone

impl Clone for String
std.cmp.

Compare

impl Compare for String
std.cmp.

Equal

impl Equal for String
std.drop.

Drop

impl Drop for String
std.fmt.

Format

impl Format for String
std.hash.

Hash

impl Hash for String
std.ops.

Add

impl Add[String, String] for String
std.string.

IntoString

impl IntoString for String
std.string.

ToString

impl ToString for String