...

Source file src/github.com/go-kivik/kivik/v4/mockdb/gen/parse.go

Documentation: github.com/go-kivik/kivik/v4/mockdb/gen

     1  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
     2  // use this file except in compliance with the License. You may obtain a copy of
     3  // the License at
     4  //
     5  //  http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     9  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    10  // License for the specific language governing permissions and limitations under
    11  // the License.
    12  
    13  package main
    14  
    15  import (
    16  	"context"
    17  	"errors"
    18  	"reflect"
    19  
    20  	kivik "github.com/go-kivik/kivik/v4"
    21  	"github.com/go-kivik/kivik/v4/driver"
    22  )
    23  
    24  // method contains the relevant information for a driver method.
    25  type method struct {
    26  	// The method name
    27  	Name string
    28  	// Accepted values, except for context and options
    29  	Accepts []reflect.Type
    30  	// Return values, except for error
    31  	Returns        []reflect.Type
    32  	AcceptsContext bool
    33  	AcceptsOptions bool
    34  	ReturnsError   bool
    35  	DBMethod       bool
    36  }
    37  
    38  var (
    39  	typeContext       = reflect.TypeOf((*context.Context)(nil)).Elem()
    40  	typeDriverOptions = reflect.TypeOf((*driver.Options)(nil)).Elem()
    41  	typeClientOptions = reflect.TypeOf([]kivik.Option{})
    42  	typeError         = reflect.TypeOf((*error)(nil)).Elem()
    43  	typeString        = reflect.TypeOf("")
    44  )
    45  
    46  func parseMethods(input interface{}, isClient bool, skip map[string]struct{}) ([]*method, error) {
    47  	var hasReceiver bool
    48  	t := reflect.TypeOf(input)
    49  	if t.Kind() != reflect.Struct {
    50  		return nil, errors.New("input must be struct")
    51  	}
    52  	if t.NumField() != 1 || t.Field(0).Name != "X" {
    53  		return nil, errors.New("wrapper struct must have a single field: X")
    54  	}
    55  	fType := t.Field(0).Type
    56  	if isClient {
    57  		if fType.Kind() != reflect.Ptr {
    58  			return nil, errors.New("field X must be of type pointer to struct")
    59  		}
    60  		if fType.Elem().Kind() != reflect.Struct {
    61  			return nil, errors.New("field X must be of type pointer to struct")
    62  		}
    63  		hasReceiver = true
    64  	} else if fType.Kind() != reflect.Interface {
    65  		return nil, errors.New("field X must be of type interface")
    66  	}
    67  	result := make([]*method, 0, fType.NumMethod())
    68  	for i := 0; i < fType.NumMethod(); i++ {
    69  		m := fType.Method(i)
    70  		if _, ok := skip[m.Name]; ok {
    71  			continue
    72  		}
    73  		dm := &method{
    74  			Name: m.Name,
    75  		}
    76  		result = append(result, dm)
    77  		accepts := make([]reflect.Type, m.Type.NumIn())
    78  		for j := 0; j < m.Type.NumIn(); j++ {
    79  			accepts[j] = m.Type.In(j)
    80  		}
    81  		if hasReceiver {
    82  			accepts = accepts[1:]
    83  		}
    84  		if len(accepts) > 0 && accepts[0].Kind() == reflect.Interface && accepts[0].Implements(typeContext) {
    85  			dm.AcceptsContext = true
    86  			accepts = accepts[1:]
    87  		}
    88  		if !isClient && len(accepts) > 0 && accepts[len(accepts)-1] == typeDriverOptions {
    89  			dm.AcceptsOptions = true
    90  			accepts = accepts[:len(accepts)-1]
    91  		}
    92  		if isClient && m.Type.IsVariadic() && len(accepts) > 0 && accepts[len(accepts)-1].String() == typeClientOptions.String() {
    93  			dm.AcceptsOptions = true
    94  			accepts = accepts[:len(accepts)-1]
    95  		}
    96  		if len(accepts) > 0 {
    97  			dm.Accepts = accepts
    98  		}
    99  
   100  		returns := make([]reflect.Type, m.Type.NumOut())
   101  		for j := 0; j < m.Type.NumOut(); j++ {
   102  			returns[j] = m.Type.Out(j)
   103  		}
   104  		if len(returns) > 0 && returns[len(returns)-1] == typeError {
   105  			dm.ReturnsError = true
   106  			returns = returns[:len(returns)-1]
   107  		}
   108  		if len(returns) > 0 {
   109  			dm.Returns = returns
   110  		}
   111  	}
   112  	return result, nil
   113  }
   114  

View as plain text