qp.go 3.91 KB
Newer Older
1
// qp helps to quickly build LD nodes.
2 3 4 5 6 7 8 9 10 11
//
// It contains top-level Build funcs, such as BuildMap and BuildList, which
// return the final node as well as an error.
//
// Underneath, one can use a number of Assemble functions to construct basic
// nodes, such as String or Int.
//
// Finally, functions like MapEntry and ListEntry allow inserting into maps and
// lists.
//
12
// These all use the same LD interfaces such as NodePrototype and
13
// NodeAssembler, but with some magic to reduce verbosity.
14 15 16
package qp

import (
17 18
	"fmt"

tavit ohanian's avatar
tavit ohanian committed
19
	ld "gitlab.dms3.io/ld/go-ld-prime"
20 21
)

tavit ohanian's avatar
tavit ohanian committed
22
type Assemble = func(ld.NodeAssembler)
23

tavit ohanian's avatar
tavit ohanian committed
24
func BuildMap(np ld.NodePrototype, sizeHint int64, fn func(ld.MapAssembler)) (_ ld.Node, err error) {
25 26
	defer func() {
		if r := recover(); r != nil {
27 28 29 30 31 32
			if rerr, ok := r.(error); ok {
				err = rerr
			} else {
				// A reasonable fallback, for e.g. strings.
				err = fmt.Errorf("%v", r)
			}
33 34 35 36 37 38 39 40 41
		}
	}()
	nb := np.NewBuilder()
	Map(sizeHint, fn)(nb)
	return nb.Build(), nil
}

type mapParams struct {
	sizeHint int64
tavit ohanian's avatar
tavit ohanian committed
42
	fn       func(ld.MapAssembler)
43 44
}

tavit ohanian's avatar
tavit ohanian committed
45
func (mp mapParams) Assemble(na ld.NodeAssembler) {
46 47 48 49 50 51 52 53 54 55
	ma, err := na.BeginMap(mp.sizeHint)
	if err != nil {
		panic(err)
	}
	mp.fn(ma)
	if err := ma.Finish(); err != nil {
		panic(err)
	}
}

tavit ohanian's avatar
tavit ohanian committed
56
func Map(sizeHint int64, fn func(ld.MapAssembler)) Assemble {
57 58 59
	return mapParams{sizeHint, fn}.Assemble
}

tavit ohanian's avatar
tavit ohanian committed
60
func MapEntry(ma ld.MapAssembler, k string, fn Assemble) {
61 62 63 64 65 66 67
	na, err := ma.AssembleEntry(k)
	if err != nil {
		panic(err)
	}
	fn(na)
}

tavit ohanian's avatar
tavit ohanian committed
68
func BuildList(np ld.NodePrototype, sizeHint int64, fn func(ld.ListAssembler)) (_ ld.Node, err error) {
69 70
	defer func() {
		if r := recover(); r != nil {
71 72 73 74 75 76
			if rerr, ok := r.(error); ok {
				err = rerr
			} else {
				// A reasonable fallback, for e.g. strings.
				err = fmt.Errorf("%v", r)
			}
77 78 79 80 81 82 83 84 85
		}
	}()
	nb := np.NewBuilder()
	List(sizeHint, fn)(nb)
	return nb.Build(), nil
}

type listParams struct {
	sizeHint int64
tavit ohanian's avatar
tavit ohanian committed
86
	fn       func(ld.ListAssembler)
87 88
}

tavit ohanian's avatar
tavit ohanian committed
89
func (lp listParams) Assemble(na ld.NodeAssembler) {
90 91 92 93 94 95 96 97 98 99
	la, err := na.BeginList(lp.sizeHint)
	if err != nil {
		panic(err)
	}
	lp.fn(la)
	if err := la.Finish(); err != nil {
		panic(err)
	}
}

tavit ohanian's avatar
tavit ohanian committed
100
func List(sizeHint int64, fn func(ld.ListAssembler)) Assemble {
101 102 103
	return listParams{sizeHint, fn}.Assemble
}

tavit ohanian's avatar
tavit ohanian committed
104
func ListEntry(la ld.ListAssembler, fn Assemble) {
105 106 107
	fn(la.AssembleValue())
}

108
type nullParam struct{}
109

tavit ohanian's avatar
tavit ohanian committed
110
func (s nullParam) Assemble(na ld.NodeAssembler) {
111
	if err := na.AssignNull(); err != nil {
112 113 114 115
		panic(err)
	}
}

116 117 118 119 120 121
func Null() Assemble {
	return nullParam{}.Assemble
}

type boolParam bool

tavit ohanian's avatar
tavit ohanian committed
122
func (s boolParam) Assemble(na ld.NodeAssembler) {
123 124 125 126 127 128 129
	if err := na.AssignBool(bool(s)); err != nil {
		panic(err)
	}
}

func Bool(b bool) Assemble {
	return boolParam(b).Assemble
130 131 132 133
}

type intParam int64

tavit ohanian's avatar
tavit ohanian committed
134
func (i intParam) Assemble(na ld.NodeAssembler) {
135 136 137 138 139 140 141 142
	if err := na.AssignInt(int64(i)); err != nil {
		panic(err)
	}
}

func Int(i int64) Assemble {
	return intParam(i).Assemble
}
143 144 145

type floatParam float64

tavit ohanian's avatar
tavit ohanian committed
146
func (f floatParam) Assemble(na ld.NodeAssembler) {
147 148 149 150 151 152 153 154 155 156 157
	if err := na.AssignFloat(float64(f)); err != nil {
		panic(err)
	}
}

func Float(f float64) Assemble {
	return intParam(f).Assemble
}

type stringParam string

tavit ohanian's avatar
tavit ohanian committed
158
func (s stringParam) Assemble(na ld.NodeAssembler) {
159 160 161 162 163 164 165 166 167 168 169
	if err := na.AssignString(string(s)); err != nil {
		panic(err)
	}
}

func String(s string) Assemble {
	return stringParam(s).Assemble
}

type bytesParam []byte

tavit ohanian's avatar
tavit ohanian committed
170
func (p bytesParam) Assemble(na ld.NodeAssembler) {
171 172 173 174 175 176 177 178 179 180
	if err := na.AssignBytes([]byte(p)); err != nil {
		panic(err)
	}
}

func Bytes(p []byte) Assemble {
	return bytesParam(p).Assemble
}

type linkParam struct {
tavit ohanian's avatar
tavit ohanian committed
181
	x ld.Link
182 183
}

tavit ohanian's avatar
tavit ohanian committed
184 185
func (l linkParam) Assemble(na ld.NodeAssembler) {
	if err := na.AssignLink(ld.Link(l.x)); err != nil {
186 187 188 189
		panic(err)
	}
}

tavit ohanian's avatar
tavit ohanian committed
190
func Link(l ld.Link) Assemble {
191 192 193 194
	return linkParam{l}.Assemble
}

type nodeParam struct {
tavit ohanian's avatar
tavit ohanian committed
195
	x ld.Node
196 197
}

tavit ohanian's avatar
tavit ohanian committed
198 199
func (n nodeParam) Assemble(na ld.NodeAssembler) {
	if err := na.AssignNode(ld.Node(n.x)); err != nil {
200 201 202 203
		panic(err)
	}
}

tavit ohanian's avatar
tavit ohanian committed
204
func Node(n ld.Node) Assemble {
205 206
	return nodeParam{n}.Assemble
}