Documentation

Batteries.Data.String.Lemmas

theorem String.lt_antisymm {s₁ s₂ : String} (h₁ : ¬s₁ < s₂) (h₂ : ¬s₂ < s₁) :
s₁ = s₂
@[deprecated String.length_ofList (since := "2025-10-31")]
theorem String.Pos.Raw.offsetBy_eq {p q : Raw} :
p.offsetBy q = { byteIdx := q.byteIdx + p.byteIdx }
@[inline]

The UTF-8 byte length of a list of characters. (This is intended for specification purposes.)

Equations
    Instances For
      @[deprecated String.utf8ByteSize_ofList (since := "2025-10-31")]
      @[simp]
      theorem String.utf8Len_cons (c : Char) (cs : List Char) :
      @[simp]
      theorem String.utf8Len_append (cs₁ cs₂ : List Char) :
      utf8Len (cs₁ ++ cs₂) = utf8Len cs₁ + utf8Len cs₂
      theorem String.utf8Len_reverseAux (cs₁ cs₂ : List Char) :
      utf8Len (cs₁.reverseAux cs₂) = utf8Len cs₁ + utf8Len cs₂
      @[simp]
      theorem String.utf8Len_le_of_sublist {cs₁ cs₂ : List Char} :
      cs₁.Sublist cs₂utf8Len cs₁ utf8Len cs₂
      theorem String.utf8Len_le_of_infix {cs₁ cs₂ : List Char} (h : cs₁ <:+: cs₂) :
      utf8Len cs₁ utf8Len cs₂
      theorem String.utf8Len_le_of_suffix {cs₁ cs₂ : List Char} (h : cs₁ <:+ cs₂) :
      utf8Len cs₁ utf8Len cs₂
      theorem String.utf8Len_le_of_prefix {cs₁ cs₂ : List Char} (h : cs₁ <+: cs₂) :
      utf8Len cs₁ utf8Len cs₂
      @[simp]
      theorem String.rawEndPos_ofList (cs : List Char) :
      (ofList cs).rawEndPos = { byteIdx := utf8Len cs }
      @[deprecated String.rawEndPos_ofList (since := "2025-10-31")]
      theorem String.rawEndPos_asString (cs : List Char) :
      (ofList cs).rawEndPos = { byteIdx := utf8Len cs }
      @[deprecated String.rawEndPos_ofList (since := "2025-10-21")]
      theorem String.endPos_asString (cs : List Char) :
      (ofList cs).rawEndPos = { byteIdx := utf8Len cs }
      @[deprecated String.rawEndPos_ofList (since := "2025-10-21")]
      theorem String.rawEndPos_mk (cs : List Char) :
      (ofList cs).rawEndPos = { byteIdx := utf8Len cs }
      @[deprecated String.rawEndPos_ofList (since := "2025-10-21")]
      theorem String.endPos_mk (cs : List Char) :
      (ofList cs).rawEndPos = { byteIdx := utf8Len cs }
      @[deprecated String.utf8Len_toList (since := "2025-10-21")]
      theorem String.Pos.Raw.lt_addChar (p : Raw) (c : Char) :
      p < p + c
      inductive String.Pos.Raw.Valid :
      StringRawProp

      A string position is valid if it is equal to the UTF-8 length of an initial substring of s.

      Instances For
        theorem String.Pos.Raw.Valid.intro {s : String} {p : Raw} (h : (cs : List Char), (cs' : List Char), cs ++ cs' = s.toList p.byteIdx = utf8Len cs) :
        Valid s p
        theorem String.Pos.Raw.Valid.exists {s : String} {p : Raw} :
        Valid s p (cs : List Char), (cs' : List Char), ofList (cs ++ cs') = s p = { byteIdx := utf8Len cs }
        @[simp]
        @[deprecated String.Pos.Raw.valid_rawEndPos (since := "2025-10-21")]
        @[deprecated String.Pos.Raw.Valid.le_rawEndPos (since := "2025-10-21")]
        theorem String.Pos.Raw.Valid.le_endPos {s : String} {p : Raw} :
        Valid s pp s.rawEndPos
        @[deprecated String.rawEndPos_eq_zero_iff (since := "2025-10-21")]
        theorem String.endPos_eq_zero (s : String) :
        s.rawEndPos = 0 s = ""
        def String.utf8InductionOn {motive : List CharPos.RawSort u} (s : List Char) (i p : Pos.Raw) (nil : (i : Pos.Raw) → motive [] i) (eq : (c : Char) → (cs : List Char) → motive (c :: cs) p) (ind : (c : Char) → (cs : List Char) → (i : Pos.Raw) → i pmotive cs (i + c)motive (c :: cs) i) :
        motive s i

        Induction along the valid positions in a list of characters. (This definition is intended only for specification purposes.)

        Equations
          Instances For
            theorem String.utf8GetAux_add_right_cancel (s : List Char) (i p n : Nat) :
            Pos.Raw.utf8GetAux s { byteIdx := i + n } { byteIdx := p + n } = Pos.Raw.utf8GetAux s { byteIdx := i } { byteIdx := p }
            theorem String.utf8GetAux_of_valid (cs cs' : List Char) {i p : Nat} (hp : i + utf8Len cs = p) :
            Pos.Raw.utf8GetAux (cs ++ cs') { byteIdx := i } { byteIdx := p } = cs'.headD default
            theorem String.get_of_valid (cs cs' : List Char) :
            Pos.Raw.get (ofList (cs ++ cs')) { byteIdx := utf8Len cs } = cs'.headD default
            theorem String.get_cons_addChar (c : Char) (cs : List Char) (i : Pos.Raw) :
            Pos.Raw.get (ofList (c :: cs)) (i + c) = Pos.Raw.get (ofList cs) i
            theorem String.utf8GetAux?_of_valid (cs cs' : List Char) {i p : Nat} (hp : i + utf8Len cs = p) :
            Pos.Raw.utf8GetAux? (cs ++ cs') { byteIdx := i } { byteIdx := p } = cs'.head?
            theorem String.get?_of_valid (cs cs' : List Char) :
            Pos.Raw.get? (ofList (cs ++ cs')) { byteIdx := utf8Len cs } = cs'.head?
            theorem String.utf8SetAux_of_valid (c' : Char) (cs cs' : List Char) {i p : Nat} (hp : i + utf8Len cs = p) :
            Pos.Raw.utf8SetAux c' (cs ++ cs') { byteIdx := i } { byteIdx := p } = cs ++ List.modifyHead (fun (x : Char) => c') cs'
            theorem String.set_of_valid (cs cs' : List Char) (c' : Char) :
            Pos.Raw.set (ofList (cs ++ cs')) { byteIdx := utf8Len cs } c' = ofList (cs ++ List.modifyHead (fun (x : Char) => c') cs')
            theorem String.modify_of_valid {f : CharChar} (cs cs' : List Char) :
            Pos.Raw.modify (ofList (cs ++ cs')) { byteIdx := utf8Len cs } f = ofList (cs ++ List.modifyHead f cs')
            theorem String.next_of_valid' (cs cs' : List Char) :
            Pos.Raw.next (ofList (cs ++ cs')) { byteIdx := utf8Len cs } = { byteIdx := utf8Len cs + (cs'.headD default).utf8Size }
            theorem String.next_of_valid (cs : List Char) (c : Char) (cs' : List Char) :
            Pos.Raw.next (ofList (cs ++ c :: cs')) { byteIdx := utf8Len cs } = { byteIdx := utf8Len cs + c.utf8Size }
            theorem String.valid_next {s : String} {p : Pos.Raw} (h : Pos.Raw.Valid s p) (h₂ : p < s.rawEndPos) :
            theorem String.utf8PrevAux_of_valid {cs cs' : List Char} {c : Char} {i p : Nat} (hp : i + (utf8Len cs + c.utf8Size) = p) :
            Pos.Raw.utf8PrevAux (cs ++ c :: cs') { byteIdx := i } { byteIdx := p } = { byteIdx := i + utf8Len cs }
            theorem String.prev_of_valid (cs : List Char) (c : Char) (cs' : List Char) :
            Pos.Raw.prev (ofList (cs ++ c :: cs')) { byteIdx := utf8Len cs + c.utf8Size } = { byteIdx := utf8Len cs }
            theorem String.prev_of_valid' (cs cs' : List Char) :
            Pos.Raw.prev (ofList (cs ++ cs')) { byteIdx := utf8Len cs } = { byteIdx := utf8Len cs.dropLast }
            theorem String.atEnd_of_valid (cs cs' : List Char) :
            Pos.Raw.atEnd (ofList (cs ++ cs')) { byteIdx := utf8Len cs } = true cs' = []
            theorem String.posOfAux_eq (s : String) (c : Char) :
            Legacy.posOfAux s c = Legacy.findAux s fun (x : Char) => x == c
            theorem String.posOf_eq (s : String) (c : Char) :
            Legacy.posOf s c = Legacy.find s fun (x : Char) => x == c
            theorem String.revPosOf_eq (s : String) (c : Char) :
            Legacy.revPosOf s c = Legacy.revFind s fun (x : Char) => x == c
            theorem String.findAux_of_valid (p : CharBool) (l m r : List Char) :
            Legacy.findAux (ofList (l ++ m ++ r)) p { byteIdx := utf8Len l + utf8Len m } { byteIdx := utf8Len l } = { byteIdx := utf8Len l + utf8Len (List.takeWhile (fun (x : Char) => !p x) m) }
            theorem String.find_of_valid (p : CharBool) (s : String) :
            Legacy.find s p = { byteIdx := utf8Len (List.takeWhile (fun (x : Char) => !p x) s.toList) }
            theorem String.revFindAux_of_valid (p : CharBool) (l r : List Char) :
            Legacy.revFindAux (ofList (l.reverse ++ r)) p { byteIdx := utf8Len l } = Option.map (fun (x : List Char) => { byteIdx := utf8Len x }) (List.dropWhile (fun (x : Char) => !p x) l).tail?
            theorem String.revFind_of_valid (p : CharBool) (s : String) :
            Legacy.revFind s p = Option.map (fun (x : List Char) => { byteIdx := utf8Len x }) (List.dropWhile (fun (x : Char) => !p x) s.toList.reverse).tail?
            @[irreducible]
            theorem String.firstDiffPos_loop_eq (l₁ l₂ r₁ r₂ : List Char) (stop p : Nat) (hl₁ : p = utf8Len l₁) (hl₂ : p = utf8Len l₂) (hstop : stop = min (utf8Len l₁ + utf8Len r₁) (utf8Len l₂ + utf8Len r₂)) :
            firstDiffPos.loop (ofList (l₁ ++ r₁)) (ofList (l₂ ++ r₂)) { byteIdx := stop } { byteIdx := p } = { byteIdx := p + utf8Len (List.takeWhile₂ (fun (x1 x2 : Char) => decide (x1 = x2)) r₁ r₂).fst }
            theorem String.firstDiffPos_eq (a b : String) :
            a.firstDiffPos b = { byteIdx := utf8Len (List.takeWhile₂ (fun (x1 x2 : Char) => decide (x1 = x2)) a.toList b.toList).fst }
            theorem String.Pos.Raw.extract.go₂_add_right_cancel (s : List Char) (i e n : Nat) :
            go₂ s { byteIdx := i + n } { byteIdx := e + n } = go₂ s { byteIdx := i } { byteIdx := e }
            theorem String.Pos.Raw.extract.go₂_append_left (s t : List Char) (i e : Nat) :
            e = utf8Len s + igo₂ (s ++ t) { byteIdx := i } { byteIdx := e } = s
            theorem String.Pos.Raw.extract.go₁_add_right_cancel (s : List Char) (i b e n : Nat) :
            go₁ s { byteIdx := i + n } { byteIdx := b + n } { byteIdx := e + n } = go₁ s { byteIdx := i } { byteIdx := b } { byteIdx := e }
            theorem String.Pos.Raw.extract.go₁_cons_addChar (c : Char) (cs : List Char) (b e : Raw) :
            go₁ (c :: cs) 0 (b + c) (e + c) = go₁ cs 0 b e
            theorem String.Pos.Raw.extract.go₁_append_right (s t : List Char) (i b : Nat) (e : Raw) :
            b = utf8Len s + igo₁ (s ++ t) { byteIdx := i } { byteIdx := b } e = go₂ t { byteIdx := b } e
            theorem String.extract_cons_addChar (c : Char) (cs : List Char) (b e : Pos.Raw) :
            Pos.Raw.extract (ofList (c :: cs)) (b + c) (e + c) = Pos.Raw.extract (ofList cs) b e
            @[deprecated String.extract_zero_rawEndPos (since := "2025-10-21")]
            theorem String.extract_of_valid (l m r : List Char) :
            Pos.Raw.extract (ofList (l ++ m ++ r)) { byteIdx := utf8Len l } { byteIdx := utf8Len l + utf8Len m } = ofList m
            @[irreducible]
            theorem String.splitAux_of_valid (p : CharBool) (l m r : List Char) (acc : List String) :
            (ofList (l ++ m ++ r)).splitAux p { byteIdx := utf8Len l } { byteIdx := utf8Len l + utf8Len m } acc = acc.reverse ++ List.map ofList (List.splitOnP.go p r m.reverse)
            @[deprecated String.splitToList_of_valid (since := "2025-10-18")]
            @[deprecated String.toList_join (since := "2025-10-31")]
            theorem String.Legacy.Iterator.hasNext_cons_addChar (c : Char) (cs : List Char) (i : Pos.Raw) :
            { s := ofList (c :: cs), i := i + c }.hasNext = { s := ofList cs, i := i }.hasNext

            Validity for a string iterator.

            Equations
              Instances For

                it.ValidFor l r means that it is a string iterator whose underlying string is l.reverse ++ r, and where the cursor is pointing at the end of l.reverse.

                Instances For
                  theorem String.Legacy.Iterator.ValidFor.out {l r : List Char} {it : Iterator} :
                  ValidFor l r itit = { s := ofList (l.reverseAux r), i := { byteIdx := utf8Len l } }
                  theorem String.Legacy.Iterator.ValidFor.out' {l r : List Char} {it : Iterator} :
                  ValidFor l r itit = { s := ofList (l.reverse ++ r), i := { byteIdx := utf8Len l.reverse } }
                  theorem String.Legacy.Iterator.ValidFor.mk' {l r : List Char} :
                  ValidFor l r { s := ofList (l.reverse ++ r), i := { byteIdx := utf8Len l.reverse } }
                  theorem String.Legacy.Iterator.ValidFor.pos {l r : List Char} {it : Iterator} :
                  ValidFor l r itit.i = { byteIdx := utf8Len l }
                  @[deprecated String.Legacy.Iterator.ValidFor.pos_eq_rawEndPos (since := "2025-10-21")]
                  theorem String.Legacy.Iterator.ValidFor.next {l : List Char} {c : Char} {r : List Char} {it : Iterator} :
                  ValidFor l (c :: r) itValidFor (c :: l) r it.next
                  theorem String.Legacy.Iterator.ValidFor.prev {c : Char} {l r : List Char} {it : Iterator} :
                  ValidFor (c :: l) r itValidFor l (c :: r) it.prev
                  theorem String.Legacy.Iterator.ValidFor.setCurr' {l r : List Char} {c : Char} {it : Iterator} :
                  ValidFor l r itValidFor l (List.modifyHead (fun (x : Char) => c) r) (it.setCurr c)
                  theorem String.Legacy.Iterator.ValidFor.setCurr {l : List Char} {c : Char} {r : List Char} {it : Iterator} (h : ValidFor l (c :: r) it) :
                  ValidFor l (c :: r) (it.setCurr c)
                  theorem String.Legacy.Iterator.ValidFor.extract {l m r : List Char} {it₁ it₂ : Iterator} (h₁ : ValidFor l (m ++ r) it₁) (h₂ : ValidFor (m.reverse ++ l) r it₂) :
                  it₁.extract it₂ = ofList m
                  theorem String.Legacy.Iterator.ValidFor.nextn {l r : List Char} {it : Iterator} :
                  ValidFor l r it∀ (n : Nat), n r.lengthValidFor ((List.take n r).reverse ++ l) (List.drop n r) (it.nextn n)
                  theorem String.Legacy.Iterator.ValidFor.prevn {l r : List Char} {it : Iterator} :
                  ValidFor l r it∀ (n : Nat), n l.lengthValidFor (List.drop n l) ((List.take n l).reverse ++ r) (it.prevn n)
                  theorem String.offsetOfPosAux_of_valid (l m r : List Char) (n : Nat) :
                  Pos.Raw.offsetOfPosAux (ofList (l ++ m ++ r)) { byteIdx := utf8Len l + utf8Len m } { byteIdx := utf8Len l } n = n + m.length
                  theorem String.foldlAux_of_valid {α : Type u_1} (f : αCharα) (l m r : List Char) (a : α) :
                  Legacy.foldlAux f (ofList (l ++ m ++ r)) { byteIdx := utf8Len l + utf8Len m } { byteIdx := utf8Len l } a = List.foldl f a m
                  theorem String.foldl_eq {α : Type u_1} (f : αCharα) (s : String) (a : α) :
                  theorem String.foldrAux_of_valid {α : Type u_1} (f : Charαα) (l m r : List Char) (a : α) :
                  Legacy.foldrAux f a (ofList (l ++ m ++ r)) { byteIdx := utf8Len l + utf8Len m } { byteIdx := utf8Len l } = List.foldr f a m
                  theorem String.foldr_eq {α : Type u_1} (f : Charαα) (s : String) (a : α) :
                  theorem String.anyAux_of_valid (p : CharBool) (l m r : List Char) :
                  Legacy.anyAux (ofList (l ++ m ++ r)) { byteIdx := utf8Len l + utf8Len m } p { byteIdx := utf8Len l } = m.any p
                  theorem String.any_eq (s : String) (p : CharBool) :
                  theorem String.any_iff (s : String) (p : CharBool) :
                  theorem String.all_eq (s : String) (p : CharBool) :
                  theorem String.all_iff (s : String) (p : CharBool) :
                  Legacy.all s p = true ∀ (c : Char), c s.toListp c = true
                  theorem String.mapAux_of_valid (f : CharChar) (l r : List Char) :
                  Legacy.mapAux f { byteIdx := utf8Len l } (ofList (l ++ r)) = ofList (l ++ List.map f r)
                  theorem String.map_eq (f : CharChar) (s : String) :
                  theorem String.takeWhileAux_of_valid (p : CharBool) (l m r : List Char) :
                  Substring.Raw.takeWhileAux (ofList (l ++ m ++ r)) { byteIdx := utf8Len l + utf8Len m } p { byteIdx := utf8Len l } = { byteIdx := utf8Len l + utf8Len (List.takeWhile p m) }
                  @[simp]
                  theorem String.map_eq_empty_iff (s : String) (f : CharChar) :
                  Legacy.map f s = "" s = ""
                  @[simp]
                  theorem String.Legacy.length_map (s : String) (f : CharChar) :
                  (map f s).length = s.length
                  theorem String.Legacy.length_eq_of_map_eq {a b : String} {f g : CharChar} :
                  map f a = map g ba.length = b.length
                  theorem String.length_eq_of_map_eq {a b : String} {f g : CharChar} :
                  map f a = map g ba.length = b.length
                  structure Substring.Raw.Valid (s : Raw) :

                  Validity for a substring.

                  Instances For
                    inductive Substring.Raw.ValidFor (l m r : List Char) :
                    RawProp

                    A substring is represented by three lists l m r, where m is the middle section (the actual substring) and l ++ m ++ r is the underlying string.

                    Instances For
                      theorem Substring.Raw.ValidFor.valid {l m r : List Char} {s : Raw} :
                      ValidFor l m r ss.Valid
                      theorem Substring.Raw.ValidFor.str {l m r : List Char} {s : Raw} :
                      ValidFor l m r ss.str = String.ofList (l ++ m ++ r)
                      theorem Substring.Raw.ValidFor.startPos {l m r : List Char} {s : Raw} :
                      ValidFor l m r ss.startPos = { byteIdx := String.utf8Len l }
                      theorem Substring.Raw.ValidFor.stopPos {l m r : List Char} {s : Raw} :
                      ValidFor l m r ss.stopPos = { byteIdx := String.utf8Len l + String.utf8Len m }
                      theorem Substring.Raw.ValidFor.isEmpty {l m r : List Char} {s : Raw} :
                      ValidFor l m r s → (s.isEmpty = true m = [])
                      theorem Substring.Raw.ValidFor.get {l m₁ : List Char} {c : Char} {m₂ r : List Char} {s : Raw} :
                      ValidFor l (m₁ ++ c :: m₂) r ss.get { byteIdx := String.utf8Len m₁ } = c
                      theorem Substring.Raw.ValidFor.next {l m₁ : List Char} {c : Char} {m₂ r : List Char} {s : Raw} :
                      ValidFor l (m₁ ++ c :: m₂) r ss.next { byteIdx := String.utf8Len m₁ } = { byteIdx := String.utf8Len m₁ + c.utf8Size }
                      theorem Substring.Raw.ValidFor.next_stop {l m r : List Char} {s : Raw} :
                      ValidFor l m r ss.next { byteIdx := String.utf8Len m } = { byteIdx := String.utf8Len m }
                      theorem Substring.Raw.ValidFor.prev {l m₁ : List Char} {c : Char} {m₂ r : List Char} {s : Raw} :
                      ValidFor l (m₁ ++ c :: m₂) r ss.prev { byteIdx := String.utf8Len m₁ + c.utf8Size } = { byteIdx := String.utf8Len m₁ }
                      theorem Substring.Raw.ValidFor.nextn_stop {l m r : List Char} {s : Raw} :
                      ValidFor l m r s∀ (n : Nat), s.nextn n { byteIdx := String.utf8Len m } = { byteIdx := String.utf8Len m }
                      theorem Substring.Raw.ValidFor.nextn {l m₁ m₂ r : List Char} {s : Raw} :
                      ValidFor l (m₁ ++ m₂) r s∀ (n : Nat), s.nextn n { byteIdx := String.utf8Len m₁ } = { byteIdx := String.utf8Len m₁ + String.utf8Len (List.take n m₂) }
                      theorem Substring.Raw.ValidFor.prevn {l m₂ r m₁ : List Char} {s : Raw} :
                      ValidFor l (m₁.reverse ++ m₂) r s∀ (n : Nat), s.prevn n { byteIdx := String.utf8Len m₁ } = { byteIdx := String.utf8Len (List.drop n m₁) }
                      theorem Substring.Raw.ValidFor.front {l : List Char} {c : Char} {m r : List Char} {s : Raw} :
                      ValidFor l (c :: m) r ss.front = c
                      theorem Substring.Raw.ValidFor.drop {l m r : List Char} {s : Raw} :
                      ValidFor l m r s∀ (n : Nat), ValidFor (l ++ List.take n m) (List.drop n m) r (s.drop n)
                      theorem Substring.Raw.ValidFor.take {l m r : List Char} {s : Raw} :
                      ValidFor l m r s∀ (n : Nat), ValidFor l (List.take n m) (List.drop n m ++ r) (s.take n)
                      theorem Substring.Raw.ValidFor.atEnd {l m r : List Char} {p : Nat} {s : Raw} :
                      ValidFor l m r s → (s.atEnd { byteIdx := p } = true p = String.utf8Len m)
                      theorem Substring.Raw.ValidFor.extract' {l ml mm mr r : List Char} {b e : String.Pos.Raw} {s : Raw} :
                      ValidFor l (ml ++ mm ++ mr) r sValidFor ml mm mr { str := String.ofList (ml ++ mm ++ mr), startPos := b, stopPos := e } (l' : List Char), (r' : List Char), ValidFor l' mm r' (s.extract b e)
                      theorem Substring.Raw.ValidFor.extract {l m r ml mm mr : List Char} {b e : String.Pos.Raw} {s : Raw} :
                      ValidFor l m r sValidFor ml mm mr { str := String.ofList m, startPos := b, stopPos := e } (l' : List Char), (r' : List Char), ValidFor l' mm r' (s.extract b e)
                      theorem Substring.Raw.ValidFor.foldl {α : Type u_1} {l m r : List Char} (f : αCharα) (init : α) {s : Raw} :
                      ValidFor l m r sLegacy.foldl f init s = List.foldl f init m
                      theorem Substring.Raw.ValidFor.foldr {α : Type u_1} {l m r : List Char} (f : Charαα) (init : α) {s : Raw} :
                      ValidFor l m r sLegacy.foldr f init s = List.foldr f init m
                      theorem Substring.Raw.ValidFor.any {l m r : List Char} (f : CharBool) {s : Raw} :
                      ValidFor l m r sLegacy.any s f = m.any f
                      theorem Substring.Raw.ValidFor.all {l m r : List Char} (f : CharBool) {s : Raw} :
                      ValidFor l m r sLegacy.all s f = m.all f
                      theorem Substring.Raw.ValidFor.contains {l m r : List Char} (c : Char) {s : Raw} :
                      ValidFor l m r s → (Legacy.contains s c = true c m)
                      theorem Substring.Raw.ValidFor.takeWhile {l m r : List Char} (p : CharBool) {s : Raw} :
                      ValidFor l m r sValidFor l (List.takeWhile p m) (List.dropWhile p m ++ r) (s.takeWhile p)
                      theorem Substring.Raw.ValidFor.dropWhile {l m r : List Char} (p : CharBool) {s : Raw} :
                      ValidFor l m r sValidFor (l ++ List.takeWhile p m) (List.dropWhile p m) r (s.dropWhile p)
                      theorem Substring.Raw.Valid.valid {l m r : List Char} {s : Raw} :
                      ValidFor l m r ss.Valid
                      theorem Substring.Raw.Valid.get {m₁ : List Char} {c : Char} {m₂ : List Char} {s : Raw} :
                      s.Valids.toString.toList = m₁ ++ c :: m₂s.get { byteIdx := String.utf8Len m₁ } = c
                      theorem Substring.Raw.Valid.next {m₁ : List Char} {c : Char} {m₂ : List Char} {s : Raw} :
                      s.Valids.toString.toList = m₁ ++ c :: m₂s.next { byteIdx := String.utf8Len m₁ } = { byteIdx := String.utf8Len m₁ + c.utf8Size }
                      theorem Substring.Raw.Valid.next_stop {s : Raw} :
                      s.Valids.next { byteIdx := s.bsize } = { byteIdx := s.bsize }
                      theorem Substring.Raw.Valid.prev {m₁ : List Char} {c : Char} {m₂ : List Char} {s : Raw} :
                      s.Valids.toString.toList = m₁ ++ c :: m₂s.prev { byteIdx := String.utf8Len m₁ + c.utf8Size } = { byteIdx := String.utf8Len m₁ }
                      theorem Substring.Raw.Valid.nextn_stop {s : Raw} :
                      s.Valid∀ (n : Nat), s.nextn n { byteIdx := s.bsize } = { byteIdx := s.bsize }
                      theorem Substring.Raw.Valid.nextn {m₁ m₂ : List Char} {s : Raw} :
                      s.Valids.toString.toList = m₁ ++ m₂∀ (n : Nat), s.nextn n { byteIdx := String.utf8Len m₁ } = { byteIdx := String.utf8Len m₁ + String.utf8Len (List.take n m₂) }
                      theorem Substring.Raw.Valid.prevn {m₂ m₁ : List Char} {s : Raw} :
                      s.Valids.toString.toList = m₁.reverse ++ m₂∀ (n : Nat), s.prevn n { byteIdx := String.utf8Len m₁ } = { byteIdx := String.utf8Len (List.drop n m₁) }
                      theorem Substring.Raw.Valid.front {c : Char} {m : List Char} {s : Raw} :
                      s.Valids.toString.toList = c :: ms.front = c
                      theorem Substring.Raw.Valid.drop {s : Raw} :
                      s.Valid∀ (n : Nat), (s.drop n).Valid
                      theorem Substring.Raw.Valid.take {s : Raw} :
                      s.Valid∀ (n : Nat), (s.take n).Valid
                      theorem Substring.Raw.Valid.atEnd {p : Nat} {s : Raw} :
                      s.Valid → (s.atEnd { byteIdx := p } = true p = s.toString.utf8ByteSize)
                      theorem Substring.Raw.Valid.extract {b e : String.Pos.Raw} {s : Raw} :
                      s.Valid{ str := s.toString, startPos := b, stopPos := e }.Valid(s.extract b e).Valid
                      theorem Substring.Raw.Valid.toString_extract {b e : String.Pos.Raw} {s : Raw} :
                      s.Valid{ str := s.toString, startPos := b, stopPos := e }.Valid(s.extract b e).toString = String.Pos.Raw.extract s.toString b e
                      theorem Substring.Raw.Valid.foldl {α : Type u_1} (f : αCharα) (init : α) {s : Raw} :
                      s.ValidLegacy.foldl f init s = List.foldl f init s.toString.toList
                      theorem Substring.Raw.Valid.foldr {α : Type u_1} (f : Charαα) (init : α) {s : Raw} :
                      s.ValidLegacy.foldr f init s = List.foldr f init s.toString.toList
                      @[simp]
                      @[simp]
                      theorem String.drop_empty {n : Nat} :
                      Legacy.drop "" n = ""
                      @[simp]