64 lines
1.5 KiB
Go
64 lines
1.5 KiB
Go
|
package schema
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
)
|
||
|
|
||
|
// MultiLevelFieldReader reads from other field readers,
|
||
|
// merging their results along the way in a specific order. You can specify
|
||
|
// "levels" and name them in order to read only an exact level or up to
|
||
|
// a specific level.
|
||
|
//
|
||
|
// This is useful for saying things such as "read the field from the state
|
||
|
// and config and merge them" or "read the latest value of the field".
|
||
|
type MultiLevelFieldReader struct {
|
||
|
Readers map[string]FieldReader
|
||
|
Levels []string
|
||
|
}
|
||
|
|
||
|
func (r *MultiLevelFieldReader) ReadField(address []string) (FieldReadResult, error) {
|
||
|
return r.ReadFieldMerge(address, r.Levels[len(r.Levels)-1])
|
||
|
}
|
||
|
|
||
|
func (r *MultiLevelFieldReader) ReadFieldExact(
|
||
|
address []string, level string) (FieldReadResult, error) {
|
||
|
reader, ok := r.Readers[level]
|
||
|
if !ok {
|
||
|
return FieldReadResult{}, fmt.Errorf(
|
||
|
"Unknown reader level: %s", level)
|
||
|
}
|
||
|
|
||
|
result, err := reader.ReadField(address)
|
||
|
if err != nil {
|
||
|
return FieldReadResult{}, fmt.Errorf(
|
||
|
"Error reading level %s: %s", level, err)
|
||
|
}
|
||
|
|
||
|
return result, nil
|
||
|
}
|
||
|
|
||
|
func (r *MultiLevelFieldReader) ReadFieldMerge(
|
||
|
address []string, level string) (FieldReadResult, error) {
|
||
|
var result FieldReadResult
|
||
|
for _, l := range r.Levels {
|
||
|
if r, ok := r.Readers[l]; ok {
|
||
|
out, err := r.ReadField(address)
|
||
|
if err != nil {
|
||
|
return FieldReadResult{}, fmt.Errorf(
|
||
|
"Error reading level %s: %s", l, err)
|
||
|
}
|
||
|
|
||
|
// TODO: computed
|
||
|
if out.Exists {
|
||
|
result = out
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if l == level {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result, nil
|
||
|
}
|