Skip to content
REFERENCE / ZLIB × LEAN

inflate.c.window-public-mode.lean

Source snapshot · f7d2aeeb28dcf9f0 · Source at the matching commit ↗

Lean source with line numbers. Follow a line number to locate a statement, or an import to read its dependency.

1import ZlibF.Proof.«inflate.c.window-public-ring»
2import ZlibF.Spec.Public.Lifecycle
3
4namespace Zlib.Inflate.Proofs
5open C Zlib.Inflate Zlib.Inflate.Spec ZlibF.Spec.Public
6
7private theorem uwPost_mode (s : InflateState) (a b : Array UInt8) (eo : Nat) (n : UInt32) :
8    (uwPost (initWinS s) a b eo n).2.mode = s.mode := by
9  have hh : (uwPost (initWinS s) a b eo n).2 =
10      { s with
11        window := (uwPost (initWinS s) a b eo n).2.window
12        wsize := (uwPost (initWinS s) a b eo n).2.wsize
13        whave := (uwPost (initWinS s) a b eo n).2.whave
14        wnext := (uwPost (initWinS s) a b eo n).2.wnext } := by
15    unfold uwPost initWinS
16    repeat' split
17    all_goals rfl
18  have hm := congrArg InflateState.mode hh
19  exact hm
20
21/-- An existing-window update changes only the owned state and window blocks. -/
22theorem uw_existing_frame {h : Heap} {r : ZStreamRef} {zs w : Nat} {st st0 st1 : InflateState}
23    {a : Array UInt8} (hw : st.window = .ref (.blk w) 0) :
24    Frame h (setI { setI h zs st0 with bytes := upd h.bytes w (some a) } zs st1)
25      (fun b => StreamRoot r b ∨ InflateOwned zs st b) := by
26  simp only [Frame, setI, true_and]
27  refine ⟨Nat.le_refl _, Nat.le_refl _, ?_⟩
28  intro b _ hb
29  have hi : b ≠ zs := fun he => hb (Or.inr (Or.inl he))
30  have hw' : b ≠ w := fun he => hb (Or.inr (Or.inr (by simpa [hw] using he.symm)))
31  simp [upd_ne, hi, hw']
32
33/-- A new-window update changes only the owned state among pre-existing
34objects; the allocated block was not live before the call. -/
35theorem uw_new_frame {h : Heap} {r : ZStreamRef} {zs n : Nat} {st st0 st1 st2 : InflateState}
36    {a : Array UInt8} (hf : Fresh h) :
37    let alloc := Zlib.Zutil.Proofs.allocHeap h n
38    let prior := setI alloc zs st0
39    Frame h (setI { setI prior zs st1 with bytes := upd prior.bytes h.nextBlk (some a) } zs st2)
40      (fun b => StreamRoot r b ∨ InflateOwned zs st b) := by
41  dsimp only
42  simp only [Frame, setI, Zlib.Zutil.Proofs.allocHeap, true_and]
43  refine ⟨Nat.le_succ _, Nat.le_succ _, ?_⟩
44  intro b hl hb
45  have hi : b ≠ zs := fun he => hb (Or.inr (Or.inl he))
46  have hn : b ≠ h.nextBlk := fun he => hf b (by omega) hl
47  simp [upd_ne, hi, hn]
48
49/-- Allocation followed by a successful window update preserves the stream mode. -/
50theorem uw_null_mode_public {h : Heap} {r : ZStreamRef} {zs : Nat} {z : ZStream}
51    {st : InflateState} {eo : Nat} {source : BRef} {ebytes : Array UInt8} {copy : UInt32}
52    (hG : Good h r zs z st) (hza : z.zalloc = .fn "zcalloc") (hw : st.window = .null)
53    (hok : h.allocOk h.nalloc = true) (heb : Space.get h source = some ebytes)
54    (hc : copy.toNat ≤ eo) (hoff : eo ≤ ebytes.size) :
55    ∃ after state, updatewindow (some r) (.ref source eo) copy h = .ok (0, after) ∧
56      Good after r zs z state ∧ state.mode = st.mode := by
57  have hL := hG.live
58  have hI := hG.inv
59  have hF := hG.fresh
60  have hne : source ≠ .blk h.nextBlk := by
61    intro he
62    subst source
63    have hfresh := Fresh.bytes hF (b := h.nextBlk) (Nat.le_refl _)
64    have hbytes : h.bytes h.nextBlk = some ebytes := by simpa using heb
65    rw [hbytes] at hfresh
66    cases hfresh
67  rw [uw_alloc_ok hL hza hI.win.wbits hw hok hF]
68  have hn : ((1 <<< st.wbits : UInt32) * 1).toNat = 2 ^ st.wbits.toNat := by
69    have := shl_toNat_aux hI.win.wbits
70    simpa using this
71  obtain ⟨A0, hA0⟩ : ∃ A0 : Array UInt8, A0 = Array.ofFn (n := ((1 <<< st.wbits : UInt32) * 1).toNat)
72      fun i => Junk.of (h.garbage h.nalloc i.val) := ⟨_, rfl⟩
73  have hA0sz : A0.size = 2 ^ st.wbits.toNat := by rw [hA0, Array.size_ofFn]; exact hn
74  have hws0 := hI.win.nullws hw
75  have hws0n : st.wsize.toNat = 0 := by rw [hws0]; rfl
76  have hA := Zlib.Zutil.Proofs.allocHeap_frame h ((1 <<< st.wbits : UInt32) * 1).toNat
77  have hAb : (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat).bytes h.nextBlk = some A0 := by
78    rw [hA0]; simp [Zlib.Zutil.Proofs.allocHeap]
79  have hAro : (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat).ro h.nextBlk = false := by
80    simp [Zlib.Zutil.Proofs.allocHeap]
81  have hS : Shape (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat)
82      (setI (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat) zs (withWin st h.nextBlk)) :=
83    shape_setI (s0 := st) (by simpa [Zlib.Zutil.Proofs.allocHeap] using hL.hs) _
84  have hUa := uniq_allocHeap hG.uniq hF ((1 <<< st.wbits : UInt32) * 1).toNat
85  have hFa := hA.2.1 hF
86  have hG2 : Good (setI (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat) zs (withWin st h.nextBlk))
87      r zs z (withWin st h.nextBlk) := by
88    refine ⟨⟨?_, by simp, hL.zst, hL.back, hL.mode, hL.zalloc, hL.zfree⟩, ?_, hS.uniq hUa, hS.fresh rfl hFa⟩
89    · cases r <;> simpa [ZStreamRef.get, Zlib.Zutil.Proofs.allocHeap, setI] using hL.hz
90    · refine ⟨hI.wf, ⟨hI.win.wbits, Or.inr ⟨h.nextBlk, A0, rfl, ?_, ?_, ?_⟩, fun h0 => absurd h0 (by simp [withWin]), ?_, ?_, ?_, ?_⟩,
91        hI.reqbits, hI.bits, hI.ptr⟩
92      · simpa [setI] using hAb
93      · simpa [setI] using hAro
94      · exact hA0sz
95      · exact Or.inl hws0n
96      · have := hI.win.hv; show st.whave.toNat ≤ st.wsize.toNat; exact this
97      · right; refine ⟨hws0n, ?_⟩
98        have := hI.win.wn; show st.wnext.toNat = 0; omega
99      · intro hh; have := hI.win.hv; show st.wnext.toNat = st.whave.toNat; have := hI.win.wn; have := hI.win.hv
100        change st.whave.toNat < st.wsize.toNat at hh; omega
101  have hz2 : r.get (setI (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat) zs (withWin st h.nextBlk)) = some z :=
102    hG2.live.hz
103  have hbe : Space.get (setI (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat) zs
104      (withWin st h.nextBlk)) source = some ebytes := by
105    cases source with
106    | blk b =>
107      have hbn : b ≠ h.nextBlk := fun he => hne (by cases he; rfl)
108      simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI, upd_ne _ _ _ _ hbn] using heb
109    | str b => simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI] using heb
110    | st_dist_code => simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI] using heb
111    | st_length_code => simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI] using heb
112    | dstate_depth b => simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI] using heb
113  have hsep : ZlibF.Spec.Public.Separate (.ref source (eo - copy.toNat)) copy.toNat
114      (withWin st h.nextBlk).window (2 ^ (withWin st h.nextBlk).wbits.toNat) := by
115    simp [ZlibF.Spec.Public.Separate, withWin, hne]
116  obtain ⟨after, state, hr, _, hstate, hgood, _, _, _, _, _, _⟩ :=
117    uw_post_public (hG := hG2) (w := h.nextBlk) (source := source) (eo := eo)
118      (a := A0) (ebytes := ebytes) (copy := copy) rfl (by simpa [setI] using hAb)
119      (by simpa [setI] using hAro) hA0sz hbe hc hoff hsep
120  refine ⟨after, state, hr, hgood, ?_⟩
121  rw [hstate, uwPost_mode]
122  rfl
123
124/-- Allocation followed by an update preserves the public frame of every
125pre-existing unowned object. -/
126theorem uw_null_frame_public {h : Heap} {r : ZStreamRef} {zs : Nat} {z : ZStream}
127    {st : InflateState} {eo : Nat} {source : BRef} {ebytes : Array UInt8} {copy : UInt32}
128    (hG : Good h r zs z st) (hza : z.zalloc = .fn "zcalloc") (hw : st.window = .null)
129    (hok : h.allocOk h.nalloc = true) (heb : Space.get h source = some ebytes)
130    (hc : copy.toNat ≤ eo) (hoff : eo ≤ ebytes.size) :
131    ∃ after state, updatewindow (some r) (.ref source eo) copy h = .ok (0, after) ∧
132      Good after r zs z state ∧ Frame h after (fun b => StreamRoot r b ∨ InflateOwned zs st b) := by
133  have hL := hG.live
134  have hI := hG.inv
135  have hF := hG.fresh
136  have hne : source ≠ .blk h.nextBlk := by
137    intro he
138    subst source
139    have hfresh := Fresh.bytes hF (b := h.nextBlk) (Nat.le_refl _)
140    have hbytes : h.bytes h.nextBlk = some ebytes := by simpa using heb
141    rw [hbytes] at hfresh
142    cases hfresh
143  rw [uw_alloc_ok hL hza hI.win.wbits hw hok hF]
144  have hn : ((1 <<< st.wbits : UInt32) * 1).toNat = 2 ^ st.wbits.toNat := by
145    have := shl_toNat_aux hI.win.wbits
146    simpa using this
147  obtain ⟨A0, hA0⟩ : ∃ A0 : Array UInt8, A0 = Array.ofFn (n := ((1 <<< st.wbits : UInt32) * 1).toNat)
148      fun i => Junk.of (h.garbage h.nalloc i.val) := ⟨_, rfl⟩
149  have hA0sz : A0.size = 2 ^ st.wbits.toNat := by rw [hA0, Array.size_ofFn]; exact hn
150  have hws0 := hI.win.nullws hw
151  have hws0n : st.wsize.toNat = 0 := by rw [hws0]; rfl
152  have hA := Zlib.Zutil.Proofs.allocHeap_frame h ((1 <<< st.wbits : UInt32) * 1).toNat
153  have hAb : (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat).bytes h.nextBlk = some A0 := by
154    rw [hA0]; simp [Zlib.Zutil.Proofs.allocHeap]
155  have hAro : (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat).ro h.nextBlk = false := by
156    simp [Zlib.Zutil.Proofs.allocHeap]
157  have hS : Shape (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat)
158      (setI (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat) zs (withWin st h.nextBlk)) :=
159    shape_setI (s0 := st) (by simpa [Zlib.Zutil.Proofs.allocHeap] using hL.hs) _
160  have hUa := uniq_allocHeap hG.uniq hF ((1 <<< st.wbits : UInt32) * 1).toNat
161  have hFa := hA.2.1 hF
162  have hG2 : Good (setI (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat) zs (withWin st h.nextBlk))
163      r zs z (withWin st h.nextBlk) := by
164    refine ⟨⟨?_, by simp, hL.zst, hL.back, hL.mode, hL.zalloc, hL.zfree⟩, ?_, hS.uniq hUa, hS.fresh rfl hFa⟩
165    · cases r <;> simpa [ZStreamRef.get, Zlib.Zutil.Proofs.allocHeap, setI] using hL.hz
166    · refine ⟨hI.wf, ⟨hI.win.wbits, Or.inr ⟨h.nextBlk, A0, rfl, ?_, ?_, ?_⟩, fun h0 => absurd h0 (by simp [withWin]), ?_, ?_, ?_, ?_⟩,
167        hI.reqbits, hI.bits, hI.ptr⟩
168      · simpa [setI] using hAb
169      · simpa [setI] using hAro
170      · exact hA0sz
171      · exact Or.inl hws0n
172      · have := hI.win.hv; show st.whave.toNat ≤ st.wsize.toNat; exact this
173      · right; refine ⟨hws0n, ?_⟩
174        have := hI.win.wn; show st.wnext.toNat = 0; omega
175      · intro hh; have := hI.win.hv; show st.wnext.toNat = st.whave.toNat; have := hI.win.wn; have := hI.win.hv
176        change st.whave.toNat < st.wsize.toNat at hh; omega
177  have hz2 : r.get (setI (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat) zs (withWin st h.nextBlk)) = some z :=
178    hG2.live.hz
179  have hbe : Space.get (setI (Zlib.Zutil.Proofs.allocHeap h ((1 <<< st.wbits : UInt32) * 1).toNat) zs
180      (withWin st h.nextBlk)) source = some ebytes := by
181    cases source with
182    | blk b =>
183      have hbn : b ≠ h.nextBlk := fun he => hne (by cases he; rfl)
184      simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI, upd_ne _ _ _ _ hbn] using heb
185    | str b => simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI] using heb
186    | st_dist_code => simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI] using heb
187    | st_length_code => simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI] using heb
188    | dstate_depth b => simpa [Space.get, Zlib.Zutil.Proofs.allocHeap, setI] using heb
189  have hsep : ZlibF.Spec.Public.Separate (.ref source (eo - copy.toNat)) copy.toNat
190      (withWin st h.nextBlk).window (2 ^ (withWin st h.nextBlk).wbits.toNat) := by
191    simp [ZlibF.Spec.Public.Separate, withWin, hne]
192  obtain ⟨after, state, hr, he, _, hgood, _, _, _, _, _, _⟩ :=
193    uw_post_public (hG := hG2) (w := h.nextBlk) (source := source) (eo := eo)
194      (a := A0) (ebytes := ebytes) (copy := copy) rfl (by simpa [setI] using hAb)
195      (by simpa [setI] using hAro) hA0sz hbe hc hoff hsep
196  refine ⟨after, state, hr, hgood, ?_⟩
197  rw [he]
198  exact uw_new_frame hF
199
200/-- A successful `updatewindow` preserves the stream mode for all readable
201sources permitted by the public range-separation condition. -/
202theorem updatewindow_mode_public {h after : Heap} {r : ZStreamRef} {zs : Nat} {z : ZStream}
203    {st state : InflateState} {off : Nat} {source : BRef} {bytes : Array UInt8} {copy : UInt32}
204    (hg : Good h r zs z st) (hza : z.zalloc = .fn "zcalloc")
205    (hsrc : Space.get h source = some bytes) (hfit : off + copy.toNat ≤ bytes.size)
206    (hsep : Separate (.ref source off) copy.toNat st.window (2 ^ st.wbits.toNat))
207    (hr : C.run (updatewindow (some r) (.ref source (off + copy.toNat)) copy) h = .ok (0, after))
208    (hstate : after.istates zs = some state) : state.mode = st.mode := by
209  change updatewindow (some r) (.ref source (off + copy.toNat)) copy h = .ok (0, after) at hr
210  have hsep' : Separate (.ref source ((off + copy.toNat) - copy.toNat)) copy.toNat
211      st.window (2 ^ st.wbits.toNat) := by simpa using hsep
212  rcases hg.inv.win.block with hw | ⟨w, a, hw, ha, hro, hasz⟩
213  · by_cases hok : h.allocOk h.nalloc = true
214    · obtain ⟨result, s', hrun, hgood, hmode⟩ :=
215        uw_null_mode_public (copy := copy) (eo := off + copy.toNat) hg hza hw hok hsrc (by omega) hfit
216      have he : after = result := by rw [hr] at hrun; cases hrun; rfl
217      subst result
218      have hs : state = s' := Option.some.inj (hstate.symm.trans hgood.live.hs)
219      simpa [hs] using hmode
220    · have hfail := uw_alloc_fail hg.live hza hg.inv.win.wbits hw hok
221        (.ref source (off + copy.toNat)) copy
222      rw [hr] at hfail
223      cases hfail
224  · obtain ⟨result, s', hrun, _, hs', hgood, _, _, _, _, _, _⟩ :=
225      uw_post_public (copy := copy) (eo := off + copy.toNat) hg hw ha hro hasz hsrc (by omega) hfit hsep'
226    have he : after = result := by rw [hr] at hrun; cases hrun; rfl
227    have hgood' : Good after r zs z s' := by rw [he]; exact hgood
228    have hs : state = s' := Option.some.inj (hstate.symm.trans hgood'.live.hs)
229    rw [hs, hs', uwPost_mode]
230
231/-- A successful `updatewindow` preserves the public frame. -/
232theorem updatewindow_frame_public {h after : Heap} {r : ZStreamRef} {zs : Nat} {z : ZStream}
233    {st : InflateState} {off : Nat} {source : BRef} {bytes : Array UInt8} {copy : UInt32}
234    (hg : Good h r zs z st) (hza : z.zalloc = .fn "zcalloc")
235    (hsrc : Space.get h source = some bytes) (hfit : off + copy.toNat ≤ bytes.size)
236    (hsep : Separate (.ref source off) copy.toNat st.window (2 ^ st.wbits.toNat))
237    (hr : C.run (updatewindow (some r) (.ref source (off + copy.toNat)) copy) h = .ok (0, after)) :
238    Frame h after (fun b => StreamRoot r b ∨ InflateOwned zs st b) := by
239  change updatewindow (some r) (.ref source (off + copy.toNat)) copy h = .ok (0, after) at hr
240  have hsep' : Separate (.ref source ((off + copy.toNat) - copy.toNat)) copy.toNat
241      st.window (2 ^ st.wbits.toNat) := by simpa using hsep
242  rcases hg.inv.win.block with hw | ⟨w, a, hw, ha, hro, hasz⟩
243  · by_cases hok : h.allocOk h.nalloc = true
244    · obtain ⟨result, _, hrun, _, hframe⟩ :=
245        uw_null_frame_public (copy := copy) (eo := off + copy.toNat) hg hza hw hok hsrc (by omega) hfit
246      have he : after = result := by rw [hr] at hrun; cases hrun; rfl
247      simpa [he] using hframe
248    · have hfail := uw_alloc_fail hg.live hza hg.inv.win.wbits hw hok
249        (.ref source (off + copy.toNat)) copy
250      rw [hr] at hfail
251      cases hfail
252  · obtain ⟨result, s', hrun, he, _, _, _, _, _, _, _, _⟩ :=
253      uw_post_public (copy := copy) (eo := off + copy.toNat) hg hw ha hro hasz hsrc (by omega) hfit hsep'
254    have heq : after = result := by rw [hr] at hrun; cases hrun; rfl
255    rw [heq, he]
256    exact uw_existing_frame hw
257
258/-- A successful `updatewindow` retains all existing objects and allocates
259only its new owned window, if one was needed. -/
260theorem updatewindow_live_public {h after : Heap} {r : ZStreamRef} {zs : Nat} {z : ZStream}
261    {st state : InflateState} {off : Nat} {source : BRef} {bytes : Array UInt8} {copy : UInt32}
262    (hg : Good h r zs z st) (hza : z.zalloc = .fn "zcalloc")
263    (hsrc : Space.get h source = some bytes) (hfit : off + copy.toNat ≤ bytes.size)
264    (hsep : Separate (.ref source off) copy.toNat st.window (2 ^ st.wbits.toNat))
265    (hr : C.run (updatewindow (some r) (.ref source (off + copy.toNat)) copy) h = .ok (0, after))
266    (hstate : after.istates zs = some state) :
267    LiveChange h after (fun b => InflateOwned zs state b ∧ ¬ h.live b) (fun _ => False) := by
268  change updatewindow (some r) (.ref source (off + copy.toNat)) copy h = .ok (0, after) at hr
269  have hzs : h.live zs := by simp [Heap.live, hg.live.hs]
270  have hsep' : Separate (.ref source ((off + copy.toNat) - copy.toNat)) copy.toNat
271      st.window (2 ^ st.wbits.toNat) := by simpa using hsep
272  rcases hg.inv.win.block with hw | ⟨w, a, hw, ha, hro, hasz⟩
273  · by_cases hok : h.allocOk h.nalloc = true
274    · obtain ⟨result, s', hrun, hgood, hwin, _, hown, _, _⟩ :=
275        uw_null_ok_public (copy := copy) (eo := off + copy.toNat) hg hza hw hok hsrc (by omega) hfit
276      have he : after = result := by rw [hr] at hrun; cases hrun; rfl
277      subst result
278      have hs : state = s' := Option.some.inj (hstate.symm.trans hgood.live.hs)
279      subst state
280      have ho := hown (fun b => h.live b) (fun _ => Iff.rfl)
281      intro b
282      have hl : after.live b ↔ h.live b ∨ b = h.nextBlk := ho b
283      by_cases hb : h.live b
284      · simp [LiveChange, hb, hl.mpr (Or.inl hb)]
285      · have hbi : b ≠ zs := fun he => hb (he ▸ hzs)
286        have hwnd : InflateOwned zs s' b ↔ b = h.nextBlk := by
287          simp [InflateOwned, hwin, hbi, eq_comm]
288        simpa [LiveChange, hb, hwnd] using hl
289    · have hfail := uw_alloc_fail hg.live hza hg.inv.win.wbits hw hok
290        (.ref source (off + copy.toNat)) copy
291      rw [hr] at hfail
292      cases hfail
293  · obtain ⟨result, s', hrun, _, _, hgood, hwin, _, _, _, hlive, _⟩ :=
294      uw_post_public (copy := copy) (eo := off + copy.toNat) hg hw ha hro hasz hsrc (by omega) hfit hsep'
295    have he : after = result := by rw [hr] at hrun; cases hrun; rfl
296    have hgood' : Good after r zs z s' := by rw [he]; exact hgood
297    have hs : state = s' := Option.some.inj (hstate.symm.trans hgood'.live.hs)
298    have hwindow : state.window = .ref (.blk w) 0 := by rw [hs, hwin, hw]
299    have howned : ∀ b, InflateOwned zs state b → h.live b := by
300      intro b ho
301      rcases ho with he | he
302      · subst b; exact hzs
303      · rw [hwindow] at he
304        cases he
305        simp [Heap.live, ha]
306    intro b
307    have hl : after.live b ↔ h.live b := by rw [he]; exact hlive b
308    simp only [LiveChange, not_false_eq_true, and_true]
309    constructor
310    · intro he; exact Or.inl (hl.mp he)
311    · intro he
312      rcases he with he | ⟨ho, hn⟩
313      · exact hl.mpr he
314      · exact (hn (howned b ho)).elim
315
316#print axioms uw_null_frame_public
317#print axioms uw_null_mode_public
318#print axioms updatewindow_mode_public
319#print axioms updatewindow_frame_public
320#print axioms updatewindow_live_public
321end Zlib.Inflate.Proofs
ZLIB × LEAN

Global contents

READING NOWinflate.c.window-public-mode.lean