Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(473)

Side by Side Diff: mojo/public/go/bindings/decoder.go

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/public/go/bindings/connector.go ('k') | mojo/public/go/bindings/encoder.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package bindings
6
7 import (
8 "encoding/binary"
9 "fmt"
10 "math"
11
12 "mojo/public/go/system"
13 )
14
15 // Decoder is a helper to decode mojo complex elements from mojo archive format.
16 type Decoder struct {
17 // Buffer containing data to decode.
18 buf []byte
19
20 // Index of the first unclaimed byte in buf.
21 end int
22
23 // Array containing handles to decode.
24 handles []system.UntypedHandle
25
26 // The first unclaimed handle index.
27 nextHandle int
28
29 // A stack of encoding states matching current one-level value stack
30 // of the decoding data structure.
31 stateStack []encodingState
32 }
33
34 // NewDecoder returns a decoder that will decode structured data from provided
35 // byte array and with handles.
36 func NewDecoder(bytes []byte, handles []system.UntypedHandle) *Decoder {
37 return &Decoder{buf: bytes, handles: handles}
38 }
39
40 // claimData claims a block of |size| bytes for a one-level value.
41 func (d *Decoder) claimData(size int) error {
42 if d.end+size > len(d.buf) {
43 return &ValidationError{IllegalMemoryRange, "data buffer is too small"}
44 }
45 d.end += size
46 return nil
47 }
48
49 func (d *Decoder) claimHandle(index int) (system.UntypedHandle, error) {
50 if index >= len(d.handles) {
51 return nil, &ValidationError{IllegalHandle, "trying to access no n present handle"}
52 }
53 if index < d.nextHandle {
54 return nil, &ValidationError{IllegalHandle, "trying to access ha ndle out of order"}
55 }
56 d.nextHandle = index + 1
57 return d.handles[index], nil
58 }
59
60 func (d *Decoder) popState() {
61 if len(d.stateStack) != 0 {
62 d.stateStack = d.stateStack[:len(d.stateStack)-1]
63 }
64 }
65
66 func (d *Decoder) pushState(header DataHeader, checkElements bool) error {
67 oldEnd := d.end
68 if err := d.claimData(int(header.Size - dataHeaderSize)); err != nil {
69 return err
70 }
71 elements := uint32(0)
72 if checkElements {
73 elements = header.ElementsOrVersion
74 }
75 d.stateStack = append(d.stateStack, encodingState{
76 offset: oldEnd,
77 limit: d.end,
78 elements: elements,
79 checkElements: checkElements,
80 })
81 return nil
82 }
83
84 // state returns state of the top-level value.
85 func (d *Decoder) state() *encodingState {
86 if len(d.stateStack) == 0 {
87 return nil
88 }
89 return &d.stateStack[len(d.stateStack)-1]
90 }
91
92 // StartArray starts decoding an array and reads its data header,
93 // returning number of elements declared in data header.
94 // Note: it doesn't read a pointer to the encoded array.
95 // Call |Finish()| after reading all array elements.
96 func (d *Decoder) StartArray(elementBitSize uint32) (uint32, error) {
97 header, err := d.readDataHeader()
98 if err != nil {
99 return 0, err
100 }
101 minSize := bytesForBits(uint64(header.ElementsOrVersion) * uint64(elemen tBitSize))
102 if got, want := int(header.Size), dataHeaderSize+minSize; got < want {
103 return 0, &ValidationError{UnexpectedArrayHeader,
104 fmt.Sprintf("data header size(%d) should be at least %d" , got, want),
105 }
106 }
107 if err := d.pushState(header, true); err != nil {
108 return 0, err
109 }
110 return header.ElementsOrVersion, nil
111 }
112
113 // StartMap starts decoding a map and reads its data header.
114 // Note: it doesn't read a pointer to the encoded map.
115 // Call |Finish()| after reading keys array and values array.
116 func (d *Decoder) StartMap() error {
117 header, err := d.readDataHeader()
118 if err != nil {
119 return err
120 }
121 if header != mapHeader {
122 return &ValidationError{UnexpectedStructHeader,
123 fmt.Sprintf("invalid map header: %v", header),
124 }
125 }
126 if err := d.pushState(header, false); err != nil {
127 return err
128 }
129 return nil
130 }
131
132 // StartStruct starts decoding a struct and reads its data header.
133 // Returns the read data header. The caller should check if it is valid.
134 // Note: it doesn't read a pointer to the encoded struct.
135 // Call |Finish()| after reading all fields.
136 func (d *Decoder) StartStruct() (DataHeader, error) {
137 header, err := d.readDataHeader()
138 if err != nil {
139 return DataHeader{}, err
140 }
141 if header.Size < dataHeaderSize {
142 return DataHeader{}, &ValidationError{UnexpectedStructHeader,
143 fmt.Sprintf("data header size(%d) should be at least %d" , header.Size, dataHeaderSize),
144 }
145 }
146 if err := d.pushState(header, false); err != nil {
147 return DataHeader{}, err
148 }
149 return header, nil
150 }
151
152 // StartNestedUnion starts decoding a union.
153 // Note: it doesn't read a pointer to the encoded struct or the union header.
154 // Call |Finish()| after reading the header and data.
155 func (d *Decoder) StartNestedUnion() error {
156 // We have to trick pushState into claiming 16 bytes.
157 header := DataHeader{uint32(24), uint32(0)}
158 if err := d.pushState(header, false); err != nil {
159 return err
160 }
161 return nil
162 }
163
164 // ReadUnionHeader reads the union header and returns the union's size and tag.
165 func (d *Decoder) ReadUnionHeader() (uint32, uint32, error) {
166 if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil {
167 return 0, 0, err
168 }
169 d.state().alignOffsetToBytes()
170 d.state().offset = align(d.state().offset, 8)
171 size := binary.LittleEndian.Uint32(d.buf[d.state().offset:])
172 tag := binary.LittleEndian.Uint32(d.buf[d.state().offset+4:])
173 d.state().offset += 8
174 if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil {
175 return 0, 0, err
176 }
177 return size, tag, nil
178 }
179
180 // FinishReadingUnionValue should be called after the union value has been read
181 // in order to indicate to move the decoder past the union value field.
182 func (d *Decoder) FinishReadingUnionValue() {
183 d.state().offset = align(d.state().offset, 8)
184 d.state().alignOffsetToBytes()
185 }
186
187 // SkipUnionValue skips the union's value.
188 func (d *Decoder) SkipUnionValue() {
189 d.state().offset += 8
190 d.state().elementsProcessed += 1
191 }
192
193 func (d *Decoder) readDataHeader() (DataHeader, error) {
194 if err := d.claimData(dataHeaderSize); err != nil {
195 return DataHeader{}, err
196 }
197 oldEnd := d.end - dataHeaderSize
198 header := DataHeader{
199 Size: binary.LittleEndian.Uint32(d.buf[oldEnd:]),
200 ElementsOrVersion: binary.LittleEndian.Uint32(d.buf[oldEnd+4:]),
201 }
202 return header, nil
203 }
204
205 // Finish indicates the decoder that you have finished reading elements of
206 // a one-level value.
207 func (d *Decoder) Finish() error {
208 if d.state() == nil {
209 return fmt.Errorf("state stack is empty")
210 }
211 if d.state().checkElements && d.state().elementsProcessed != d.state().e lements {
212 return fmt.Errorf("unexpected number of elements read: defined i n header %d, but read %d", d.state().elements, d.state().elementsProcessed)
213 }
214 d.popState()
215 return nil
216 }
217
218 // ReadBool reads a bool value.
219 func (d *Decoder) ReadBool() (bool, error) {
220 if err := ensureElementBitSizeAndCapacity(d.state(), 1); err != nil {
221 return false, err
222 }
223 value := ((d.buf[d.state().offset] >> d.state().bitOffset) & 1) == 1
224 d.state().skipBits(1)
225 d.state().elementsProcessed++
226 return value, nil
227 }
228
229 // ReadInt8 reads an int8 value.
230 func (d *Decoder) ReadInt8() (int8, error) {
231 value, err := d.ReadUint8()
232 return int8(value), err
233 }
234
235 // ReadUint8 reads an uint8 value.
236 func (d *Decoder) ReadUint8() (uint8, error) {
237 if err := ensureElementBitSizeAndCapacity(d.state(), 8); err != nil {
238 return 0, err
239 }
240 d.state().alignOffsetToBytes()
241 value := d.buf[d.state().offset]
242 d.state().skipBytes(1)
243 d.state().elementsProcessed++
244 return value, nil
245 }
246
247 // ReadInt16 reads an int16 value.
248 func (d *Decoder) ReadInt16() (int16, error) {
249 value, err := d.ReadUint16()
250 return int16(value), err
251 }
252
253 // ReadUint16 reads an uint16 value.
254 func (d *Decoder) ReadUint16() (uint16, error) {
255 if err := ensureElementBitSizeAndCapacity(d.state(), 16); err != nil {
256 return 0, err
257 }
258 d.state().alignOffsetToBytes()
259 d.state().offset = align(d.state().offset, 2)
260 value := binary.LittleEndian.Uint16(d.buf[d.state().offset:])
261 d.state().skipBytes(2)
262 d.state().elementsProcessed++
263 return value, nil
264 }
265
266 // ReadInt32 reads an int32 value.
267 func (d *Decoder) ReadInt32() (int32, error) {
268 value, err := d.ReadUint32()
269 return int32(value), err
270 }
271
272 // ReadUint32 reads an uint32 value.
273 func (d *Decoder) ReadUint32() (uint32, error) {
274 if err := ensureElementBitSizeAndCapacity(d.state(), 32); err != nil {
275 return 0, err
276 }
277 d.state().alignOffsetToBytes()
278 d.state().offset = align(d.state().offset, 4)
279 value := binary.LittleEndian.Uint32(d.buf[d.state().offset:])
280 d.state().skipBytes(4)
281 d.state().elementsProcessed++
282 return value, nil
283 }
284
285 // ReadInt64 reads an int64 value.
286 func (d *Decoder) ReadInt64() (int64, error) {
287 value, err := d.ReadUint64()
288 return int64(value), err
289 }
290
291 // ReadUint64 reads an uint64 value.
292 func (d *Decoder) ReadUint64() (uint64, error) {
293 if err := ensureElementBitSizeAndCapacity(d.state(), 64); err != nil {
294 return 0, err
295 }
296 d.state().alignOffsetToBytes()
297 d.state().offset = align(d.state().offset, 8)
298 value := binary.LittleEndian.Uint64(d.buf[d.state().offset:])
299 d.state().skipBytes(8)
300 d.state().elementsProcessed++
301 return value, nil
302 }
303
304 // ReadFloat32 reads a float32 value.
305 func (d *Decoder) ReadFloat32() (float32, error) {
306 bits, err := d.ReadUint32()
307 return math.Float32frombits(bits), err
308 }
309
310 // ReadFloat64 reads a float64 value.
311 func (d *Decoder) ReadFloat64() (float64, error) {
312 bits, err := d.ReadUint64()
313 return math.Float64frombits(bits), err
314 }
315
316 // ReadString reads a string value. It doesn't read a pointer to the encoded
317 // string.
318 func (d *Decoder) ReadString() (string, error) {
319 length, err := d.StartArray(8)
320 if err != nil {
321 return "", err
322 }
323 var bytes []byte
324 for i := uint32(0); i < length; i++ {
325 b, err := d.ReadUint8()
326 if err != nil {
327 return "", err
328 }
329 bytes = append(bytes, b)
330 }
331 if err := d.Finish(); err != nil {
332 return "", err
333 }
334 return string(bytes), nil
335 }
336
337 // ReadPointer reads a pointer and reassigns first unclaimed byte index if the
338 // pointer is not null.
339 func (d *Decoder) ReadPointer() (uint64, error) {
340 pointer, err := d.ReadUint64()
341 if err != nil {
342 return pointer, err
343 }
344 if pointer == 0 {
345 return pointer, nil
346 }
347
348 newEnd := uint64(d.state().offset-8) + pointer
349 if pointer >= uint64(len(d.buf)) || newEnd >= uint64(len(d.buf)) {
350 return 0, &ValidationError{IllegalPointer, "trying to access out of range memory"}
351 }
352 if newEnd < uint64(d.end) {
353 return 0, &ValidationError{IllegalMemoryRange, "trying to access memory out of order"}
354 }
355 if newEnd%8 != 0 {
356 return 0, &ValidationError{MisalignedObject,
357 fmt.Sprintf("incorrect pointer data alignment: %d", newE nd),
358 }
359 }
360 d.claimData(int(newEnd) - d.end)
361 return pointer, nil
362 }
363
364 // ReadUntypedHandle reads an untyped handle.
365 func (d *Decoder) ReadUntypedHandle() (system.UntypedHandle, error) {
366 handleIndex, err := d.ReadUint32()
367 if err != nil {
368 return nil, err
369 }
370 if handleIndex == ^uint32(0) {
371 return &InvalidHandle{}, nil
372 }
373 return d.claimHandle(int(handleIndex))
374 }
375
376 // ReadHandle reads a handle.
377 func (d *Decoder) ReadHandle() (system.Handle, error) {
378 return d.ReadUntypedHandle()
379 }
380
381 // ReadMessagePipeHandle reads a message pipe handle.
382 func (d *Decoder) ReadMessagePipeHandle() (system.MessagePipeHandle, error) {
383 if handle, err := d.ReadUntypedHandle(); err != nil {
384 return nil, err
385 } else {
386 return handle.ToMessagePipeHandle(), nil
387 }
388 }
389
390 // ReadConsumerHandle reads a data pipe consumer handle.
391 func (d *Decoder) ReadConsumerHandle() (system.ConsumerHandle, error) {
392 if handle, err := d.ReadUntypedHandle(); err != nil {
393 return nil, err
394 } else {
395 return handle.ToConsumerHandle(), nil
396 }
397 }
398
399 // ReadProducerHandle reads a data pipe producer handle.
400 func (d *Decoder) ReadProducerHandle() (system.ProducerHandle, error) {
401 if handle, err := d.ReadUntypedHandle(); err != nil {
402 return nil, err
403 } else {
404 return handle.ToProducerHandle(), nil
405 }
406 }
407
408 // ReadSharedBufferHandle reads a shared buffer handle.
409 func (d *Decoder) ReadSharedBufferHandle() (system.SharedBufferHandle, error) {
410 if handle, err := d.ReadUntypedHandle(); err != nil {
411 return nil, err
412 } else {
413 return handle.ToSharedBufferHandle(), nil
414 }
415 }
416
417 // ReadInterface reads an encoded interface and returns the message pipe handle.
418 // The version field is ignored for now.
419 func (d *Decoder) ReadInterface() (system.MessagePipeHandle, error) {
420 handle, err := d.ReadMessagePipeHandle()
421 if err != nil {
422 return nil, err
423 }
424 d.state().elementsProcessed--
425 if _, err := d.ReadUint32(); err != nil {
426 return nil, err
427 }
428 return handle, nil
429 }
OLDNEW
« no previous file with comments | « mojo/public/go/bindings/connector.go ('k') | mojo/public/go/bindings/encoder.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698