File: .lake/packages/lean4/src/lean/Init/Data/String/Basic.lean

full_name: List.asString
code: def List.asString (s : List Char) : String 
goal: String

full_name: String.«instOfNatPos_.lake»
code: instance : OfNat String.Pos (nat_lit 0) 
goal: OfNat String.Pos 0

full_name: String.«instLT_.lake»
code: instance : LT String 
goal: LT String

full_name: String.decLt
code: @[extern "lean_string_dec_lt"]
instance decLt (s₁ s₂ : @& String) : Decidable (s₁ < s₂) 
goal: Decidable (s₁ < s₂)

full_name: String.le
code: @[reducible] protected def le (a b : String) : Prop 
goal: Prop

full_name: String.«instLE_.lake»
code: instance : LE String 
goal: LE String

full_name: String.decLE
code: instance decLE (s₁ s₂ : String) : Decidable (s₁ ≤ s₂) 
goal: Decidable (s₁ ≤ s₂)

full_name: String.length
code: /--
Returns the length of a string in Unicode code points.

Examples:
* `"".length = 0`
* `"abc".length = 3`
* `"L∃∀N".length = 4`
-/
@[extern "lean_string_length"]
def length : (@& String) → Nat
  
goal: String → Nat

full_name: String.push
code: /--
Pushes a character onto the end of a string.

The internal implementation uses dynamic arrays and will perform destructive updates
if the string is not shared.

Example: `"abc".push 'd' = "abcd"`
-/
@[extern "lean_string_push"]
def push : String → Char → String
  
goal: String → Char → String

full_name: String.append
code: /--
Appends two strings.

The internal implementation uses dynamic arrays and will perform destructive updates
if the string is not shared.

Example: `"abc".append "def" = "abcdef"`
-/
@[extern "lean_string_append"]
def append : String → (@& String) → String
  
goal: String → String → String

full_name: String.toList
code: /--
Converts a string to a list of characters.

Even though the logical model of strings is as a structure that wraps a list of characters,
this operation takes time and space linear in the length of the string, because the compiler
uses an optimized representation as dynamic arrays.

Example: `"abc".toList = ['a', 'b', 'c']`
-/
def toList (s : String) : List Char 
goal: List Char

full_name: String.Pos.isValid
code: /-- Returns true if `p` is a valid UTF-8 position in the string `s`, meaning that `p ≤ s.endPos`
and `p` lies on a UTF-8 character boundary. This has an O(1) implementation in the runtime. -/
@[extern "lean_string_is_valid_pos"]
def Pos.isValid (s : @&String) (p : @& Pos) : Bool 
goal: Bool

full_name: String.Pos.isValid.go
code: /-- Returns true if `p` is a valid UTF-8 position in the string `s`, meaning that `p ≤ s.endPos`
and `p` lies on a UTF-8 character boundary. This has an O(1) implementation in the runtime. -/
@[extern "lean_string_is_valid_pos"]
def Pos.isValid (s : @&String) (p : @& Pos) : Bool 
goal: List Char → String.Pos → Bool

full_name: String.utf8GetAux
code: def utf8GetAux : List Char → Pos → Pos → Char
  
goal: List Char → String.Pos → String.Pos → Char

full_name: String.get
code: /--
Returns the character at position `p` of a string. If `p` is not a valid position,
returns `(default : Char)`.

See `utf8GetAux` for the reference implementation.

Examples:
* `"abc".get ⟨1⟩ = 'b'`
* `"abc".get ⟨3⟩ = (default : Char) = 'A'`

Positions can also be invalid if a byte index points into the middle of a multi-byte UTF-8
character. For example,`"L∃∀N".get ⟨2⟩ = (default : Char) = 'A'`.
-/
@[extern "lean_string_utf8_get"]
def get (s : @& String) (p : @& Pos) : Char 
goal: Char

full_name: String.utf8GetAux?
code: def utf8GetAux? : List Char → Pos → Pos → Option Char
  
goal: List Char → String.Pos → String.Pos → Option Char

full_name: String.get?
code: /--
Returns the character at position `p`. If `p` is not a valid position, returns `none`.

Examples:
* `"abc".get? ⟨1⟩ = some 'b'`
* `"abc".get? ⟨3⟩ = none`

Positions can also be invalid if a byte index points into the middle of a multi-byte UTF-8
character. For example, `"L∃∀N".get? ⟨2⟩ = none`
-/
@[extern "lean_string_utf8_get_opt"]
def get? : (@& String) → (@& Pos) → Option Char
  
goal: String → String.Pos → Option Char

full_name: String.get!
code: /--
Returns the character at position `p` of a string. If `p` is not a valid position,
returns `(default : Char)` and produces a panic error message.

Examples:
* `"abc".get! ⟨1⟩ = 'b'`
* `"abc".get! ⟨3⟩` panics

Positions can also be invalid if a byte index points into the middle of a multi-byte UTF-8 character. For example,
`"L∃∀N".get! ⟨2⟩` panics.
-/
@[extern "lean_string_utf8_get_bang"]
def get! (s : @& String) (p : @& Pos) : Char 
goal: Char

