1// Copyright 2019+ Klaus Post. All rights reserved. 2// License information can be found in the LICENSE file. 3// Based on work by Yann Collet, released under BSD License. 4 5package zstd 6 7import ( 8 "errors" 9 "fmt" 10 "runtime" 11) 12 13// DOption is an option for creating a decoder. 14type DOption func(*decoderOptions) error 15 16// options retains accumulated state of multiple options. 17type decoderOptions struct { 18 lowMem bool 19 concurrent int 20 maxDecodedSize uint64 21 dicts []dict 22} 23 24func (o *decoderOptions) setDefault() { 25 *o = decoderOptions{ 26 // use less ram: true for now, but may change. 27 lowMem: true, 28 concurrent: runtime.GOMAXPROCS(0), 29 } 30 o.maxDecodedSize = 1 << 63 31} 32 33// WithDecoderLowmem will set whether to use a lower amount of memory, 34// but possibly have to allocate more while running. 35func WithDecoderLowmem(b bool) DOption { 36 return func(o *decoderOptions) error { o.lowMem = b; return nil } 37} 38 39// WithDecoderConcurrency will set the concurrency, 40// meaning the maximum number of decoders to run concurrently. 41// The value supplied must be at least 1. 42// By default this will be set to GOMAXPROCS. 43func WithDecoderConcurrency(n int) DOption { 44 return func(o *decoderOptions) error { 45 if n <= 0 { 46 return fmt.Errorf("Concurrency must be at least 1") 47 } 48 o.concurrent = n 49 return nil 50 } 51} 52 53// WithDecoderMaxMemory allows to set a maximum decoded size for in-memory 54// non-streaming operations or maximum window size for streaming operations. 55// This can be used to control memory usage of potentially hostile content. 56// For streaming operations, the maximum window size is capped at 1<<30 bytes. 57// Maximum and default is 1 << 63 bytes. 58func WithDecoderMaxMemory(n uint64) DOption { 59 return func(o *decoderOptions) error { 60 if n == 0 { 61 return errors.New("WithDecoderMaxMemory must be at least 1") 62 } 63 if n > 1<<63 { 64 return fmt.Errorf("WithDecoderMaxmemory must be less than 1 << 63") 65 } 66 o.maxDecodedSize = n 67 return nil 68 } 69} 70 71// WithDecoderDicts allows to register one or more dictionaries for the decoder. 72// If several dictionaries with the same ID is provided the last one will be used. 73func WithDecoderDicts(dicts ...[]byte) DOption { 74 return func(o *decoderOptions) error { 75 for _, b := range dicts { 76 d, err := loadDict(b) 77 if err != nil { 78 return err 79 } 80 o.dicts = append(o.dicts, *d) 81 } 82 return nil 83 } 84} 85