aboutsummaryrefslogtreecommitdiff
path: root/std/prelude/strings.pk
blob: a8c72fb598c5a00bd0303894128dcc448b0a0250 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
## std.strings: The standard implementation of strings.
## This module is imported by default.
# reference: https://doc.rust-lang.org/std/string/struct.String.html

## A primitive string type.
##
## We do not want methods defined on `list[byte]` to carry over,
## so we define `str` as a newtype.
@[opaque]
pub type str = struct
  data: list[byte]

## Initialize and return an empty string.
pub func init: str = { data = [] }

## Gets the length of a string.
## This is an O(n) operation, due to UTF-8 encoding.
pub func len(self: lent str): uint =
  var res: uint
  for _ in self do
    res += 1
  res

## Pushes a character to the end of a mutable string.
pub func push(self: mut str, val: chr) =
  self.data.push(val.byte) # todo: obsolete by from/to conversion??

## Pushes an owned string to the end of a mutable string.
pub func push(self: mut str, val: str) =
  self.data.push(val.bytes) # todo: obsolete by from/to conversion??

## Removes and returns the last character of a string, if it exists.
##
## SAFETY: We return early upon an empty string.
## And decrement by one char for a non-empty string.
@[safe]
pub func pop(self: mut str): chr? =
  let char = self.chars.rev.next?
  self.data.set_len(self.len - char.len) # this is normally unsafe.
  Some(char)

## Returns the character at the provided index, if it exists.
pub func get(self: str, i: uint): chr? =
  ...

## Sets the character at the provided index, if it exists.
## As strings are packed, this may call str.grow and reallocate.
## oh fuck we have to insert + remove anyway
pub func set(self: mut str, i: uint, val: chr) =
  ...

## Inserts a character at an arbitrary position within a string.
## Panics on failure. (todo: can we do better?)
pub func insert(self: mut str, i: uint, val: chr) =
  ...

## Removes and returns a character at an arbitrary position within a string.
## Panics on failure. (todo: can we do better?)
pub func remove(self: mut str, i: uint): chr =
  ...

## Syntactic sugar for string appending.
pub func &=(a: mut str, b: str) =
  a.push(b)

## The concatenation operator. Consumes two strings.
pub func &(a: str, b: str): str =
  a.push(b)
  a

## Conversion from a string to a list of bytes. Zero-cost.
pub func to(self: str): list[byte] = self.data
## Conversion from a str to a list[chr]. Reallocates.
pub func to(self: str): list[chr] =
  var res: list[chr]
  for char in self do res.push(char)
  res
## Conversion from a char to an array of bytes. Zero-cost.
@[safe] # possibly unsafe?? depends on repr of arrays
pub func to(self: chr): array[byte, 4] = self.cast[array[byte, 4]]

# pub func next(self: mut StrIter)
# pub func peek(self: mut StrIter)
# pub func peek_nth(self: mut StrIter, i: uint)