renaming doc to object

master
Jordan Orelli 10 years ago
parent c6cbb01fa2
commit c34f8c91d9

@ -29,19 +29,19 @@ import (
"strings" "strings"
) )
// Doc is a representation of a Moon document in its native form. It has no // Object is a representation of a Moon object in its native form. It has no
// configured options and deals only with opaque types. // configured options and deals only with opaque types.
type Doc struct { type Object struct {
items map[string]interface{} items map[string]interface{}
} }
func (d *Doc) MarshalJSON() ([]byte, error) { func (o *Object) MarshalJSON() ([]byte, error) {
return json.Marshal(d.items) return json.Marshal(o.items)
} }
func (d *Doc) MarshalMoon() ([]byte, error) { func (o *Object) MarshalMoon() ([]byte, error) {
var buf bytes.Buffer var buf bytes.Buffer
for k, v := range d.items { for k, v := range o.items {
buf.WriteString(k) buf.WriteString(k)
buf.WriteByte(':') buf.WriteByte(':')
buf.WriteByte(' ') buf.WriteByte(' ')
@ -57,20 +57,23 @@ func (d *Doc) MarshalMoon() ([]byte, error) {
return buf.Bytes(), nil return buf.Bytes(), nil
} }
// Get reads a value from the Moon document at a given path, assigning the // Get reads a value from the Moon object at a given path, assigning the
// value to supplied destination pointer. The argument dest MUST be a pointer, // value to supplied destination pointer. The argument dest MUST be a pointer,
// otherwise Get will be unable to overwrite the value that it (should) point // otherwise Get will be unable to overwrite the value that it (should) point
// to. // to.
// //
// path may represent either a top-level key or a path to a value found within the document. // path may represent either a top-level key or a path to a value found within the object.
// //
// Let's say you have a simple document that contains just a few values: // Let's say you have a simple document that contains just a few values:
//
// name: jordan // name: jordan
// city: brooklyn // city: brooklyn
//
// Calling Get("name", &name) would read the value in the document at the // Calling Get("name", &name) would read the value in the document at the
// "name" key and assign it to the location pointed at by the *string name. // "name" key and assign it to the location pointed at by the *string name.
// //
// Let's take a more complex example: // Let's take a more complex example:
//
// @webserver: { // @webserver: {
// host: www.example.com // host: www.example.com
// port: 80 // port: 80
@ -87,15 +90,15 @@ func (d *Doc) MarshalMoon() ([]byte, error) {
// retrieve the item at index 1 in that list, and then read the field named // retrieve the item at index 1 in that list, and then read the field named
// "host" within that item, assigning the value to the address pointed to by // "host" within that item, assigning the value to the address pointed to by
// the *string named host // the *string named host
func (d *Doc) Get(path string, dest interface{}) error { func (o *Object) Get(path string, dest interface{}) error {
if d.items == nil { if o.items == nil {
return fmt.Errorf("no item found at path %s (doc is empty)", path) return fmt.Errorf("no item found at path %s (object is empty)", path)
} }
var v interface{} var v interface{}
parts := strings.Split(path, "/") parts := strings.Split(path, "/")
v, err := seekValue(path, parts, d.items) v, err := seekValue(path, parts, o.items)
if err != nil { if err != nil {
return err return err
} }
@ -111,11 +114,11 @@ func (d *Doc) Get(path string, dest interface{}) error {
return nil return nil
} }
// Fill takes the raw values from the Moon document and assigns them to the // Fill takes the raw values from the Moon object and assigns them to the
// fields of the struct pointed at by dest. Dest must be a struct pointer; any // fields of the struct pointed at by dest. Dest must be a struct pointer; any
// other type for dest will result in an error. Please see the Parse // other type for dest will result in an error. Please see the Parse
// documentation for a description of how the values will be filled. // documentation for a description of how the values will be filled.
func (d *Doc) Fill(dest interface{}) error { func (o *Object) Fill(dest interface{}) error {
// dt = destination type // dt = destination type
dt := reflect.TypeOf(dest) dt := reflect.TypeOf(dest)
if dt.Kind() != reflect.Ptr { if dt.Kind() != reflect.Ptr {
@ -132,7 +135,7 @@ func (d *Doc) Fill(dest interface{}) error {
for fname, req := range reqs { for fname, req := range reqs {
// fv = field value // fv = field value
fv := dv.FieldByName(fname) fv := dv.FieldByName(fname)
v, ok := d.items[req.name] v, ok := o.items[req.name]
if ok { if ok {
if !fv.Type().AssignableTo(reflect.TypeOf(v)) { if !fv.Type().AssignableTo(reflect.TypeOf(v)) {
return fmt.Errorf("unable to assign field %s: source type %v is not assignable to destination type %v", req.name, fv.Type(), reflect.TypeOf(v)) return fmt.Errorf("unable to assign field %s: source type %v is not assignable to destination type %v", req.name, fv.Type(), reflect.TypeOf(v))

@ -140,3 +140,24 @@ func ExampleDoc_Get_two() {
fmt.Println(name) fmt.Println(name)
// Output: sean // Output: sean
} }
// func TestFillEmbeds(t *testing.T) {
// in := `top: {val: some_data}`
//
// var dest struct {
// Top *struct {
// Val string `name: val`
// } `name: top`
// }
//
// doc, err := ReadString(in)
// if err != nil {
// t.Error(err)
// return
// }
//
// if err := doc.Fill(&dest); err != nil {
// t.Error(err)
// return
// }
// }

@ -82,45 +82,45 @@ func bail(status int, t string, args ...interface{}) {
// //
// Any value provied as a command-line argument will override the value // Any value provied as a command-line argument will override the value
// supplied by the config file at "./config" // supplied by the config file at "./config"
func Parse(dest interface{}) *Doc { func Parse(dest interface{}) *Object {
cliArgs, err := parseArgs(os.Args, dest) cliArgs, err := parseArgs(os.Args, dest)
if err != nil { if err != nil {
bail(1, "unable to parse cli args: %s", err) bail(1, "unable to parse cli args: %s", err)
} }
var doc *Doc var obj *Object
if Path != "" { if Path != "" {
f, err := os.Open(Path) f, err := os.Open(Path)
if err == nil { if err == nil {
defer f.Close() defer f.Close()
d, err := Read(f) o, err := Read(f)
if err != nil { if err != nil {
bail(1, "unable to parse moon config file at path %s: %s", Path, err) bail(1, "unable to parse moon config file at path %s: %s", Path, err)
} }
doc = d obj = o
} }
} }
if doc == nil { if obj == nil {
doc = &Doc{items: make(map[string]interface{})} obj = &Object{items: make(map[string]interface{})}
} }
for k, v := range cliArgs { for k, v := range cliArgs {
doc.items[k] = v obj.items[k] = v
} }
if err := doc.Fill(dest); err != nil { if err := obj.Fill(dest); err != nil {
bail(1, "unable to fill moon config values: %s", err) bail(1, "unable to fill moon config values: %s", err)
} }
return doc return obj
} }
// Reads a moon document from a given io.Reader. The io.Reader is advanced to // Reads a moon object from a given io.Reader. The io.Reader is advanced to
// EOF. The reader is not closed after reading, since it's an io.Reader and not // EOF. The reader is not closed after reading, since it's an io.Reader and not
// an io.ReadCloser. In the event of error, the state that the source reader // an io.ReadCloser. In the event of error, the state that the source reader
// will be left in is undefined. // will be left in is undefined.
func Read(r io.Reader) (*Doc, error) { func Read(r io.Reader) (*Object, error) {
tree, err := parse(r) tree, err := parse(r)
if err != nil { if err != nil {
return nil, err return nil, err
@ -129,22 +129,22 @@ func Read(r io.Reader) (*Doc, error) {
if _, err := tree.eval(ctx); err != nil { if _, err := tree.eval(ctx); err != nil {
return nil, fmt.Errorf("eval error: %s\n", err) return nil, fmt.Errorf("eval error: %s\n", err)
} }
return &Doc{items: ctx.public}, nil return &Object{items: ctx.public}, nil
} }
// Reads a moon document from a string. This is purely a convenience method; // Reads a moon object from a string. This is purely a convenience method;
// all it does is create a buffer and call the moon.Read function. // all it does is create a buffer and call the moon.Read function.
func ReadString(source string) (*Doc, error) { func ReadString(source string) (*Object, error) {
return Read(strings.NewReader(source)) return Read(strings.NewReader(source))
} }
// Reads a moon document from a slice of bytes. This is purely a concenience // Reads a moon object from a slice of bytes. This is purely a concenience
// method; like ReadString, it simply creates a buffer and calls moon.Read // method; like ReadString, it simply creates a buffer and calls moon.Read
func ReadBytes(b []byte) (*Doc, error) { func ReadBytes(b []byte) (*Object, error) {
return Read(bytes.NewBuffer(b)) return Read(bytes.NewBuffer(b))
} }
func ReadFile(path string) (*Doc, error) { func ReadFile(path string) (*Object, error) {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {
return nil, err return nil, err

Loading…
Cancel
Save