blob: 3262a34aaa5577018d0e816f9a0b2828b0116382 [file]
// Copyright 2026 The Wuffs Authors.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT
// --------
// RFC 6386 Section 7. Boolean Entropy Decoder.
pri func decoder.read_bit!(workbuf: roslice base.u8, part: base.u32[..= 8], prob: base.u32[..= 0xFF]) base.u32[..= 1] {
var p : base.u32[..= 8]
var c8 : base.u8
var shift : base.u32[..= 31]
var split_m1 : base.u32[..= 0xFE]
var ret : base.u32[..= 1]
p = args.part
if this.part_n_bits[p] < 8 {
c8 = 0
if this.part_workbuf_ris[p] < args.workbuf.length() {
assert this.part_workbuf_ris[p] < 0xFFFF_FFFF_FFFF_FFFF via "a < b: a < c; c <= b"(c: args.workbuf.length())
c8 = args.workbuf[this.part_workbuf_ris[p]]
this.part_workbuf_ris[p] += 1
}
this.part_bits[p] = (this.part_bits[p] ~mod<< 8) | (c8 as base.u32)
this.part_n_bits[p] ~mod+= 8
}
shift = (this.part_n_bits[p] ~mod- 8) & 31
split_m1 = ((this.part_range_m1s[p] * args.prob) >> 8)
if (this.part_bits[p] >> shift) > split_m1 {
ret = 1
this.part_range_m1s[p] = (this.part_range_m1s[p] ~mod- (split_m1 + 1)) & 0xFF
this.part_bits[p] ~mod-= (split_m1 + 1) ~mod<< shift
} else {
ret = 0
this.part_range_m1s[p] = split_m1
}
this.part_n_bits[p] ~mod-= RENORM_SHIFT[this.part_range_m1s[p]] as base.u32
this.part_range_m1s[p] = RENORM_RANGE_M1[this.part_range_m1s[p]] as base.u32
return ret
}
pri func decoder.read_unsigned!(workbuf: roslice base.u8, part: base.u32[..= 8], n: base.u32[..= 31]) base.u32 {
var n : base.u32[..= 31]
var v1 : base.u32[..= 1]
var v32 : base.u32
n = args.n
while n > 0 {
n -= 1
v1 = this.read_bit!(workbuf: args.workbuf, part: args.part, prob: 128)
v32 |= v1 ~mod<< n
}
return v32
}
pri func decoder.read_signed!(workbuf: roslice base.u8, part: base.u32[..= 8], n: base.u32[..= 31]) base.u32 {
var v1 : base.u32[..= 1]
var v32 : base.u32
v1 = this.read_bit!(workbuf: args.workbuf, part: args.part, prob: 128)
if v1 == 0 {
return 0
}
v32 = this.read_unsigned!(workbuf: args.workbuf, part: args.part, n: args.n)
v1 = this.read_bit!(workbuf: args.workbuf, part: args.part, prob: 128)
if v1 == 0 {
return v32
}
return 0 ~mod- v32
}