Skip to content
REFERENCE / ZLIB × LEAN

Inflate.lean

Source snapshot · bda113e61f898f9c · 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.Spec.Api.Goals
2import ZlibF.Proof.Format.Api
3import ZlibF.Proof.Api.InflateCausality
4import ZlibF.Proof.Api.InflateDictionary
5
6/-!
7# Inflate model: determined output and regression proofs
8
9These theorems concern the heap-free API model. They do not assert refinement of the
10translated implementation.
11-/
12
13namespace ZlibF.Spec.Api.Proofs
14open ZlibF.Spec
15
16/-- Output from a complete stream is determined among all compatible complete streams. -/
17theorem inflate_determined_of_decodes {w : Wrap} {b : Nat} {dict x out : List UInt8}
18    (h : Layer.Decodes w b dict x out) : Layer.Determined w b dict x out := by
19  intro stream decoded comparable hd
20  rcases comparable with ⟨tail, heq⟩ | ⟨tail, heq⟩
21  · have hx := Layer.ext h (by simpa only [← heq] using hd)
22    simpa only [← hx.2] using (List.prefix_refl out)
23  · have hx := Layer.ext hd (by simpa only [← heq] using h)
24    simpa only [hx.2] using (List.prefix_refl out)
25
26/-- The empty stored raw stream used by the speculative-output regression is valid. -/
27theorem inflate_regression_raw_empty :
28    Layer.Decodes .raw 15 [] [1, 0, 0, 255, 255] [] :=
29  ⟨_, .last rfl rfl (.stored rfl rfl rfl rfl), by decide⟩
30
31/-- A running OK call cannot invent `a` without consuming input from a fresh raw stream. -/
32theorem inflate_no_input_ok_cannot_guess (after : InflState) :
33    ¬ InflRunOk (InflStart .raw 15 []) ⟨[], 1, .block, false⟩ ⟨0, [97], Z.ok⟩ after := by
34  intro h
35  rcases h with ⟨_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, hd, _⟩
36  have hp := hd ⟨rfl, rfl⟩ (Or.inl rfl) [] rfl [1, 0, 0, 255, 255] []
37    (Or.inl List.nil_prefix) inflate_regression_raw_empty
38  simp [InflStart, InflState.fresh] at hp
39
40/-- The window-allocation-failure outcome also cannot invent `a` without consuming input. -/
41theorem inflate_no_input_mem_cannot_guess (after : InflState) :
42    ¬ InflRunMem (InflStart .raw 15 []) ⟨[], 1, .block, false⟩ ⟨0, [97], Z.memError⟩ after := by
43  intro h
44  rcases h with ⟨_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, hd, _⟩
45  have hp := hd ⟨rfl, rfl⟩ [] rfl [1, 0, 0, 255, 255] []
46    (Or.inl List.nil_prefix) inflate_regression_raw_empty
47  simp [InflStart, InflState.fresh] at hp
48
49private theorem fullWindow_prefix {w : Wrap} {b : Nat} {part stream : List UInt8}
50    (hp : part <+: stream) (hw : FullWindow w b stream) : FullWindow w b part := by
51  rcases hp with ⟨tail, rfl⟩
52  cases part with
53  | nil =>
54    cases w with
55    | raw => exact hw
56    | gzip => exact hw
57    | zlib => rcases hw with h | ⟨h, _⟩ <;> simp_all [FullWindow]
58    | auto => rcases hw with h | ⟨h, _⟩ <;> simp_all [FullWindow]
59  | cons x xs => cases w <;> simpa only [FullWindow, List.cons_append, List.head?_cons] using hw
60
61private theorem needsDict_prefix {w : Wrap} {b : Nat} {part stream : List UInt8}
62    (hp : part <+: stream) (hlen : 2 ≤ part.length) (hn : HdrNeedsDict w b stream) :
63    HdrNeedsDict w b part := by
64  rcases hp with ⟨tail, heq⟩
65  cases part with
66  | nil => simp at hlen
67  | cons a rest =>
68    cases rest with
69    | nil => simp at hlen
70    | cons f rest =>
71      rcases hn with ⟨hw, cmf, flg, r, hz, hh, hb, hf⟩
72      have hhead : a = cmf ∧ f = flg := by
73        rw [← heq] at hz
74        simp only [List.cons_append, List.cons.injEq] at hz
75        exact ⟨hz.1, hz.2.1⟩
76      obtain ⟨rfl, rfl⟩ := hhead
77      refine ⟨hw, a, f, rest, rfl, hh, hb, ?_⟩
78      simpa only [ZlibFits, ← heq, List.cons_append, List.head?_cons] using hf
79
80private theorem needsDict_decoding_prefix_length {w : Wrap} {b : Nat}
81    {d part stream out : List UInt8} (hp : part <+: stream)
82    (hn : HdrNeedsDict w b stream) (hd : Layer.Decodes w b d part out) :
83    6 ≤ part.length := by
84  rcases hn with ⟨hw, cmf, flg, rest, hz, hh, hb, hf⟩
85  have hzlib (hd' : Zlib.Decodes d part out) : 6 ≤ part.length := by
86    rcases hd' with ⟨cmf', flg', pre, body, hs, hh', h0, h1⟩
87    rcases hp with ⟨tail, heq⟩
88    rw [hs, hz] at heq
89    simp only [List.cons_append, List.cons.injEq] at heq
90    obtain ⟨rfl, rfl, _⟩ := heq
91    have hpre := (h1 hb).1
92    rw [hs, hpre]
93    simp [be32]
94  rcases hw with rfl | rfl
95  · exact hzlib hd.1
96  · rcases hd with hd | hd
97    · exact hzlib hd.1
98    · obtain ⟨tail, hg⟩ := gzip_head hd
99      rcases hp with ⟨tail', heq⟩
100      rw [hg, hz] at heq
101      simp only [List.cons_append, List.cons.injEq] at heq
102      have hc : cmf = 31 := heq.1.symm
103      rw [hc] at hh
104      exact False.elim (absurd hh.1 (by decide))
105
106private theorem dict_step_fields {st after : InflState} {dictionary : List UInt8} {rc : Int}
107    (hd : InflSetDict st dictionary rc after) (hp : st.PermitsDictionary dictionary) :
108    after.wrap = st.wrap ∧ after.wbits = st.wbits ∧ after.seen = st.seen ∧
109      after.out = st.out ∧ after.precise = st.precise ∧ after.validate = st.validate ∧
110      after.PermitsDictionary dictionary ∧
111      (after.phase = .done → st.phase = .done) ∧
112      (after.phase = .bad → st.phase = .bad) ∧
113      (after.phase = .syncing → st.phase = .syncing) ∧
114      (after.dict = none → after.phase = .running → st.dict = none ∧ st.phase = .running) := by
115  cases hw : st.wrap <;> simp only [InflSetDict, hw] at hd
116  · rcases hd with ⟨_, ⟨_, rfl⟩ | ⟨_, rfl⟩⟩ <;> simp_all [InflState.PermitsDictionary]
117  all_goals
118    split at hd
119    · split at hd
120      · rcases hd with ⟨_, rfl⟩ | ⟨_, rfl⟩ <;> simp_all [InflState.PermitsDictionary]
121      · obtain ⟨_, rfl⟩ := hd
122        simp_all
123    · obtain ⟨_, rfl⟩ := hd
124      simp_all
125
126/-- A valid FDICT stream whose preset dictionary and decoded output are both empty. -/
127theorem inflate_regression_fdict_empty :
128    Layer.Decodes .zlib 15 []
129      [120, 32, 0, 0, 0, 1, 1, 0, 0, 255, 255, 0, 0, 0, 1] [] := by
130  refine ⟨?_, Or.inr ⟨120, rfl, by decide⟩⟩
131  refine ⟨120, 32, [0, 0, 0, 1], _, rfl, by decide, ?_, ?_⟩
132  · intro h; exact absurd h (by decide)
133  · intro _
134    refine ⟨by decide, _, .last rfl rfl (.stored rfl rfl rfl rfl), by decide⟩
135
136/-- Reading only a legal FDICT header cannot justify a data-error result. -/
137theorem inflate_fdict_header_cannot_fail (after : InflState) :
138    ¬ InflRunOk (InflStart .zlib 15 []) ⟨[120, 32], 10, .block, false⟩
139      ⟨2, [], Z.dataError⟩ after := by
140  intro h
141  rcases h with ⟨_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, hd, _⟩
142  have hn := hd ⟨rfl, rfl⟩ rfl (Or.inl rfl) [] (Or.inl (by decide))
143  apply hn
144  exact Or.inr ⟨[0, 0, 0, 1, 1, 0, 0, 255, 255, 0, 0, 0, 1], [], 15,
145    by simpa [InflStart, InflState.fresh] using inflate_regression_fdict_empty⟩
146
147/-- An unknown preset dictionary does not rule out a valid wrapped input prefix.
148The empty output is determined for every still-permitted dictionary. -/
149theorem inflate_unknown_dictionary_prefix {w : Wrap} {b : Nat}
150    {dictionary stream decoded : List UInt8} (hw : w ≠ .raw)
151    (hd : Layer.Decodes w b dictionary stream decoded) (n : Nat) :
152    (InflState.fresh w b).Consistent (stream.take n) [] ∧
153      (InflState.fresh w b).Determined (stream.take n) [] := by
154  constructor
155  · exact output_evidence_nil (Or.inl hw) hd (stream.take n)
156  · intro _ _ _ _ _ _
157    exact List.nil_prefix
158
159/-- Priming one low bit of minus one inserts a true bit. -/
160theorem inflate_prime_negative_low_bit :
161    InflPrime (InflState.fresh .raw 15) 1 (-1) Z.ok
162      { InflState.fresh .raw 15 with pre := [true], precise := false } := by
163  simp [InflPrime, InflState.fresh]
164
165/-- The earlier false-bit result of priming minus one is rejected. -/
166theorem inflate_prime_negative_rejects_false :
167    ¬ InflPrime (InflState.fresh .raw 15) 1 (-1) Z.ok
168      { InflState.fresh .raw 15 with pre := [false], precise := false } := by
169  simp [InflPrime, InflState.fresh]
170
171/-- A valid decode trace preserves its format, dictionary and output invariants.
172This is a property of the API model; implementation refinement is separate. -/
173theorem inflate_trace_fields {w : Wrap} {b : Nat} {d z o : List UInt8} {final : InflState}
174    (hdecode : Layer.Decodes w b d z o) (hwindow : FullWindow w b z)
175    (htrace : InflTrace z d (InflStart w b d) final) :
176    final.wrap = w ∧ final.wbits = b ∧ final.Exact ∧ final.PermitsDictionary d ∧
177    final.phase ≠ .bad ∧ final.phase ≠ .syncing ∧ final.out <+: o ∧ final.seen <+: z ∧
178    (final.phase = .done → final.out = o ∧ final.seen = z) ∧
179    (final.dict = none → HdrNeedsDict w b z → final.phase = .running → final.seen.length < 6) := by
180  let Inv (st : InflState) : Prop :=
181    st.wrap = w ∧ st.wbits = b ∧ st.Exact ∧ st.PermitsDictionary d ∧
182    st.phase ≠ .bad ∧ st.phase ≠ .syncing ∧ st.out <+: o ∧ st.seen <+: z ∧
183    (st.phase = .done → st.out = o ∧ st.seen = z) ∧
184    (st.dict = none → HdrNeedsDict w b z → st.phase = .running → st.seen.length < 6)
185  have keep : ∀ {start stop}, InflTrace z d start stop → Inv start → Inv stop := by
186    intro start stop trace
187    induction trace with
188    | nil => exact id
189    | @dict s0 s1 s2 r hm ht ih =>
190      intro hi
191      apply ih
192      obtain ⟨hw, hb, he, hp, hbad, hsync, ho, hz, hdone, hearly⟩ := hi
193      obtain ⟨hw', hb', hz', ho', hprec', hval', hp', hdone', hbad', hsync', hearly'⟩ :=
194        dict_step_fields hm hp
195      refine ⟨hw'.trans hw, hb'.trans hb, ⟨hprec'.trans he.1, hval'.trans he.2⟩,
196        hp', fun h => hbad (hbad' h), fun h => hsync (hsync' h), ?_, ?_, ?_, ?_⟩
197      · simpa only [ho'] using ho
198      · simpa only [hz'] using hz
199      · intro h
200        simpa only [ho', hz'] using hdone (hdone' h)
201      · intro hn hd hr
202        obtain ⟨hn', hr'⟩ := hearly' hn hr
203        simpa only [hz'] using hearly hn' hd hr'
204    | @step s0 s1 s2 c r hinput hm ht ih =>
205      intro hi
206      apply ih
207      obtain ⟨hw, hb, he, hp, hbad, hsync, ho, hz, hdone, hearly⟩ := hi
208      have hall : s0.seen ++ c.inp <+: z := by
209        obtain ⟨tail, heq⟩ := hinput
210        refine ⟨tail, ?_⟩
211        rw [List.append_assoc, heq]
212        obtain ⟨tail', rfl⟩ := hz
213        simp
214      have hnew : s0.seen ++ c.inp.take r.out.consumed <+: z := by
215        apply List.IsPrefix.trans (l₂ := s0.seen ++ c.inp) _ hall
216        refine ⟨c.inp.drop r.out.consumed, ?_⟩
217        simp only [List.append_assoc, List.take_append_drop]
218      have hdstate : Layer.Decodes s0.wrap s0.wbits d z o := by simpa only [hw, hb] using hdecode
219      have hwstate : FullWindow s0.wrap s0.wbits (s0.seen ++ c.inp) :=
220        fullWindow_prefix hall (by simpa only [hw, hb] using hwindow)
221      obtain ⟨⟨hbuf, hvalidbuf⟩, _⟩ := hm
222      cases hbf : c.badBuf with
223      | true =>
224        have heq := (hbuf hbf).2.2.2
225        subst s1
226        exact ⟨hw, hb, he, hp, hbad, hsync, ho, hz, hdone, hearly⟩
227      | false =>
228        have hrun := hvalidbuf hbf
229        cases hphase : s0.phase with
230        | bad => exact False.elim (hbad hphase)
231        | syncing => exact False.elim (hsync hphase)
232        | done | mem | needDict =>
233          simp only [hphase] at hrun
234          have heq := hrun.2.2.2
235          subst s1
236          exact ⟨hw, hb, he, hp, hbad, hsync, ho, hz, hdone, hearly⟩
237        | running =>
238          simp only [hphase] at hrun
239          rcases hrun with hrun | hrun
240          · rcases hrun with ⟨hcons, hprod, hseen, hout, _, _, hwrap, hbits, hdict,
241              hprec, hvalidate, _, _, _, hrc, hok, hbuferr, hend, hbaderr, hneed,
242              _, hdec, hdata, _, _, _, hneedlive, _, hdetermined, _⟩
243            have hp' : s1.PermitsDictionary d := by
244              simpa only [InflState.PermitsDictionary, hdict, hwrap] using hp
245            refine ⟨hwrap.trans hw, hbits.trans hb, ⟨hprec.trans he.1, hvalidate.trans he.2⟩,
246              hp', ?_⟩
247            have hforces (hnone : s0.dict = none) (hneeddict : HdrNeedsDict w b z)
248                (hlen : 6 ≤ (s0.seen ++ c.inp).length) : r.out.rc = Z.needDict := by
249              have hnd : HdrNeedsDict s0.wrap s0.wbits (s0.seen ++ c.inp) := by
250                simpa only [hw, hb] using needsDict_prefix hall (by omega) hneeddict
251              exact (hneedlive hnone (hearly hnone hneeddict hphase) hlen hnd).1
252            have hshort : s1.dict = none → HdrNeedsDict w b z → s1.phase = .running →
253                s1.seen.length < 6 := by
254              intro hn hnd hr
255              have hn0 : s0.dict = none := hdict.symm.trans hn
256              by_cases hlen : 6 ≤ (s0.seen ++ c.inp).length
257              · have hph := (hneed (hforces hn0 hnd hlen)).1
258                rw [hph] at hr
259                cases hr
260              · have hlen' : (s0.seen ++ c.inp.take r.out.consumed).length ≤
261                    (s0.seen ++ c.inp).length := by
262                  simp only [List.length_append, List.length_take]
263                  omega
264                rw [hseen]
265                omega
266            have hnotbad : r.out.rc ≠ Z.dataError := by
267              intro herr
268              have hnv := hdata he herr hwstate d hp
269              apply hnv
270              obtain ⟨tail, heq⟩ := hnew
271              exact Or.inr ⟨tail, o, z.length, by simpa only [heq, List.take_length] using hdstate⟩
272            have hprogress (hrunrc : r.out.rc = Z.ok ∨ r.out.rc = Z.bufError)
273                (hph : s1.phase = .running) :
274                s1.phase ≠ .bad ∧ s1.phase ≠ .syncing ∧ s1.out <+: o ∧ s1.seen <+: z ∧
275                  (s1.phase = .done → s1.out = o ∧ s1.seen = z) ∧
276                  (s1.dict = none → HdrNeedsDict w b z → s1.phase = .running → s1.seen.length < 6) := by
277              refine ⟨by simp [hph], by simp [hph], ?_, ?_, ?_, hshort⟩
278              · rw [hout]
279                exact hdetermined he hrunrc d hp z o (Or.inl hnew) hdstate
280              · simpa only [hseen] using hnew
281              · intro h; rw [hph] at h; cases h
282            rcases hrc with hrc | hrc | hrc | hrc | hrc
283            · exact hprogress (Or.inl hrc) (hok hrc).2.2
284            · have hdecode' := hdec he hrc
285              have hdeceff : Layer.Decodes s0.wrap s0.wbits s0.dictEff z o := by
286                by_cases heff : s0.dictEff = d
287                · simpa only [heff] using hdstate
288                · have hnone : s0.dict = none := by
289                    cases hdict0 : s0.dict with
290                    | none => rfl
291                    | some known =>
292                      have hk : d = known := by simpa only [InflState.PermitsDictionary, hdict0] using hp
293                      exact False.elim (heff (by simp [InflState.dictEff, hdict0, hk]))
294                  have hnraw : s0.wrap ≠ .raw := by
295                    intro hr
296                    have hk : d = [] := (by
297                      simpa only [InflState.PermitsDictionary, hnone, hr, ne_eq, not_true_eq_false, false_or] using hp)
298                    exact heff (by simp [InflState.dictEff, hnone, hk])
299                  have hn : ¬ HdrNeedsDict w b z := by
300                    intro hnd
301                    have hlen := needsDict_decoding_prefix_length hnew hnd
302                      (by simpa only [hw, hb] using hdecode')
303                    have halllen : 6 ≤ (s0.seen ++ c.inp).length := by
304                      simp only [List.length_append, List.length_take] at hlen ⊢
305                      omega
306                    have hc : Z.streamEnd = Z.needDict := hrc.symm.trans (hforces hnone hnd halllen)
307                    exact absurd hc (by decide)
308                  exact layer_decodes_dictionary_irrelevant hnraw (by simpa only [hw, hb] using hn) hdstate
309              have hnewcopy := hnew
310              obtain ⟨tail, heq⟩ := hnewcopy
311              have hsame := Layer.ext hdecode' (by simpa only [← heq] using hdeceff)
312              have hsfull : s0.seen ++ c.inp.take r.out.consumed = z := by simpa only [hsame.1, List.append_nil] using heq
313              have hph := hend hrc
314              refine ⟨by simp [hph], by simp [hph], ?_, ?_, ?_, hshort⟩
315              · rw [hout, hsame.2]
316                exact List.prefix_refl _
317              · simpa only [hseen] using hnew
318              · intro _
319                exact ⟨hout.trans hsame.2, hseen.trans hsfull⟩
320            · have hph := (hneed hrc).1
321              have hnil := (hneed hrc).2.1
322              refine ⟨by simp [hph], by simp [hph], ?_, ?_, ?_, hshort⟩
323              · simpa only [hout, hnil, List.append_nil] using ho
324              · simpa only [hseen] using hnew
325              · intro h; rw [hph] at h; cases h
326            · exact False.elim (hnotbad hrc)
327            · exact hprogress (Or.inr hrc) (hbuferr hrc).2
328          · rcases hrun with ⟨_, _, _, _, hphase', hseen, hout, _, _, _, hwrap, hbits,
329              hdict, hprec, hvalidate, _, _, _, _, hdetermined, _⟩
330            have hp' : s1.PermitsDictionary d := by
331              simpa only [InflState.PermitsDictionary, hdict, hwrap] using hp
332            refine ⟨hwrap.trans hw, hbits.trans hb, ⟨hprec.trans he.1, hvalidate.trans he.2⟩,
333              hp', by simp [hphase'], by simp [hphase'], ?_, ?_, ?_, ?_⟩
334            · rw [hout]
335              exact hdetermined he d hp z o (Or.inl hnew) hdstate
336            · simpa only [hseen] using hnew
337            · intro h; rw [hphase'] at h; cases h
338            · intro _ _ h; rw [hphase'] at h; cases h
339  have initial : Inv (InflStart w b d) := by
340    cases hw : w <;> simp [Inv, InflStart, InflState.fresh, InflState.Exact,
341      InflState.PermitsDictionary, hw]
342  exact keep htrace initial
343
344/-- Every model trace on a valid input preserves its decoding and ends at the exact boundary.
345This is a theorem about the API model; implementation refinement is separate. -/
346theorem inflate_decodes : Goal.inflate_decodes := by
347  intro w b d z o final _ hdecode hwindow htrace
348  have h := inflate_trace_fields hdecode hwindow htrace
349  exact ⟨h.2.2.2.2.1, h.2.2.2.2.2.1, h.2.2.2.2.2.2.1,
350    h.2.2.2.2.2.2.2.1, h.2.2.2.2.2.2.2.2.1⟩
351
352/-- A model call with the remaining input and enough space completes or reports allocation failure. -/
353theorem inflate_completes : Goal.inflate_completes := by
354  intro w b d z o st c r st' _ hdecode hwindow hnodict htrace hphase hbuf hin hroom hflush hm
355  obtain ⟨hw, hb, hexact, hperm, _, _, hout, hseen, _, _⟩ :=
356    inflate_trace_fields hdecode hwindow htrace
357  have hcat : st.seen ++ c.inp = z := by
358    rw [hin]
359    obtain ⟨tail, he⟩ := hseen
360    rw [← he, List.drop_left]
361  have hdecode' : Layer.Decodes st.wrap st.wbits st.dictEff z o := by
362    cases hd : st.dict with
363    | some known =>
364      have he : d = known := by simpa [InflState.PermitsDictionary, hd] using hperm
365      simpa [hw, hb, InflState.dictEff, hd, he] using hdecode
366    | none =>
367      by_cases hraw : st.wrap = .raw
368      · have he : d = [] := by simpa [InflState.PermitsDictionary, hd, hraw] using hperm
369        simpa [hw, hb, InflState.dictEff, hd, he] using hdecode
370      · have hdstate : Layer.Decodes st.wrap st.wbits d z o := by simpa [hw, hb] using hdecode
371        have hnstate : ¬ HdrNeedsDict st.wrap st.wbits z := by simpa [hw, hb] using hnodict
372        have he := layer_decodes_dictionary_irrelevant (d2 := []) hraw hnstate hdstate
373        simpa [InflState.dictEff, hd] using he
374  have hrun : InflRun st c r.out st' := by
375    have h := hm.1.2 hbuf
376    simpa only [hphase] using h
377  rcases hrun with hrun | hmem
378  · rcases hrun with ⟨hcons, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
379      _, hdec, _, _, hlive, _, _, _, _, _⟩
380    have hr : r.out.rc = Z.streamEnd := by
381      apply hlive hexact hflush
382      · simpa [hw, hb, hcat] using hwindow
383      · intro _
384        simpa [hw, hb, hcat] using hnodict
385      · refine ⟨z.length, o, ?_, ?_, ?_, hout, hroom⟩
386        · obtain ⟨tail, he⟩ := hseen
387          rw [← he, List.length_append]
388          omega
389        · simp [hcat]
390        · simpa [hcat] using hdecode'
391    have hfinal := hdec hexact hr
392    have hpart : st.seen ++ c.inp.take r.out.consumed <+: z := by
393      refine ⟨c.inp.drop r.out.consumed, ?_⟩
394      simpa [List.append_assoc, List.take_append_drop] using hcat
395    obtain ⟨tail, he⟩ := hpart
396    have hext := Layer.ext hfinal (by simpa [← he] using hdecode')
397    have hstream : st.seen ++ c.inp.take r.out.consumed = z := by
398      simpa [hext.1] using he
399    have hlen := congrArg List.length hstream
400    have hcin := congrArg List.length hcat
401    simp only [List.length_append, List.length_take] at hlen
402    simp only [List.length_append] at hcin
403    refine Or.inl ⟨hm.2.trans hr, ?_, ?_⟩
404    · omega
405    · rw [← hext.2, List.drop_left]
406  · exact Or.inr (hm.2.trans hmem.1)
407
408#print axioms inflate_completes
409
410end ZlibF.Spec.Api.Proofs
ZLIB × LEAN

Global contents

READING NOWInflate.lean