stred-go

Stred: Streaming Tree Editor. Like sed but for JSON. This is the go implementation
git clone https://shtanton.xyz/git/stred-go.git
Log | Files | Refs | README

walk.go (4969B)


      1 package walk
      2 
      3 import (
      4 	"fmt"
      5 	"strings"
      6 	"unicode/utf8"
      7 )
      8 
      9 type valueIter struct {
     10 	values []Value
     11 	index int
     12 }
     13 func (iter *valueIter) Next() Edible {
     14 	if iter.index >= len(iter.values) {
     15 		return nil
     16 	}
     17 	iter.index += 1
     18 	return iter.values[iter.index - 1]
     19 }
     20 
     21 func NewValueIter(values []Value) StructureIter {
     22 	return &valueIter {
     23 		values: values,
     24 		index: 0,
     25 	}
     26 }
     27 
     28 type OutputList interface {
     29 	outputList()
     30 }
     31 
     32 type StructureIter interface {
     33 	Next() Edible
     34 }
     35 
     36 type Edible interface {
     37 	edible()
     38 }
     39 
     40 type Atom interface {
     41 	Edible
     42 	atom()
     43 }
     44 
     45 type Scalar interface {
     46 	Atom
     47 	Value
     48 }
     49 
     50 type Structure interface {
     51 	Value
     52 	structure()
     53 	Iter() StructureIter
     54 }
     55 
     56 type Value interface {
     57 	Edible
     58 	value()
     59 	Debug() string
     60 }
     61 
     62 type Terminal interface {
     63 	Atom
     64 	terminal()
     65 }
     66 
     67 type ValueList []Value
     68 func (_ ValueList) outputList() {}
     69 
     70 type RuneList []StringRuneAtom
     71 func (_ RuneList) outputList() {}
     72 
     73 type NullScalar struct{}
     74 func (_ NullScalar) edible() {}
     75 func (_ NullScalar) atom() {}
     76 func (_ NullScalar) value() {}
     77 func (_ NullScalar) Debug() string {
     78 	return "null"
     79 }
     80 
     81 type BoolScalar bool
     82 func (_ BoolScalar) edible() {}
     83 func (_ BoolScalar) atom() {}
     84 func (_ BoolScalar) value() {}
     85 func (b BoolScalar) Debug() string {
     86 	if b {
     87 		return "true"
     88 	}
     89 	return "false"
     90 }
     91 
     92 type NumberScalar float64
     93 func (_ NumberScalar) edible() {}
     94 func (_ NumberScalar) atom() {}
     95 func (_ NumberScalar) value() {}
     96 func (n NumberScalar) Debug() string {
     97 	return fmt.Sprintf("%v", float64(n))
     98 }
     99 
    100 type StringStructure string
    101 func (_ StringStructure) edible() {}
    102 func (_ StringStructure) value() {}
    103 func (_ StringStructure) structure() {}
    104 func (s StringStructure) Iter() StructureIter {
    105 	return &stringStructureIter {
    106 		string: string(s),
    107 		position: 0,
    108 	}
    109 }
    110 func (s StringStructure) Debug() string {
    111 	return fmt.Sprintf("%q", string(s))
    112 }
    113 
    114 type stringStructureIter struct {
    115 	string string
    116 	position int
    117 }
    118 func (iter *stringStructureIter) Next() Edible {
    119 	if iter.position == -1 {
    120 		return nil
    121 	}
    122 	r, width := utf8.DecodeRuneInString(iter.string[iter.position:])
    123 	if width == 0 {
    124 		iter.position = -1
    125 		return StringEndTerminal{}
    126 	}
    127 	iter.position += width
    128 	return StringRuneAtom(r)
    129 }
    130 
    131 type StringBeginTerminal struct{}
    132 func (_ StringBeginTerminal) edible() {}
    133 func (_ StringBeginTerminal) atom() {}
    134 func (_ StringBeginTerminal) terminal() {}
    135 
    136 type StringEndTerminal struct{}
    137 func (_ StringEndTerminal) edible() {}
    138 func (_ StringEndTerminal) atom() {}
    139 func (_ StringEndTerminal) terminal() {}
    140 
    141 type StringRuneAtom rune
    142 func (_ StringRuneAtom) edible() {}
    143 func (_ StringRuneAtom) atom() {}
    144 
    145 type ArrayStructure []Value
    146 func (_ ArrayStructure) edible() {}
    147 func (_ ArrayStructure) value() {}
    148 func (_ ArrayStructure) structure() {}
    149 func (array ArrayStructure) Iter() StructureIter {
    150 	return &arrayStructureIter {
    151 		array: []Value(array),
    152 		index: 0,
    153 	}
    154 }
    155 func (array ArrayStructure) Debug() string {
    156 	builder := strings.Builder{}
    157 	builder.WriteRune('[')
    158 	var sep string
    159 	for _, element := range array {
    160 		builder.WriteString(sep)
    161 		builder.WriteString(fmt.Sprintf("%v", element))
    162 		sep = ", "
    163 	}
    164 	builder.WriteRune(']')
    165 	return builder.String()
    166 }
    167 
    168 type arrayStructureIter struct {
    169 	array []Value
    170 	index int
    171 }
    172 func (iter *arrayStructureIter) Next() Edible {
    173 	if iter.index > len(iter.array) {
    174 		return nil
    175 	}
    176 	if iter.index == len(iter.array) {
    177 		iter.index += 1
    178 		return ArrayEndTerminal{}
    179 	}
    180 	iter.index += 1
    181 	return iter.array[iter.index - 1]
    182 }
    183 
    184 type ArrayBeginTerminal struct{}
    185 func (_ ArrayBeginTerminal) edible() {}
    186 func (_ ArrayBeginTerminal) atom() {}
    187 func (_ ArrayBeginTerminal) terminal() {}
    188 
    189 type ArrayEndTerminal struct{}
    190 func (_ ArrayEndTerminal) edible() {}
    191 func (_ ArrayEndTerminal) atom() {}
    192 func (_ ArrayEndTerminal) terminal() {}
    193 
    194 type MapStructure map[string]Value
    195 func (_ MapStructure) edible() {}
    196 func (_ MapStructure) value() {}
    197 func (_ MapStructure) structure() {}
    198 func (m MapStructure) Debug() string {
    199 	builder := strings.Builder{}
    200 	builder.WriteRune('{')
    201 	var sep string
    202 	for key, value := range m {
    203 		builder.WriteString(sep)
    204 		builder.WriteString(fmt.Sprintf("%q", key))
    205 		builder.WriteString(": ")
    206 		builder.WriteString(fmt.Sprintf("%q", value))
    207 		sep = ", "
    208 	}
    209 	builder.WriteRune('}')
    210 	return builder.String()
    211 }
    212 
    213 type MapBeginTerminal struct{}
    214 func (_ MapBeginTerminal) edible() {}
    215 func (_ MapBeginTerminal) atom() {}
    216 func (_ MapBeginTerminal) terminal() {}
    217 
    218 type MapEndTerminal struct{}
    219 func (_ MapEndTerminal) edible() {}
    220 func (_ MapEndTerminal) atom() {}
    221 func (_ MapEndTerminal) terminal() {}
    222 
    223 type WalkItem struct {
    224 	Value ValueList
    225 	Path ValueList
    226 }
    227 
    228 func (item WalkItem) Debug() string {
    229 	builder := strings.Builder{}
    230 	var sep string
    231 	for _, pathSegment := range item.Path {
    232 		builder.WriteString(sep)
    233 		builder.WriteString(fmt.Sprintf("%s", pathSegment.Debug()))
    234 		sep = "."
    235 	}
    236 	builder.WriteString(": ")
    237 	sep = ""
    238 	for _, value := range item.Value {
    239 		builder.WriteString(sep)
    240 		builder.WriteString(fmt.Sprintf("%s", value.Debug()))
    241 		sep = ", "
    242 	}
    243 	return builder.String()
    244 }