open-vault/vendor/layeh.com/radius/dictionary.go

130 lines
3.0 KiB
Go

package radius // import "layeh.com/radius"
import (
"errors"
"sync"
)
// Builtin is the built-in dictionary. It is initially loaded with the
// attributes defined in RFC 2865 and RFC 2866.
var Builtin *Dictionary
type dictEntry struct {
Type byte
Name string
Codec AttributeCodec
}
// Dictionary stores mappings between attribute names and types and
// AttributeCodecs.
type Dictionary struct {
mu sync.RWMutex
attributesByType [256]*dictEntry
attributesByName map[string]*dictEntry
}
// Register registers the AttributeCodec for the given attribute name and type.
func (d *Dictionary) Register(name string, t byte, codec AttributeCodec) error {
d.mu.Lock()
if d.attributesByType[t] != nil {
d.mu.Unlock()
return errors.New("radius: attribute already registered")
}
entry := &dictEntry{
Type: t,
Name: name,
Codec: codec,
}
d.attributesByType[t] = entry
if d.attributesByName == nil {
d.attributesByName = make(map[string]*dictEntry)
}
d.attributesByName[name] = entry
d.mu.Unlock()
return nil
}
// MustRegister is a helper for Register that panics if it returns an error.
func (d *Dictionary) MustRegister(name string, t byte, codec AttributeCodec) {
if err := d.Register(name, t, codec); err != nil {
panic(err)
}
}
func (d *Dictionary) get(name string) (t byte, codec AttributeCodec, ok bool) {
d.mu.RLock()
entry := d.attributesByName[name]
d.mu.RUnlock()
if entry == nil {
return
}
t = entry.Type
codec = entry.Codec
ok = true
return
}
// Attr returns a new *Attribute whose type is registered under the given
// name.
//
// If name is not registered, nil and an error is returned.
func (d *Dictionary) Attr(name string, value interface{}) (*Attribute, error) {
t, _, ok := d.get(name)
if !ok {
return nil, errors.New("radius: attribute name not registered")
}
return &Attribute{
Type: t,
Value: value,
}, nil
}
// MustAttr is a helper for Attr that panics if Attr were to return an error.
func (d *Dictionary) MustAttr(name string, value interface{}) *Attribute {
attr, err := d.Attr(name, value)
if err != nil {
panic(err)
}
return attr
}
// Name returns the registered name for the given attribute type. ok is false
// if the given type is not registered.
func (d *Dictionary) Name(t byte) (name string, ok bool) {
d.mu.RLock()
entry := d.attributesByType[t]
d.mu.RUnlock()
if entry == nil {
return
}
name = entry.Name
ok = true
return
}
// Type returns the registered type for the given attribute name. ok is false
// if the given name is not registered.
func (d *Dictionary) Type(name string) (t byte, ok bool) {
d.mu.RLock()
entry := d.attributesByName[name]
d.mu.RUnlock()
if entry == nil {
return
}
t = entry.Type
ok = true
return
}
// Codec returns the AttributeCodec for the given registered type. nil is
// returned if the given type is not registered.
func (d *Dictionary) Codec(t byte) AttributeCodec {
d.mu.RLock()
entry := d.attributesByType[t]
d.mu.RUnlock()
if entry == nil {
return AttributeUnknown
}
return entry.Codec
}