feat: add ByteArray indexing and set! lemmas (#13457)

This PR adds the missing `ByteArray` push and `set!` lemmas that are
still carried locally in `ZipForStd.ByteArray` downstream.

These lemmas provide one coherent API layer for reasoning about
`ByteArray` pushes and `set!` updates on top of the existing upstream
append, extract, and size lemmas. Previous downstream code had to keep
local compatibility lemmas for these common proof steps.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kim Morrison 2026-05-16 16:28:43 +10:00 committed by GitHub
parent c993d3f237
commit 1b8f1f140c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -328,4 +328,81 @@ theorem extract_eq_extract_iff_getElem {as bs : ByteArray} {i j len : Nat}
· exact h k hk'
· exact (by omega : k = len) ▸ h'
theorem getElem!_push_lt (data : ByteArray) (b : UInt8) (i : Nat) (hi : i < data.size) :
(data.push b)[i]! = data[i]! := by
have hi' : i < (data.push b).size := by
simp only [ByteArray.size_push]
omega
rw [getElem!_pos (data.push b) i hi', getElem!_pos data i hi]
exact Array.getElem_push_lt hi
@[simp] theorem getElem!_push_eq (data : ByteArray) (b : UInt8) :
(data.push b)[data.size]! = b := by
have h : data.size < (data.push b).size := by
simp only [ByteArray.size_push]
omega
rw [getElem!_pos (data.push b) data.size h]
exact Array.getElem_push_eq
@[grind =] theorem getElem!_push (data : ByteArray) (b : UInt8) (i : Nat) :
(data.push b)[i]! = if i = data.size then b else data[i]! := by
split
· subst i
exact getElem!_push_eq data b
· by_cases hi : i < data.size
· exact getElem!_push_lt data b i hi
· rw [getElem!_neg data i hi,
getElem!_neg (data.push b) i (by simp only [ByteArray.size_push]; omega)]
private theorem getElem!_eq_data_getElem! (data : ByteArray) (i : Nat) :
data[i]! = data.data[i]! := by
by_cases h : i < data.size
· rw [getElem!_pos data i h, getElem!_pos data.data i h]
rfl
· rw [getElem!_neg data i h, getElem!_neg data.data i h]
@[simp, grind =] theorem size_set! (data : ByteArray) (i : Nat) (v : UInt8) :
(data.set! i v).size = data.size := by
show (data.data.setIfInBounds i v).size = data.data.size
exact Array.size_setIfInBounds ..
@[simp] theorem getElem!_set!_self (data : ByteArray) (i : Nat) (v : UInt8) (h : i < data.size) :
(data.set! i v)[i]! = v := by
rw [getElem!_eq_data_getElem!]
show (data.data.set! i v)[i]! = v
simp only [Array.set!_eq_setIfInBounds, Array.getElem!_eq_getD, Array.getD_eq_getD_getElem?,
Array.getElem?_setIfInBounds_self_of_lt h, Option.getD_some]
@[simp] theorem getElem!_set!_ne (data : ByteArray) (i j : Nat) (v : UInt8) (hij : i ≠ j) :
(data.set! i v)[j]! = data[j]! := by
rw [getElem!_eq_data_getElem!, getElem!_eq_data_getElem!]
show (data.data.set! i v)[j]! = data.data[j]!
simp only [Array.set!_eq_setIfInBounds, Array.getElem!_eq_getD, Array.getD_eq_getD_getElem?,
Array.getElem?_setIfInBounds_ne hij]
@[grind =] theorem getElem!_set! (data : ByteArray) (i : Nat) (v : UInt8) (j : Nat) (h : i < data.size) :
(data.set! i v)[j]! = if i = j then v else data[j]! := by
split
· next hij => subst hij; exact getElem!_set!_self data i v h
· next hij => exact getElem!_set!_ne data i j v hij
@[simp] theorem getElem_set!_ne (data : ByteArray) (i j : Nat) (v : UInt8) (hij : i ≠ j)
(hj : j < data.size) :
(data.set! i v)[j]'(by rw [size_set!]; exact hj) = data[j] := by
rw [← getElem!_pos (data.set! i v) j (by rw [size_set!]; exact hj),
← getElem!_pos data j hj,
getElem!_set!_ne _ _ _ _ hij]
@[simp] theorem getElem_set!_self (data : ByteArray) (i : Nat) (v : UInt8) (h : i < data.size) :
(data.set! i v)[i]'(by rw [size_set!]; exact h) = v := by
rw [← getElem!_pos (data.set! i v) i (by rw [size_set!]; exact h),
getElem!_set!_self _ _ _ h]
@[grind =] theorem getElem_set! (data : ByteArray) (i j : Nat) (v : UInt8) (h : i < data.size)
(hj : j < data.size) :
(data.set! i v)[j]'(by rw [size_set!]; exact hj) = if i = j then v else data[j] := by
split
· next hij => subst hij; exact getElem_set!_self data i v h
· next hij => exact getElem_set!_ne data i j v hij hj
end ByteArray