9 type Inv []NamedInvList
11 type NamedInvList struct {
16 func (inv Inv) List(name string) *NamedInvList {
17 for i, l := range inv {
25 func (i Inv) Serialize(w io.Writer) error {
26 return i.SerializeKeep(w, nil)
29 func (i Inv) SerializeKeep(w io.Writer, old Inv) error {
30 ew := &errWriter{w: w}
34 if l := old.List(l.Name); l != nil {
38 if reflect.DeepEqual(&i, oldList) {
39 fmt.Fprintln(ew, "KeepList", l.Name)
43 fmt.Fprintln(ew, "List", l.Name, len(l.Stacks))
44 l.SerializeKeep(ew, oldList)
46 fmt.Fprintln(ew, "EndInventory")
51 func (i *Inv) Deserialize(r io.Reader) (err error) {
59 if err := readCmdLn(r, map[string]interface{}{
60 "List": func(name string, size int) {
63 l = &NamedInvList{Name: name}
66 if err := l.Deserialize(r); err != nil {
67 s.ret(fmt.Errorf("List %s %d: %w", name, size, err))
69 if len(l.Stacks) != size {
70 s.ret(fmt.Errorf("List %s %d: contains %d stacks", name, size, len(l.Stacks)))
75 "KeepList": func(name string) {
78 s.ret(fmt.Errorf("KeepList %s: list does not exist", name))
83 "EndInventory": func() {
88 return io.ErrUnexpectedEOF
100 func (l InvList) Serialize(w io.Writer) error {
101 return l.SerializeKeep(w, InvList{})
104 func (l InvList) SerializeKeep(w io.Writer, old InvList) error {
105 ew := &errWriter{w: w}
107 fmt.Fprintln(ew, "Width", l.Width)
108 for i, s := range l.Stacks {
109 if i < len(old.Stacks) && s == old.Stacks[i] {
110 fmt.Fprintln(ew, "Keep")
115 fmt.Fprintln(ew, "Item", s)
117 fmt.Fprintln(ew, "Empty")
120 fmt.Fprintln(ew, "EndInventoryList")
125 func (l *InvList) Deserialize(r io.Reader) (err error) {
127 defer s.recover(&err)
129 if _, err := fmt.Fscanf(r, "Width %d\n", &l.Width); err != nil {
137 if err := readCmdLn(r, map[string]interface{}{
139 l.Stacks = append(l.Stacks, Stack{})
141 "Item": func(stk Stack) {
142 l.Stacks = append(l.Stacks, stk)
145 if i := len(l.Stacks); i < len(old) {
146 l.Stacks = append(l.Stacks, old[i])
148 l.Stacks = append(l.Stacks, Stack{})
151 "EndInventoryList": func() {
156 return io.ErrUnexpectedEOF
163 func readCmdLn(r io.Reader, cmds map[string]interface{}) error {
164 if _, ok := r.(io.RuneScanner); !ok {
165 r = &readRune{Reader: r, peekRune: -1}
169 if _, err := fmt.Fscan(r, &cmd); err != nil {
175 return fmt.Errorf("unsupported line type: %+q", cmd)
178 t := reflect.TypeOf(f)
180 a := make([]interface{}, t.NumIn())
182 a[i] = reflect.New(t.In(i)).Interface()
186 args := make([]reflect.Value, t.NumIn())
187 for i := range args {
188 args[i] = reflect.ValueOf(a[i]).Elem()
190 reflect.ValueOf(f).Call(args)
195 type sentinel struct {
199 func (s *sentinel) ret(err error) {
204 func (s *sentinel) recover(p *error) {
205 if r := recover(); r != nil {
214 type errWriter struct {
219 func (ew *errWriter) Write(p []byte) (int, error) {
224 n, err := ew.w.Write(p)