blob: adfcc97cfac76cf8756fb165c532c7fd06080cad [file] [log] [blame]
// Copyright 2017 The Puffs 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.
pub error "invalid zlib compression method"
pub error "invalid zlib compression window size"
pub error "invalid zlib parity check"
pub error "TODO: unsupported zlib preset dictionary"
pub struct zlib_decoder?(
dec decoder,
adler adler32,
)
pub func zlib_decoder.decode?(dst writer1, src reader1)() {
var x u16 = in.src.read_u16be?()
if ((x >> 8) & 0x0F) != 0x08 {
return error "invalid zlib compression method"
}
if (x >> 12) > 0x07 {
return error "invalid zlib compression window size"
}
if (x & 0x20) != 0 {
return error "TODO: unsupported zlib preset dictionary"
}
if (x % 31) != 0 {
return error "invalid zlib parity check"
}
this.dec.decode?(dst:in.dst, src:in.src)
var checksum u32 = in.src.read_u32be?()
// TODO: verify the checksum.
}
// TODO: drop the '?' but still generate puffs_flate_adler_initialize?
pri struct adler32?(
state u32 = 1,
)
pri func adler32.update(x[] u8)(checksum u32) {
// The Adler-32 checksum's magic 65521 and 5552 numbers are discussed in
// RFC 1950.
var s1 u32 = this.state.low_bits(n:16)
var s2 u32 = this.state.high_bits(n:16)
while in.x.length() > 0 {
var remaining[] u8
if in.x.length() > 5552 {
remaining = in.x[5552:]
in.x = in.x[:5552]
// TODO: this redundant if should be unnecessary.
if in.x.length() > 5552 {
return 0 // Unreachable.
}
}
iterate (p ptr u8:in.x) {
// TODO: uncomment this loop body, and delete the while loop below.
// s1 ~+= deref p as u32
// s2 ~+= s1
}
// TODO: can u64 be u32? Does it matter?
var i u64
while i < in.x.length(),
inv in.x.length() <= 5552,
{
assert i < 5552 via "a < b: a < c; c <= b"(c:in.x.length())
s1 ~+= in.x[i] as u32
s2 ~+= s1
i += 1
}
s1 %= 65521
s2 %= 65521
in.x = remaining
}
this.state = ((s2 & 0xFFFF) << 16) | (s1 & 0xFFFF)
return this.state
}