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) :
        s.posOfAux c = s.findAux fun (x : Char) => x == c
        theorem String.posOf_eq (s : String) (c : Char) :
        s.posOf c = s.find fun (x : Char) => x == c
        theorem String.revPosOfAux_eq (s : String) (c : Char) :
        s.revPosOfAux c = s.revFindAux fun (x : Char) => x == c
        theorem String.revPosOf_eq (s : String) (c : Char) :
        s.revPosOf c = s.revFind fun (x : Char) => x == c
        theorem String.findAux_of_valid (p : CharBool) (l m r : List Char) :
        (ofList (l ++ m ++ r)).findAux 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) :
        s.find p = { byteIdx := utf8Len (List.takeWhile (fun (x : Char) => !p x) s.toList) }
        theorem String.revFindAux_of_valid (p : CharBool) (l r : List Char) :
        (ofList (l.reverse ++ r)).revFindAux 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) :
        s.revFind 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) :
            (ofList (l ++ m ++ r)).offsetOfPosAux { 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 : α) :
            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 : α) :
            foldl f a s = List.foldl f a s.toList
            theorem String.foldrAux_of_valid {α : Type u_1} (f : Charαα) (l m r : List Char) (a : α) :
            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 : α) :
            foldr f a s = List.foldr f a s.toList
            theorem String.anyAux_of_valid (p : CharBool) (l m r : List Char) :
            (ofList (l ++ m ++ r)).anyAux { byteIdx := utf8Len l + utf8Len m } p { byteIdx := utf8Len l } = m.any p
            theorem String.any_eq (s : String) (p : CharBool) :
            s.any p = s.toList.any p
            theorem String.any_iff (s : String) (p : CharBool) :
            theorem String.all_eq (s : String) (p : CharBool) :
            s.all p = s.toList.all p
            theorem String.all_iff (s : String) (p : CharBool) :
            s.all 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 sRaw.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 sRaw.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 ss.any f = m.any f
                theorem Substring.Raw.ValidFor.all {l m r : List Char} (f : CharBool) {s : Raw} :
                ValidFor l m r ss.all f = m.all f
                theorem Substring.Raw.ValidFor.contains {l m r : List Char} (c : Char) {s : Raw} :
                ValidFor l m r s → (s.contains 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.ValidRaw.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.ValidRaw.foldr f init s = List.foldr f init s.toString.toList
                theorem Substring.Raw.Valid.any (f : CharBool) {s : Raw} :
                s.Valids.any f = s.toString.toList.any f
                theorem Substring.Raw.Valid.all (f : CharBool) {s : Raw} :
                s.Valids.all f = s.toString.toList.all f
                theorem String.drop_eq (s : String) (n : Nat) :
                @[simp]
                theorem String.toList_drop (s : String) (n : Nat) :
                @[simp]
                theorem String.drop_empty {n : Nat} :
                "".drop n = ""
                theorem String.take_eq (s : String) (n : Nat) :
                @[simp]
                theorem String.toList_take (s : String) (n : Nat) :