OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / btcjson / register.go
diff --git a/vendor/github.com/btcsuite/btcd/btcjson/register.go b/vendor/github.com/btcsuite/btcd/btcjson/register.go
deleted file mode 100644 (file)
index 5de001c..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright (c) 2014 The btcsuite developers
-// Use of this source code is governed by an ISC
-// license that can be found in the LICENSE file.
-
-package btcjson
-
-import (
-       "encoding/json"
-       "fmt"
-       "reflect"
-       "sort"
-       "strconv"
-       "strings"
-       "sync"
-)
-
-// UsageFlag define flags that specify additional properties about the
-// circumstances under which a command can be used.
-type UsageFlag uint32
-
-const (
-       // UFWalletOnly indicates that the command can only be used with an RPC
-       // server that supports wallet commands.
-       UFWalletOnly UsageFlag = 1 << iota
-
-       // UFWebsocketOnly indicates that the command can only be used when
-       // communicating with an RPC server over websockets.  This typically
-       // applies to notifications and notification registration functions
-       // since neiher makes since when using a single-shot HTTP-POST request.
-       UFWebsocketOnly
-
-       // UFNotification indicates that the command is actually a notification.
-       // This means when it is marshalled, the ID must be nil.
-       UFNotification
-
-       // highestUsageFlagBit is the maximum usage flag bit and is used in the
-       // stringer and tests to ensure all of the above constants have been
-       // tested.
-       highestUsageFlagBit
-)
-
-// Map of UsageFlag values back to their constant names for pretty printing.
-var usageFlagStrings = map[UsageFlag]string{
-       UFWalletOnly:    "UFWalletOnly",
-       UFWebsocketOnly: "UFWebsocketOnly",
-       UFNotification:  "UFNotification",
-}
-
-// String returns the UsageFlag in human-readable form.
-func (fl UsageFlag) String() string {
-       // No flags are set.
-       if fl == 0 {
-               return "0x0"
-       }
-
-       // Add individual bit flags.
-       s := ""
-       for flag := UFWalletOnly; flag < highestUsageFlagBit; flag <<= 1 {
-               if fl&flag == flag {
-                       s += usageFlagStrings[flag] + "|"
-                       fl -= flag
-               }
-       }
-
-       // Add remaining value as raw hex.
-       s = strings.TrimRight(s, "|")
-       if fl != 0 {
-               s += "|0x" + strconv.FormatUint(uint64(fl), 16)
-       }
-       s = strings.TrimLeft(s, "|")
-       return s
-}
-
-// methodInfo keeps track of information about each registered method such as
-// the parameter information.
-type methodInfo struct {
-       maxParams    int
-       numReqParams int
-       numOptParams int
-       defaults     map[int]reflect.Value
-       flags        UsageFlag
-       usage        string
-}
-
-var (
-       // These fields are used to map the registered types to method names.
-       registerLock         sync.RWMutex
-       methodToConcreteType = make(map[string]reflect.Type)
-       methodToInfo         = make(map[string]methodInfo)
-       concreteTypeToMethod = make(map[reflect.Type]string)
-)
-
-// baseKindString returns the base kind for a given reflect.Type after
-// indirecting through all pointers.
-func baseKindString(rt reflect.Type) string {
-       numIndirects := 0
-       for rt.Kind() == reflect.Ptr {
-               numIndirects++
-               rt = rt.Elem()
-       }
-
-       return fmt.Sprintf("%s%s", strings.Repeat("*", numIndirects), rt.Kind())
-}
-
-// isAcceptableKind returns whether or not the passed field type is a supported
-// type.  It is called after the first pointer indirection, so further pointers
-// are not supported.
-func isAcceptableKind(kind reflect.Kind) bool {
-       switch kind {
-       case reflect.Chan:
-               fallthrough
-       case reflect.Complex64:
-               fallthrough
-       case reflect.Complex128:
-               fallthrough
-       case reflect.Func:
-               fallthrough
-       case reflect.Ptr:
-               fallthrough
-       case reflect.Interface:
-               return false
-       }
-
-       return true
-}
-
-// RegisterCmd registers a new command that will automatically marshal to and
-// from JSON-RPC with full type checking and positional parameter support.  It
-// also accepts usage flags which identify the circumstances under which the
-// command can be used.
-//
-// This package automatically registers all of the exported commands by default
-// using this function, however it is also exported so callers can easily
-// register custom types.
-//
-// The type format is very strict since it needs to be able to automatically
-// marshal to and from JSON-RPC 1.0.  The following enumerates the requirements:
-//
-//   - The provided command must be a single pointer to a struct
-//   - All fields must be exported
-//   - The order of the positional parameters in the marshalled JSON will be in
-//     the same order as declared in the struct definition
-//   - Struct embedding is not supported
-//   - Struct fields may NOT be channels, functions, complex, or interface
-//   - A field in the provided struct with a pointer is treated as optional
-//   - Multiple indirections (i.e **int) are not supported
-//   - Once the first optional field (pointer) is encountered, the remaining
-//     fields must also be optional fields (pointers) as required by positional
-//     params
-//   - A field that has a 'jsonrpcdefault' struct tag must be an optional field
-//     (pointer)
-//
-// NOTE: This function only needs to be able to examine the structure of the
-// passed struct, so it does not need to be an actual instance.  Therefore, it
-// is recommended to simply pass a nil pointer cast to the appropriate type.
-// For example, (*FooCmd)(nil).
-func RegisterCmd(method string, cmd interface{}, flags UsageFlag) error {
-       registerLock.Lock()
-       defer registerLock.Unlock()
-
-       if _, ok := methodToConcreteType[method]; ok {
-               str := fmt.Sprintf("method %q is already registered", method)
-               return makeError(ErrDuplicateMethod, str)
-       }
-
-       // Ensure that no unrecognized flag bits were specified.
-       if ^(highestUsageFlagBit-1)&flags != 0 {
-               str := fmt.Sprintf("invalid usage flags specified for method "+
-                       "%s: %v", method, flags)
-               return makeError(ErrInvalidUsageFlags, str)
-       }
-
-       rtp := reflect.TypeOf(cmd)
-       if rtp.Kind() != reflect.Ptr {
-               str := fmt.Sprintf("type must be *struct not '%s (%s)'", rtp,
-                       rtp.Kind())
-               return makeError(ErrInvalidType, str)
-       }
-       rt := rtp.Elem()
-       if rt.Kind() != reflect.Struct {
-               str := fmt.Sprintf("type must be *struct not '%s (*%s)'",
-                       rtp, rt.Kind())
-               return makeError(ErrInvalidType, str)
-       }
-
-       // Enumerate the struct fields to validate them and gather parameter
-       // information.
-       numFields := rt.NumField()
-       numOptFields := 0
-       defaults := make(map[int]reflect.Value)
-       for i := 0; i < numFields; i++ {
-               rtf := rt.Field(i)
-               if rtf.Anonymous {
-                       str := fmt.Sprintf("embedded fields are not supported "+
-                               "(field name: %q)", rtf.Name)
-                       return makeError(ErrEmbeddedType, str)
-               }
-               if rtf.PkgPath != "" {
-                       str := fmt.Sprintf("unexported fields are not supported "+
-                               "(field name: %q)", rtf.Name)
-                       return makeError(ErrUnexportedField, str)
-               }
-
-               // Disallow types that can't be JSON encoded.  Also, determine
-               // if the field is optional based on it being a pointer.
-               var isOptional bool
-               switch kind := rtf.Type.Kind(); kind {
-               case reflect.Ptr:
-                       isOptional = true
-                       kind = rtf.Type.Elem().Kind()
-                       fallthrough
-               default:
-                       if !isAcceptableKind(kind) {
-                               str := fmt.Sprintf("unsupported field type "+
-                                       "'%s (%s)' (field name %q)", rtf.Type,
-                                       baseKindString(rtf.Type), rtf.Name)
-                               return makeError(ErrUnsupportedFieldType, str)
-                       }
-               }
-
-               // Count the optional fields and ensure all fields after the
-               // first optional field are also optional.
-               if isOptional {
-                       numOptFields++
-               } else {
-                       if numOptFields > 0 {
-                               str := fmt.Sprintf("all fields after the first "+
-                                       "optional field must also be optional "+
-                                       "(field name %q)", rtf.Name)
-                               return makeError(ErrNonOptionalField, str)
-                       }
-               }
-
-               // Ensure the default value can be unsmarshalled into the type
-               // and that defaults are only specified for optional fields.
-               if tag := rtf.Tag.Get("jsonrpcdefault"); tag != "" {
-                       if !isOptional {
-                               str := fmt.Sprintf("required fields must not "+
-                                       "have a default specified (field name "+
-                                       "%q)", rtf.Name)
-                               return makeError(ErrNonOptionalDefault, str)
-                       }
-
-                       rvf := reflect.New(rtf.Type.Elem())
-                       err := json.Unmarshal([]byte(tag), rvf.Interface())
-                       if err != nil {
-                               str := fmt.Sprintf("default value of %q is "+
-                                       "the wrong type (field name %q)", tag,
-                                       rtf.Name)
-                               return makeError(ErrMismatchedDefault, str)
-                       }
-                       defaults[i] = rvf
-               }
-       }
-
-       // Update the registration maps.
-       methodToConcreteType[method] = rtp
-       methodToInfo[method] = methodInfo{
-               maxParams:    numFields,
-               numReqParams: numFields - numOptFields,
-               numOptParams: numOptFields,
-               defaults:     defaults,
-               flags:        flags,
-       }
-       concreteTypeToMethod[rtp] = method
-       return nil
-}
-
-// MustRegisterCmd performs the same function as RegisterCmd except it panics
-// if there is an error.  This should only be called from package init
-// functions.
-func MustRegisterCmd(method string, cmd interface{}, flags UsageFlag) {
-       if err := RegisterCmd(method, cmd, flags); err != nil {
-               panic(fmt.Sprintf("failed to register type %q: %v\n", method,
-                       err))
-       }
-}
-
-// RegisteredCmdMethods returns a sorted list of methods for all registered
-// commands.
-func RegisteredCmdMethods() []string {
-       registerLock.Lock()
-       defer registerLock.Unlock()
-
-       methods := make([]string, 0, len(methodToInfo))
-       for k := range methodToInfo {
-               methods = append(methods, k)
-       }
-
-       sort.Sort(sort.StringSlice(methods))
-       return methods
-}