1
1
mirror of https://github.com/wader/fq.git synced 2024-11-23 00:57:15 +03:00

decode: change PosLoopDetector to use generics

This commit is contained in:
David McDonald 2022-12-17 13:26:40 -06:00
parent 3232f9cc15
commit 93f2aa5d73
3 changed files with 11 additions and 7 deletions

View File

@ -301,7 +301,7 @@ const (
)
func makeDecodeRecord() func(d *decode.D) {
var pld apple.PosLoopDetector
var pld apple.PosLoopDetector[int64]
var decodeRecord func(d *decode.D)
decodeRecord = func(d *decode.D) {

View File

@ -197,7 +197,7 @@ func (pl *plist) decodeReference(d *decode.D, idx uint64) bool {
}
pl.consumed[idx] = true
defer pl.pld.PushAndPop(int64(idx), func() { d.Fatalf("infinite recursion detected") })()
defer pl.pld.PushAndPop(idx, func() { d.Fatalf("infinite recursion detected") })()
itemOffset := pl.o[idx]
if itemOffset >= pl.t.offsetTableStart {
@ -224,7 +224,7 @@ type plist struct {
t trailer
o []uint64
consumed map[uint64]bool
pld apple.PosLoopDetector
pld apple.PosLoopDetector[uint64]
}
func bplistDecode(d *decode.D, _ any) any {

View File

@ -1,12 +1,16 @@
package apple
import (
"golang.org/x/exp/constraints"
)
// PosLoopDetector is used for detecting loops when writing decoders, and can
// short-circuit infinite recursion that can cause stack overflows.
type PosLoopDetector []int64
type PosLoopDetector[T constraints.Integer] []T
// Push adds the current offset to the stack and executes the supplied
// detection function
func (pld *PosLoopDetector) Push(offset int64, detect func()) {
func (pld *PosLoopDetector[T]) Push(offset T, detect func()) {
for _, o := range *pld {
if offset == o {
detect()
@ -16,14 +20,14 @@ func (pld *PosLoopDetector) Push(offset int64, detect func()) {
}
// Pop removes the most recently added offset from the stack.
func (pld *PosLoopDetector) Pop() {
func (pld *PosLoopDetector[T]) Pop() {
*pld = (*pld)[:len(*pld)-1]
}
// PushAndPop adds the current offset to the stack, executes the supplied
// detection function, and returns the Pop method. A good usage of this is to
// pair this method call with a defer statement.
func (pld *PosLoopDetector) PushAndPop(i int64, detect func()) func() {
func (pld *PosLoopDetector[T]) PushAndPop(i T, detect func()) func() {
pld.Push(i, detect)
return pld.Pop
}