full_name: String.utf8SetAux
code: def utf8SetAux (c' : Char) : List Char → Pos → Pos → List Char
  
goal: List Char → String.Pos → String.Pos → List Char

full_name: String.set
code: /--
Replaces the character at a specified position in a string with a new character. If the position
is invalid, the string is returned unchanged.

If both the replacement character and the replaced character are ASCII characters and the string
is not shared, destructive updates are used.

Examples:
* `"abc".set ⟨1⟩ 'B' = "aBc"`
* `"abc".set ⟨3⟩ 'D' = "abc"`
* `"L∃∀N".set ⟨4⟩ 'X' = "L∃XN"`

Because `'∃'` is a multi-byte character, the byte index `2` in `L∃∀N` is an invalid position,
so `"L∃∀N".set ⟨2⟩ 'X' = "L∃∀N"`.
-/
@[extern "lean_string_utf8_set"]
def set : String → (@& Pos) → Char → String
  
goal: String → String.Pos → Char → String

full_name: String.modify
code: /--
Replaces the character at position `p` in the string `s` with the result of applying `f` to that character.
If `p` is an invalid position, the string is returned unchanged.

Examples:
* `abc.modify ⟨1⟩ Char.toUpper = "aBc"`
* `abc.modify ⟨3⟩ Char.toUpper = "abc"`
-/
def modify (s : String) (i : Pos) (f : Char → Char) : String 
goal: String

full_name: String.next
code: /--
Returns the next position in a string after position `p`. If `p` is not a valid position or `p = s.endPos`,
the result is unspecified.

Examples:
Given `def abc := "abc"` and `def lean := "L∃∀N"`,
* `abc.get (0 |> abc.next) = 'b'`
* `lean.get (0 |> lean.next |> lean.next) = '∀'`

Cases where the result is unspecified:
* `"abc".next ⟨3⟩`, since `3 = s.endPos`
* `"L∃∀N".next ⟨2⟩`, since `2` points into the middle of a multi-byte UTF-8 character
-/
@[extern "lean_string_utf8_next"]
def next (s : @& String) (p : @& Pos) : Pos 
goal: String.Pos

full_name: String.utf8PrevAux
code: def utf8PrevAux : List Char → Pos → Pos → Pos
  
goal: List Char → String.Pos → String.Pos → String.Pos

full_name: String.prev
code: /--
Returns the position in a string before a specified position, `p`. If `p = ⟨0⟩`, returns `0`.
If `p` is not a valid position, the result is unspecified.

Examples:
Given `def abc := "abc"` and `def lean := "L∃∀N"`,
* `abc.get (abc.endPos |> abc.prev) = 'c'`
* `lean.get (lean.endPos |> lean.prev |> lean.prev |> lean.prev) = '∃'`
* `"L∃∀N".prev ⟨3⟩` is unspecified, since byte 3 occurs in the middle of the multi-byte character `'∃'`.
-/
@[extern "lean_string_utf8_prev"]
def prev : (@& String) → (@& Pos) → Pos
  
goal: String → String.Pos → String.Pos

full_name: String.front
code: /--
Returns the first character in `s`. If `s = ""`, returns `(default : Char)`.

Examples:
* `"abc".front = 'a'`
* `"".front = (default : Char)`
-/
def front (s : String) : Char 
goal: Char

full_name: String.back
code: /--
Returns the last character in `s`. If `s = ""`, returns `(default : Char)`.

Examples:
* `"abc".back = 'c'`
* `"".back = (default : Char)`
-/
def back (s : String) : Char 
goal: Char

full_name: String.atEnd
code: /--
Returns `true` if a specified position is greater than or equal to the position which
points to the end of a string. Otherwise, returns `false`.

Examples:
Given `def abc := "abc"` and `def lean := "L∃∀N"`,
* `(0 |> abc.next |> abc.next |> abc.atEnd) = false`
* `(0 |> abc.next |> abc.next |> abc.next |> abc.next |> abc.atEnd) = true`
* `(0 |> lean.next |> lean.next |> lean.next |> lean.next |> lean.atEnd) = true`

Because `"L∃∀N"` contains multi-byte characters, `lean.next (lean.next 0)` is not equal to `abc.next (abc.next 0)`.
-/
@[extern "lean_string_utf8_at_end"]
def atEnd : (@& String) → (@& Pos) → Bool
  
goal: String → String.Pos → Bool

full_name: String.get'
code: /--
Returns the character at position `p` of a string.
If `p` is not a valid position, returns `(default : Char)`.

Requires evidence, `h`, that `p` is within bounds
instead of performing a runtime bounds check as in `get`.

Examples:
* `"abc".get' 0 (by decide) = 'a'`
* `let lean := "L∃∀N"; lean.get' (0 |> lean.next |> lean.next) (by decide) = '∀'`

A typical pattern combines `get'` with a dependent if-else expression
to avoid the overhead of an additional bounds check. For example:
```
def getInBounds? (s : String) (p : String.Pos) : Option Char :=
  if h : s.atEnd p then none else some (s.get' p h)
```

Even with evidence of `¬ s.atEnd p`,
`p` may be invalid if a byte index points into the middle of a multi-byte UTF-8 character.
For example, `"L∃∀N".get' ⟨2⟩ (by decide) = (default : Char)`.
-/
@[extern "lean_string_utf8_get_fast"]
def get' (s : @& String) (p : @& Pos) (h : ¬ s.atEnd p) : Char 
goal: Char

full_name: String.next'
code: /--
Returns the next position in a string after position `p`.
If `p` is not a valid position, the result is unspecified.

Requires evidence, `h`, that `p` is within bounds
instead of performing a runtime bounds check as in `next`.

Examples:
* `let abc := "abc"; abc.get (abc.next' 0 (by decide)) = 'b'`

A typical pattern combines `next'` with a dependent if-else expression
to avoid the overhead of an additional bounds check. For example:
```
def next? (s: String) (p : String.Pos) : Option Char :=
  if h : s.atEnd p then none else s.get (s.next' p h)
```
-/
@[extern "lean_string_utf8_next_fast"]
def next' (s : @& String) (p : @& Pos) (h : ¬ s.atEnd p) : Pos 
goal: String.Pos

full_name: Char.utf8Size_pos
code: theorem _root_.Char.utf8Size_pos (c : Char) : 0 < c.utf8Size 
goal: 0 < c.utf8Size

full_name: Char.utf8Size_le_four
code: theorem _root_.Char.utf8Size_le_four (c : Char) : c.utf8Size ≤ 4 
goal: c.utf8Size ≤ 4

full_name: String.one_le_csize
code: @[deprecated Char.utf8Size_pos (since := "2026-06-04")] abbrev one_le_csize 
goal: 0 < c.utf8Size

full_name: String.pos_lt_eq
code: @[simp] theorem pos_lt_eq (p₁ p₂ : Pos) : (p₁ < p₂) = (p₁.1 < p₂.1) 
goal: (p₁ < p₂) = (p₁.byteIdx < p₂.byteIdx)

full_name: String.pos_add_char
code: @[simp] theorem pos_add_char (p : Pos) (c : Char) : (p + c).byteIdx = p.byteIdx + c.utf8Size 
goal: (p + c).byteIdx = p.byteIdx + c.utf8Size

full_name: String.lt_next
code: theorem lt_next (s : String) (i : Pos) : i.1 < (s.next i).1 
goal: i.byteIdx < (s.next i).byteIdx

full_name: String.utf8PrevAux_lt_of_pos
code: theorem utf8PrevAux_lt_of_pos : ∀ (cs : List Char) (i p : Pos), p ≠ 0 →
    (utf8PrevAux cs i p).1 < p.1
  
goal: p ≠ 0 → (String.utf8PrevAux cs i p).byteIdx < p.byteIdx

full_name: String.prev_lt_of_pos
code: theorem prev_lt_of_pos (s : String) (i : Pos) (h : i ≠ 0) : (s.prev i).1 < i.1 
goal: (s.prev i).byteIdx < i.byteIdx

full_name: String.posOfAux
code: def posOfAux (s : String) (c : Char) (stopPos : Pos) (pos : Pos) : Pos 
goal: String.Pos

full_name: String.posOf
code: /--
Returns the position of the first occurrence of a character, `c`, in `s`.
If `s` does not contain `c`, returns `s.endPos`.

Examples:
* `"abba".posOf 'a' = ⟨0⟩`
* `"abba".posOf 'z' = ⟨4⟩`
* `"L∃∀N".posOf '∀' = ⟨4⟩`
-/
@[inline] def posOf (s : String) (c : Char) : Pos 
goal: String.Pos

full_name: String.revPosOfAux
code: def revPosOfAux (s : String) (c : Char) (pos : Pos) : Option Pos 
goal: Option String.Pos

full_name: String.revPosOf
code: /--
Returns the position of the last occurrence of a character, `c`, in `s`.
If `s` does not contain `c`, returns `none`.

Examples:
* `"abba".posOf 'a' = some ⟨3⟩`
* `"abba".posOf 'z' = none`
* `"L∃∀N".posOf '∀' = some ⟨4⟩`
-/
def revPosOf (s : String) (c : Char) : Option Pos 
goal: Option String.Pos

full_name: String.findAux
code: def findAux (s : String) (p : Char → Bool) (stopPos : Pos) (pos : Pos) : Pos 
goal: String.Pos

full_name: String.find
code: @[inline] def find (s : String) (p : Char → Bool) : Pos 
goal: String.Pos

full_name: String.revFindAux
code: def revFindAux (s : String) (p : Char → Bool) (pos : Pos) : Option Pos 
goal: Option String.Pos

full_name: String.revFind
code: def revFind (s : String) (p : Char → Bool) : Option Pos 
goal: Option String.Pos

full_name: String.Pos.min
code: abbrev Pos.min (p₁ p₂ : Pos) : Pos 
goal: String.Pos

full_name: String.firstDiffPos
code: /-- Returns the first position where the two strings differ. -/
def firstDiffPos (a b : String) : Pos 
goal: String.Pos

full_name: String.firstDiffPos.loop
code: /-- Returns the first position where the two strings differ. -/
def firstDiffPos (a b : String) : Pos 
goal: String.Pos

full_name: String.extract
code: @[extern "lean_string_utf8_extract"]
def extract : (@& String) → (@& Pos) → (@& Pos) → String
  
goal: String → String.Pos → String.Pos → String

full_name: String.extract.go₂
code: @[extern "lean_string_utf8_extract"]
def extract : (@& String) → (@& Pos) → (@& Pos) → String
  
goal: List Char → String.Pos → String.Pos → List Char

full_name: String.extract.go₁
code: @[extern "lean_string_utf8_extract"]
def extract : (@& String) → (@& Pos) → (@& Pos) → String
  
goal: List Char → String.Pos → String.Pos → String.Pos → List Char

full_name: String.splitAux
code: @[specialize] def splitAux (s : String) (p : Char → Bool) (b : Pos) (i : Pos) (r : List String) : List String 
goal: List String

full_name: String.split
code: @[specialize] def split (s : String) (p : Char → Bool) : List String 
goal: List String

full_name: String.splitOnAux
code: /--
Auxiliary for `splitOn`. Preconditions:
* `sep` is not empty
* `b <= i` are indexes into `s`
* `j` is an index into `sep`, and not at the end

It represents the state where we have currently parsed some split parts into `r` (in reverse order),
`b` is the beginning of the string / the end of the previous match of `sep`, and the first `j` bytes
of `sep` match the bytes `i-j .. i` of `s`.
-/
def splitOnAux (s sep : String) (b : Pos) (i : Pos) (j : Pos) (r : List String) : List String 
goal: List String

full_name: String.splitOn
code: /--
Splits a string `s` on occurrences of the separator `sep`. When `sep` is empty, it returns `[s]`;
when `sep` occurs in overlapping patterns, the first match is taken. There will always be exactly
`n+1` elements in the returned list if there were `n` nonoverlapping matches of `sep` in the string.
The default separator is `" "`. The separators are not included in the returned substrings.

```
"here is some text ".splitOn = ["here", "is", "some", "text", ""]
"here is some text ".splitOn "some" = ["here is ", " text "]
"here is some text ".splitOn "" = ["here is some text "]
"ababacabac".splitOn "aba" = ["", "bac", "c"]
```
-/
def splitOn (s : String) (sep : String := " ") : List String 
goal: List String

full_name: String.«instInhabited_.lake»
code: instance : Inhabited String 
goal: Inhabited String

full_name: String.«instAppend_.lake»
code: instance : Append String 
goal: Append String

full_name: String.str
code: @[deprecated push (since := "2024-04-06")]
def str : String → Char → String 
goal: String → Char → String

full_name: String.pushn
code: def pushn (s : String) (c : Char) (n : Nat) : String 
goal: String

full_name: String.isEmpty
code: def isEmpty (s : String) : Bool 
goal: Bool

full_name: String.join
code: def join (l : List String) : String 
goal: String

full_name: String.singleton
code: def singleton (c : Char) : String 
goal: String

full_name: String.intercalate.go
code: def intercalate (s : String) : List String → String
  
goal: List String → String

full_name: String.intercalate
code: def intercalate (s : String) : List String → String
  
goal: List String → String

full_name: String.Iterator.s
code: /-- Iterator over the characters (`Char`) of a `String`.

Typically created by `s.iter`, where `s` is a `String`.

An iterator is *valid* if the position `i` is *valid* for the string `s`, meaning `0 ≤ i ≤ s.endPos`
and `i` lies on a UTF8 byte boundary. If `i = s.endPos`, the iterator is at the end of the string.

Most operations on iterators return arbitrary values if the iterator is not valid. The functions in
the `String.Iterator` API should rule out the creation of invalid iterators, with two exceptions:

- `Iterator.next iter` is invalid if `iter` is already at the end of the string (`iter.atEnd` is
  `true`), and
- `Iterator.forward iter n`/`Iterator.nextn iter n` is invalid if `n` is strictly greater than the
  number of remaining characters.
-/
structure Iterator where
  /-- The string the iterator is for. -/
  s : String
  /-- The current position.

  This position is not necessarily valid for the string, for instance if one keeps calling
  `Iterator.next` when `Iterator.atEnd` is true. If the position is not valid, then the
  current character is `(default : Char)`, similar to `String.get` on an invalid position. -/
  i : Pos
  deriving DecidableEq
goal: String

full_name: String.Iterator
code: /-- Iterator over the characters (`Char`) of a `String`.

Typically created by `s.iter`, where `s` is a `String`.

An iterator is *valid* if the position `i` is *valid* for the string `s`, meaning `0 ≤ i ≤ s.endPos`
and `i` lies on a UTF8 byte boundary. If `i = s.endPos`, the iterator is at the end of the string.

Most operations on iterators return arbitrary values if the iterator is not valid. The functions in
the `String.Iterator` API should rule out the creation of invalid iterators, with two exceptions:

- `Iterator.next iter` is invalid if `iter` is already at the end of the string (`iter.atEnd` is
  `true`), and
- `Iterator.forward iter n`/`Iterator.nextn iter n` is invalid if `n` is strictly greater than the
  number of remaining characters.
-/
structure Iterator where
  /-- The string the iterator is for. -/
  s : String
  /-- The current position.

  This position is not necessarily valid for the string, for instance if one keeps calling
  `Iterator.next` when `Iterator.atEnd` is true. If the position is not valid, then the
  current character is `(default : Char)`, similar to `String.get` on an invalid position. -/
  i : Pos
  deriving DecidableEq
goal: Type

full_name: String.Iterator.i
code: /-- Iterator over the characters (`Char`) of a `String`.

Typically created by `s.iter`, where `s` is a `String`.

An iterator is *valid* if the position `i` is *valid* for the string `s`, meaning `0 ≤ i ≤ s.endPos`
and `i` lies on a UTF8 byte boundary. If `i = s.endPos`, the iterator is at the end of the string.

Most operations on iterators return arbitrary values if the iterator is not valid. The functions in
the `String.Iterator` API should rule out the creation of invalid iterators, with two exceptions:

- `Iterator.next iter` is invalid if `iter` is already at the end of the string (`iter.atEnd` is
  `true`), and
- `Iterator.forward iter n`/`Iterator.nextn iter n` is invalid if `n` is strictly greater than the
  number of remaining characters.
-/
structure Iterator where
  /-- The string the iterator is for. -/
  s : String
  /-- The current position.

  This position is not necessarily valid for the string, for instance if one keeps calling
  `Iterator.next` when `Iterator.atEnd` is true. If the position is not valid, then the
  current character is `(default : Char)`, similar to `String.get` on an invalid position. -/
  i : Pos
  deriving DecidableEq
goal: String.Pos

full_name: String.mkIterator
code: /-- Creates an iterator at the beginning of a string. -/
def mkIterator (s : String) : Iterator 
goal: String.Iterator

full_name: String.iter
code: @[inherit_doc mkIterator]
abbrev iter 
goal: String.Iterator

full_name: String.instSizeOfIterator
code: /-- The size of a string iterator is the number of bytes remaining. -/
instance : SizeOf String.Iterator 
goal: SizeOf String.Iterator

full_name: String.Iterator.sizeOf_eq
code: theorem Iterator.sizeOf_eq (i : String.Iterator) : sizeOf i = i.1.utf8ByteSize - i.2.byteIdx 
goal: sizeOf i = i.s.utf8ByteSize - i.i.byteIdx

full_name: String.Iterator.toString
code: @[inherit_doc Iterator.s]
def toString 
goal: String

full_name: String.Iterator.remainingBytes
code: /-- Number of bytes remaining in the iterator. -/
def remainingBytes : Iterator → Nat
  
goal: String.Iterator → Nat

full_name: String.Iterator.pos
code: @[inherit_doc Iterator.i]
def pos 
goal: String.Pos

full_name: String.Iterator.curr
code: /-- The character at the current position.

On an invalid position, returns `(default : Char)`. -/
def curr : Iterator → Char
  
goal: String.Iterator → Char

full_name: String.Iterator.next
code: /-- Moves the iterator's position forward by one character, unconditionally.

It is only valid to call this function if the iterator is not at the end of the string, *i.e.*
`Iterator.atEnd` is `false`; otherwise, the resulting iterator will be invalid. -/
def next : Iterator → Iterator
  
goal: String.Iterator → String.Iterator

full_name: String.Iterator.prev
code: /-- Decreases the iterator's position.

If the position is zero, this function is the identity. -/
def prev : Iterator → Iterator
  
goal: String.Iterator → String.Iterator

full_name: String.Iterator.atEnd
code: /-- True if the iterator is past the string's last character. -/
def atEnd : Iterator → Bool
  
goal: String.Iterator → Bool

full_name: String.Iterator.hasNext
code: /-- True if the iterator is not past the string's last character. -/
def hasNext : Iterator → Bool
  
goal: String.Iterator → Bool

full_name: String.Iterator.hasPrev
code: /-- True if the position is not zero. -/
def hasPrev : Iterator → Bool
  
goal: String.Iterator → Bool

full_name: String.Iterator.setCurr
code: /-- Replaces the current character in the string.

Does nothing if the iterator is at the end of the string. If the iterator contains the only
reference to its string, this function will mutate the string in-place instead of allocating a new
one. -/
def setCurr : Iterator → Char → Iterator
  
goal: String.Iterator → Char → String.Iterator

full_name: String.Iterator.toEnd
code: /-- Moves the iterator's position to the end of the string.

Note that `i.toEnd.atEnd` is always `true`. -/
def toEnd : Iterator → Iterator
  
goal: String.Iterator → String.Iterator

full_name: String.Iterator.extract
code: /-- Extracts the substring between the positions of two iterators.

Returns the empty string if the iterators are for different strings, or if the position of the first
iterator is past the position of the second iterator. -/
def extract : Iterator → Iterator → String
  
goal: String.Iterator → String.Iterator → String

full_name: String.Iterator.forward
code: /-- Moves the iterator's position several characters forward.

The resulting iterator is only valid if the number of characters to skip is less than or equal to
the number of characters left in the iterator. -/
def forward : Iterator → Nat → Iterator
  
goal: String.Iterator → Nat → String.Iterator

full_name: String.Iterator.remainingToString
code: /-- The remaining characters in an iterator, as a string. -/
def remainingToString : Iterator → String
  
goal: String.Iterator → String

full_name: String.Iterator.nextn
code: @[inherit_doc forward]
def nextn : Iterator → Nat → Iterator
  
goal: String.Iterator → Nat → String.Iterator

full_name: String.Iterator.prevn
code: /-- Moves the iterator's position several characters back.

If asked to go back more characters than available, stops at the beginning of the string. -/
def prevn : Iterator → Nat → Iterator
  
goal: String.Iterator → Nat → String.Iterator

full_name: String.offsetOfPosAux
code: def offsetOfPosAux (s : String) (pos : Pos) (i : Pos) (offset : Nat) : Nat 
goal: Nat

full_name: String.offsetOfPos
code: def offsetOfPos (s : String) (pos : Pos) : Nat 
goal: Nat

full_name: String.foldlAux
code: @[specialize] def foldlAux {α : Type u} (f : α → Char → α) (s : String) (stopPos : Pos) (i : Pos) (a : α) : α 
goal: α

full_name: String.foldl
code: @[inline] def foldl {α : Type u} (f : α → Char → α) (init : α) (s : String) : α 
goal: α

full_name: String.foldrAux
code: @[specialize] def foldrAux {α : Type u} (f : Char → α → α) (a : α) (s : String) (i begPos : Pos) : α 
goal: α

full_name: String.foldr
code: @[inline] def foldr {α : Type u} (f : Char → α → α) (init : α) (s : String) : α 
goal: α

full_name: String.anyAux
code: @[specialize] def anyAux (s : String) (stopPos : Pos) (p : Char → Bool) (i : Pos) : Bool 
goal: Bool

full_name: String.any
code: @[inline] def any (s : String) (p : Char → Bool) : Bool 
goal: Bool

full_name: String.all
code: @[inline] def all (s : String) (p : Char → Bool) : Bool 
goal: Bool

full_name: String.contains
code: def contains (s : String) (c : Char) : Bool 
goal: Bool

full_name: String.utf8SetAux_of_gt
code: theorem utf8SetAux_of_gt (c' : Char) : ∀ (cs : List Char) {i p : Pos}, i > p → utf8SetAux c' cs i p = cs
  
goal: i > p → String.utf8SetAux c' cs i p = cs

full_name: String.set_next_add
code: theorem set_next_add (s : String) (i : Pos) (c : Char) (b₁ b₂)
    (h : (s.next i).1 + b₁ = s.endPos.1 + b₂) :
    ((s.set i c).next i).1 + b₁ = (s.set i c).endPos.1 + b₂ 
goal: ((s.set i c).next i).byteIdx + b₁ = (s.set i c).endPos.byteIdx + b₂

full_name: String.set_next_add.foo
code: theorem set_next_add (s : String) (i : Pos) (c : Char) (b₁ b₂)
    (h : (s.next i).1 + b₁ = s.endPos.1 + b₂) :
    ((s.set i c).next i).1 + b₁ = (s.set i c).endPos.1 + b₂ 
goal: (String.utf8GetAux cs a i).utf8Size + b₁ = String.utf8ByteSize.go cs + b₂ →
  (String.utf8GetAux (String.utf8SetAux c cs a i) a i).utf8Size + b₁ =
    String.utf8ByteSize.go (String.utf8SetAux c cs a i) + b₂

full_name: String.mapAux_lemma
code: theorem mapAux_lemma (s : String) (i : Pos) (c : Char) (h : ¬s.atEnd i) :
    (s.set i c).endPos.1 - ((s.set i c).next i).1 < s.endPos.1 - i.1 
goal: (s.set i c).endPos.byteIdx - ((s.set i c).next i).byteIdx < s.endPos.byteIdx - i.byteIdx

full_name: String.mapAux
code: @[specialize] def mapAux (f : Char → Char) (i : Pos) (s : String) : String 
goal: String

full_name: String.map
code: @[inline] def map (f : Char → Char) (s : String) : String 
goal: String

full_name: String.isNat
code: def isNat (s : String) : Bool 
goal: Bool

full_name: String.toNat?
code: def toNat? (s : String) : Option Nat 
goal: Option Nat

full_name: String.substrEq.loop
code: /--
Return `true` iff the substring of byte size `sz` starting at position `off1` in `s1` is equal to that starting at `off2` in `s2.`.
False if either substring of that byte size does not exist. -/
def substrEq (s1 : String) (off1 : String.Pos) (s2 : String) (off2 : String.Pos) (sz : Nat) : Bool 
goal: Bool

full_name: String.substrEq
code: /--
Return `true` iff the substring of byte size `sz` starting at position `off1` in `s1` is equal to that starting at `off2` in `s2.`.
False if either substring of that byte size does not exist. -/
def substrEq (s1 : String) (off1 : String.Pos) (s2 : String) (off2 : String.Pos) (sz : Nat) : Bool 
goal: Bool

full_name: String.isPrefixOf
code: /-- Return true iff `p` is a prefix of `s` -/
def isPrefixOf (p : String) (s : String) : Bool 
goal: Bool

full_name: String.replace
code: /-- Replace all occurrences of `pattern` in `s` with `replacement`. -/
def replace (s pattern replacement : String) : String 
goal: String

full_name: String.replace.loop
code: /-- Replace all occurrences of `pattern` in `s` with `replacement`. -/
def replace (s pattern replacement : String) : String 
goal: String

full_name: String.findLineStart
code: /-- Return the beginning of the line that contains character `pos`. -/
def findLineStart (s : String) (pos : String.Pos) : String.Pos 
goal: String.Pos

full_name: Substring.isEmpty
code: @[inline] def isEmpty (ss : Substring) : Bool 
goal: Bool

full_name: Substring.toString
code: @[inline] def toString : Substring → String
  
goal: Substring → String

full_name: Substring.toIterator
code: @[inline] def toIterator : Substring → String.Iterator
  
goal: Substring → String.Iterator

full_name: Substring.get
code: /-- Return the codepoint at the given offset into the substring. -/
@[inline] def get : Substring → String.Pos → Char
  
goal: Substring → String.Pos → Char

full_name: Substring.next
code: /-- Given an offset of a codepoint into the substring,
return the offset there of the next codepoint. -/
@[inline] def next : Substring → String.Pos → String.Pos
  
goal: Substring → String.Pos → String.Pos

full_name: Substring.lt_next
code: theorem lt_next (s : Substring) (i : String.Pos) (h : i.1 < s.bsize) :
    i.1 < (s.next i).1 
goal: i.byteIdx < (s.next i).byteIdx

full_name: Substring.prev
code: /-- Given an offset of a codepoint into the substring,
return the offset there of the previous codepoint. -/
@[inline] def prev : Substring → String.Pos → String.Pos
  
goal: Substring → String.Pos → String.Pos

full_name: Substring.nextn
code: def nextn : Substring → Nat → String.Pos → String.Pos
  
goal: Substring → Nat → String.Pos → String.Pos

full_name: Substring.prevn
code: def prevn : Substring → Nat → String.Pos → String.Pos
  
goal: Substring → Nat → String.Pos → String.Pos

full_name: Substring.front
code: @[inline] def front (s : Substring) : Char 
goal: Char

full_name: Substring.posOf
code: /-- Return the offset into `s` of the first occurrence of `c` in `s`,
or `s.bsize` if `c` doesn't occur. -/
@[inline] def posOf (s : Substring) (c : Char) : String.Pos 
goal: String.Pos

full_name: Substring.drop
code: @[inline] def drop : Substring → Nat → Substring
  
goal: Substring → Nat → Substring

full_name: Substring.dropRight
code: @[inline] def dropRight : Substring → Nat → Substring
  
goal: Substring → Nat → Substring

full_name: Substring.take
code: @[inline] def take : Substring → Nat → Substring
  
goal: Substring → Nat → Substring

full_name: Substring.takeRight
code: @[inline] def takeRight : Substring → Nat → Substring
  
goal: Substring → Nat → Substring

full_name: Substring.atEnd
code: @[inline] def atEnd : Substring → String.Pos → Bool
  
goal: Substring → String.Pos → Bool

full_name: Substring.extract
code: @[inline] def extract : Substring → String.Pos → String.Pos → Substring
  
goal: Substring → String.Pos → String.Pos → Substring

full_name: Substring.splitOn.loop
code: def splitOn (s : Substring) (sep : String := " ") : List Substring 
goal: List Substring

full_name: Substring.splitOn
code: def splitOn (s : Substring) (sep : String := " ") : List Substring 
goal: List Substring

full_name: Substring.foldl
code: @[inline] def foldl {α : Type u} (f : α → Char → α) (init : α) (s : Substring) : α 
goal: α

full_name: Substring.foldr
code: @[inline] def foldr {α : Type u} (f : Char → α → α) (init : α) (s : Substring) : α 
goal: α

full_name: Substring.any
code: @[inline] def any (s : Substring) (p : Char → Bool) : Bool 
goal: Bool

full_name: Substring.all
code: @[inline] def all (s : Substring) (p : Char → Bool) : Bool 
goal: Bool

full_name: Substring.contains
code: def contains (s : Substring) (c : Char) : Bool 
goal: Bool

full_name: Substring.takeWhileAux
code: @[specialize] def takeWhileAux (s : String) (stopPos : String.Pos) (p : Char → Bool) (i : String.Pos) : String.Pos 
goal: String.Pos

full_name: Substring.takeWhile
code: @[inline] def takeWhile : Substring → (Char → Bool) → Substring
  
goal: Substring → (Char → Bool) → Substring

full_name: Substring.dropWhile
code: @[inline] def dropWhile : Substring → (Char → Bool) → Substring
  
goal: Substring → (Char → Bool) → Substring

full_name: Substring.takeRightWhileAux
code: @[specialize] def takeRightWhileAux (s : String) (begPos : String.Pos) (p : Char → Bool) (i : String.Pos) : String.Pos 
goal: String.Pos

full_name: Substring.takeRightWhile
code: @[inline] def takeRightWhile : Substring → (Char → Bool) → Substring
  
goal: Substring → (Char → Bool) → Substring

full_name: Substring.dropRightWhile
code: @[inline] def dropRightWhile : Substring → (Char → Bool) → Substring
  
goal: Substring → (Char → Bool) → Substring

full_name: Substring.trimLeft
code: @[inline] def trimLeft (s : Substring) : Substring 
goal: Substring

full_name: Substring.trimRight
code: @[inline] def trimRight (s : Substring) : Substring 
goal: Substring

full_name: Substring.trim
code: @[inline] def trim : Substring → Substring
  
goal: Substring → Substring

full_name: Substring.isNat
code: def isNat (s : Substring) : Bool 
goal: Bool

full_name: Substring.toNat?
code: def toNat? (s : Substring) : Option Nat 
goal: Option Nat

full_name: Substring.beq
code: def beq (ss1 ss2 : Substring) : Bool 
goal: Bool

full_name: Substring.hasBeq
code: instance hasBeq : BEq Substring 
goal: BEq Substring

full_name: Substring.sameAs
code: /-- Checks whether two substrings have the same position and content. -/
def sameAs (ss1 ss2 : Substring) : Bool 
goal: Bool

full_name: String.drop
code: def drop (s : String) (n : Nat) : String 
goal: String

full_name: String.dropRight
code: def dropRight (s : String) (n : Nat) : String 
goal: String

full_name: String.take
code: def take (s : String) (n : Nat) : String 
goal: String

full_name: String.takeRight
code: def takeRight (s : String) (n : Nat) : String 
goal: String

full_name: String.takeWhile
code: def takeWhile (s : String) (p : Char → Bool) : String 
goal: String

full_name: String.dropWhile
code: def dropWhile (s : String) (p : Char → Bool) : String 
goal: String

full_name: String.takeRightWhile
code: def takeRightWhile (s : String) (p : Char → Bool) : String 
goal: String

full_name: String.dropRightWhile
code: def dropRightWhile (s : String) (p : Char → Bool) : String 
goal: String

full_name: String.startsWith
code: def startsWith (s pre : String) : Bool 
goal: Bool

full_name: String.endsWith
code: def endsWith (s post : String) : Bool 
goal: Bool

full_name: String.trimRight
code: def trimRight (s : String) : String 
goal: String

full_name: String.trimLeft
code: def trimLeft (s : String) : String 
goal: String

full_name: String.trim
code: def trim (s : String) : String 
goal: String

full_name: String.nextWhile
code: @[inline] def nextWhile (s : String) (p : Char → Bool) (i : String.Pos) : String.Pos 
goal: String.Pos

full_name: String.nextUntil
code: @[inline] def nextUntil (s : String) (p : Char → Bool) (i : String.Pos) : String.Pos 
goal: String.Pos

full_name: String.toUpper
code: def toUpper (s : String) : String 
goal: String

full_name: String.toLower
code: def toLower (s : String) : String 
goal: String

full_name: String.capitalize
code: def capitalize (s : String) 
goal: String

full_name: String.decapitalize
code: def decapitalize (s : String) 
goal: String

full_name: Char.toString
code: protected def toString (c : Char) : String 
goal: String

full_name: Char.length_toString
code: @[simp] theorem length_toString (c : Char) : c.toString.length = 1 
goal: c.toString.length = 1

full_name: String.ext
code: theorem ext {s₁ s₂ : String} (h : s₁.data = s₂.data) : s₁ = s₂ 
goal: s₁ = s₂

full_name: String.ext_iff
code: theorem ext_iff {s₁ s₂ : String} : s₁ = s₂ ↔ s₁.data = s₂.data 
goal: s₁ = s₂ ↔ s₁.data = s₂.data

full_name: String.default_eq
code: @[simp] theorem default_eq : default = "" 
goal: default = ""

full_name: String.length_mk
code: @[simp] theorem length_mk (s : List Char) : (String.mk s).length = s.length 
goal: { data := s }.length = s.length

full_name: String.length_empty
code: @[simp] theorem length_empty : "".length = 0 
goal: "".length = 0

full_name: String.length_singleton
code: @[simp] theorem length_singleton (c : Char) : (String.singleton c).length = 1 
goal: (String.singleton c).length = 1

full_name: String.length_push
code: @[simp] theorem length_push (c : Char) : (String.push s c).length = s.length + 1 
goal: (s.push c).length = s.length + 1

full_name: String.length_pushn
code: @[simp] theorem length_pushn (c : Char) (n : Nat) : (pushn s c n).length = s.length + n 
goal: (s.pushn c n).length = s.length + n

full_name: String.length_append
code: @[simp] theorem length_append (s t : String) : (s ++ t).length = s.length + t.length 
goal: (s ++ t).length = s.length + t.length

full_name: String.data_push
code: @[simp] theorem data_push (s : String) (c : Char) : (s.push c).data = s.data ++ [c] 
goal: (s.push c).data = s.data ++ c :: List.nil

full_name: String.data_append
code: @[simp] theorem data_append (s t : String) : (s ++ t).data = s.data ++ t.data 
goal: (s ++ t).data = s.data ++ t.data

full_name: String.lt_iff
code: theorem lt_iff (s t : String) : s < t ↔ s.data < t.data 
goal: s < t ↔ s.data < t.data

full_name: String.Pos.byteIdx_zero
code: @[simp] theorem byteIdx_zero : (0 : Pos).byteIdx = 0 
goal: String.Pos.byteIdx 0 = 0

full_name: String.Pos.byteIdx_mk
code: theorem byteIdx_mk (n : Nat) : byteIdx ⟨n⟩ = n 
goal: { byteIdx := n }.byteIdx = n

full_name: String.Pos.mk_zero
code: @[simp] theorem mk_zero : ⟨0⟩ = (0 : Pos) 
goal: { byteIdx := 0 } = 0

full_name: String.Pos.mk_byteIdx
code: @[simp] theorem mk_byteIdx (p : Pos) : ⟨p.byteIdx⟩ = p 
goal: { byteIdx := p.byteIdx } = p

full_name: String.Pos.ext
code: theorem ext {i₁ i₂ : Pos} (h : i₁.byteIdx = i₂.byteIdx) : i₁ = i₂ 
goal: i₁ = i₂

full_name: String.Pos.ext_iff
code: theorem ext_iff {i₁ i₂ : Pos} : i₁ = i₂ ↔ i₁.byteIdx = i₂.byteIdx 
goal: i₁ = i₂ ↔ i₁.byteIdx = i₂.byteIdx

full_name: String.Pos.add_byteIdx
code: @[simp] theorem add_byteIdx (p₁ p₂ : Pos) : (p₁ + p₂).byteIdx = p₁.byteIdx + p₂.byteIdx 
goal: (p₁ + p₂).byteIdx = p₁.byteIdx + p₂.byteIdx

full_name: String.Pos.add_eq
code: theorem add_eq (p₁ p₂ : Pos) : p₁ + p₂ = ⟨p₁.byteIdx + p₂.byteIdx⟩ 
goal: p₁ + p₂ = { byteIdx := p₁.byteIdx + p₂.byteIdx }

full_name: String.Pos.sub_byteIdx
code: @[simp] theorem sub_byteIdx (p₁ p₂ : Pos) : (p₁ - p₂).byteIdx = p₁.byteIdx - p₂.byteIdx 
goal: (p₁ - p₂).byteIdx = p₁.byteIdx - p₂.byteIdx

full_name: String.Pos.sub_eq
code: theorem sub_eq (p₁ p₂ : Pos) : p₁ - p₂ = ⟨p₁.byteIdx - p₂.byteIdx⟩ 
goal: p₁ - p₂ = { byteIdx := p₁.byteIdx - p₂.byteIdx }

full_name: String.Pos.addChar_byteIdx
code: @[simp] theorem addChar_byteIdx (p : Pos) (c : Char) : (p + c).byteIdx = p.byteIdx + c.utf8Size 
goal: (p + c).byteIdx = p.byteIdx + c.utf8Size

full_name: String.Pos.addChar_eq
code: theorem addChar_eq (p : Pos) (c : Char) : p + c = ⟨p.byteIdx + c.utf8Size⟩ 
goal: p + c = { byteIdx := p.byteIdx + c.utf8Size }

full_name: String.Pos.zero_addChar_byteIdx
code: theorem zero_addChar_byteIdx (c : Char) : ((0 : Pos) + c).byteIdx = c.utf8Size 
goal: (0 + c).byteIdx = c.utf8Size

full_name: String.Pos.zero_addChar_eq
code: theorem zero_addChar_eq (c : Char) : (0 : Pos) + c = ⟨c.utf8Size⟩ 
goal: 0 + c = { byteIdx := c.utf8Size }

full_name: String.Pos.addChar_right_comm
code: theorem addChar_right_comm (p : Pos) (c₁ c₂ : Char) : p + c₁ + c₂ = p + c₂ + c₁ 
goal: p + c₁ + c₂ = p + c₂ + c₁

full_name: String.Pos.ne_of_lt
code: theorem ne_of_lt {i₁ i₂ : Pos} (h : i₁ < i₂) : i₁ ≠ i₂ 
goal: i₁ ≠ i₂

full_name: String.Pos.ne_of_gt
code: theorem ne_of_gt {i₁ i₂ : Pos} (h : i₁ < i₂) : i₂ ≠ i₁ 
goal: i₂ ≠ i₁

full_name: String.Pos.addString_byteIdx
code: @[simp] theorem addString_byteIdx (p : Pos) (s : String) :
    (p + s).byteIdx = p.byteIdx + s.utf8ByteSize 
goal: (p + s).byteIdx = p.byteIdx + s.utf8ByteSize

full_name: String.Pos.addString_eq
code: theorem addString_eq (p : Pos) (s : String) : p + s = ⟨p.byteIdx + s.utf8ByteSize⟩ 
goal: p + s = { byteIdx := p.byteIdx + s.utf8ByteSize }

full_name: String.Pos.zero_addString_byteIdx
code: theorem zero_addString_byteIdx (s : String) : ((0 : Pos) + s).byteIdx = s.utf8ByteSize 
goal: (0 + s).byteIdx = s.utf8ByteSize

full_name: String.Pos.zero_addString_eq
code: theorem zero_addString_eq (s : String) : (0 : Pos) + s = ⟨s.utf8ByteSize⟩ 
goal: 0 + s = { byteIdx := s.utf8ByteSize }

full_name: String.Pos.le_iff
code: theorem le_iff {i₁ i₂ : Pos} : i₁ ≤ i₂ ↔ i₁.byteIdx ≤ i₂.byteIdx 
goal: i₁ ≤ i₂ ↔ i₁.byteIdx ≤ i₂.byteIdx

full_name: String.Pos.mk_le_mk
code: @[simp] theorem mk_le_mk {i₁ i₂ : Nat} : Pos.mk i₁ ≤ Pos.mk i₂ ↔ i₁ ≤ i₂ 
goal: { byteIdx := i₁ } ≤ { byteIdx := i₂ } ↔ i₁ ≤ i₂

full_name: String.Pos.lt_iff
code: theorem lt_iff {i₁ i₂ : Pos} : i₁ < i₂ ↔ i₁.byteIdx < i₂.byteIdx 
goal: i₁ < i₂ ↔ i₁.byteIdx < i₂.byteIdx

full_name: String.Pos.mk_lt_mk
code: @[simp] theorem mk_lt_mk {i₁ i₂ : Nat} : Pos.mk i₁ < Pos.mk i₂ ↔ i₁ < i₂ 
goal: { byteIdx := i₁ } < { byteIdx := i₂ } ↔ i₁ < i₂

full_name: String.get!_eq_get
code: @[simp] theorem get!_eq_get (s : String) (p : Pos) : get! s p = get s p 
goal: s.get! p = s.get p

full_name: String.lt_next'
code: theorem lt_next' (s : String) (p : Pos) : p < next s p 
goal: p < s.next p

full_name: String.prev_zero
code: @[simp] theorem prev_zero (s : String) : prev s 0 = 0 
goal: s.prev 0 = 0

full_name: String.get'_eq
code: @[simp] theorem get'_eq (s : String) (p : Pos) (h) : get' s p h = get s p 
goal: s.get' p h = s.get p

full_name: String.next'_eq
code: @[simp] theorem next'_eq (s : String) (p : Pos) (h) : next' s p h = next s p 
goal: s.next' p h = s.next p

full_name: String.singleton_eq
code: theorem singleton_eq (c : Char) : singleton c = ⟨[c]⟩ 
goal: String.singleton c = { data := c :: List.nil }

full_name: String.data_singleton
code: @[simp] theorem data_singleton (c : Char) : (singleton c).data = [c] 
goal: (String.singleton c).data = c :: List.nil

full_name: String.append_empty
code: @[simp] theorem append_empty (s : String) : s ++ "" = s 
goal: s ++ "" = s

full_name: String.empty_append
code: @[simp] theorem empty_append (s : String) : "" ++ s = s 
goal: "" ++ s = s

full_name: String.append_assoc
code: theorem append_assoc (s₁ s₂ s₃ : String) : (s₁ ++ s₂) ++ s₃ = s₁ ++ (s₂ ++ s₃) 
goal: s₁ ++ s₂ ++ s₃ = s₁ ++ (s₂ ++ s₃)

full_name: Substring.prev_zero
code: @[simp] theorem prev_zero (s : Substring) : s.prev 0 = 0 
goal: s.prev 0 = 0

full_name: Substring.prevn_zero
code: @[simp] theorem prevn_zero (s : Substring) : ∀ n, s.prevn n 0 = 0
  
goal: s.prevn n 0 = 0