参考文档 / ZLIB × LEAN
inflate.c.sync4.lean
此页源文件快照 ·
b4e5514c96bffb84 · 对应提交的原文 ↗本页保留 Lean 源码及行号。点击行号可定位语句,点击 import 中的模块名可查看依赖。
1import ZlibF.Proof.«inflate.c.sync3»
2
3/-!
4# inflate.c: `inflateSync`, the first call (restore of the bit buffer)
5
6On the first call (`mode != SYNC`) the whole bytes of the bit buffer are moved to `buf` and searched first.
7-/
8
9namespace Zlib.Inflate.Spec
10open C
11
12/-- `x >> (8 n)`, as the restore loop computes it: `n` shifts by 8. -/
13def shr8N : Nat → UInt64 → UInt64
14 | 0, x => x
15 | n + 1, x => shr8N n x >>> 8
16
17/-- The array `buf` after the restore loop has stored the low bytes of `x`, `i` times. -/
18def fillBuf (A : Array UInt8) (x : UInt64) : Nat → Array UInt8
19 | 0 => A
20 | i + 1 => (fillBuf A x i).set! i (shr8N i x).toUInt8
21
22/-- The bit buffer after its partial byte (`bits & 7` bits) is dropped. -/
23def syncHold0 (st : InflateState) : UInt64 := st.hold >>> (st.bits &&& 7).toUInt64
24
25/-- The number of whole bytes in the bit buffer. -/
26def syncNB (st : InflateState) : Nat := (st.bits.toNat) / 8
27
28/-- The bytes `inflateSync` moves out of the bit buffer, in the order they were read from the input (low byte first). -/
29def syncRestore (st : InflateState) : List UInt8 :=
30 (List.range (syncNB st)).map fun j => (shr8N j (syncHold0 st)).toUInt8
31
32end Zlib.Inflate.Spec
33
34namespace Zlib.Inflate.Proofs
35open C Zlib.Inflate _root_.Zlib.Inflate.Spec
36
37theorem sync_and7_toNat (x : UInt32) : (x &&& 7).toNat = x.toNat % 8 := by
38 rw [UInt32.toNat_and]
39 have : (7 : UInt32).toNat = 2 ^ 3 - 1 := by decide
40 rw [this, Nat.and_two_pow_sub_one_eq_mod]
41
42theorem bitsDrop_toNat (b : UInt32) (hb : b.toNat ≤ 39) :
43 (b - (b &&& 7)) = UInt32.ofNat (8 * (b.toNat / 8)) := by
44 apply UInt32.toNat_inj.mp
45 have h7 := sync_and7_toNat b
46 have hle : (b &&& 7) ≤ b := by
47 rw [UInt32.le_iff_toNat_le, h7]; omega
48 rw [UInt32.toNat_sub_of_le _ _ hle, h7, UInt32.toNat_ofNat_of_lt' (by simp [UInt32.size]; omega)]
49 omega
50
51theorem sync_shr64_run (h : Heap) (x : UInt64) (n : UInt32) (hn : n < 64) : shr64 x n h = .ok (x >>> n.toUInt64, h) := by
52 simp [shr64, hn]
53
54theorem fillBuf_size (A : Array UInt8) (x : UInt64) (i : Nat) : (fillBuf A x i).size = A.size := by
55 induction i with
56 | zero => rfl
57 | succ i ih => simp [fillBuf, ih]
58
59/-- The heap after `i` iterations of the restore loop. -/
60def restoreHeap (H0 : Heap) (zs nb : Nat) (s0 : InflateState) (A : Array UInt8) (n i : Nat) : Heap :=
61 { H0 with
62 istates := upd H0.istates zs (some { s0 with hold := shr8N i s0.hold, bits := UInt32.ofNat (8 * (n - i)) }),
63 bytes := upd H0.bytes nb (some (fillBuf A s0.hold i)) }
64
65/-- **The restore loop.** `cond` and `body` are the loop of `inflateSync`; the hypotheses say what they do on the heap
66`restoreHeap ... i`: the test is `bits >= 8`, the body stores the low byte of `hold` at `buf[len]`, shifts the buffer and
67counts. -/
68theorem restore_loop {cond : UInt32 → M (Bool × UInt32)} {body : UInt32 → M UInt32} {H0 : Heap} {zs nb : Nat}
69 {s0 : InflateState} {A : Array UInt8} (n : Nat) (hn : n ≤ 4)
70 (hc : ∀ i len, len = UInt32.ofNat i → i ≤ n → cond len (restoreHeap H0 zs nb s0 A n i) =
71 .ok ((decide (i < n), len), restoreHeap H0 zs nb s0 A n i))
72 (hb : ∀ i len, len = UInt32.ofNat i → i < n → body len (restoreHeap H0 zs nb s0 A n i) =
73 .ok (len + 1, restoreHeap H0 zs nb s0 A n (i + 1))) :
74 cwhile cond body 0 (restoreHeap H0 zs nb s0 A n 0) = .ok (UInt32.ofNat n, restoreHeap H0 zs nb s0 A n n) := by
75 have key := cwhile_run (cond := cond) (body := body)
76 (fun k len H => ∃ i, i + k = n ∧ len = UInt32.ofNat i ∧ H = restoreHeap H0 zs nb s0 A n i)
77 (fun len H => len = UInt32.ofNat n ∧ H = restoreHeap H0 zs nb s0 A n n) ?_ ?_
78 (k := n) (s := 0) (h := restoreHeap H0 zs nb s0 A n 0) ⟨0, by omega, rfl, rfl⟩ (by unfold fuel; omega)
79 · obtain ⟨s', h', hh, hq1, hq2⟩ := key
80 rw [hh, hq1, hq2]
81 · intro k len H ⟨i, hi, hl, hH⟩
82 subst hl; subst hH
83 refine ⟨_, _, _, _, ?_, hb i _ rfl (by omega), i + 1, by omega, ?_, rfl⟩
84 · rw [hc i _ rfl (by omega)]
85 simp [show i < n by omega]
86 · have : (UInt32.ofNat i + 1) = UInt32.ofNat (i + 1) := by
87 apply UInt32.toNat_inj.mp
88 rw [UInt32.toNat_add, UInt32.toNat_ofNat_of_lt' (by simp [UInt32.size]; omega),
89 UInt32.toNat_ofNat_of_lt' (by simp [UInt32.size]; omega)]
90 simp; omega
91 exact this
92 · intro len H ⟨i, hi, hl, hH⟩
93 subst hl; subst hH
94 have : i = n := by omega
95 subst this
96 refine ⟨_, _, ?_, rfl, rfl⟩
97 rw [hc i _ rfl (Nat.le_refl _)]
98 simp
99
100end Zlib.Inflate.Proofs
101
102namespace Zlib.Inflate.Spec
103open C
104/-- The state after the restore and the search of its bytes. -/
105def syncFirstState (st : InflateState) : InflateState :=
106 { st with «have» := (syncScan 0 (syncRestore st)).1, mode := SYNC, hold := shr8N (syncNB st) (syncHold0 st), bits := 0 }
107
108/-- The heap after the restore and the search of its bytes (`buf` is the block `nb` with content `A`). -/
109def syncFirstHeap (H0 : Heap) (zs nb : Nat) (st : InflateState) (A : Array UInt8) : Heap :=
110 { H0 with bytes := upd H0.bytes nb (some (fillBuf A (syncHold0 st) (syncNB st))), istates := upd H0.istates zs (some (syncFirstState st)) }
111end Zlib.Inflate.Spec
112
113namespace Zlib.Inflate.Proofs
114open C Zlib.Inflate _root_.Zlib.Inflate.Spec
115
116theorem syncHold0_eq (st : InflateState) : syncHold0 st = st.hold >>> (st.bits.toUInt64 &&& 7) := by
117 unfold syncHold0
118 congr 1
119
120theorem fillBuf_get (A : Array UInt8) (x : UInt64) : ∀ i j, j < i → i ≤ A.size →
121 (fillBuf A x i)[j]? = some (shr8N j x).toUInt8 := by
122 intro i
123 induction i with
124 | zero => intro j hj; omega
125 | succ i ih =>
126 intro j hj hi
127 have hs := fillBuf_size A x i
128 simp only [fillBuf, Array.set!_eq_setIfInBounds, Array.getElem?_setIfInBounds]
129 by_cases hji : j = i
130 · subst hji; simp [hs]; omega
131 · have := ih j (by omega) (by omega)
132 have hij : ¬ i = j := fun h => hji h.symm
133 simpa [hij] using this
134
135theorem syncBytes_fillBuf (A : Array UInt8) (x : UInt64) (n : Nat) (hn : n ≤ 4) (hA : A.size = 4) :
136 syncBytes (fillBuf A x n) 0 (UInt32.ofNat n) = (List.range n).map fun j => (shr8N j x).toUInt8 := by
137 have hs := fillBuf_size A x n
138 unfold syncBytes
139 rw [UInt32.toNat_ofNat_of_lt' (by simp [UInt32.size]; omega)]
140 apply List.ext_getElem?
141 intro j
142 by_cases hj : j < n
143 · have := fillBuf_get A x n j hj (by omega)
144 simp [List.getElem?_take, hj, List.getElem?_range]
145 simpa using this
146 · simp [List.getElem?_take, hj, List.getElem?_range]
147
148theorem dec8 (m : Nat) (hm : m ≤ 4) : decide (8 ≤ UInt32.ofNat (8 * m)) = decide (0 < m) := by
149 have : m = 0 ∨ m = 1 ∨ m = 2 ∨ m = 3 ∨ m = 4 := by omega
150 rcases this with rfl | rfl | rfl | rfl | rfl <;> decide
151
152theorem ofNat_sub8 (m : Nat) (hm : m ≤ 4) (h1 : 1 ≤ m) : UInt32.ofNat (8 * m) - 8 = UInt32.ofNat (8 * (m - 1)) := by
153 have : m = 0 ∨ m = 1 ∨ m = 2 ∨ m = 3 ∨ m = 4 := by omega
154 rcases this with rfl | rfl | rfl | rfl | rfl <;> first | (exfalso; omega) | decide
155
156theorem bits_step (m : Nat) (hm : m ≤ 4) (h1 : 1 ≤ m) : 8 * UInt32.ofNat m - 8 = 8 * UInt32.ofNat (m - 1) := by
157 have : m = 0 ∨ m = 1 ∨ m = 2 ∨ m = 3 ∨ m = 4 := by omega
158 rcases this with rfl | rfl | rfl | rfl | rfl <;> first | (exfalso; omega) | decide
159
160theorem ofNat_succ (i : Nat) (hi : i ≤ 4) : UInt32.ofNat i + 1 = UInt32.ofNat (i + 1) := by
161 have : i = 0 ∨ i = 1 ∨ i = 2 ∨ i = 3 ∨ i = 4 := by omega
162 rcases this with rfl | rfl | rfl | rfl | rfl <;> decide
163
164theorem syncFirst_run {H0 : Heap} {zs nb : Nat} {st : InflateState} {A : Array UInt8}
165 (hs : H0.istates zs = some st) (hA : H0.bytes nb = some A) (hAs : A.size = 4) (hro : H0.ro nb = false)
166 (hb39 : st.bits.toNat ≤ 39) :
167 syncFirst (some (.tab zs)) (.ref (.blk nb) 0) st H0 = .ok ((), syncFirstHeap H0 zs nb st A) := by
168 have h7 : (st.bits &&& 7) < 64 := by
169 rw [UInt32.lt_iff_toNat_lt, sync_and7_toNat]; simp; omega
170 have hbd := bitsDrop_toNat st.bits hb39
171 unfold syncFirst
172 isimp [hs, sync_shr64_run H0 _ _ h7]
173 have hn4 : syncNB st ≤ 4 := by unfold syncNB; omega
174 have hs0 : (setI H0 zs { st with mode := SYNC, hold := st.hold >>> (st.bits.toUInt64 &&& 7), bits := st.bits - (st.bits &&& 7) }) = restoreHeap H0 zs nb { st with mode := SYNC, hold := st.hold >>> (st.bits.toUInt64 &&& 7), bits := st.bits - (st.bits &&& 7) } A (syncNB st) 0 := by
175 have hb8 : UInt32.ofNat (8 * syncNB st) = st.bits - (st.bits &&& 7) := by rw [hbd]; rfl
176 unfold restoreHeap setI
177 simp only [shr8N, Nat.sub_zero, fillBuf, upd_self _ _ _ hA, hb8]
178 rw [hs0]
179 rw [restore_loop (n := syncNB st) hn4 ?hc ?hb]
180 case hc =>
181 intro i len hl hi
182 have hlt : decide (8 ≤ UInt32.ofNat (8 * (syncNB st - i))) = decide (i < syncNB st) := by
183 rw [dec8 _ (by omega)]; simp; omega
184 have hi : (restoreHeap H0 zs nb { st with mode := SYNC, hold := st.hold >>> (st.bits.toUInt64 &&& 7), bits := st.bits - (st.bits &&& 7) } A (syncNB st) i).istates zs = some { st with mode := SYNC, hold := shr8N i (st.hold >>> (st.bits.toUInt64 &&& 7)), bits := UInt32.ofNat (8 * (syncNB st - i)) } := by
185 simp [restoreHeap]
186 simp only [bind_app, pure_app, rdI_eq, hi, hlt]
187 case hb =>
188 intro i len hl hi
189 have hlen : len.toNat = i := by rw [hl, UInt32.toNat_ofNat_of_lt' (by simp [UInt32.size]; omega)]
190 have hg : Space.get (restoreHeap H0 zs nb { st with mode := SYNC, hold := st.hold >>> (st.bits.toUInt64 &&& 7), bits := st.bits - (st.bits &&& 7) } A (syncNB st) i) (BRef.blk nb) = some (fillBuf A (st.hold >>> (st.bits.toUInt64 &&& 7)) i) := by
191 simp [Space.get, restoreHeap]
192 have hsz : (fillBuf A (st.hold >>> (st.bits.toUInt64 &&& 7)) i).size = 4 := by rw [fillBuf_size]; exact hAs
193 have hadd := Ptr.add_nat_ok (r := BRef.blk nb) (off := 0) (n := i) hg (by omega)
194 have hro' : Space.ro (restoreHeap H0 zs nb { st with mode := SYNC, hold := st.hold >>> (st.bits.toUInt64 &&& 7), bits := st.bits - (st.bits &&& 7) } A (syncNB st) i) (BRef.blk nb) = false := by
195 simpa [Space.ro, restoreHeap] using hro
196 have hstore := fun v => Ptr.store_ok (r := BRef.blk nb) (off := i) (v := v) hg hro' (by omega)
197 have hi : (restoreHeap H0 zs nb { st with mode := SYNC, hold := st.hold >>> (st.bits.toUInt64 &&& 7), bits := st.bits - (st.bits &&& 7) } A (syncNB st) i).istates zs = some { st with mode := SYNC, hold := shr8N i (st.hold >>> (st.bits.toUInt64 &&& 7)), bits := UInt32.ofNat (8 * (syncNB st - i)) } := by
198 simp [restoreHeap]
199 have hsub := ofNat_sub8 (syncNB st - i) (by omega) (by omega)
200 have hsu := ofNat_succ i (by omega)
201 have hadd' := hadd
202 unfold OkOn at hadd'
203 simp only [Nat.zero_add] at hadd'
204 simp only [bind_app, pure_app, ldI_eq, hi, hlen, hadd', store8, hstore, wrI_eq, Space.put]
205 simp [restoreHeap, setI, upd_upd, fillBuf, shr8N, hsub, hsu, hsub, Nat.sub_sub]
206 have e1 : 8 * UInt32.ofNat (syncNB st - i) - 8 = 8 * UInt32.ofNat (syncNB st - (i + 1)) := by
207 rw [bits_step (syncNB st - i) (by omega) (by omega)]
208 congr 2
209 rw [e1]
210 have hist : (restoreHeap H0 zs nb { st with mode := SYNC, hold := st.hold >>> (st.bits.toUInt64 &&& 7), bits := st.bits - (st.bits &&& 7) } A (syncNB st) (syncNB st)).istates zs = some { st with mode := SYNC, hold := shr8N (syncNB st) (st.hold >>> (st.bits.toUInt64 &&& 7)), bits := UInt32.ofNat (8 * (syncNB st - syncNB st)) } := by
211 simp [restoreHeap]
212 simp only [bind_app, pure_app, ldI_eq, hist, wrI_eq]
213 have hsz : (fillBuf A (st.hold >>> (st.bits.toUInt64 &&& 7)) (syncNB st)).size = 4 := by rw [fillBuf_size]; exact hAs
214 have hnn : (UInt32.ofNat (syncNB st)).toNat = syncNB st := UInt32.toNat_ofNat_of_lt' (by simp [UInt32.size]; omega)
215 rw [syncsearch_run (r := BRef.blk nb) (a := fillBuf A (st.hold >>> (st.bits.toUInt64 &&& 7)) (syncNB st)) (o := 0)
216 (len := UInt32.ofNat (syncNB st)) 0 (by simp [Space.get, restoreHeap, setI]) (by rw [hnn, hsz]; omega)]
217 have hR : syncBytes (fillBuf A (st.hold >>> (st.bits.toUInt64 &&& 7)) (syncNB st)) 0 (UInt32.ofNat (syncNB st)) = syncRestore st := by
218 rw [syncBytes_fillBuf _ _ _ hn4 hAs]
219 unfold syncRestore; rw [syncHold0_eq]
220 rw [hR]
221 simp only [bind_app, pure_app, ldI_eq, setI_istates_same]
222 simp [setI, restoreHeap, syncFirstHeap, syncFirstState, upd_upd, Nat.sub_self, syncHold0_eq]
223
224theorem good_setBuf {H : Heap} {r : ZStreamRef} {zs : Nat} {z : ZStream} {st : InflateState} {nb : Nat} {a0 : Array UInt8}
225 (hG : Good H r zs z st) (e : H.bytes nb = some a0) (hn : ∀ w, st.window = .ref (.blk w) 0 → w ≠ nb)
226 (A : Array UInt8) : Good { H with bytes := upd H.bytes nb (some A) } r zs z st := by
227 have hS := shape_setB e A
228 obtain ⟨⟨hz, hs, zst, back, hm, za, zf⟩, ⟨wf, win, rq, bits, ptr⟩, hU, hF⟩ := hG
229 refine ⟨⟨hz, hs, zst, back, hm, za, zf⟩, ⟨wf, ?_, rq, bits, ptr⟩, hS.uniq hU, hS.fresh rfl hF⟩
230 refine ⟨win.wbits, ?_, win.nullws, win.ws, win.hv, win.wn, win.eq⟩
231 rcases win.block with h0 | ⟨w, a, hw, ha, hro, hsz⟩
232 · exact Or.inl h0
233 · exact Or.inr ⟨w, a, hw, by rw [upd_ne _ _ _ _ (hn w hw)]; exact ha, hro, hsz⟩
234
235theorem good_firstState {H : Heap} {r : ZStreamRef} {zs : Nat} {z : ZStream} {st : InflateState} {nb : Nat} {A : Array UInt8}
236 (hG : Good H r zs z st) (e : H.bytes nb = some A) (hn : ∀ w, st.window = .ref (.blk w) 0 → w ≠ nb) :
237 Good (syncFirstHeap H zs nb st A) r zs z (syncFirstState st) := by
238 have h1 := good_setBuf hG e hn (fillBuf A (syncHold0 st) (syncNB st))
239 have h2 := good_state h1 (st' := syncFirstState st) rfl (by simp [syncFirstState]; decide)
240 (h1.inv.of_fields rfl rfl rfl rfl rfl rfl rfl rfl rfl (by simp [syncFirstState]) rfl rfl rfl)
241 exact h2
242
243theorem syncIn_first {h : Heap} (hF : Fresh h) {zs : Nat} {st : InflateState} {A : Array UInt8}
244 {p : BPtr} {len : UInt32} {bs : List UInt8} (I : SyncIn h p len bs) :
245 SyncIn (syncFirstHeap (syncAlloc h) zs h.nextBlk st A) p len bs := by
246 rcases I with ⟨b, a, o, rfl, hg, hl, rfl⟩ | h2
247 · have hb : b ≠ h.nextBlk := by
248 intro hh; subst hh
249 obtain ⟨e0, -⟩ := fresh_dead hF (Nat.le_refl _)
250 rw [hg] at e0; cases e0
251 exact Or.inl ⟨b, a, o, rfl, by simp [syncFirstHeap, syncAlloc, upd_ne _ _ _ _ hb, hg], hl, rfl⟩
252 · exact Or.inr h2
253
254theorem syncAt_restore (st : InflateState) : SyncAt (syncScan 0 (syncRestore st)).1 (syncRestore st) := by
255 obtain ⟨-, h2, h3⟩ := syncScan_spec syncSt_zero (syncRestore st) rfl
256 by_cases h4 : (syncScan 0 (syncRestore st)).1 = 4
257 · right
258 refine ⟨h4, ?_⟩
259 obtain ⟨-, a, -⟩ := h2 h4
260 have hin : [] ++ (syncRestore st).take (syncScan 0 (syncRestore st)).2 <:+: syncRestore st :=
261 ⟨[], (syncRestore st).drop (syncScan 0 (syncRestore st)).2, by simp⟩
262 exact (List.IsSuffix.isInfix a).trans (by simpa using hin)
263 · left
264 simpa using (h3 h4).2
265
266/-- **inflateSync, first call** (`mode != SYNC`). The whole bytes of the bit buffer (`syncRestore st`: the bits below the next
267byte boundary are dropped; at most 4 bytes, as the bit buffer holds at most 39 bits) are searched first, then the input
268`next_in[0 .. avail_in)` (`SyncIn`), in the same state machine, so the pattern `00 00 FF FF` is found if it occurs in
269`restore ++ input` (`syncScan_spec`; the search stops after its first occurrence and `N` counts input bytes only, 0 if the
270pattern lies in the restored bytes). The state gets `mode = SYNC`, the bit buffer emptied (`hold` shifted, `bits = 0`) and `have`
271set; the stream consumes `N` bytes. Not found (`G ≠ 4`): `Z_DATA_ERROR`, all input consumed. Found: `Z_OK` with the heap
272`syncOkHeap` (reset, totals kept, mode `TYPE`). There must be input or a whole byte in the bit buffer (else `Z_BUF_ERROR`,
273`inflateSync_buf_error`). The local array is made and freed. Default `zfree` only. -/
274theorem inflateSync_first {h : Heap} {r : ZStreamRef} {zs : Nat} {z : ZStream} {st : InflateState} {bs : List UInt8}
275 (hG : Good h r zs z st) (hf : z.zfree = .fn "zcfree") (hmode : st.mode ≠ SYNC)
276 (hprog : ¬ (z.avail_in = 0 ∧ st.bits < 8)) (hI : SyncIn h z.next_in z.avail_in bs) :
277 ∃ N G, N.toNat ≤ z.avail_in.toNat ∧
278 (G = 4 → syncPat <:+: syncRestore st ++ bs.take N.toNat ∧ ∀ L', L' < N.toNat → ¬ syncPat <:+: syncRestore st ++ bs.take L') ∧
279 (G ≠ 4 → N = z.avail_in ∧ SyncSt G (syncRestore st ++ bs)) ∧
280 (G ≠ 4 → ∃ h', C.run (inflateSync (some r)) h = .ok (Z_DATA_ERROR, h') ∧
281 h' = freeWin (setI (r.put (syncFirstHeap (syncAlloc h) zs h.nextBlk st (syncJunk h)) (syncAdvance z N)) zs
282 (syncHave (syncFirstState st) G)) (syncBuf h) ∧
283 Good h' r zs (syncAdvance z N) (syncHave (syncFirstState st) G)) ∧
284 (G = 4 → ∃ h', C.run (inflateSync (some r)) h = .ok (Z_OK, h') ∧
285 h' = freeWin (syncOkHeap (setI (r.put (syncFirstHeap (syncAlloc h) zs h.nextBlk st (syncJunk h)) (syncAdvance z N)) zs
286 (syncHave (syncFirstState st) G)) r zs (syncAdvance z N) (syncHave (syncFirstState st) G)) (syncBuf h) ∧
287 Good h' r zs (syncOkStream (syncAdvance z N) (syncHave (syncFirstState st) G))
288 (syncOkState zs (syncHave (syncFirstState st) G))) := by
289 have hF := hG.fresh
290 have hG0 := good_syncAlloc hG
291 have hwn := win_ne_buf hF hG.inv.win
292 have hbb : (syncAlloc h).bytes h.nextBlk = some (syncJunk h) := syncAlloc_bytes_buf h
293 have hAs : (syncJunk h).size = 4 := by simp [syncJunk]
294 have hGf := good_firstState hG0 hbb hwn
295 have hIf := syncIn_first (zs := zs) (st := st) (A := syncJunk h) hF hI
296 have hL0 := hG0.live
297 have hrun1 := syncFirst_run (H0 := syncAlloc h) (zs := zs) (nb := h.nextBlk) (st := st) (A := syncJunk h)
298 (by simpa using hG.live.hs) hbb hAs (syncAlloc_ro_buf h) hG.inv.bits
299 obtain ⟨N, G, hN, h4, h3, hG1, hne, he⟩ := syncTail_run hGf hf hIf (syncAt_restore st)
300 have hnbf : (syncFirstHeap (syncAlloc h) zs h.nextBlk st (syncJunk h)).bytes h.nextBlk =
301 some (fillBuf (syncJunk h) (syncHold0 st) (syncNB st)) := by simp [syncFirstHeap]
302 have hrof : (syncFirstHeap (syncAlloc h) zs h.nextBlk st (syncJunk h)).ro h.nextBlk = false := by
303 simp [syncFirstHeap, syncAlloc_ro_buf]
304 refine ⟨N, G, hN, h4, h3, fun hG4 => ?_, fun hG4 => ?_⟩
305 · refine ⟨_, ?_, rfl, ?_⟩
306 · show inflateSync (some r) h = _
307 rw [inflateSync_split]
308 isimp [allocLocalB_run h hF, stateCheck_live hL0, hL0.zst, hG.live.hz, hG.live.hs, hprog, hmode, syncBuf, hrun1,
309 hne hG4, freeBuf_run (H := setI (r.put (syncFirstHeap (syncAlloc h) zs h.nextBlk st (syncJunk h)) (syncAdvance z N)) zs
310 (syncHave (syncFirstState st) G)) (nb := h.nextBlk) (a := fillBuf (syncJunk h) (syncHold0 st) (syncNB st))
311 (by simpa using hnbf) (by simpa using hrof)]
312 · exact good_freeBuf (nb := h.nextBlk) hG1 (fun w hw => hwn w (by simpa [syncHave, syncFirstState] using hw))
313 · refine ⟨_, ?_, rfl, ?_⟩
314 · have hbn : ∀ w', (syncHave (syncFirstState st) G).window = .ref (.blk w') 0 → w' ≠ h.nextBlk :=
315 fun w' hw' => hwn w' (by simpa [syncHave, syncFirstState] using hw')
316 have hby := syncOkHeap_bytes_ne (setI (r.put (syncFirstHeap (syncAlloc h) zs h.nextBlk st (syncJunk h)) (syncAdvance z N)) zs
317 (syncHave (syncFirstState st) G)) r zs (syncAdvance z N) (syncHave (syncFirstState st) G) hbn
318 show inflateSync (some r) h = _
319 rw [inflateSync_split]
320 isimp [allocLocalB_run h hF, stateCheck_live hL0, hL0.zst, hG.live.hz, hG.live.hs, hprog, hmode, syncBuf, hrun1,
321 he hG4, freeBuf_run (H := syncOkHeap (setI (r.put (syncFirstHeap (syncAlloc h) zs h.nextBlk st (syncJunk h)) (syncAdvance z N)) zs
322 (syncHave (syncFirstState st) G)) r zs (syncAdvance z N) (syncHave (syncFirstState st) G)) (nb := h.nextBlk)
323 (a := fillBuf (syncJunk h) (syncHold0 st) (syncNB st))
324 (by rw [hby.1]; simpa using hnbf) (by rw [hby.2]; simpa using hrof)]
325 · have hGd := (syncDone_good hG1).1
326 exact good_freeBuf (nb := h.nextBlk) hGd (fun w hw => hwn w (by simpa [syncHave, syncFirstState] using syncOkState_window_ref hw))
327
328end Zlib.Inflate.Proofs