Skip to content

Commit

Permalink
Merge pull request #3 from koron/proxy-set
Browse files Browse the repository at this point in the history
Proxy set
  • Loading branch information
koron committed Dec 16, 2015
2 parents f71408f + 7ac20cd commit 009e119
Show file tree
Hide file tree
Showing 8 changed files with 481 additions and 55 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# dProxy - document proxy

dProxy is a proxy to access `interface{}` (document) by simple query.
It is intetedd to be used with `json.Unmarshal()` or `json.NewDecorder()`.
It is intented to be used with `json.Unmarshal()` or `json.NewDecorder()`.

See codes for overview.

Expand Down Expand Up @@ -79,7 +79,17 @@ _, err = dproxy.New(v).M("data").M("kustom").String()
fmt.Println(err)
```
You can verify queries easily.
7. If you tried to get a value as different type, get an error.
```go
// OOPS! "cities[3]" (=200) should be float64 or int64.
_, err := p.M("cities").A(3).String()
// "not matched types: expected=string actual=float64: cities[3]"
fmt.Println(err)
```
8. You can verify queries easily.
## LICENSE
Expand Down
94 changes: 72 additions & 22 deletions error.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package dproxy

import "fmt"
import (
"fmt"
"strconv"
)

// ErrorType is type of errors
type ErrorType int
Expand All @@ -24,12 +27,19 @@ type Error interface {

type errorProxy struct {
errorType ErrorType
parent Proxy
address string
parent frame
label string
expected Type
actual Type
}

// errorProxy implements error, Proxy and ProxySet.
var (
_ error = (*errorProxy)(nil)
_ Proxy = (*errorProxy)(nil)
_ ProxySet = (*errorProxy)(nil)
)

func (p *errorProxy) Nil() bool {
return false
}
Expand Down Expand Up @@ -66,12 +76,56 @@ func (p *errorProxy) M(k string) Proxy {
return p
}

func (p *errorProxy) getParent() Proxy {
func (p *errorProxy) Empty() bool {
return true
}

func (p *errorProxy) Len() int {
return 0
}

func (p *errorProxy) BoolArray() ([]bool, error) {
return nil, p
}

func (p *errorProxy) Int64Array() ([]int64, error) {
return nil, p
}

func (p *errorProxy) Float64Array() ([]float64, error) {
return nil, p
}

func (p *errorProxy) StringArray() ([]string, error) {
return nil, p
}

func (p *errorProxy) ArrayArray() ([][]interface{}, error) {
return nil, p
}

func (p *errorProxy) MapArray() ([]map[string]interface{}, error) {
return nil, p
}

func (p *errorProxy) ProxySet() ProxySet {
return p
}

func (p *errorProxy) Q(k string) ProxySet {
return p
}

func (p *errorProxy) Qc(k string) ProxySet {
return p
}

func (p *errorProxy) parentFrame() frame {
return p.parent
}

func (p *errorProxy) getAddress() string {
return p.address
func (p *errorProxy) frameLabel() string {
return p.label
}

func (p *errorProxy) Error() string {
Expand All @@ -91,22 +145,10 @@ func (p *errorProxy) ErrorType() ErrorType {
}

func (p *errorProxy) FullAddress() string {
x := 0
for q := Proxy(p); q != nil; q = q.getParent() {
x += len(q.getAddress())
}
b := make([]byte, x)
for q := Proxy(p); q != nil; q = q.getParent() {
x -= len(q.getAddress())
copy(b[x:], q.getAddress())
}
if b[0] == '.' {
return string(b[1:])
}
return string(b)
return fullAddress(p)
}

func mismatchError(p Proxy, expected Type, actual interface{}) *errorProxy {
func typeError(p frame, expected Type, actual interface{}) *errorProxy {
return &errorProxy{
errorType: Etype,
parent: p,
Expand All @@ -115,10 +157,18 @@ func mismatchError(p Proxy, expected Type, actual interface{}) *errorProxy {
}
}

func addressError(p Proxy, address string) *errorProxy {
func elementTypeError(p frame, index int, expected Type, actual interface{}) *errorProxy {
q := &simpleFrame{
parent: p,
label: "[" + strconv.Itoa(index) + "]",
}
return typeError(q, expected, actual)
}

func notfoundError(p frame, address string) *errorProxy {
return &errorProxy{
errorType: Enotfound,
parent: p,
address: address,
label: address,
}
}
39 changes: 39 additions & 0 deletions frame.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dproxy

type frame interface {
// parentFrame returns parent frame.
parentFrame() frame
// frameLabel return label of frame.
frameLabel() string
}

func fullAddress(f frame) string {
x := 0
for g := f; g != nil; g = g.parentFrame() {
x += len(g.frameLabel())
}
b := make([]byte, x)
for g := f; g != nil; g = g.parentFrame() {
x -= len(g.frameLabel())
copy(b[x:], g.frameLabel())
}
if b[0] == '.' {
return string(b[1:])
}
return string(b)
}

type simpleFrame struct {
parent frame
label string
}

var _ frame = (*simpleFrame)(nil)

func (f *simpleFrame) parentFrame() frame {
return f.parent
}

func (f *simpleFrame) frameLabel() string {
return f.label
}
56 changes: 53 additions & 3 deletions proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,61 @@ type Proxy interface {
// M returns an item from value treated as the map.
M(k string) Proxy

getParent() Proxy
getAddress() string
// ProxySet returns a set which converted from its array value.
ProxySet() ProxySet

// Q returns set of all items which property matchs with k.
Q(k string) ProxySet

// Proxy implements frame.
frame
}

// ProxySet proxies to access to set.
type ProxySet interface {
// Empty returns true when the set is empty.
Empty() bool

// Len returns count of items in the set.
Len() int

// BoolArray returns []bool which converterd from the set.
BoolArray() ([]bool, error)

// Int64Array returns []int64 which converterd from the set.
Int64Array() ([]int64, error)

// Float64Array returns []float64 which converterd from the set.
Float64Array() ([]float64, error)

// StringArray returns []string which converterd from the set.
StringArray() ([]string, error)

// ArrayArray returns [][]interface{} which converterd from the set.
ArrayArray() ([][]interface{}, error)

// MapArray returns []map[string]interface{} which converterd from the set.
MapArray() ([]map[string]interface{}, error)

// A returns an proxy for index in the set.
A(n int) Proxy

// Q returns set of all items which property matchs with k.
Q(k string) ProxySet

// Qc returns set of property of all items.
Qc(k string) ProxySet

// Proxy implements frame.
frame
}

// New creates a new proxy object.
// New creates a new Proxy instance for v.
func New(v interface{}) Proxy {
return &valueProxy{value: v}
}

// NewSet create a new ProxySet instance for v.
func NewSet(v []interface{}) ProxySet {
return &setProxy{values: v}
}
24 changes: 24 additions & 0 deletions proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,30 @@ func parseJSON(s string) interface{} {
return v
}

func equalStrings(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i, s := range a {
if s != b[i] {
return false
}
}
return true
}

func equalInts(a, b []int64) bool {
if len(a) != len(b) {
return false
}
for i, s := range a {
if s != b[i] {
return false
}
}
return true
}

func TestReadme(t *testing.T) {
v := parseJSON(`{
"cities": [ "tokyo", 100, "osaka", 200, "hakata", 300 ],
Expand Down
Loading

0 comments on commit 009e119

Please sign in to comment.