OSDN Git Service

add package
[bytom/vapor.git] / vendor / github.com / multiformats / go-multihash / multihash.go
diff --git a/vendor/github.com/multiformats/go-multihash/multihash.go b/vendor/github.com/multiformats/go-multihash/multihash.go
new file mode 100644 (file)
index 0000000..8c5efbf
--- /dev/null
@@ -0,0 +1,293 @@
+// Package multihash is the Go implementation of
+// https://github.com/multiformats/multihash, or self-describing
+// hashes.
+package multihash
+
+import (
+       "encoding/binary"
+       "encoding/hex"
+       "errors"
+       "fmt"
+       "math"
+
+       b58 "github.com/mr-tron/base58/base58"
+)
+
+// errors
+var (
+       ErrUnknownCode      = errors.New("unknown multihash code")
+       ErrTooShort         = errors.New("multihash too short. must be >= 2 bytes")
+       ErrTooLong          = errors.New("multihash too long. must be < 129 bytes")
+       ErrLenNotSupported  = errors.New("multihash does not yet support digests longer than 127 bytes")
+       ErrInvalidMultihash = errors.New("input isn't valid multihash")
+
+       ErrVarintBufferShort = errors.New("uvarint: buffer too small")
+       ErrVarintTooLong     = errors.New("uvarint: varint too big (max 64bit)")
+)
+
+// ErrInconsistentLen is returned when a decoded multihash has an inconsistent length
+type ErrInconsistentLen struct {
+       dm *DecodedMultihash
+}
+
+func (e ErrInconsistentLen) Error() string {
+       return fmt.Sprintf("multihash length inconsistent: %v", e.dm)
+}
+
+// constants
+const (
+       ID         = 0x00
+       SHA1       = 0x11
+       SHA2_256   = 0x12
+       SHA2_512   = 0x13
+       SHA3_224   = 0x17
+       SHA3_256   = 0x16
+       SHA3_384   = 0x15
+       SHA3_512   = 0x14
+       SHA3       = SHA3_512
+       KECCAK_224 = 0x1A
+       KECCAK_256 = 0x1B
+       KECCAK_384 = 0x1C
+       KECCAK_512 = 0x1D
+
+       SHAKE_128 = 0x18
+       SHAKE_256 = 0x19
+
+       BLAKE2B_MIN = 0xb201
+       BLAKE2B_MAX = 0xb240
+       BLAKE2S_MIN = 0xb241
+       BLAKE2S_MAX = 0xb260
+
+       DBL_SHA2_256 = 0x56
+
+       MURMUR3 = 0x22
+
+       X11 = 0x1100
+)
+
+func init() {
+       // Add blake2b (64 codes)
+       for c := uint64(BLAKE2B_MIN); c <= BLAKE2B_MAX; c++ {
+               n := c - BLAKE2B_MIN + 1
+               name := fmt.Sprintf("blake2b-%d", n*8)
+               Names[name] = c
+               Codes[c] = name
+               DefaultLengths[c] = int(n)
+       }
+
+       // Add blake2s (32 codes)
+       for c := uint64(BLAKE2S_MIN); c <= BLAKE2S_MAX; c++ {
+               n := c - BLAKE2S_MIN + 1
+               name := fmt.Sprintf("blake2s-%d", n*8)
+               Names[name] = c
+               Codes[c] = name
+               DefaultLengths[c] = int(n)
+       }
+}
+
+// Names maps the name of a hash to the code
+var Names = map[string]uint64{
+       "id":           ID,
+       "sha1":         SHA1,
+       "sha2-256":     SHA2_256,
+       "sha2-512":     SHA2_512,
+       "sha3":         SHA3_512,
+       "sha3-224":     SHA3_224,
+       "sha3-256":     SHA3_256,
+       "sha3-384":     SHA3_384,
+       "sha3-512":     SHA3_512,
+       "dbl-sha2-256": DBL_SHA2_256,
+       "murmur3":      MURMUR3,
+       "keccak-224":   KECCAK_224,
+       "keccak-256":   KECCAK_256,
+       "keccak-384":   KECCAK_384,
+       "keccak-512":   KECCAK_512,
+       "shake-128":    SHAKE_128,
+       "shake-256":    SHAKE_256,
+       "x11":          X11,
+}
+
+// Codes maps a hash code to it's name
+var Codes = map[uint64]string{
+       ID:           "id",
+       SHA1:         "sha1",
+       SHA2_256:     "sha2-256",
+       SHA2_512:     "sha2-512",
+       SHA3_224:     "sha3-224",
+       SHA3_256:     "sha3-256",
+       SHA3_384:     "sha3-384",
+       SHA3_512:     "sha3-512",
+       DBL_SHA2_256: "dbl-sha2-256",
+       MURMUR3:      "murmur3",
+       KECCAK_224:   "keccak-224",
+       KECCAK_256:   "keccak-256",
+       KECCAK_384:   "keccak-384",
+       KECCAK_512:   "keccak-512",
+       SHAKE_128:    "shake-128",
+       SHAKE_256:    "shake-256",
+       X11:          "x11",
+}
+
+// DefaultLengths maps a hash code to it's default length
+var DefaultLengths = map[uint64]int{
+       ID:           -1,
+       SHA1:         20,
+       SHA2_256:     32,
+       SHA2_512:     64,
+       SHA3_224:     28,
+       SHA3_256:     32,
+       SHA3_384:     48,
+       SHA3_512:     64,
+       DBL_SHA2_256: 32,
+       KECCAK_224:   28,
+       KECCAK_256:   32,
+       MURMUR3:      4,
+       KECCAK_384:   48,
+       KECCAK_512:   64,
+       SHAKE_128:    32,
+       SHAKE_256:    64,
+       X11:          64,
+}
+
+func uvarint(buf []byte) (uint64, []byte, error) {
+       n, c := binary.Uvarint(buf)
+
+       if c == 0 {
+               return n, buf, ErrVarintBufferShort
+       } else if c < 0 {
+               return n, buf[-c:], ErrVarintTooLong
+       } else {
+               return n, buf[c:], nil
+       }
+}
+
+// DecodedMultihash represents a parsed multihash and allows
+// easy access to the different parts of a multihash.
+type DecodedMultihash struct {
+       Code   uint64
+       Name   string
+       Length int    // Length is just int as it is type of len() opearator
+       Digest []byte // Digest holds the raw multihash bytes
+}
+
+// Multihash is byte slice with the following form:
+// <hash function code><digest size><hash function output>.
+// See the spec for more information.
+type Multihash []byte
+
+// HexString returns the hex-encoded representation of a multihash.
+func (m *Multihash) HexString() string {
+       return hex.EncodeToString([]byte(*m))
+}
+
+// String is an alias to HexString().
+func (m *Multihash) String() string {
+       return m.HexString()
+}
+
+// FromHexString parses a hex-encoded multihash.
+func FromHexString(s string) (Multihash, error) {
+       b, err := hex.DecodeString(s)
+       if err != nil {
+               return Multihash{}, err
+       }
+
+       return Cast(b)
+}
+
+// B58String returns the B58-encoded representation of a multihash.
+func (m Multihash) B58String() string {
+       return b58.Encode([]byte(m))
+}
+
+// FromB58String parses a B58-encoded multihash.
+func FromB58String(s string) (m Multihash, err error) {
+       b, err := b58.Decode(s)
+       if err != nil {
+               return Multihash{}, ErrInvalidMultihash
+       }
+
+       return Cast(b)
+}
+
+// Cast casts a buffer onto a multihash, and returns an error
+// if it does not work.
+func Cast(buf []byte) (Multihash, error) {
+       dm, err := Decode(buf)
+       if err != nil {
+               return Multihash{}, err
+       }
+
+       if !ValidCode(dm.Code) {
+               return Multihash{}, ErrUnknownCode
+       }
+
+       return Multihash(buf), nil
+}
+
+// Decode parses multihash bytes into a DecodedMultihash.
+func Decode(buf []byte) (*DecodedMultihash, error) {
+
+       if len(buf) < 2 {
+               return nil, ErrTooShort
+       }
+
+       var err error
+       var code, length uint64
+
+       code, buf, err = uvarint(buf)
+       if err != nil {
+               return nil, err
+       }
+
+       length, buf, err = uvarint(buf)
+       if err != nil {
+               return nil, err
+       }
+
+       if length > math.MaxInt32 {
+               return nil, errors.New("digest too long, supporting only <= 2^31-1")
+       }
+
+       dm := &DecodedMultihash{
+               Code:   code,
+               Name:   Codes[code],
+               Length: int(length),
+               Digest: buf,
+       }
+
+       if len(dm.Digest) != dm.Length {
+               return nil, ErrInconsistentLen{dm}
+       }
+
+       return dm, nil
+}
+
+// Encode a hash digest along with the specified function code.
+// Note: the length is derived from the length of the digest itself.
+func Encode(buf []byte, code uint64) ([]byte, error) {
+
+       if !ValidCode(code) {
+               return nil, ErrUnknownCode
+       }
+
+       start := make([]byte, 2*binary.MaxVarintLen64, 2*binary.MaxVarintLen64+len(buf))
+       spot := start
+       n := binary.PutUvarint(spot, code)
+       spot = start[n:]
+       n += binary.PutUvarint(spot, uint64(len(buf)))
+
+       return append(start[:n], buf...), nil
+}
+
+// EncodeName is like Encode() but providing a string name
+// instead of a numeric code. See Names for allowed values.
+func EncodeName(buf []byte, name string) ([]byte, error) {
+       return Encode(buf, Names[name])
+}
+
+// ValidCode checks whether a multihash code is valid.
+func ValidCode(code uint64) bool {
+       _, ok := Codes[code]
+       return ok
+}