13 func (s *sentinal) ret(err error) {
18 type Inv []NamedInvList
20 type NamedInvList struct {
25 func (inv Inv) List(name string) *NamedInvList {
26 for i, l := range inv {
34 func (i Inv) Serialize(w io.Writer) error {
36 if _, err := fmt.Fprintln(w, "List", l.Name, len(l.Stacks)); err != nil {
39 if err := l.Serialize(w); err != nil {
43 _, err := fmt.Fprintln(w, "EndInventory")
47 func (i *Inv) Deserialize(r io.Reader) (err error) {
51 if r, ok := r.(sentinal); ok {
60 if err := readCmdLn(r, map[string]interface{}{
61 "List": func(name string, size int) {
64 l = &NamedInvList{Name: name}
67 if err := l.Deserialize(r); err != nil {
68 s.ret(fmt.Errorf("List %s %d: %w", name, size, err))
70 if len(l.Stacks) != size {
71 s.ret(fmt.Errorf("List %s %d: contains %d stacks", name, size, len(l.Stacks)))
76 "KeepList": func(name string) {
79 s.ret(fmt.Errorf("KeepList %s: list does not exist", name))
84 "EndInventory": func() {
89 s.ret(io.ErrUnexpectedEOF)
101 func (l InvList) Serialize(w io.Writer) error {
102 if _, err := fmt.Fprintln(w, "Width", l.Width); err != nil {
105 for _, i := range l.Stacks {
107 if _, err := fmt.Fprintln(w, "Item", i); err != nil {
111 if _, err := fmt.Fprintln(w, "Empty"); err != nil {
116 _, err := fmt.Fprintln(w, "EndInventoryList")
120 func (i *InvList) Deserialize(r io.Reader) (err error) {
124 if r, ok := r.(sentinal); ok {
129 if _, err := fmt.Fscanf(r, "Width %d\n", &i.Width); err != nil {
133 i.Stacks = i.Stacks[:0]
136 if err := readCmdLn(r, map[string]interface{}{
138 i.Stacks = append(i.Stacks, Stack{})
140 "Item": func(stk Stack) {
141 i.Stacks = append(i.Stacks, stk)
144 if len(i.Stacks) < cap(i.Stacks) {
145 i.Stacks = i.Stacks[:len(i.Stacks)+1]
147 i.Stacks = append(i.Stacks, Stack{})
150 "EndInventoryList": func() {
155 s.ret(io.ErrUnexpectedEOF)
162 func readCmdLn(r io.Reader, cmds map[string]interface{}) error {
163 if _, ok := r.(io.RuneScanner); !ok {
164 r = &readRune{Reader: r, peekRune: -1}
168 if _, err := fmt.Fscan(r, &cmd); err != nil {
174 return fmt.Errorf("unsupported line type: %+q", cmd)
177 t := reflect.TypeOf(f)
179 a := make([]interface{}, t.NumIn())
181 a[i] = reflect.New(t.In(i)).Interface()
185 args := make([]reflect.Value, t.NumIn())
186 for i := range args {
187 args[i] = reflect.ValueOf(a[i]).Elem()
189 reflect.ValueOf(f).Call(args)