ceph-csi/vendor/github.com/gemalto/kmip-go/ttlv/registry.go

249 lines
6.3 KiB
Go
Raw Normal View History

package ttlv
import (
"sort"
"github.com/ansel1/merry"
"github.com/gemalto/kmip-go/internal/kmiputil"
)
// DefaultRegistry holds the default mappings of types, tags, enums, and bitmasks
// to canonical names and normalized names from the KMIP spec. It is pre-populated with the 1.4 spec's
// values. It can be replaced, or additional values can be registered with it.
//
// It is not currently concurrent-safe, so replace or configure it early in your
// program.
var DefaultRegistry Registry
// nolint:gochecknoinits
func init() {
RegisterTypes(&DefaultRegistry)
}
var (
ErrInvalidHexString = kmiputil.ErrInvalidHexString
ErrUnregisteredEnumName = merry.New("unregistered enum name")
)
// NormalizeName tranforms KMIP names from the spec into the
// normalized form of the name. Typically, this means removing spaces,
// and replacing some special characters. The normalized form of the name
// is used in the JSON and XML encodings from the KMIP Profiles.
// The spec describes the normalization process in 5.4.1.1 and 5.5.1.1
func NormalizeName(s string) string {
return kmiputil.NormalizeName(s)
}
// Enum represents an enumeration of KMIP values (as uint32), and maps them
// to the canonical string names and the normalized string names of the
// value as declared in the KMIP specs.
// Enum is used to transpose values from strings to byte values, as required
// by the JSON and XML encodings defined in the KMIP Profiles spec.
// These mappings are also used to pretty print KMIP values, and to marshal
// and unmarshal enum and bitmask values to golang string values.
//
// Enum currently uses plain maps, so it is not thread safe to register new values
// concurrently. You should register all values at the start of your program before
// using this package concurrently.
//
// Enums are used in the KMIP spec for two purposes: for defining the possible values
// for values encoded as the KMIP Enumeration type, and for bitmask values. Bitmask
// values are encoded as Integers, but are really enum values bitwise-OR'd together.
//
// Enums are registered with a Registry. The code to register enums is typically
// generated by the kmipgen tool.
type Enum struct {
valuesToName map[uint32]string
valuesToCanonicalName map[uint32]string
nameToValue map[string]uint32
canonicalNamesToValue map[string]uint32
bitMask bool
}
func NewEnum() Enum {
return Enum{}
}
func NewBitmask() Enum {
return Enum{
bitMask: true,
}
}
// RegisterValue adds a mapping of a uint32 value to a name. The name will be
// processed by NormalizeName to produce the normalized enum value name as described
// in the KMIP spec.
func (e *Enum) RegisterValue(v uint32, name string) {
nn := NormalizeName(name)
if e.valuesToName == nil {
e.valuesToName = map[uint32]string{}
e.nameToValue = map[string]uint32{}
e.valuesToCanonicalName = map[uint32]string{}
e.canonicalNamesToValue = map[string]uint32{}
}
e.valuesToName[v] = nn
e.nameToValue[nn] = v
e.valuesToCanonicalName[v] = name
e.canonicalNamesToValue[name] = v
}
func (e *Enum) Name(v uint32) (string, bool) {
if e == nil {
return "", false
}
name, ok := e.valuesToName[v]
return name, ok
}
func (e *Enum) CanonicalName(v uint32) (string, bool) {
if e == nil {
return "", false
}
name, ok := e.valuesToCanonicalName[v]
return name, ok
}
func (e *Enum) Value(name string) (uint32, bool) {
if e == nil {
return 0, false
}
v, ok := e.nameToValue[name]
if !ok {
v, ok = e.canonicalNamesToValue[name]
}
return v, ok
}
func (e *Enum) Values() []uint32 {
values := make([]uint32, 0, len(e.valuesToName))
for v := range e.valuesToName {
values = append(values, v)
}
// Always list them in order of value so output is stable.
sort.Sort(uint32Slice(values))
return values
}
func (e *Enum) Bitmask() bool {
if e == nil {
return false
}
return e.bitMask
}
// Registry holds all the known tags, types, enums and bitmaps declared in
// a KMIP spec. It's used throughout the package to map values their canonical
// and normalized names.
type Registry struct {
enums map[Tag]EnumMap
tags Enum
types Enum
}
func (r *Registry) RegisterType(t Type, name string) {
r.types.RegisterValue(uint32(t), name)
}
func (r *Registry) RegisterTag(t Tag, name string) {
r.tags.RegisterValue(uint32(t), name)
}
func (r *Registry) RegisterEnum(t Tag, def EnumMap) {
if r.enums == nil {
r.enums = map[Tag]EnumMap{}
}
r.enums[t] = def
}
// EnumForTag returns the enum map registered for a tag. Returns
// nil if no map is registered for this tag.
func (r *Registry) EnumForTag(t Tag) EnumMap {
if r.enums == nil {
return nil
}
return r.enums[t]
}
func (r *Registry) IsBitmask(t Tag) bool {
if e := r.EnumForTag(t); e != nil {
return e.Bitmask()
}
return false
}
func (r *Registry) IsEnum(t Tag) bool {
if e := r.EnumForTag(t); e != nil {
return !e.Bitmask()
}
return false
}
func (r *Registry) Tags() EnumMap {
return &r.tags
}
func (r *Registry) Types() EnumMap {
return &r.types
}
func (r *Registry) FormatEnum(t Tag, v uint32) string {
return FormatEnum(v, r.EnumForTag(t))
}
func (r *Registry) FormatInt(t Tag, v int32) string {
return FormatInt(v, r.EnumForTag(t))
}
func (r *Registry) FormatTag(t Tag) string {
return FormatTag(uint32(t), &r.tags)
}
func (r *Registry) FormatTagCanonical(t Tag) string {
return FormatTagCanonical(uint32(t), &r.tags)
}
func (r *Registry) FormatType(t Type) string {
return FormatType(byte(t), &r.types)
}
func (r *Registry) ParseEnum(t Tag, s string) (uint32, error) {
return ParseEnum(s, r.EnumForTag(t))
}
func (r *Registry) ParseInt(t Tag, s string) (int32, error) {
return ParseInt(s, r.EnumForTag(t))
}
// ParseTag parses a string into Tag according the rules
// in the KMIP Profiles regarding encoding tag values.
// Returns TagNone if not found.
// Returns error if s is a malformed hex string, or a hex string of incorrect length
func (r *Registry) ParseTag(s string) (Tag, error) {
return ParseTag(s, &r.tags)
}
func (r *Registry) ParseType(s string) (Type, error) {
return ParseType(s, &r.types)
}
// uint32Slice attaches the methods of Interface to []int, sorting in increasing order.
type uint32Slice []uint32
func (p uint32Slice) Len() int { return len(p) }
func (p uint32Slice) Less(i, j int) bool { return p[i] < p[j] }
func (p uint32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }