github.com/git-amp/amp-sdk-go@v0.7.5/stdlib/symbol/api.symbol.go (about)

     1  package symbol
     2  
     3  import (
     4  	"encoding/binary"
     5  	"errors"
     6  
     7  	"github.com/git-amp/amp-sdk-go/stdlib/generics"
     8  )
     9  
    10  // ID is a persistent integer value associated with an immutable string or buffer value.
    11  // ID == 0 always maps to the empty string / buf.
    12  type ID uint32
    13  
    14  // Ord returns the ordinal value of this ID (a type recasting to uint32)
    15  func (id ID) Ord() uint32 {
    16  	return uint32(id)
    17  }
    18  
    19  // IDSz is the byte size of a symbol.ID (big endian)
    20  // The tradeoff is between key bytes idle (wasted) in a massive db and exponentially more IDs available.
    21  //
    22  // The thinking of a 4 byte ID is that an symbol table exceeding 100 million entries is impractical and inefficient.
    23  // If a billion symbol IDs is "not enough"  then you are issuing IDs for the wrong purpose.
    24  const IDSz = 4
    25  
    26  // DefaultIssuerMin specifies the default minimum ID value for newly issued IDs.
    27  //
    28  // ID values less than this value are reserved for clients to represent hard-wired or "out of band" meaning.
    29  // "Hard-wired" meaning that Table.SetSymbolID() can be called with IDs less than MinIssuedID without risk
    30  // of an auto-issued ID contending with it.
    31  const DefaultIssuerMin = 600
    32  
    33  type Issuer interface {
    34  	generics.RefCloser
    35  
    36  	// Issues the next sequential unique ID, starting at MinIssuedID.
    37  	IssueNextID() (ID, error)
    38  }
    39  
    40  var ErrIssuerNotOpen = errors.New("issuer not open")
    41  
    42  // Table abstracts value-ID storage and two-way lookup.
    43  type Table interface {
    44  	generics.RefCloser
    45  
    46  	// Returns the Issuer being used by this Table (passed via TableOpts.Issuer or auto-created if no TableOpts.Issuer was given)
    47  	// Note that retained references should make use of generics.RefCloser to ensure proper closure.
    48  	Issuer() Issuer
    49  
    50  	// Returns the symbol ID previously associated with the given string/buffer value.
    51  	// The given value buffer is never retained.
    52  	//
    53  	// If not found and autoIssue == true, a new entry is created and the new ID returned.
    54  	// Newly issued IDs are always > 0 and use the lower bytes of the returned ID (see type ID comments).
    55  	//
    56  	// If not found and autoIssue == false, 0 is returned.
    57  	GetSymbolID(value []byte, autoIssue bool) ID
    58  
    59  	// Associates the given buffer value to the given symbol ID, allowing multiple values to be mapped to a single ID.
    60  	// If ID == 0, then this is the equivalent to GetSymbolID(value, true).
    61  	SetSymbolID(value []byte, ID ID) ID
    62  
    63  	// Looks up and appends the byte string associated with the given symbol ID to the given buf.
    64  	// If ID is invalid or not found, nil is returned.
    65  	GetSymbol(ID ID, io []byte) []byte
    66  }
    67  
    68  // Reads a big endian encoded uint32 ID from the given byte slice
    69  func ReadID(in []byte) (uint32, []byte) {
    70  	ID := binary.BigEndian.Uint32(in)
    71  	return ID, in[IDSz:]
    72  }
    73  
    74  // Reads an ID from the given byte slice (reading IDSz=4 bytes)
    75  func (id *ID) ReadFrom(in []byte) {
    76  	*id = ID(binary.BigEndian.Uint32(in))
    77  }
    78  
    79  func AppendID(io []byte, ID uint32) []byte {
    80  	return append(io, // big endian marshal
    81  		byte(ID>>24),
    82  		byte(ID>>16),
    83  		byte(ID>>8),
    84  		byte(ID))
    85  }
    86  
    87  func (id ID) AppendTo(io []byte) []byte {
    88  	return append(io, // big endian marshal
    89  		byte(uint32(id)>>24),
    90  		byte(uint32(id)>>16),
    91  		byte(uint32(id)>>8),
    92  		byte(id))
    93  }