|
|
@@ -1,617 +0,0 @@
|
|
|
-////////////////////////////////////////////////////////////////////////////////
|
|
|
-//
|
|
|
-// DO NOT MODIFY
|
|
|
-//
|
|
|
-// ┻━┻ ︵ヽ(`Д´)ノ︵ ┻━┻
|
|
|
-//
|
|
|
-//
|
|
|
-// This source file was automatically generated by bingen.
|
|
|
-//
|
|
|
-////////////////////////////////////////////////////////////////////////////////
|
|
|
-
|
|
|
-package shared
|
|
|
-
|
|
|
-import (
|
|
|
- "fmt"
|
|
|
- util "github.com/opencost/opencost/core/pkg/util"
|
|
|
- "io"
|
|
|
- "iter"
|
|
|
- "os"
|
|
|
- "reflect"
|
|
|
- "strings"
|
|
|
- "sync"
|
|
|
- "unsafe"
|
|
|
-)
|
|
|
-
|
|
|
-const (
|
|
|
- // GeneratorPackageName is the package the generator is targetting
|
|
|
- GeneratorPackageName string = "shared"
|
|
|
-)
|
|
|
-
|
|
|
-// BinaryTags represent the formatting tag used for specific optimization features
|
|
|
-const (
|
|
|
- // BinaryTagStringTable is written and/or read prior to the existence of a string
|
|
|
- // table (where each index is encoded as a string entry in the resource
|
|
|
- BinaryTagStringTable string = "BGST"
|
|
|
-)
|
|
|
-
|
|
|
-const (
|
|
|
- // DefaultCodecVersion is used for any resources listed in the Default version set
|
|
|
- DefaultCodecVersion uint8 = 1
|
|
|
-)
|
|
|
-
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-// Configuration
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-
|
|
|
-var (
|
|
|
- bingenConfigLock sync.RWMutex
|
|
|
- bingenConfig *BingenConfiguration = DefaultBingenConfiguration()
|
|
|
-)
|
|
|
-
|
|
|
-// BingenConfiguration is used to set any custom configuration in the way files are encoded
|
|
|
-// or decoded.
|
|
|
-type BingenConfiguration struct {
|
|
|
- // FileBackedStringTableEnabled enables the use of file-backed string tables for streaming
|
|
|
- // bingen decoding.
|
|
|
- FileBackedStringTableEnabled bool
|
|
|
-
|
|
|
- // FileBackedStringTableDir is the directory to write the string table files for reading.
|
|
|
- FileBackedStringTableDir string
|
|
|
-}
|
|
|
-
|
|
|
-// DefaultBingenConfiguration creates the default implementation of the bingen configuration
|
|
|
-// and returns it.
|
|
|
-func DefaultBingenConfiguration() *BingenConfiguration {
|
|
|
- return &BingenConfiguration{
|
|
|
- FileBackedStringTableEnabled: false,
|
|
|
- FileBackedStringTableDir: os.TempDir(),
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// ConfigureBingen accepts a new *BingenConfiguration instance which updates the internal decoder
|
|
|
-// and encoder behavior.
|
|
|
-func ConfigureBingen(config *BingenConfiguration) {
|
|
|
- bingenConfigLock.Lock()
|
|
|
- defer bingenConfigLock.Unlock()
|
|
|
-
|
|
|
- if config == nil {
|
|
|
- config = DefaultBingenConfiguration()
|
|
|
- }
|
|
|
- bingenConfig = config
|
|
|
-}
|
|
|
-
|
|
|
-// IsBingenFileBackedStringTableEnabled accessor for file backed string table configuration
|
|
|
-func IsBingenFileBackedStringTableEnabled() bool {
|
|
|
- bingenConfigLock.RLock()
|
|
|
- defer bingenConfigLock.RUnlock()
|
|
|
-
|
|
|
- return bingenConfig.FileBackedStringTableEnabled
|
|
|
-}
|
|
|
-
|
|
|
-// BingenFileBackedStringTableDir returns the directory configured for file backed string tables.
|
|
|
-func BingenFileBackedStringTableDir() string {
|
|
|
- bingenConfigLock.RLock()
|
|
|
- defer bingenConfigLock.RUnlock()
|
|
|
-
|
|
|
- return bingenConfig.FileBackedStringTableDir
|
|
|
-}
|
|
|
-
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-// Type Map
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-
|
|
|
-// Generated type map for resolving interface implementations to
|
|
|
-// to concrete types
|
|
|
-var typeMap map[string]reflect.Type = map[string]reflect.Type{}
|
|
|
-
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-// Type Helpers
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-
|
|
|
-// isBinaryTag returns true when the first bytes in the provided binary matches the tag
|
|
|
-func isBinaryTag(data []byte, tag string) bool {
|
|
|
- if len(data) < len(tag) {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- return string(data[:len(tag)]) == tag
|
|
|
-}
|
|
|
-
|
|
|
-// isReaderBinaryTag is used to peek the header for an io.Reader Buffer
|
|
|
-func isReaderBinaryTag(buff *util.Buffer, tag string) bool {
|
|
|
- data, err := buff.Peek(len(tag))
|
|
|
- if err != nil && err != io.EOF {
|
|
|
- panic(fmt.Sprintf("called Peek() on a non buffered reader: %s", err))
|
|
|
- }
|
|
|
- if len(data) < len(tag) {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- return string(data[:len(tag)]) == tag
|
|
|
-}
|
|
|
-
|
|
|
-// appendBytes combines a and b into a new byte array
|
|
|
-func appendBytes(a []byte, b []byte) []byte {
|
|
|
- al := len(a)
|
|
|
- bl := len(b)
|
|
|
- tl := al + bl
|
|
|
-
|
|
|
- // allocate a new byte array for the combined
|
|
|
- // use native copy for speedy byte copying
|
|
|
- result := make([]byte, tl)
|
|
|
- copy(result, a)
|
|
|
- copy(result[al:], b)
|
|
|
-
|
|
|
- return result
|
|
|
-}
|
|
|
-
|
|
|
-// typeToString determines the basic properties of the type, the qualifier, package path, and
|
|
|
-// type name, and returns the qualified type
|
|
|
-func typeToString(f interface{}) string {
|
|
|
- qual := ""
|
|
|
- t := reflect.TypeOf(f)
|
|
|
- if t.Kind() == reflect.Ptr {
|
|
|
- t = t.Elem()
|
|
|
- qual = "*"
|
|
|
- }
|
|
|
-
|
|
|
- return fmt.Sprintf("%s%s.%s", qual, t.PkgPath(), t.Name())
|
|
|
-}
|
|
|
-
|
|
|
-// resolveType uses the name of a type and returns the package, base type name, and whether
|
|
|
-// or not it's a pointer.
|
|
|
-func resolveType(t string) (pkg string, name string, isPtr bool) {
|
|
|
- isPtr = t[:1] == "*"
|
|
|
- if isPtr {
|
|
|
- t = t[1:]
|
|
|
- }
|
|
|
-
|
|
|
- slashIndex := strings.LastIndex(t, "/")
|
|
|
- if slashIndex >= 0 {
|
|
|
- t = t[slashIndex+1:]
|
|
|
- }
|
|
|
- parts := strings.Split(t, ".")
|
|
|
- if parts[0] == GeneratorPackageName {
|
|
|
- parts[0] = ""
|
|
|
- }
|
|
|
-
|
|
|
- pkg = parts[0]
|
|
|
- name = parts[1]
|
|
|
- return
|
|
|
-}
|
|
|
-
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-// Stream Helpers
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-
|
|
|
-// StreamFactoryFunc is an alias for a func that creates a BingenStream implementation.
|
|
|
-type StreamFactoryFunc func(io.Reader) BingenStream
|
|
|
-
|
|
|
-// Generated streamable factory map for finding the specific new stream methods
|
|
|
-// by T type
|
|
|
-var streamFactoryMap map[reflect.Type]StreamFactoryFunc = map[reflect.Type]StreamFactoryFunc{}
|
|
|
-
|
|
|
-// NewStreamFor accepts an io.Reader, and returns a new BingenStream for the generic T
|
|
|
-// type provided _if_ it is a registered bingen type that is annotated as 'streamable'. See
|
|
|
-// the streamFactoryMap for generated type listings.
|
|
|
-func NewStreamFor[T any](reader io.Reader) (BingenStream, error) {
|
|
|
- typeKey := reflect.TypeFor[T]()
|
|
|
-
|
|
|
- factory, ok := streamFactoryMap[typeKey]
|
|
|
- if !ok {
|
|
|
- return nil, fmt.Errorf("the type: %s is not a registered bingen streamable type", typeKey.Name())
|
|
|
- }
|
|
|
-
|
|
|
- return factory(reader), nil
|
|
|
-}
|
|
|
-
|
|
|
-// BingenStream is the stream interface for all streamable types
|
|
|
-type BingenStream interface {
|
|
|
- // Stream returns the iterator which will stream each field of the target type and
|
|
|
- // return the field info as well as the value.
|
|
|
- Stream() iter.Seq2[BingenFieldInfo, *BingenValue]
|
|
|
-
|
|
|
- // Close will close any dynamic io.Reader used to stream in the fields
|
|
|
- Close()
|
|
|
-
|
|
|
- // Error returns an error if one occurred during the process of streaming the type's fields.
|
|
|
- // This can be checked after iterating through the Stream().
|
|
|
- Error() error
|
|
|
-}
|
|
|
-
|
|
|
-// BingenValue contains the value of a field as well as any index/key associated with that value.
|
|
|
-type BingenValue struct {
|
|
|
- Value any
|
|
|
- Index any
|
|
|
-}
|
|
|
-
|
|
|
-// IsNil is just a method accessor way to check to see if the value returned was nil
|
|
|
-func (bv *BingenValue) IsNil() bool {
|
|
|
- return bv == nil
|
|
|
-}
|
|
|
-
|
|
|
-// creates a single BingenValue instance without a key or index
|
|
|
-func singleV(value any) *BingenValue {
|
|
|
- return &BingenValue{
|
|
|
- Value: value,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// creates a pair of key/index and value.
|
|
|
-func pairV(index any, value any) *BingenValue {
|
|
|
- return &BingenValue{
|
|
|
- Value: value,
|
|
|
- Index: index,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// BingenFieldInfo contains the type of the field being streamed as well as the name of the field.
|
|
|
-type BingenFieldInfo struct {
|
|
|
- Type reflect.Type
|
|
|
- Name string
|
|
|
-}
|
|
|
-
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-// String Table Writer
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-
|
|
|
-// StringTableWriter maps strings to specific indices for encoding
|
|
|
-type StringTableWriter struct {
|
|
|
- l sync.Mutex
|
|
|
- indices map[string]int
|
|
|
- next int
|
|
|
-}
|
|
|
-
|
|
|
-// NewStringTableWriter Creates a new StringTableWriter instance with provided contents
|
|
|
-func NewStringTableWriter(contents ...string) *StringTableWriter {
|
|
|
- st := &StringTableWriter{
|
|
|
- indices: make(map[string]int, len(contents)),
|
|
|
- next: len(contents),
|
|
|
- }
|
|
|
-
|
|
|
- for i, entry := range contents {
|
|
|
- st.indices[entry] = i
|
|
|
- }
|
|
|
-
|
|
|
- return st
|
|
|
-}
|
|
|
-
|
|
|
-// AddOrGet atomically retrieves a string entry's index if it exist. Otherwise, it will
|
|
|
-// add the entry and return the index.
|
|
|
-func (st *StringTableWriter) AddOrGet(s string) int {
|
|
|
- st.l.Lock()
|
|
|
- defer st.l.Unlock()
|
|
|
-
|
|
|
- if ind, ok := st.indices[s]; ok {
|
|
|
- return ind
|
|
|
- }
|
|
|
-
|
|
|
- current := st.next
|
|
|
- st.next++
|
|
|
-
|
|
|
- st.indices[s] = current
|
|
|
- return current
|
|
|
-}
|
|
|
-
|
|
|
-// ToSlice Converts the contents to a string array for encoding.
|
|
|
-func (st *StringTableWriter) ToSlice() []string {
|
|
|
- st.l.Lock()
|
|
|
- defer st.l.Unlock()
|
|
|
-
|
|
|
- if st.next == 0 {
|
|
|
- return []string{}
|
|
|
- }
|
|
|
-
|
|
|
- sl := make([]string, st.next)
|
|
|
- for s, i := range st.indices {
|
|
|
- sl[i] = s
|
|
|
- }
|
|
|
- return sl
|
|
|
-}
|
|
|
-
|
|
|
-// ToBytes Converts the contents to a binary encoded representation
|
|
|
-func (st *StringTableWriter) ToBytes() []byte {
|
|
|
- buff := util.NewBuffer()
|
|
|
- buff.WriteBytes([]byte(BinaryTagStringTable)) // bingen table header
|
|
|
-
|
|
|
- strs := st.ToSlice()
|
|
|
-
|
|
|
- buff.WriteInt(len(strs)) // table length
|
|
|
- for _, s := range strs {
|
|
|
- buff.WriteString(s)
|
|
|
- }
|
|
|
-
|
|
|
- return buff.Bytes()
|
|
|
-}
|
|
|
-
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-// String Table Reader
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-
|
|
|
-// StringTableReader is the interface used to read the string table from the decoding.
|
|
|
-type StringTableReader interface {
|
|
|
- // At returns the string entry at a specific index, or panics on out of bounds.
|
|
|
- At(index int) string
|
|
|
-
|
|
|
- // Len returns the total number of strings loaded in the string table.
|
|
|
- Len() int
|
|
|
-
|
|
|
- // Close will clear the loaded table, and drop any external resources used.
|
|
|
- Close() error
|
|
|
-}
|
|
|
-
|
|
|
-// SliceStringTableReader is a basic pre-loaded []string that provides index-based access.
|
|
|
-// The cost of this implementation is holding all strings in memory, which provides faster
|
|
|
-// lookup performance for memory usage.
|
|
|
-type SliceStringTableReader struct {
|
|
|
- table []string
|
|
|
-}
|
|
|
-
|
|
|
-// NewSliceStringTableReaderFrom creates a new SliceStringTableReader instance loading
|
|
|
-// data directly from the buffer. The buffer's position should start at the table length.
|
|
|
-func NewSliceStringTableReaderFrom(buffer *util.Buffer) StringTableReader {
|
|
|
- // table length
|
|
|
- tl := buffer.ReadInt()
|
|
|
-
|
|
|
- var table []string
|
|
|
- if tl > 0 {
|
|
|
- table = make([]string, tl)
|
|
|
- for i := range tl {
|
|
|
- table[i] = buffer.ReadString()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return &SliceStringTableReader{
|
|
|
- table: table,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// At returns the string entry at a specific index, or panics on out of bounds.
|
|
|
-func (sstr *SliceStringTableReader) At(index int) string {
|
|
|
- if index < 0 || index >= len(sstr.table) {
|
|
|
- panic(fmt.Errorf("%s: string table index out of bounds: %d", GeneratorPackageName, index))
|
|
|
- }
|
|
|
-
|
|
|
- return sstr.table[index]
|
|
|
-}
|
|
|
-
|
|
|
-// Len returns the total number of strings loaded in the string table.
|
|
|
-func (sstr *SliceStringTableReader) Len() int {
|
|
|
- if sstr == nil {
|
|
|
- return 0
|
|
|
- }
|
|
|
-
|
|
|
- return len(sstr.table)
|
|
|
-}
|
|
|
-
|
|
|
-// Close for the slice tables just nils out the slice and returns
|
|
|
-func (sstr *SliceStringTableReader) Close() error {
|
|
|
- sstr.table = nil
|
|
|
- return nil
|
|
|
-}
|
|
|
-
|
|
|
-// fileStringRef maps a bingen string-table index to a payload stored in a temp file.
|
|
|
-type fileStringRef struct {
|
|
|
- off int64
|
|
|
- length int
|
|
|
-}
|
|
|
-
|
|
|
-// FileStringTableReader leverages a local file to write string table data for lookup. On
|
|
|
-// memory focused systems, this allows a slower parse with a significant decrease in memory
|
|
|
-// usage. This implementation is often pair with streaming readers for high throughput with
|
|
|
-// reduced memory usage.
|
|
|
-type FileStringTableReader struct {
|
|
|
- f *os.File
|
|
|
- refs []fileStringRef
|
|
|
-}
|
|
|
-
|
|
|
-// NewFileStringTableFromBuffer reads exactly tl length-prefixed (uint16) string payloads from buffer
|
|
|
-// and appends each payload to a new temp file. It does not retain full strings in memory.
|
|
|
-func NewFileStringTableReaderFrom(buffer *util.Buffer, dir string) StringTableReader {
|
|
|
- // helper func to cast a string in-place to a byte slice.
|
|
|
- // NOTE: Return value is READ-ONLY. DO NOT MODIFY!
|
|
|
- byteSliceFor := func(s string) []byte {
|
|
|
- return unsafe.Slice(unsafe.StringData(s), len(s))
|
|
|
- }
|
|
|
-
|
|
|
- err := os.MkdirAll(dir, 0755)
|
|
|
- if err != nil {
|
|
|
- panic(fmt.Errorf("%s: failed to create string table directory: %w", GeneratorPackageName, err))
|
|
|
- }
|
|
|
-
|
|
|
- f, err := os.CreateTemp(dir, fmt.Sprintf("%s-bgst-*", GeneratorPackageName))
|
|
|
- if err != nil {
|
|
|
- panic(fmt.Errorf("%s: failed to create string table file: %w", GeneratorPackageName, err))
|
|
|
- }
|
|
|
-
|
|
|
- var writeErr error
|
|
|
- defer func() {
|
|
|
- if writeErr != nil {
|
|
|
- _ = f.Close()
|
|
|
- }
|
|
|
- }()
|
|
|
-
|
|
|
- // table length
|
|
|
- tl := buffer.ReadInt()
|
|
|
-
|
|
|
- var refs []fileStringRef
|
|
|
- if tl > 0 {
|
|
|
- refs = make([]fileStringRef, tl)
|
|
|
-
|
|
|
- for i := range tl {
|
|
|
- payload := byteSliceFor(buffer.ReadString())
|
|
|
-
|
|
|
- var off int64
|
|
|
- if len(payload) > 0 {
|
|
|
- off, err = f.Seek(0, io.SeekEnd)
|
|
|
- if err != nil {
|
|
|
- writeErr = fmt.Errorf("%s: failed to seek string table file: %w", GeneratorPackageName, err)
|
|
|
- panic(writeErr)
|
|
|
- }
|
|
|
- if _, err := f.Write(payload); err != nil {
|
|
|
- writeErr = fmt.Errorf("%s: failed to write string table entry %d: %w", GeneratorPackageName, i, err)
|
|
|
- panic(writeErr)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- refs[i] = fileStringRef{
|
|
|
- off: off,
|
|
|
- length: len(payload),
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return &FileStringTableReader{
|
|
|
- f: f,
|
|
|
- refs: refs,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// At returns the string from the internal file using the reference's offset and length.
|
|
|
-func (fstr *FileStringTableReader) At(index int) string {
|
|
|
- if fstr == nil || fstr.f == nil {
|
|
|
- panic(fmt.Errorf("%s: failed to read file string table data", GeneratorPackageName))
|
|
|
- }
|
|
|
- if index < 0 || index >= len(fstr.refs) {
|
|
|
- panic(fmt.Errorf("%s: string table index out of bounds: %d", GeneratorPackageName, index))
|
|
|
- }
|
|
|
-
|
|
|
- ref := fstr.refs[index]
|
|
|
- if ref.length == 0 {
|
|
|
- return ""
|
|
|
- }
|
|
|
-
|
|
|
- b := make([]byte, ref.length)
|
|
|
- _, err := fstr.f.ReadAt(b, ref.off)
|
|
|
- if err != nil {
|
|
|
- return ""
|
|
|
- }
|
|
|
-
|
|
|
- // cast the allocated bytes to a string in-place, as we
|
|
|
- // were the ones that allocated the bytes
|
|
|
- return unsafe.String(unsafe.SliceData(b), len(b))
|
|
|
-}
|
|
|
-
|
|
|
-// Len returns the total number of strings loaded in the string table.
|
|
|
-func (fstr *FileStringTableReader) Len() int {
|
|
|
- if fstr == nil {
|
|
|
- return 0
|
|
|
- }
|
|
|
-
|
|
|
- return len(fstr.refs)
|
|
|
-}
|
|
|
-
|
|
|
-// Close for the file string table reader closes the file and deletes it.
|
|
|
-func (fstr *FileStringTableReader) Close() error {
|
|
|
- if fstr == nil || fstr.f == nil {
|
|
|
- return nil
|
|
|
- }
|
|
|
-
|
|
|
- path := fstr.f.Name()
|
|
|
- err := fstr.f.Close()
|
|
|
- fstr.f = nil
|
|
|
- fstr.refs = nil
|
|
|
-
|
|
|
- if path != "" {
|
|
|
- _ = os.Remove(path)
|
|
|
- }
|
|
|
-
|
|
|
- return err
|
|
|
-}
|
|
|
-
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-// Codec Context
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-
|
|
|
-// EncodingContext is a context object passed to the encoders to ensure reuse of buffer
|
|
|
-// and table data
|
|
|
-type EncodingContext struct {
|
|
|
- Buffer *util.Buffer
|
|
|
- Table *StringTableWriter
|
|
|
-}
|
|
|
-
|
|
|
-// IsStringTable returns true if the table is available
|
|
|
-func (ec *EncodingContext) IsStringTable() bool {
|
|
|
- return ec.Table != nil
|
|
|
-}
|
|
|
-
|
|
|
-// DecodingContext is a context object passed to the decoders to ensure parent objects
|
|
|
-// reuse as much data as possible
|
|
|
-type DecodingContext struct {
|
|
|
- Buffer *util.Buffer
|
|
|
- Table StringTableReader
|
|
|
-}
|
|
|
-
|
|
|
-// NewDecodingContextFromBytes creates a new DecodingContext instance using an byte slice
|
|
|
-func NewDecodingContextFromBytes(data []byte) *DecodingContext {
|
|
|
- var table StringTableReader
|
|
|
-
|
|
|
- buff := util.NewBufferFromBytes(data)
|
|
|
-
|
|
|
- // string table header validation
|
|
|
- if isBinaryTag(data, BinaryTagStringTable) {
|
|
|
- buff.ReadBytes(len(BinaryTagStringTable)) // strip tag length
|
|
|
-
|
|
|
- // always use a slice string table with a byte array since the
|
|
|
- // data is already in memory
|
|
|
- table = NewSliceStringTableReaderFrom(buff)
|
|
|
- }
|
|
|
-
|
|
|
- return &DecodingContext{
|
|
|
- Buffer: buff,
|
|
|
- Table: table,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// NewDecodingContextFromReader creates a new DecodingContext instance using an io.Reader
|
|
|
-// implementation
|
|
|
-func NewDecodingContextFromReader(reader io.Reader) *DecodingContext {
|
|
|
- var table StringTableReader
|
|
|
-
|
|
|
- buff := util.NewBufferFromReader(reader)
|
|
|
-
|
|
|
- if isReaderBinaryTag(buff, BinaryTagStringTable) {
|
|
|
- buff.ReadBytes(len(BinaryTagStringTable)) // strip tag length
|
|
|
-
|
|
|
- // create correct string table implementation
|
|
|
- if IsBingenFileBackedStringTableEnabled() {
|
|
|
- table = NewFileStringTableReaderFrom(buff, BingenFileBackedStringTableDir())
|
|
|
- } else {
|
|
|
- table = NewSliceStringTableReaderFrom(buff)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return &DecodingContext{
|
|
|
- Buffer: buff,
|
|
|
- Table: table,
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// IsStringTable returns true if the table is available
|
|
|
-func (dc *DecodingContext) IsStringTable() bool {
|
|
|
- return dc.Table != nil && dc.Table.Len() > 0
|
|
|
-}
|
|
|
-
|
|
|
-// Close will ensure that any string table resources and buffer resources are
|
|
|
-// cleaned up.
|
|
|
-func (dc *DecodingContext) Close() {
|
|
|
- if dc.Table != nil {
|
|
|
- _ = dc.Table.Close()
|
|
|
- dc.Table = nil
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-// Binary Codec
|
|
|
-//--------------------------------------------------------------------------
|
|
|
-
|
|
|
-// BinEncoder is an encoding interface which defines a context based marshal contract.
|
|
|
-type BinEncoder interface {
|
|
|
- MarshalBinaryWithContext(*EncodingContext) error
|
|
|
-}
|
|
|
-
|
|
|
-// BinDecoder is a decoding interface which defines a context based unmarshal contract.
|
|
|
-type BinDecoder interface {
|
|
|
- UnmarshalBinaryWithContext(*DecodingContext) error
|
|
|
-}
|