summaryrefslogtreecommitdiff
path: root/vendor/github.com/lann/builder
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/lann/builder')
-rw-r--r--vendor/github.com/lann/builder/.gitignore2
-rw-r--r--vendor/github.com/lann/builder/.travis.yml7
-rw-r--r--vendor/github.com/lann/builder/LICENSE21
-rw-r--r--vendor/github.com/lann/builder/README.md68
-rw-r--r--vendor/github.com/lann/builder/builder.go225
-rw-r--r--vendor/github.com/lann/builder/reflect.go24
-rw-r--r--vendor/github.com/lann/builder/registry.go59
7 files changed, 406 insertions, 0 deletions
diff --git a/vendor/github.com/lann/builder/.gitignore b/vendor/github.com/lann/builder/.gitignore
new file mode 100644
index 0000000..f54eb28
--- /dev/null
+++ b/vendor/github.com/lann/builder/.gitignore
@@ -0,0 +1,2 @@
+*~
+\#*#
diff --git a/vendor/github.com/lann/builder/.travis.yml b/vendor/github.com/lann/builder/.travis.yml
new file mode 100644
index 0000000..c8860f6
--- /dev/null
+++ b/vendor/github.com/lann/builder/.travis.yml
@@ -0,0 +1,7 @@
+language: go
+
+go:
+ - '1.8'
+ - '1.9'
+ - '1.10'
+ - tip
diff --git a/vendor/github.com/lann/builder/LICENSE b/vendor/github.com/lann/builder/LICENSE
new file mode 100644
index 0000000..a109e80
--- /dev/null
+++ b/vendor/github.com/lann/builder/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2014-2015 Lann Martin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/lann/builder/README.md b/vendor/github.com/lann/builder/README.md
new file mode 100644
index 0000000..3b18550
--- /dev/null
+++ b/vendor/github.com/lann/builder/README.md
@@ -0,0 +1,68 @@
+# Builder - fluent immutable builders for Go
+
+[![GoDoc](https://godoc.org/github.com/lann/builder?status.png)](https://godoc.org/github.com/lann/builder)
+[![Build Status](https://travis-ci.org/lann/builder.png?branch=master)](https://travis-ci.org/lann/builder)
+
+Builder was originally written for
+[Squirrel](https://github.com/lann/squirrel), a fluent SQL generator. It
+is probably the best example of Builder in action.
+
+Builder helps you write **fluent** DSLs for your libraries with method chaining:
+
+```go
+resp := ReqBuilder.
+ Url("http://golang.org").
+ Header("User-Agent", "Builder").
+ Get()
+```
+
+Builder uses **immutable** persistent data structures
+([these](https://github.com/mndrix/ps), specifically)
+so that each step in your method chain can be reused:
+
+```go
+build := WordBuilder.AddLetters("Build")
+builder := build.AddLetters("er")
+building := build.AddLetters("ing")
+```
+
+Builder makes it easy to **build** structs using the **builder** pattern
+(*surprise!*):
+
+```go
+import "github.com/lann/builder"
+
+type Muppet struct {
+ Name string
+ Friends []string
+}
+
+type muppetBuilder builder.Builder
+
+func (b muppetBuilder) Name(name string) muppetBuilder {
+ return builder.Set(b, "Name", name).(muppetBuilder)
+}
+
+func (b muppetBuilder) AddFriend(friend string) muppetBuilder {
+ return builder.Append(b, "Friends", friend).(muppetBuilder)
+}
+
+func (b muppetBuilder) Build() Muppet {
+ return builder.GetStruct(b).(Muppet)
+}
+
+var MuppetBuilder = builder.Register(muppetBuilder{}, Muppet{}).(muppetBuilder)
+```
+```go
+MuppetBuilder.
+ Name("Beaker").
+ AddFriend("Dr. Honeydew").
+ Build()
+
+=> Muppet{Name:"Beaker", Friends:[]string{"Dr. Honeydew"}}
+```
+
+## License
+
+Builder is released under the
+[MIT License](http://www.opensource.org/licenses/MIT).
diff --git a/vendor/github.com/lann/builder/builder.go b/vendor/github.com/lann/builder/builder.go
new file mode 100644
index 0000000..ff62140
--- /dev/null
+++ b/vendor/github.com/lann/builder/builder.go
@@ -0,0 +1,225 @@
+// Package builder provides a method for writing fluent immutable builders.
+package builder
+
+import (
+ "github.com/lann/ps"
+ "go/ast"
+ "reflect"
+)
+
+// Builder stores a set of named values.
+//
+// New types can be declared with underlying type Builder and used with the
+// functions in this package. See example.
+//
+// Instances of Builder should be treated as immutable. It is up to the
+// implementor to ensure mutable values set on a Builder are not mutated while
+// the Builder is in use.
+type Builder struct {
+ builderMap ps.Map
+}
+
+var (
+ EmptyBuilder = Builder{ps.NewMap()}
+ emptyBuilderValue = reflect.ValueOf(EmptyBuilder)
+)
+
+func getBuilderMap(builder interface{}) ps.Map {
+ b := convert(builder, Builder{}).(Builder)
+
+ if b.builderMap == nil {
+ return ps.NewMap()
+ }
+
+ return b.builderMap
+}
+
+// Set returns a copy of the given builder with a new value set for the given
+// name.
+//
+// Set (and all other functions taking a builder in this package) will panic if
+// the given builder's underlying type is not Builder.
+func Set(builder interface{}, name string, v interface{}) interface{} {
+ b := Builder{getBuilderMap(builder).Set(name, v)}
+ return convert(b, builder)
+}
+
+// Delete returns a copy of the given builder with the given named value unset.
+func Delete(builder interface{}, name string) interface{} {
+ b := Builder{getBuilderMap(builder).Delete(name)}
+ return convert(b, builder)
+}
+
+// Append returns a copy of the given builder with new value(s) appended to the
+// named list. If the value was previously unset or set with Set (even to a e.g.
+// slice values), the new value(s) will be appended to an empty list.
+func Append(builder interface{}, name string, vs ...interface{}) interface{} {
+ return Extend(builder, name, vs)
+}
+
+// Extend behaves like Append, except it takes a single slice or array value
+// which will be concatenated to the named list.
+//
+// Unlike a variadic call to Append - which requires a []interface{} value -
+// Extend accepts slices or arrays of any type.
+//
+// Extend will panic if the given value is not a slice, array, or nil.
+func Extend(builder interface{}, name string, vs interface{}) interface{} {
+ if vs == nil {
+ return builder
+ }
+
+ maybeList, ok := getBuilderMap(builder).Lookup(name)
+
+ var list ps.List
+ if ok {
+ list, ok = maybeList.(ps.List)
+ }
+ if !ok {
+ list = ps.NewList()
+ }
+
+ forEach(vs, func(v interface{}) {
+ list = list.Cons(v)
+ })
+
+ return Set(builder, name, list)
+}
+
+func listToSlice(list ps.List, arrayType reflect.Type) reflect.Value {
+ size := list.Size()
+ slice := reflect.MakeSlice(arrayType, size, size)
+ for i := size - 1; i >= 0; i-- {
+ val := reflect.ValueOf(list.Head())
+ slice.Index(i).Set(val)
+ list = list.Tail()
+ }
+ return slice
+}
+
+var anyArrayType = reflect.TypeOf([]interface{}{})
+
+// Get retrieves a single named value from the given builder.
+// If the value has not been set, it returns (nil, false). Otherwise, it will
+// return (value, true).
+//
+// If the named value was last set with Append or Extend, the returned value
+// will be a slice. If the given Builder has been registered with Register or
+// RegisterType and the given name is an exported field of the registered
+// struct, the returned slice will have the same type as that field. Otherwise
+// the slice will have type []interface{}. It will panic if the given name is a
+// registered struct's exported field and the value set on the Builder is not
+// assignable to the field.
+func Get(builder interface{}, name string) (interface{}, bool) {
+ val, ok := getBuilderMap(builder).Lookup(name)
+ if !ok {
+ return nil, false
+ }
+
+ list, isList := val.(ps.List)
+ if isList {
+ arrayType := anyArrayType
+
+ if ast.IsExported(name) {
+ structType := getBuilderStructType(reflect.TypeOf(builder))
+ if structType != nil {
+ field, ok := (*structType).FieldByName(name)
+ if ok {
+ arrayType = field.Type
+ }
+ }
+ }
+
+ val = listToSlice(list, arrayType).Interface()
+ }
+
+ return val, true
+}
+
+// GetMap returns a map[string]interface{} of the values set in the given
+// builder.
+//
+// See notes on Get regarding returned slices.
+func GetMap(builder interface{}) map[string]interface{} {
+ m := getBuilderMap(builder)
+ structType := getBuilderStructType(reflect.TypeOf(builder))
+
+ ret := make(map[string]interface{}, m.Size())
+
+ m.ForEach(func(name string, val ps.Any) {
+ list, isList := val.(ps.List)
+ if isList {
+ arrayType := anyArrayType
+
+ if structType != nil {
+ field, ok := (*structType).FieldByName(name)
+ if ok {
+ arrayType = field.Type
+ }
+ }
+
+ val = listToSlice(list, arrayType).Interface()
+ }
+
+ ret[name] = val
+ })
+
+ return ret
+}
+
+// GetStruct builds a new struct from the given registered builder.
+// It will return nil if the given builder's type has not been registered with
+// Register or RegisterValue.
+//
+// All values set on the builder with names that start with an uppercase letter
+// (i.e. which would be exported if they were identifiers) are assigned to the
+// corresponding exported fields of the struct.
+//
+// GetStruct will panic if any of these "exported" values are not assignable to
+// their corresponding struct fields.
+func GetStruct(builder interface{}) interface{} {
+ structVal := newBuilderStruct(reflect.TypeOf(builder))
+ if structVal == nil {
+ return nil
+ }
+ return scanStruct(builder, structVal)
+}
+
+// GetStructLike builds a new struct from the given builder with the same type
+// as the given struct.
+//
+// All values set on the builder with names that start with an uppercase letter
+// (i.e. which would be exported if they were identifiers) are assigned to the
+// corresponding exported fields of the struct.
+//
+// ScanStruct will panic if any of these "exported" values are not assignable to
+// their corresponding struct fields.
+func GetStructLike(builder interface{}, strct interface{}) interface{} {
+ structVal := reflect.New(reflect.TypeOf(strct)).Elem()
+ return scanStruct(builder, &structVal)
+}
+
+func scanStruct(builder interface{}, structVal *reflect.Value) interface{} {
+ getBuilderMap(builder).ForEach(func(name string, val ps.Any) {
+ if ast.IsExported(name) {
+ field := structVal.FieldByName(name)
+
+ var value reflect.Value
+ switch v := val.(type) {
+ case nil:
+ switch field.Kind() {
+ case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+ value = reflect.Zero(field.Type())
+ }
+ // nil is not valid for this Type; Set will panic
+ case ps.List:
+ value = listToSlice(v, field.Type())
+ default:
+ value = reflect.ValueOf(val)
+ }
+ field.Set(value)
+ }
+ })
+
+ return structVal.Interface()
+}
diff --git a/vendor/github.com/lann/builder/reflect.go b/vendor/github.com/lann/builder/reflect.go
new file mode 100644
index 0000000..3b236e7
--- /dev/null
+++ b/vendor/github.com/lann/builder/reflect.go
@@ -0,0 +1,24 @@
+package builder
+
+import "reflect"
+
+func convert(from interface{}, to interface{}) interface{} {
+ return reflect.
+ ValueOf(from).
+ Convert(reflect.TypeOf(to)).
+ Interface()
+}
+
+func forEach(s interface{}, f func(interface{})) {
+ val := reflect.ValueOf(s)
+
+ kind := val.Kind()
+ if kind != reflect.Slice && kind != reflect.Array {
+ panic(&reflect.ValueError{Method: "builder.forEach", Kind: kind})
+ }
+
+ l := val.Len()
+ for i := 0; i < l; i++ {
+ f(val.Index(i).Interface())
+ }
+}
diff --git a/vendor/github.com/lann/builder/registry.go b/vendor/github.com/lann/builder/registry.go
new file mode 100644
index 0000000..6128454
--- /dev/null
+++ b/vendor/github.com/lann/builder/registry.go
@@ -0,0 +1,59 @@
+package builder
+
+import (
+ "reflect"
+ "sync"
+)
+
+var (
+ registry = make(map[reflect.Type]reflect.Type)
+ registryMux sync.RWMutex
+)
+
+// RegisterType maps the given builderType to a structType.
+// This mapping affects the type of slices returned by Get and is required for
+// GetStruct to work.
+//
+// Returns a Value containing an empty instance of the registered builderType.
+//
+// RegisterType will panic if builderType's underlying type is not Builder or
+// if structType's Kind is not Struct.
+func RegisterType(builderType reflect.Type, structType reflect.Type) *reflect.Value {
+ registryMux.Lock()
+ defer registryMux.Unlock()
+ structType.NumField() // Panic if structType is not a struct
+ registry[builderType] = structType
+ emptyValue := emptyBuilderValue.Convert(builderType)
+ return &emptyValue
+}
+
+// Register wraps RegisterType, taking instances instead of Types.
+//
+// Returns an empty instance of the registered builder type which can be used
+// as the initial value for builder expressions. See example.
+func Register(builderProto, structProto interface{}) interface{} {
+ empty := RegisterType(
+ reflect.TypeOf(builderProto),
+ reflect.TypeOf(structProto),
+ ).Interface()
+ return empty
+}
+
+func getBuilderStructType(builderType reflect.Type) *reflect.Type {
+ registryMux.RLock()
+ defer registryMux.RUnlock()
+ structType, ok := registry[builderType]
+ if !ok {
+ return nil
+ }
+ return &structType
+}
+
+func newBuilderStruct(builderType reflect.Type) *reflect.Value {
+ structType := getBuilderStructType(builderType)
+ if structType == nil {
+ return nil
+ }
+ newStruct := reflect.New(*structType).Elem()
+ return &newStruct
+}