diff --git a/doc.go b/doc.go index ace8a06..0ad8cce 100644 --- a/doc.go +++ b/doc.go @@ -29,19 +29,19 @@ import ( "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. -type Doc struct { +type Object struct { items map[string]interface{} } -func (d *Doc) MarshalJSON() ([]byte, error) { - return json.Marshal(d.items) +func (o *Object) MarshalJSON() ([]byte, error) { + return json.Marshal(o.items) } -func (d *Doc) MarshalMoon() ([]byte, error) { +func (o *Object) MarshalMoon() ([]byte, error) { var buf bytes.Buffer - for k, v := range d.items { + for k, v := range o.items { buf.WriteString(k) buf.WriteByte(':') buf.WriteByte(' ') @@ -57,20 +57,23 @@ func (d *Doc) MarshalMoon() ([]byte, error) { 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, // otherwise Get will be unable to overwrite the value that it (should) point // 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: +// // name: jordan // city: brooklyn +// // 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. // // Let's take a more complex example: +// // @webserver: { // host: www.example.com // 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 // "host" within that item, assigning the value to the address pointed to by // the *string named host -func (d *Doc) Get(path string, dest interface{}) error { - if d.items == nil { - return fmt.Errorf("no item found at path %s (doc is empty)", path) +func (o *Object) Get(path string, dest interface{}) error { + if o.items == nil { + return fmt.Errorf("no item found at path %s (object is empty)", path) } var v interface{} parts := strings.Split(path, "/") - v, err := seekValue(path, parts, d.items) + v, err := seekValue(path, parts, o.items) if err != nil { return err } @@ -111,11 +114,11 @@ func (d *Doc) Get(path string, dest interface{}) error { 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 // other type for dest will result in an error. Please see the Parse // 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 := reflect.TypeOf(dest) if dt.Kind() != reflect.Ptr { @@ -132,7 +135,7 @@ func (d *Doc) Fill(dest interface{}) error { for fname, req := range reqs { // fv = field value fv := dv.FieldByName(fname) - v, ok := d.items[req.name] + v, ok := o.items[req.name] if ok { 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)) diff --git a/doc_test.go b/doc_test.go index 2c3a71e..9c6d49b 100644 --- a/doc_test.go +++ b/doc_test.go @@ -140,3 +140,24 @@ func ExampleDoc_Get_two() { fmt.Println(name) // 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 +// } +// } diff --git a/parse.go b/parse.go index b4e6420..04bf982 100644 --- a/parse.go +++ b/parse.go @@ -82,45 +82,45 @@ func bail(status int, t string, args ...interface{}) { // // Any value provied as a command-line argument will override the value // supplied by the config file at "./config" -func Parse(dest interface{}) *Doc { +func Parse(dest interface{}) *Object { cliArgs, err := parseArgs(os.Args, dest) if err != nil { bail(1, "unable to parse cli args: %s", err) } - var doc *Doc + var obj *Object if Path != "" { f, err := os.Open(Path) if err == nil { defer f.Close() - d, err := Read(f) + o, err := Read(f) if err != nil { bail(1, "unable to parse moon config file at path %s: %s", Path, err) } - doc = d + obj = o } } - if doc == nil { - doc = &Doc{items: make(map[string]interface{})} + if obj == nil { + obj = &Object{items: make(map[string]interface{})} } 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) } - 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 // an io.ReadCloser. In the event of error, the state that the source reader // will be left in is undefined. -func Read(r io.Reader) (*Doc, error) { +func Read(r io.Reader) (*Object, error) { tree, err := parse(r) if err != nil { return nil, err @@ -129,22 +129,22 @@ func Read(r io.Reader) (*Doc, error) { if _, err := tree.eval(ctx); err != nil { 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. -func ReadString(source string) (*Doc, error) { +func ReadString(source string) (*Object, error) { 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 -func ReadBytes(b []byte) (*Doc, error) { +func ReadBytes(b []byte) (*Object, error) { return Read(bytes.NewBuffer(b)) } -func ReadFile(path string) (*Doc, error) { +func ReadFile(path string) (*Object, error) { f, err := os.Open(path) if err != nil { return nil, err