Blame


1 499f8c59 2015-10-27 stephen.d package p9pnew
2 499f8c59 2015-10-27 stephen.d
3 499f8c59 2015-10-27 stephen.d import (
4 fb37ce2a 2015-10-30 stephen.d "bytes"
5 499f8c59 2015-10-27 stephen.d "encoding/binary"
6 499f8c59 2015-10-27 stephen.d "fmt"
7 499f8c59 2015-10-27 stephen.d "io"
8 96ad2b22 2015-10-28 stephen.d "log"
9 499f8c59 2015-10-27 stephen.d "reflect"
10 97423e8b 2015-10-29 stephen.d "strings"
11 d6198009 2015-10-28 stephen.d "time"
12 499f8c59 2015-10-27 stephen.d )
13 96ad2b22 2015-10-28 stephen.d
14 96ad2b22 2015-10-28 stephen.d // EncodeDir is just a helper for encoding directories until we export the
15 96ad2b22 2015-10-28 stephen.d // encoder and decoder.
16 96ad2b22 2015-10-28 stephen.d func EncodeDir(wr io.Writer, d *Dir) error {
17 96ad2b22 2015-10-28 stephen.d enc := &encoder{wr}
18 96ad2b22 2015-10-28 stephen.d
19 96ad2b22 2015-10-28 stephen.d return enc.encode(d)
20 96ad2b22 2015-10-28 stephen.d }
21 96ad2b22 2015-10-28 stephen.d
22 96ad2b22 2015-10-28 stephen.d // DecodeDir is just a helper for decoding directories until we export the
23 96ad2b22 2015-10-28 stephen.d // encoder and decoder.
24 96ad2b22 2015-10-28 stephen.d func DecodeDir(rd io.Reader, d *Dir) error {
25 96ad2b22 2015-10-28 stephen.d dec := &decoder{rd}
26 96ad2b22 2015-10-28 stephen.d return dec.decode(d)
27 fb37ce2a 2015-10-30 stephen.d }
28 fb37ce2a 2015-10-30 stephen.d
29 fb37ce2a 2015-10-30 stephen.d type Codec interface {
30 fb37ce2a 2015-10-30 stephen.d Unmarshal(data []byte, v interface{}) error
31 fb37ce2a 2015-10-30 stephen.d Marshal(data []byte, v interface{}) (n int, err error)
32 fb37ce2a 2015-10-30 stephen.d }
33 fb37ce2a 2015-10-30 stephen.d
34 fb37ce2a 2015-10-30 stephen.d type codec9p struct{}
35 fb37ce2a 2015-10-30 stephen.d
36 fb37ce2a 2015-10-30 stephen.d func (c codec9p) Unmarshal(data []byte, v interface{}) error {
37 fb37ce2a 2015-10-30 stephen.d dec := &decoder{bytes.NewReader(data)}
38 fb37ce2a 2015-10-30 stephen.d return dec.decode(v)
39 fb37ce2a 2015-10-30 stephen.d }
40 fb37ce2a 2015-10-30 stephen.d
41 fb37ce2a 2015-10-30 stephen.d func (c codec9p) Marshal(data []byte, v interface{}) (n int, err error) {
42 fb37ce2a 2015-10-30 stephen.d n = int(size9p(v))
43 fb37ce2a 2015-10-30 stephen.d
44 fb37ce2a 2015-10-30 stephen.d buf := bytes.NewBuffer(data[:0])
45 fb37ce2a 2015-10-30 stephen.d enc := &encoder{buf}
46 fb37ce2a 2015-10-30 stephen.d
47 fb37ce2a 2015-10-30 stephen.d if err := enc.encode(v); err != nil {
48 fb37ce2a 2015-10-30 stephen.d return buf.Len(), nil
49 fb37ce2a 2015-10-30 stephen.d }
50 fb37ce2a 2015-10-30 stephen.d
51 fb37ce2a 2015-10-30 stephen.d if len(data) < buf.Len() {
52 fb37ce2a 2015-10-30 stephen.d return len(data), io.ErrShortBuffer
53 fb37ce2a 2015-10-30 stephen.d }
54 fb37ce2a 2015-10-30 stephen.d
55 fb37ce2a 2015-10-30 stephen.d return buf.Len(), nil
56 96ad2b22 2015-10-28 stephen.d }
57 499f8c59 2015-10-27 stephen.d
58 499f8c59 2015-10-27 stephen.d // NOTE(stevvooe): This file covers 9p encoding and decoding (despite just
59 499f8c59 2015-10-27 stephen.d // being called encoding).
60 499f8c59 2015-10-27 stephen.d
61 499f8c59 2015-10-27 stephen.d type encoder struct {
62 499f8c59 2015-10-27 stephen.d wr io.Writer
63 499f8c59 2015-10-27 stephen.d }
64 499f8c59 2015-10-27 stephen.d
65 499f8c59 2015-10-27 stephen.d func (e *encoder) encode(vs ...interface{}) error {
66 499f8c59 2015-10-27 stephen.d for _, v := range vs {
67 499f8c59 2015-10-27 stephen.d switch v := v.(type) {
68 e9f5e414 2015-10-27 stephen.d case *[]string:
69 e9f5e414 2015-10-27 stephen.d if err := e.encode(*v); err != nil {
70 e9f5e414 2015-10-27 stephen.d return err
71 e9f5e414 2015-10-27 stephen.d }
72 e9f5e414 2015-10-27 stephen.d case []string:
73 e9f5e414 2015-10-27 stephen.d if err := e.encode(uint16(len(v))); err != nil {
74 e9f5e414 2015-10-27 stephen.d return err
75 e9f5e414 2015-10-27 stephen.d }
76 e9f5e414 2015-10-27 stephen.d
77 e9f5e414 2015-10-27 stephen.d var elements []interface{}
78 e9f5e414 2015-10-27 stephen.d for _, e := range v {
79 e9f5e414 2015-10-27 stephen.d elements = append(elements, e)
80 e9f5e414 2015-10-27 stephen.d }
81 e9f5e414 2015-10-27 stephen.d
82 e9f5e414 2015-10-27 stephen.d if err := e.encode(elements...); err != nil {
83 e9f5e414 2015-10-27 stephen.d return err
84 e9f5e414 2015-10-27 stephen.d }
85 d6198009 2015-10-28 stephen.d case *[]byte:
86 a8abc687 2015-10-30 stephen.d if err := e.encode(uint32(len(*v))); err != nil {
87 d6198009 2015-10-28 stephen.d return err
88 d6198009 2015-10-28 stephen.d }
89 d6198009 2015-10-28 stephen.d
90 d6198009 2015-10-28 stephen.d if err := e.encode(*v); err != nil {
91 d6198009 2015-10-28 stephen.d return err
92 d6198009 2015-10-28 stephen.d }
93 499f8c59 2015-10-27 stephen.d case *string:
94 499f8c59 2015-10-27 stephen.d if err := e.encode(*v); err != nil {
95 499f8c59 2015-10-27 stephen.d return err
96 499f8c59 2015-10-27 stephen.d }
97 499f8c59 2015-10-27 stephen.d case string:
98 499f8c59 2015-10-27 stephen.d // implement string[s] encoding
99 499f8c59 2015-10-27 stephen.d if err := binary.Write(e.wr, binary.LittleEndian, uint16(len(v))); err != nil {
100 499f8c59 2015-10-27 stephen.d return err
101 499f8c59 2015-10-27 stephen.d }
102 499f8c59 2015-10-27 stephen.d
103 499f8c59 2015-10-27 stephen.d _, err := io.WriteString(e.wr, v)
104 499f8c59 2015-10-27 stephen.d if err != nil {
105 499f8c59 2015-10-27 stephen.d return err
106 499f8c59 2015-10-27 stephen.d }
107 74ec7ac9 2015-10-30 stephen.d case *Dir:
108 74ec7ac9 2015-10-30 stephen.d // NOTE(stevvooe): See bugs in http://man.cat-v.org/plan_9/5/stat
109 74ec7ac9 2015-10-30 stephen.d // to make sense of this. The field has been included here but we
110 74ec7ac9 2015-10-30 stephen.d // need to make sure to double emit it for Rstat.
111 96ad2b22 2015-10-28 stephen.d
112 499f8c59 2015-10-27 stephen.d elements, err := fields9p(v)
113 499f8c59 2015-10-27 stephen.d if err != nil {
114 499f8c59 2015-10-27 stephen.d return err
115 499f8c59 2015-10-27 stephen.d }
116 499f8c59 2015-10-27 stephen.d
117 74ec7ac9 2015-10-30 stephen.d elements = append([]interface{}{uint16(size9p(elements...))}, elements...)
118 74ec7ac9 2015-10-30 stephen.d
119 499f8c59 2015-10-27 stephen.d if err := e.encode(elements...); err != nil {
120 499f8c59 2015-10-27 stephen.d return err
121 499f8c59 2015-10-27 stephen.d }
122 74ec7ac9 2015-10-30 stephen.d case Message:
123 74ec7ac9 2015-10-30 stephen.d elements, err := fields9p(v)
124 74ec7ac9 2015-10-30 stephen.d if err != nil {
125 74ec7ac9 2015-10-30 stephen.d return err
126 74ec7ac9 2015-10-30 stephen.d }
127 74ec7ac9 2015-10-30 stephen.d
128 74ec7ac9 2015-10-30 stephen.d switch v.(type) {
129 74ec7ac9 2015-10-30 stephen.d case MessageRstat, *MessageRstat:
130 74ec7ac9 2015-10-30 stephen.d // encode an size header in front of the dir field
131 74ec7ac9 2015-10-30 stephen.d elements = append([]interface{}{uint16(size9p(elements...))}, elements...)
132 74ec7ac9 2015-10-30 stephen.d }
133 74ec7ac9 2015-10-30 stephen.d
134 74ec7ac9 2015-10-30 stephen.d if err := e.encode(elements...); err != nil {
135 74ec7ac9 2015-10-30 stephen.d return err
136 74ec7ac9 2015-10-30 stephen.d }
137 74ec7ac9 2015-10-30 stephen.d case *Qid:
138 74ec7ac9 2015-10-30 stephen.d if err := e.encode(*v); err != nil {
139 74ec7ac9 2015-10-30 stephen.d return err
140 74ec7ac9 2015-10-30 stephen.d }
141 74ec7ac9 2015-10-30 stephen.d case Qid:
142 74ec7ac9 2015-10-30 stephen.d if err := e.encode(v.Type, v.Version, v.Path); err != nil {
143 74ec7ac9 2015-10-30 stephen.d return err
144 74ec7ac9 2015-10-30 stephen.d }
145 d6198009 2015-10-28 stephen.d case *[]Qid:
146 d6198009 2015-10-28 stephen.d if err := e.encode(*v); err != nil {
147 d6198009 2015-10-28 stephen.d return err
148 d6198009 2015-10-28 stephen.d }
149 d6198009 2015-10-28 stephen.d case []Qid:
150 d6198009 2015-10-28 stephen.d if err := e.encode(uint16(len(v))); err != nil {
151 d6198009 2015-10-28 stephen.d return err
152 d6198009 2015-10-28 stephen.d }
153 d6198009 2015-10-28 stephen.d
154 d6198009 2015-10-28 stephen.d elements := make([]interface{}, len(v))
155 d6198009 2015-10-28 stephen.d for i := range v {
156 d6198009 2015-10-28 stephen.d elements[i] = &v[i]
157 d6198009 2015-10-28 stephen.d }
158 d6198009 2015-10-28 stephen.d
159 d6198009 2015-10-28 stephen.d if err := e.encode(elements...); err != nil {
160 d6198009 2015-10-28 stephen.d return err
161 d6198009 2015-10-28 stephen.d }
162 d6198009 2015-10-28 stephen.d case time.Time:
163 d6198009 2015-10-28 stephen.d if err := e.encode(uint32(v.Unix())); err != nil {
164 d6198009 2015-10-28 stephen.d return err
165 d6198009 2015-10-28 stephen.d }
166 d6198009 2015-10-28 stephen.d case *time.Time:
167 d6198009 2015-10-28 stephen.d if err := e.encode(*v); err != nil {
168 d6198009 2015-10-28 stephen.d return err
169 d6198009 2015-10-28 stephen.d }
170 499f8c59 2015-10-27 stephen.d case Fcall:
171 499f8c59 2015-10-27 stephen.d if err := e.encode(&v); err != nil {
172 499f8c59 2015-10-27 stephen.d return err
173 499f8c59 2015-10-27 stephen.d }
174 499f8c59 2015-10-27 stephen.d case *Fcall:
175 fb37ce2a 2015-10-30 stephen.d if err := e.encode(v.Type, v.Tag, v.Message); err != nil {
176 499f8c59 2015-10-27 stephen.d return err
177 499f8c59 2015-10-27 stephen.d }
178 499f8c59 2015-10-27 stephen.d default:
179 499f8c59 2015-10-27 stephen.d if err := binary.Write(e.wr, binary.LittleEndian, v); err != nil {
180 499f8c59 2015-10-27 stephen.d return err
181 499f8c59 2015-10-27 stephen.d }
182 499f8c59 2015-10-27 stephen.d }
183 499f8c59 2015-10-27 stephen.d }
184 499f8c59 2015-10-27 stephen.d
185 499f8c59 2015-10-27 stephen.d return nil
186 499f8c59 2015-10-27 stephen.d }
187 499f8c59 2015-10-27 stephen.d
188 499f8c59 2015-10-27 stephen.d type decoder struct {
189 499f8c59 2015-10-27 stephen.d rd io.Reader
190 499f8c59 2015-10-27 stephen.d }
191 499f8c59 2015-10-27 stephen.d
192 499f8c59 2015-10-27 stephen.d // read9p extracts values from rd and unmarshals them to the targets of vs.
193 499f8c59 2015-10-27 stephen.d func (d *decoder) decode(vs ...interface{}) error {
194 499f8c59 2015-10-27 stephen.d for _, v := range vs {
195 499f8c59 2015-10-27 stephen.d switch v := v.(type) {
196 499f8c59 2015-10-27 stephen.d case *string:
197 499f8c59 2015-10-27 stephen.d var ll uint16
198 499f8c59 2015-10-27 stephen.d
199 499f8c59 2015-10-27 stephen.d // implement string[s] encoding
200 e9f5e414 2015-10-27 stephen.d if err := d.decode(&ll); err != nil {
201 499f8c59 2015-10-27 stephen.d return err
202 499f8c59 2015-10-27 stephen.d }
203 499f8c59 2015-10-27 stephen.d
204 499f8c59 2015-10-27 stephen.d b := make([]byte, ll)
205 499f8c59 2015-10-27 stephen.d
206 499f8c59 2015-10-27 stephen.d n, err := io.ReadFull(d.rd, b)
207 499f8c59 2015-10-27 stephen.d if err != nil {
208 a8abc687 2015-10-30 stephen.d log.Println("readfull failed:", err, ll, n)
209 499f8c59 2015-10-27 stephen.d return err
210 499f8c59 2015-10-27 stephen.d }
211 499f8c59 2015-10-27 stephen.d
212 499f8c59 2015-10-27 stephen.d if n != int(ll) {
213 499f8c59 2015-10-27 stephen.d return fmt.Errorf("unexpected string length")
214 499f8c59 2015-10-27 stephen.d }
215 499f8c59 2015-10-27 stephen.d
216 499f8c59 2015-10-27 stephen.d *v = string(b)
217 e9f5e414 2015-10-27 stephen.d case *[]string:
218 e9f5e414 2015-10-27 stephen.d var ll uint16
219 e9f5e414 2015-10-27 stephen.d
220 e9f5e414 2015-10-27 stephen.d if err := d.decode(&ll); err != nil {
221 e9f5e414 2015-10-27 stephen.d return err
222 e9f5e414 2015-10-27 stephen.d }
223 e9f5e414 2015-10-27 stephen.d
224 e9f5e414 2015-10-27 stephen.d elements := make([]interface{}, int(ll))
225 e9f5e414 2015-10-27 stephen.d *v = make([]string, int(ll))
226 e9f5e414 2015-10-27 stephen.d for i := range elements {
227 e9f5e414 2015-10-27 stephen.d elements[i] = &(*v)[i]
228 e9f5e414 2015-10-27 stephen.d }
229 e9f5e414 2015-10-27 stephen.d
230 e9f5e414 2015-10-27 stephen.d if err := d.decode(elements...); err != nil {
231 d6198009 2015-10-28 stephen.d return err
232 d6198009 2015-10-28 stephen.d }
233 d6198009 2015-10-28 stephen.d case *[]byte:
234 a8abc687 2015-10-30 stephen.d var ll uint32
235 d6198009 2015-10-28 stephen.d
236 d6198009 2015-10-28 stephen.d if err := d.decode(&ll); err != nil {
237 d6198009 2015-10-28 stephen.d return err
238 d6198009 2015-10-28 stephen.d }
239 d6198009 2015-10-28 stephen.d
240 d6198009 2015-10-28 stephen.d *v = make([]byte, int(ll))
241 d6198009 2015-10-28 stephen.d
242 d6198009 2015-10-28 stephen.d if err := binary.Read(d.rd, binary.LittleEndian, v); err != nil {
243 e9f5e414 2015-10-27 stephen.d return err
244 e9f5e414 2015-10-27 stephen.d }
245 499f8c59 2015-10-27 stephen.d case *Fcall:
246 fb37ce2a 2015-10-30 stephen.d if err := d.decode(&v.Type, &v.Tag); err != nil {
247 499f8c59 2015-10-27 stephen.d return err
248 499f8c59 2015-10-27 stephen.d }
249 499f8c59 2015-10-27 stephen.d
250 499f8c59 2015-10-27 stephen.d var err error
251 499f8c59 2015-10-27 stephen.d v.Message, err = newMessage(v.Type)
252 499f8c59 2015-10-27 stephen.d if err != nil {
253 fb37ce2a 2015-10-30 stephen.d log.Printf("unknown message type %#v", v.Type)
254 499f8c59 2015-10-27 stephen.d return err
255 499f8c59 2015-10-27 stephen.d }
256 499f8c59 2015-10-27 stephen.d
257 fb37ce2a 2015-10-30 stephen.d // take the address of v.Message from the struct and encode into
258 fb37ce2a 2015-10-30 stephen.d // that.
259 fb37ce2a 2015-10-30 stephen.d
260 499f8c59 2015-10-27 stephen.d if err := d.decode(v.Message); err != nil {
261 499f8c59 2015-10-27 stephen.d return err
262 499f8c59 2015-10-27 stephen.d }
263 d6198009 2015-10-28 stephen.d case *[]Qid:
264 d6198009 2015-10-28 stephen.d var ll uint16
265 d6198009 2015-10-28 stephen.d
266 d6198009 2015-10-28 stephen.d if err := d.decode(&ll); err != nil {
267 d6198009 2015-10-28 stephen.d return err
268 d6198009 2015-10-28 stephen.d }
269 d6198009 2015-10-28 stephen.d
270 d6198009 2015-10-28 stephen.d elements := make([]interface{}, int(ll))
271 d6198009 2015-10-28 stephen.d *v = make([]Qid, int(ll))
272 d6198009 2015-10-28 stephen.d for i := range elements {
273 d6198009 2015-10-28 stephen.d elements[i] = &(*v)[i]
274 d6198009 2015-10-28 stephen.d }
275 d6198009 2015-10-28 stephen.d
276 d6198009 2015-10-28 stephen.d if err := d.decode(elements...); err != nil {
277 d6198009 2015-10-28 stephen.d return err
278 d6198009 2015-10-28 stephen.d }
279 d6198009 2015-10-28 stephen.d case *time.Time:
280 d6198009 2015-10-28 stephen.d var epoch uint32
281 d6198009 2015-10-28 stephen.d if err := d.decode(&epoch); err != nil {
282 d6198009 2015-10-28 stephen.d return err
283 d6198009 2015-10-28 stephen.d }
284 d6198009 2015-10-28 stephen.d
285 d6198009 2015-10-28 stephen.d *v = time.Unix(int64(epoch), 0).UTC()
286 a8abc687 2015-10-30 stephen.d case *Dir:
287 a8abc687 2015-10-30 stephen.d var ll uint16
288 a8abc687 2015-10-30 stephen.d
289 a8abc687 2015-10-30 stephen.d if err := d.decode(&ll); err != nil {
290 a8abc687 2015-10-30 stephen.d return err
291 a8abc687 2015-10-30 stephen.d }
292 a8abc687 2015-10-30 stephen.d
293 a8abc687 2015-10-30 stephen.d b := make([]byte, ll)
294 a8abc687 2015-10-30 stephen.d // must consume entire dir entry.
295 a8abc687 2015-10-30 stephen.d n, err := io.ReadFull(d.rd, b)
296 a8abc687 2015-10-30 stephen.d if err != nil {
297 a8abc687 2015-10-30 stephen.d log.Println("dir readfull failed:", err, ll, n)
298 a8abc687 2015-10-30 stephen.d return err
299 a8abc687 2015-10-30 stephen.d }
300 a8abc687 2015-10-30 stephen.d
301 499f8c59 2015-10-27 stephen.d elements, err := fields9p(v)
302 499f8c59 2015-10-27 stephen.d if err != nil {
303 499f8c59 2015-10-27 stephen.d return err
304 499f8c59 2015-10-27 stephen.d }
305 499f8c59 2015-10-27 stephen.d
306 a8abc687 2015-10-30 stephen.d dec := &decoder{bytes.NewReader(b)}
307 a8abc687 2015-10-30 stephen.d
308 a8abc687 2015-10-30 stephen.d if err := dec.decode(elements...); err != nil {
309 a8abc687 2015-10-30 stephen.d return err
310 a8abc687 2015-10-30 stephen.d }
311 74ec7ac9 2015-10-30 stephen.d case Message:
312 a8abc687 2015-10-30 stephen.d elements, err := fields9p(v)
313 a8abc687 2015-10-30 stephen.d if err != nil {
314 a8abc687 2015-10-30 stephen.d return err
315 74ec7ac9 2015-10-30 stephen.d }
316 74ec7ac9 2015-10-30 stephen.d
317 74ec7ac9 2015-10-30 stephen.d // special case twstat and rstat for size fields. See bugs in
318 74ec7ac9 2015-10-30 stephen.d // http://man.cat-v.org/plan_9/5/stat to make sense of this.
319 74ec7ac9 2015-10-30 stephen.d switch v.(type) {
320 74ec7ac9 2015-10-30 stephen.d case *MessageRstat, MessageRstat:
321 74ec7ac9 2015-10-30 stephen.d // decode extra size header for stat structure.
322 74ec7ac9 2015-10-30 stephen.d var ll uint16
323 74ec7ac9 2015-10-30 stephen.d if err := d.decode(&ll); err != nil {
324 74ec7ac9 2015-10-30 stephen.d return err
325 74ec7ac9 2015-10-30 stephen.d }
326 a8abc687 2015-10-30 stephen.d }
327 a8abc687 2015-10-30 stephen.d
328 499f8c59 2015-10-27 stephen.d if err := d.decode(elements...); err != nil {
329 499f8c59 2015-10-27 stephen.d return err
330 499f8c59 2015-10-27 stephen.d }
331 74ec7ac9 2015-10-30 stephen.d case *Qid:
332 74ec7ac9 2015-10-30 stephen.d if err := d.decode(&v.Type, &v.Version, &v.Path); err != nil {
333 74ec7ac9 2015-10-30 stephen.d return err
334 74ec7ac9 2015-10-30 stephen.d }
335 499f8c59 2015-10-27 stephen.d default:
336 499f8c59 2015-10-27 stephen.d if err := binary.Read(d.rd, binary.LittleEndian, v); err != nil {
337 499f8c59 2015-10-27 stephen.d return err
338 499f8c59 2015-10-27 stephen.d }
339 499f8c59 2015-10-27 stephen.d }
340 499f8c59 2015-10-27 stephen.d }
341 499f8c59 2015-10-27 stephen.d
342 499f8c59 2015-10-27 stephen.d return nil
343 499f8c59 2015-10-27 stephen.d }
344 499f8c59 2015-10-27 stephen.d
345 499f8c59 2015-10-27 stephen.d // size9p calculates the projected size of the values in vs when encoded into
346 499f8c59 2015-10-27 stephen.d // 9p binary protocol. If an element or elements are not valid for 9p encoded,
347 499f8c59 2015-10-27 stephen.d // the value 0 will be used for the size. The error will be detected when
348 499f8c59 2015-10-27 stephen.d // encoding.
349 499f8c59 2015-10-27 stephen.d func size9p(vs ...interface{}) uint32 {
350 499f8c59 2015-10-27 stephen.d var s uint32
351 499f8c59 2015-10-27 stephen.d for _, v := range vs {
352 499f8c59 2015-10-27 stephen.d if v == nil {
353 499f8c59 2015-10-27 stephen.d continue
354 499f8c59 2015-10-27 stephen.d }
355 499f8c59 2015-10-27 stephen.d
356 499f8c59 2015-10-27 stephen.d switch v := v.(type) {
357 499f8c59 2015-10-27 stephen.d case *string:
358 499f8c59 2015-10-27 stephen.d s += uint32(binary.Size(uint16(0)) + len(*v))
359 499f8c59 2015-10-27 stephen.d case string:
360 499f8c59 2015-10-27 stephen.d s += uint32(binary.Size(uint16(0)) + len(v))
361 e9f5e414 2015-10-27 stephen.d case *[]string:
362 e9f5e414 2015-10-27 stephen.d s += size9p(*v)
363 e9f5e414 2015-10-27 stephen.d case []string:
364 e9f5e414 2015-10-27 stephen.d s += size9p(uint16(0))
365 e9f5e414 2015-10-27 stephen.d elements := make([]interface{}, len(v))
366 e9f5e414 2015-10-27 stephen.d for i := range elements {
367 e9f5e414 2015-10-27 stephen.d elements[i] = v[i]
368 e9f5e414 2015-10-27 stephen.d }
369 e9f5e414 2015-10-27 stephen.d
370 e9f5e414 2015-10-27 stephen.d s += size9p(elements...)
371 d6198009 2015-10-28 stephen.d case *[]byte:
372 74ec7ac9 2015-10-30 stephen.d s += size9p(uint32(0), *v)
373 d6198009 2015-10-28 stephen.d case *[]Qid:
374 d6198009 2015-10-28 stephen.d s += size9p(*v)
375 d6198009 2015-10-28 stephen.d case []Qid:
376 d6198009 2015-10-28 stephen.d s += size9p(uint16(0))
377 d6198009 2015-10-28 stephen.d elements := make([]interface{}, len(v))
378 d6198009 2015-10-28 stephen.d for i := range elements {
379 d6198009 2015-10-28 stephen.d elements[i] = &v[i]
380 d6198009 2015-10-28 stephen.d }
381 d6198009 2015-10-28 stephen.d s += size9p(elements...)
382 d6198009 2015-10-28 stephen.d case time.Time, *time.Time:
383 d6198009 2015-10-28 stephen.d s += size9p(uint32(0))
384 74ec7ac9 2015-10-30 stephen.d case Qid:
385 74ec7ac9 2015-10-30 stephen.d s += size9p(v.Type, v.Version, v.Path)
386 74ec7ac9 2015-10-30 stephen.d case Dir:
387 499f8c59 2015-10-27 stephen.d // walk the fields of the message to get the total size. we just
388 499f8c59 2015-10-27 stephen.d // use the field order from the message struct. We may add tag
389 499f8c59 2015-10-27 stephen.d // ignoring if needed.
390 499f8c59 2015-10-27 stephen.d elements, err := fields9p(v)
391 499f8c59 2015-10-27 stephen.d if err != nil {
392 499f8c59 2015-10-27 stephen.d // BUG(stevvooe): The options here are to return 0, panic or
393 499f8c59 2015-10-27 stephen.d // make this return an error. Ideally, we make it safe to
394 499f8c59 2015-10-27 stephen.d // return 0 and have the rest of the package do the right
395 499f8c59 2015-10-27 stephen.d // thing. For now, we do this, but may want to panic until
396 499f8c59 2015-10-27 stephen.d // things are stable.
397 e9f5e414 2015-10-27 stephen.d panic(err)
398 499f8c59 2015-10-27 stephen.d }
399 499f8c59 2015-10-27 stephen.d
400 74ec7ac9 2015-10-30 stephen.d s += size9p(elements...) + size9p(uint16(0))
401 74ec7ac9 2015-10-30 stephen.d case Message:
402 74ec7ac9 2015-10-30 stephen.d
403 74ec7ac9 2015-10-30 stephen.d // special case twstat and rstat for size fields. See bugs in
404 74ec7ac9 2015-10-30 stephen.d // http://man.cat-v.org/plan_9/5/stat to make sense of this.
405 74ec7ac9 2015-10-30 stephen.d switch v.(type) {
406 74ec7ac9 2015-10-30 stephen.d case *MessageRstat, MessageRstat:
407 74ec7ac9 2015-10-30 stephen.d s += size9p(uint16(0)) // for extra size field before dir
408 74ec7ac9 2015-10-30 stephen.d }
409 74ec7ac9 2015-10-30 stephen.d
410 74ec7ac9 2015-10-30 stephen.d // walk the fields of the message to get the total size. we just
411 74ec7ac9 2015-10-30 stephen.d // use the field order from the message struct. We may add tag
412 74ec7ac9 2015-10-30 stephen.d // ignoring if needed.
413 74ec7ac9 2015-10-30 stephen.d elements, err := fields9p(v)
414 74ec7ac9 2015-10-30 stephen.d if err != nil {
415 74ec7ac9 2015-10-30 stephen.d // BUG(stevvooe): The options here are to return 0, panic or
416 74ec7ac9 2015-10-30 stephen.d // make this return an error. Ideally, we make it safe to
417 74ec7ac9 2015-10-30 stephen.d // return 0 and have the rest of the package do the right
418 74ec7ac9 2015-10-30 stephen.d // thing. For now, we do this, but may want to panic until
419 74ec7ac9 2015-10-30 stephen.d // things are stable.
420 74ec7ac9 2015-10-30 stephen.d panic(err)
421 74ec7ac9 2015-10-30 stephen.d }
422 74ec7ac9 2015-10-30 stephen.d
423 499f8c59 2015-10-27 stephen.d s += size9p(elements...)
424 74ec7ac9 2015-10-30 stephen.d case *Qid:
425 74ec7ac9 2015-10-30 stephen.d s += size9p(*v)
426 74ec7ac9 2015-10-30 stephen.d case *Dir:
427 74ec7ac9 2015-10-30 stephen.d s += size9p(*v)
428 499f8c59 2015-10-27 stephen.d case Fcall:
429 fb37ce2a 2015-10-30 stephen.d s += size9p(v.Type, v.Tag, v.Message)
430 499f8c59 2015-10-27 stephen.d case *Fcall:
431 e9f5e414 2015-10-27 stephen.d s += size9p(*v)
432 499f8c59 2015-10-27 stephen.d default:
433 499f8c59 2015-10-27 stephen.d s += uint32(binary.Size(v))
434 499f8c59 2015-10-27 stephen.d }
435 499f8c59 2015-10-27 stephen.d }
436 499f8c59 2015-10-27 stephen.d
437 499f8c59 2015-10-27 stephen.d return s
438 499f8c59 2015-10-27 stephen.d }
439 499f8c59 2015-10-27 stephen.d
440 499f8c59 2015-10-27 stephen.d // fields9p lists the settable fields from a struct type for reading and
441 499f8c59 2015-10-27 stephen.d // writing. We are using a lot of reflection here for fairly static
442 499f8c59 2015-10-27 stephen.d // serialization but we can replace this in the future with generated code if
443 499f8c59 2015-10-27 stephen.d // performance is an issue.
444 499f8c59 2015-10-27 stephen.d func fields9p(v interface{}) ([]interface{}, error) {
445 499f8c59 2015-10-27 stephen.d rv := reflect.Indirect(reflect.ValueOf(v))
446 499f8c59 2015-10-27 stephen.d
447 499f8c59 2015-10-27 stephen.d if rv.Kind() != reflect.Struct {
448 499f8c59 2015-10-27 stephen.d return nil, fmt.Errorf("cannot extract fields from non-struct: %v", rv)
449 499f8c59 2015-10-27 stephen.d }
450 499f8c59 2015-10-27 stephen.d
451 499f8c59 2015-10-27 stephen.d var elements []interface{}
452 499f8c59 2015-10-27 stephen.d for i := 0; i < rv.NumField(); i++ {
453 499f8c59 2015-10-27 stephen.d f := rv.Field(i)
454 499f8c59 2015-10-27 stephen.d
455 499f8c59 2015-10-27 stephen.d if !f.CanInterface() {
456 499f8c59 2015-10-27 stephen.d return nil, fmt.Errorf("can't interface: %v", f)
457 499f8c59 2015-10-27 stephen.d }
458 499f8c59 2015-10-27 stephen.d
459 499f8c59 2015-10-27 stephen.d if f.CanAddr() {
460 499f8c59 2015-10-27 stephen.d f = f.Addr()
461 499f8c59 2015-10-27 stephen.d }
462 499f8c59 2015-10-27 stephen.d
463 499f8c59 2015-10-27 stephen.d elements = append(elements, f.Interface())
464 499f8c59 2015-10-27 stephen.d }
465 499f8c59 2015-10-27 stephen.d
466 499f8c59 2015-10-27 stephen.d return elements, nil
467 499f8c59 2015-10-27 stephen.d }
468 e6bcde66 2015-10-29 stephen.d
469 97423e8b 2015-10-29 stephen.d func string9p(v interface{}) string {
470 97423e8b 2015-10-29 stephen.d if v == nil {
471 97423e8b 2015-10-29 stephen.d return "nil"
472 e6bcde66 2015-10-29 stephen.d }
473 e6bcde66 2015-10-29 stephen.d
474 97423e8b 2015-10-29 stephen.d rv := reflect.Indirect(reflect.ValueOf(v))
475 97423e8b 2015-10-29 stephen.d
476 97423e8b 2015-10-29 stephen.d if rv.Kind() != reflect.Struct {
477 97423e8b 2015-10-29 stephen.d panic("not a struct")
478 97423e8b 2015-10-29 stephen.d }
479 97423e8b 2015-10-29 stephen.d
480 97423e8b 2015-10-29 stephen.d var s string
481 97423e8b 2015-10-29 stephen.d
482 97423e8b 2015-10-29 stephen.d for i := 0; i < rv.NumField(); i++ {
483 97423e8b 2015-10-29 stephen.d f := rv.Field(i)
484 97423e8b 2015-10-29 stephen.d
485 74ec7ac9 2015-10-30 stephen.d s += fmt.Sprintf(" %v=%v", strings.ToLower(rv.Type().Field(i).Name), f.Interface())
486 97423e8b 2015-10-29 stephen.d }
487 97423e8b 2015-10-29 stephen.d
488 97423e8b 2015-10-29 stephen.d return s
489 e6bcde66 2015-10-29 stephen.d }