blob: accc4a8cb6fda821a24099d93a9036ed5a1222cc [file] [log] [blame]
// Copyright 2016 The Upspin Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package pack provides the registry for implementations of Packing algorithms.
package pack // import "upspin.io/pack"
import (
"fmt"
"sync"
"upspin.io/errors"
"upspin.io/upspin"
)
var (
packers = make(map[upspin.Packing]upspin.Packer)
mu sync.Mutex
)
// Register binds a Packing code to the implementation of its algorithm.
// It must be called in the init function of a Packer implementation.
// If multiple calls have the same Packing, Register will panic.
// TODO: One day, or in other languages, we may be able to bind lazily.
func Register(packer upspin.Packer) error {
packing := packer.Packing()
if packing == upspin.UnassignedPack {
return errors.E(errors.Invalid, "unassigned pack cannot be registered")
}
mu.Lock()
defer mu.Unlock()
if p, present := packers[packer.Packing()]; present {
panic(fmt.Sprintf("pack: Register(%d) already installed as %q", p.Packing(), p))
}
packers[packing] = packer
return nil
}
// Lookup returns the implementation of the specified Packing, or nil if none is registered.
func Lookup(p upspin.Packing) upspin.Packer {
mu.Lock()
packer := packers[p]
mu.Unlock() // Not worth a defer.
return packer
}
// LookupByName returns the implementation of the specified Packing, or nil if none is registered.
func LookupByName(name string) upspin.Packer {
mu.Lock()
defer mu.Unlock()
for _, packer := range packers {
if packer.String() == name {
return packer
}
}
return nil
}
var (
// ErrBadPacking indicates that the packing code is invalid.
ErrBadPacking = errors.Str("DirEntry has incorrect Packing value")
)
// CheckPacking verifies that the DirEntry matches the packing type for Pack and Packlen.
func CheckPacking(p upspin.Packer, entry *upspin.DirEntry) error {
if entry.Packing != p.Packing() {
return ErrBadPacking
}
return nil
}