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}
33 if reflect.DeepEqual(&i, old.List(l.Name)) {
34 fmt.Fprintln(ew, "KeepList", l.Name)
38 fmt.Fprintln(ew, "List", l.Name, len(l.Stacks))
41 fmt.Fprintln(ew, "EndInventory")
46 func (i *Inv) Deserialize(r io.Reader) (err error) {
54 if err := readCmdLn(r, map[string]interface{}{
55 "List": func(name string, size int) {
58 l = &NamedInvList{Name: name}
61 if err := l.Deserialize(r); err != nil {
62 s.ret(fmt.Errorf("List %s %d: %w", name, size, err))
64 if len(l.Stacks) != size {
65 s.ret(fmt.Errorf("List %s %d: contains %d stacks", name, size, len(l.Stacks)))
70 "KeepList": func(name string) {
73 s.ret(fmt.Errorf("KeepList %s: list does not exist", name))
78 "EndInventory": func() {
83 return io.ErrUnexpectedEOF
95 func (l InvList) Serialize(w io.Writer) error {
96 return l.SerializeKeep(w, InvList{})
99 func (l InvList) SerializeKeep(w io.Writer, old InvList) error {
100 ew := &errWriter{w: w}
102 fmt.Fprintln(ew, "Width", l.Width)
103 for i, s := range l.Stacks {
104 if i < len(old.Stacks) && s == old.Stacks[i] {
105 fmt.Fprintln(ew, "Keep")
109 fmt.Fprintln(ew, "Item", s)
111 fmt.Fprintln(ew, "Empty")
114 fmt.Fprintln(ew, "EndInventoryList")
119 func (l *InvList) Deserialize(r io.Reader) (err error) {
121 defer s.recover(&err)
123 if _, err := fmt.Fscanf(r, "Width %d\n", &l.Width); err != nil {
131 if err := readCmdLn(r, map[string]interface{}{
133 l.Stacks = append(l.Stacks, Stack{})
135 "Item": func(stk Stack) {
136 l.Stacks = append(l.Stacks, stk)
139 if i := len(l.Stacks); i < len(old) {
140 l.Stacks = append(l.Stacks, old[i])
142 l.Stacks = append(l.Stacks, Stack{})
145 "EndInventoryList": func() {
150 return io.ErrUnexpectedEOF
157 func readCmdLn(r io.Reader, cmds map[string]interface{}) error {
158 if _, ok := r.(io.RuneScanner); !ok {
159 r = &readRune{Reader: r, peekRune: -1}
163 if _, err := fmt.Fscan(r, &cmd); err != nil {
169 return fmt.Errorf("unsupported line type: %+q", cmd)
172 t := reflect.TypeOf(f)
174 a := make([]interface{}, t.NumIn())
176 a[i] = reflect.New(t.In(i)).Interface()
180 args := make([]reflect.Value, t.NumIn())
181 for i := range args {
182 args[i] = reflect.ValueOf(a[i]).Elem()
184 reflect.ValueOf(f).Call(args)
189 type sentinal struct {
193 func (s *sentinal) ret(err error) {
198 func (s *sentinal) recover(p *error) {
199 if r := recover(); r != nil {
208 type errWriter struct {
213 func (ew *errWriter) Write(p []byte) (int, error) {
218 n, err := ew.w.Write(p)