@@ -824,16 +824,25 @@ The region of `s` from `b` (inclusive) to `e` (exclusive) is copied to a newly-a
824824
825825If `b`'s offset is greater than or equal to that of `e`, then the resulting string is `""`.
826826
827+ If possible, prefer `String.slice`, which avoids the allocation.
827828-/
828829@[extern "lean_string_utf8_extract"]
829- def Pos. extract {s : @& String} (b e : @& s.Pos) : String where
830+ def extract {s : @& String} (b e : @& s.Pos) : String where
830831 toByteArray := s.toByteArray.extract b.offset.byteIdx e.offset.byteIdx
831832 isValidUTF8 := b.isValidUTF8_extract e
832833
834+ @[deprecated String.extract (since := "2025-12-01")]
835+ def Pos.extract {s : String} (b e : @& s.Pos) : String :=
836+ s.extract b e
837+
838+ @[simp]
839+ theorem toByteArray_extract {s : String} {b e : s.Pos} :
840+ (s.extract b e).toByteArray = s.toByteArray.extract b.offset.byteIdx e.offset.byteIdx := (rfl)
841+
833842/-- Creates a `String` from a `String.Slice` by copying the bytes. -/
834843@[inline]
835844def Slice.copy (s : Slice) : String :=
836- s.startInclusive .extract s.endExclusive
845+ s.str .extract s.startInclusive s.endExclusive
837846
838847theorem Slice.toByteArray_copy {s : Slice} :
839848 s.copy.toByteArray = s.str.toByteArray.extract s.startInclusive.offset.byteIdx s.endExclusive.offset.byteIdx := (rfl)
@@ -1387,54 +1396,58 @@ theorem Pos.offset_ofCopy {s : Slice} {pos : s.copy.Pos} : pos.ofCopy.offset = p
13871396
13881397/-- Given a slice `s` and a position on `s`, obtain the corresponding position on `s.copy.` -/
13891398@[inline]
1390- def Slice.Pos.toCopy {s : Slice} (pos : s.Pos) : s.copy.Pos where
1399+ def Slice.Pos.copy {s : Slice} (pos : s.Pos) : s.copy.Pos where
13911400 offset := pos.offset
13921401 isValid := Pos.Raw.isValid_copy_iff.2 pos.isValidForSlice
13931402
1403+ @[deprecated Slice.Pos.copy (since := "2025-12-01")]
1404+ def Slice.Pos.toCopy {s : Slice} (pos : s.Pos) : s.copy.Pos :=
1405+ pos.copy
1406+
13941407@[simp]
1395- theorem Slice.Pos.offset_toCopy {s : Slice} {pos : s.Pos} : pos.toCopy .offset = pos.offset := (rfl)
1408+ theorem Slice.Pos.offset_copy {s : Slice} {pos : s.Pos} : pos.copy .offset = pos.offset := (rfl)
13961409
13971410@[simp]
1398- theorem Slice.Pos.ofCopy_toCopy {s : Slice} {pos : s.Pos} : pos.toCopy .ofCopy = pos :=
1411+ theorem Slice.Pos.ofCopy_copy {s : Slice} {pos : s.Pos} : pos.copy .ofCopy = pos :=
13991412 Slice.Pos.ext (by simp)
14001413
14011414@[simp]
1402- theorem Pos.toCopy_ofCopy {s : Slice} {pos : s.copy.Pos} : pos.ofCopy.toCopy = pos :=
1415+ theorem Pos.copy_ofCopy {s : Slice} {pos : s.copy.Pos} : pos.ofCopy.copy = pos :=
14031416 Pos.ext (by simp)
14041417
14051418theorem Pos.ofCopy_inj {s : Slice} {pos pos' : s.copy.Pos} : pos.ofCopy = pos'.ofCopy ↔ pos = pos' :=
1406- ⟨fun h => by simpa using congrArg Slice.Pos.toCopy h, (· ▸ rfl)⟩
1419+ ⟨fun h => by simpa using congrArg Slice.Pos.copy h, (· ▸ rfl)⟩
14071420
14081421@[simp]
1409- theorem Slice.startPos_copy {s : Slice} : s.copy.startPos = s.startPos.toCopy :=
1422+ theorem Slice.startPos_copy {s : Slice} : s.copy.startPos = s.startPos.copy :=
14101423 String.Pos.ext (by simp)
14111424
14121425@[simp]
1413- theorem Slice.endPos_copy {s : Slice} : s.copy.endPos = s.endPos.toCopy :=
1426+ theorem Slice.endPos_copy {s : Slice} : s.copy.endPos = s.endPos.copy :=
14141427 String.Pos.ext (by simp)
14151428
1416- theorem Slice.Pos.get_toCopy {s : Slice} {pos : s.Pos} (h) :
1417- pos.toCopy .get h = pos.get (by rintro rfl; simp at h) := by
1429+ theorem Slice.Pos.get_copy {s : Slice} {pos : s.Pos} (h) :
1430+ pos.copy .get h = pos.get (by rintro rfl; simp at h) := by
14181431 rw [String.Pos.get, Slice.Pos.get_eq_utf8DecodeChar, Slice.Pos.get_eq_utf8DecodeChar]
1419- simp only [str_toSlice, toByteArray_copy, startInclusive_toSlice, startPos_copy, offset_toCopy ,
1432+ simp only [str_toSlice, toByteArray_copy, startInclusive_toSlice, startPos_copy, offset_copy ,
14201433 Slice.offset_startPos, Pos.Raw.byteIdx_zero, Pos.offset_toSlice, Nat.zero_add]
14211434 rw [ByteArray.utf8DecodeChar_eq_utf8DecodeChar_extract]
14221435 conv => lhs; congr; rw [ByteArray.extract_extract]
14231436 conv => rhs; rw [ByteArray.utf8DecodeChar_eq_utf8DecodeChar_extract]
14241437 exact ByteArray.utf8DecodeChar_extract_congr _ _ _
14251438
1426- theorem Slice.Pos.get_eq_get_toCopy {s : Slice} {pos : s.Pos} {h} :
1427- pos.get h = pos.toCopy .get (ne_of_apply_ne Pos.ofCopy (by simp [h])) :=
1428- (get_toCopy _).symm
1439+ theorem Slice.Pos.get_eq_get_copy {s : Slice} {pos : s.Pos} {h} :
1440+ pos.get h = pos.copy .get (ne_of_apply_ne Pos.ofCopy (by simp [h])) :=
1441+ (get_copy _).symm
14291442
1430- theorem Slice.Pos.byte_toCopy {s : Slice} {pos : s.Pos} (h) :
1431- pos.toCopy .byte h = pos.byte (by rintro rfl; simp at h) := by
1443+ theorem Slice.Pos.byte_copy {s : Slice} {pos : s.Pos} (h) :
1444+ pos.copy .byte h = pos.byte (by rintro rfl; simp at h) := by
14321445 rw [String.Pos.byte, Slice.Pos.byte, Slice.Pos.byte]
14331446 simp [getUTF8Byte, String.getUTF8Byte, toByteArray_copy, ByteArray.getElem_extract]
14341447
1435- theorem Slice.Pos.byte_eq_byte_toCopy {s : Slice} {pos : s.Pos} {h} :
1436- pos.byte h = pos.toCopy .byte (ne_of_apply_ne Pos.ofCopy (by simp [h])) :=
1437- (byte_toCopy _).symm
1448+ theorem Slice.Pos.byte_eq_byte_copy {s : Slice} {pos : s.Pos} {h} :
1449+ pos.byte h = pos.copy .byte (ne_of_apply_ne Pos.ofCopy (by simp [h])) :=
1450+ (byte_copy _).symm
14381451
14391452/-- Given a position in `s.sliceFrom p₀`, obtain the corresponding position in `s`. -/
14401453@[inline]
@@ -1521,7 +1534,7 @@ theorem Slice.Pos.copy_eq_append_get {s : Slice} {pos : s.Pos} (h : pos ≠ s.en
15211534 ∃ t₁ t₂ : String, s.copy = t₁ ++ singleton (pos.get h) ++ t₂ ∧ t₁.utf8ByteSize = pos.offset.byteIdx := by
15221535 obtain ⟨t₂, ht₂⟩ := (s.sliceFrom pos).copy.eq_singleton_append (by simpa [← Pos.ofCopy_inj, ← ofSliceFrom_inj])
15231536 refine ⟨(s.sliceTo pos).copy, t₂, ?_, by simp⟩
1524- simp only [Slice.startPos_copy, get_toCopy , get_eq_get_ofSliceFrom, ofSliceFrom_startPos] at ht₂
1537+ simp only [Slice.startPos_copy, get_copy , get_eq_get_ofSliceFrom, ofSliceFrom_startPos] at ht₂
15251538 rw [append_assoc, ← ht₂, ← copy_eq_copy_sliceTo]
15261539
15271540theorem Slice.Pos.utf8ByteSize_byte {s : Slice} {pos : s.Pos} {h : pos ≠ s.endPos} :
@@ -1751,8 +1764,8 @@ theorem Pos.offset_cast {s t : String} {pos : s.Pos} {h : s = t} :
17511764theorem Pos.cast_rfl {s : String} {pos : s.Pos} : pos.cast rfl = pos :=
17521765 Pos.ext (by simp)
17531766
1754- theorem Pos.toCopy_toSlice_eq_cast {s : String} (p : s.Pos) :
1755- p.toSlice.toCopy = p.cast copy_toSlice.symm :=
1767+ theorem Pos.copy_toSlice_eq_cast {s : String} (p : s.Pos) :
1768+ p.toSlice.copy = p.cast copy_toSlice.symm :=
17561769 Pos.ext (by simp)
17571770
17581771/-- Given a byte position within a string slice, obtains the smallest valid position that is
@@ -2435,6 +2448,35 @@ def Pos.slice! {s : String} (pos : s.Pos) (p₀ p₁ : s.Pos) :
24352448 (s.slice! p₀ p₁).Pos :=
24362449 Slice.Pos.slice! pos.toSlice _ _
24372450
2451+ theorem extract_eq_copy_slice {s : String} (p₀ p₁ : s.Pos) (h : p₀ ≤ p₁) :
2452+ s.extract p₀ p₁ = (s.slice p₀ p₁ h).copy := by
2453+ simp [← toByteArray_inj, Slice.toByteArray_copy]
2454+
2455+ /--
2456+ Copies a region of a slice to a new string.
2457+
2458+ The region of `s` from `b` (inclusive) to `e` (exclusive) is copied to a newly-allocated `String`.
2459+
2460+ If `b`'s offset is greater than or equal to that of `e`, then the resulting string is `""`.
2461+
2462+ If possible, prefer `Slice.slice`, which avoids the allocation.
2463+ -/
2464+ @[inline]
2465+ def Slice.extract (s : Slice) (p₀ p₁ : s.Pos) : String :=
2466+ s.str.extract p₀.str p₁.str
2467+
2468+ @[simp]
2469+ theorem Slice.Pos.str_le_str_iff {s : Slice} {p q : s.Pos} : p.str ≤ q.str ↔ p ≤ q := by
2470+ simp [String.Pos.le_iff, Slice.Pos.le_iff, Pos.Raw.le_iff]
2471+
2472+ @[simp]
2473+ theorem Slice.Pos.str_lt_str_iff {s : Slice} {p q : s.Pos} : p.str < q.str ↔ p < q := by
2474+ simp [String.Pos.lt_iff, Slice.Pos.lt_iff, Pos.Raw.lt_iff]
2475+
2476+ theorem Slice.extract_eq_copy_slice {s : Slice} (p₀ p₁ : s.Pos) (h : p₀ ≤ p₁) :
2477+ s.extract p₀ p₁ = (s.slice p₀ p₁ h).copy := by
2478+ simp [← toByteArray_inj, Slice.toByteArray_copy, Slice.extract]
2479+
24382480/--
24392481Advances the position `p` `n` times.
24402482
@@ -2734,10 +2776,6 @@ where
27342776 | [], _, _ => []
27352777 | c::cs, i, e => if i = e then [] else c :: go₂ cs (i + c) e
27362778
2737- @[extern "lean_string_utf8_extract", expose, deprecated Pos.Raw.extract (since := "2025-10-14")]
2738- def extract : (@& String) → (@& Pos.Raw) → (@& Pos.Raw) → String
2739- | s, b, e => Pos.Raw.extract s b e
2740-
27412779def Pos.Raw.offsetOfPosAux (s : String) (pos : Pos.Raw) (i : Pos.Raw) (offset : Nat) : Nat :=
27422780 if i >= pos then offset
27432781 else if h : i.atEnd s then
0 commit comments