blob: 3d354ddb67d006a1bca5cd55c714f9c0e20048ba [file]
// Copyright 2017 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use "std/adler32"
use "std/deflate"
pub status "?bad checksum"
pub status "?bad compression method"
pub status "?bad compression window size"
pub status "?bad parity check"
pri status "?TODO: unsupported preset dictionary"
pub struct decoder?(
flate deflate.decoder,
checksum adler32.hasher,
ignore_checksum base.bool,
)
pub func decoder.set_ignore_checksum!(ic base.bool) {
this.ignore_checksum = args.ic
}
pub func decoder.decode!??(dst base.io_writer, src base.io_reader) {
var x base.u16 = args.src.read_u16be!??()
if ((x >> 8) & 0x0F) != 0x08 {
return status "?bad compression method"
}
if (x >> 12) > 0x07 {
return status "?bad compression window size"
}
if (x & 0x20) != 0 {
return status "?TODO: unsupported preset dictionary"
}
if (x % 31) != 0 {
return status "?bad parity check"
}
// Decode and checksum the DEFLATE-encoded payload.
var checksum_got base.u32
while true {
args.dst.set_mark!()
var z base.status = try this.flate.decode!??(dst:args.dst, src:args.src)
if not this.ignore_checksum {
checksum_got = this.checksum.update!(x:args.dst.since_mark())
}
if z.is_ok() {
break
}
yield z
}
var checksum_want base.u32 = args.src.read_u32be!??()
if (not this.ignore_checksum) and (checksum_got != checksum_want) {
return status "?bad checksum"
}
}