package main import ( "fmt" "sort" ) const ( collect__child__animals = iota collect__child__chimp collect__child__food collect__child__type__text__text ) type doer interface { do(subdoc []interface{}, doc *docType) []interface{} } type xPath struct { arg1 doer } func (d *xPath) do(doc *docType) []interface{} { return d.arg1.do([]interface{}{}, doc) } type dCollect struct { ARG int arg1 doer } func (d *dCollect) do(subdoc []interface{}, doc *docType) []interface{} { result := []interface{}{} for _, r := range d.arg1.do(subdoc, doc) { switch d.ARG { case collect__child__animals: if rr, ok := r.(*animalsType); ok { result = append(result, rr) } case collect__child__chimp: if rr, ok := r.(*animalsType); ok { if rr.Chimp != nil { for _, ch := range rr.Chimp { result = append(result, ch) } } } case collect__child__food: if rr, ok := r.(*animalType); ok { result = append(result, &rr.Food) } case collect__child__type__text__text: if rr, ok := r.(*foodType); ok { result = append(result, rr.Text) } default: panic("Collect: Missing case") } } return result } type dRoot struct{} func (d *dRoot) do(subdoc []interface{}, doc *docType) []interface{} { return []interface{}{doc.animals} } type dSort struct { arg1 doer } func (d *dSort) do(subdoc []interface{}, doc *docType) []interface{} { result := d.arg1.do(subdoc, doc) if len(result) < 2 { return result } switch result[0].(type) { case string: sort.Slice(result, func(i, j int) bool { return result[i].(string) < result[j].(string) }) for i := 1; i < len(result); i++ { if result[i].(string) == result[i-1].(string) { result = append(result[:i], result[i+1:]...) i-- } } default: panic(fmt.Sprintf("Sort: Missing case for type %T", result[0])) } return result }