~wallyworld/juju-core/fast-lxc-everywhere

« back to all changes in this revision

Viewing changes to schema/schema.go

  • Committer: Gustavo Niemeyer
  • Date: 2011-09-05 20:35:00 UTC
  • mfrom: (2.1.4 go-formulas)
  • Revision ID: gustavo@niemeyer.net-20110905203500-20rf3w8b16m4zrfl
Merged go-iface-schemas branch [r=fwereade,hazmat]

This kicks off the formula schema support in the Go port.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
        "strings"
10
10
)
11
11
 
 
12
// All map types used in the schema package are of type M.
 
13
type M map[interface{}]interface{}
 
14
 
 
15
// All the slice types generated in the schema package are of type L.
 
16
type L []interface{}
 
17
 
12
18
// The Coerce method of the Checker interface is called recursively when
13
19
// v is being validated.  If err is nil, newv is used as the new value
14
20
// at the recursion point.  If err is non-nil, v is taken as invalid and
101
107
type boolC struct{}
102
108
 
103
109
func (c boolC) Coerce(v interface{}, path []string) (interface{}, os.Error) {
104
 
        if reflect.TypeOf(v).Kind() == reflect.Bool {
 
110
        if v != nil && reflect.TypeOf(v).Kind() == reflect.Bool {
105
111
                return v, nil
106
112
        }
107
113
        return nil, error{"bool", v, path}
108
114
}
109
115
 
110
116
// Int returns a Checker that accepts any integer value, and returns
111
 
// the same value typed as an int64.
 
117
// the same value consistently typed as an int64.
112
118
func Int() Checker {
113
119
        return intC{}
114
120
}
116
122
type intC struct{}
117
123
 
118
124
func (c intC) Coerce(v interface{}, path []string) (interface{}, os.Error) {
 
125
        if v == nil {
 
126
                return nil, error{"int", v, path}
 
127
        }
119
128
        switch reflect.TypeOf(v).Kind() {
120
129
        case reflect.Int:
121
130
        case reflect.Int8:
129
138
}
130
139
 
131
140
// Int returns a Checker that accepts any float value, and returns
132
 
// the same value typed as a float64.
 
141
// the same value consistently typed as a float64.
133
142
func Float() Checker {
134
143
        return floatC{}
135
144
}
137
146
type floatC struct{}
138
147
 
139
148
func (c floatC) Coerce(v interface{}, path []string) (interface{}, os.Error) {
 
149
        if v == nil {
 
150
                return nil, error{"float", v, path}
 
151
        }
140
152
        switch reflect.TypeOf(v).Kind() {
141
153
        case reflect.Float32:
142
154
        case reflect.Float64:
156
168
type stringC struct{}
157
169
 
158
170
func (c stringC) Coerce(v interface{}, path []string) (interface{}, os.Error) {
159
 
        if reflect.TypeOf(v).Kind() == reflect.String {
 
171
        if v != nil && reflect.TypeOf(v).Kind() == reflect.String {
160
172
                return reflect.ValueOf(v).String(), nil
161
173
        }
162
174
        return nil, error{"string", v, path}
172
184
        // XXX The regexp package happens to be extremely simple right now.
173
185
        //     Once exp/regexp goes mainstream, we'll have to update this
174
186
        //     logic to use a more widely accepted regexp subset.
175
 
        if reflect.TypeOf(v).Kind() == reflect.String {
 
187
        if v != nil && reflect.TypeOf(v).Kind() == reflect.String {
176
188
                s := reflect.ValueOf(v).String()
177
189
                _, err := regexp.Compile(s)
178
190
                if err != nil {
183
195
        return nil, error{"regexp string", v, path}
184
196
}
185
197
 
186
 
// String returns a Checker that accepts a slice value with values
 
198
// List returns a Checker that accepts a slice value with values
187
199
// that are processed with the elem checker.  If any element of the
188
200
// provided slice value fails to be processed, processing will stop
189
201
// and return with the obtained error.
 
202
//
 
203
// The coerced output value has type schema.L.
190
204
func List(elem Checker) Checker {
191
205
        return listC{elem}
192
206
}
204
218
        path = append(path, "[", "?", "]")
205
219
 
206
220
        l := rv.Len()
207
 
        out := make([]interface{}, 0, l)
 
221
        out := make(L, 0, l)
208
222
        for i := 0; i != l; i++ {
209
223
                path[len(path)-2] = strconv.Itoa(i)
210
224
                elem, err := c.elem.Coerce(rv.Index(i).Interface(), path)
220
234
// in the map are processed with the respective checker, and if any
221
235
// value fails to be coerced, processing stops and returns with the
222
236
// underlying error.
 
237
//
 
238
// The coerced output value has type schema.M.
223
239
func Map(key Checker, value Checker) Checker {
224
240
        return mapC{key, value}
225
241
}
238
254
        vpath := append(path, ".", "?")
239
255
 
240
256
        l := rv.Len()
241
 
        out := make(map[interface{}]interface{}, l)
 
257
        out := make(M, l)
242
258
        keys := rv.MapKeys()
243
259
        for i := 0; i != l; i++ {
244
260
                k := keys[i]
264
280
// and processing will only succeed if all the values succeed
265
281
// individually. If a field fails to be processed, processing stops
266
282
// and returns with the underlying error.
 
283
//
 
284
// The coerced output value has type schema.M.
267
285
func FieldMap(fields Fields, optional Optional) Checker {
268
286
        return fieldMapC{fields, optional}
269
287
}
291
309
        vpath := append(path, ".", "?")
292
310
 
293
311
        l := rv.Len()
294
 
        out := make(map[string]interface{}, l)
 
312
        out := make(M, l)
295
313
        for k, checker := range c.fields {
296
314
                vpath[len(vpath)-1] = k
297
315
                var value interface{}
315
333
// used is the first one whose checker associated with the selector
316
334
// field processes the map correctly. If no checker processes
317
335
// the selector value correctly, an error is returned.
 
336
//
 
337
// The coerced output value has type schema.M.
318
338
func FieldMapSet(selector string, maps []Checker) Checker {
319
339
        fmaps := make([]fieldMapC, len(maps))
320
340
        for i, m := range maps {