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

Side by Side Diff: mojo/public/go/bindings/encoder.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/decoder.go ('k') | mojo/public/go/bindings/interface.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 "sort"
12
13 "mojo/public/go/system"
14 )
15
16 // encodingState has information required to encode/decode a one-level value.
17 type encodingState struct {
18 // Index of the first unprocessed byte.
19 offset int
20
21 // Index of the first unprocessed bit of buffer[offset] byte.
22 bitOffset uint32
23
24 // Index of the first byte after the claimed buffer block for the curren t
25 // one-level value.
26 limit int
27
28 // Number of elements declared in the data header for the current one-le vel
29 // value.
30 elements uint32
31
32 // Number of elements already encoded/decoded of the current one-level
33 // value.
34 elementsProcessed uint32
35
36 // Whether the number of elements processed should be checked.
37 checkElements bool
38 }
39
40 func (s *encodingState) alignOffsetToBytes() {
41 if s.bitOffset > 0 {
42 s.offset++
43 s.bitOffset = 0
44 }
45 }
46
47 func (s *encodingState) skipBits(count uint32) {
48 s.bitOffset += count
49 s.offset += int(s.bitOffset >> 3) // equal to s.bitOffset / 8
50 s.bitOffset &= 7 // equal to s.bitOffset % 8
51 }
52
53 func (s *encodingState) skipBytes(count int) {
54 s.bitOffset = 0
55 s.offset += count
56 }
57
58 // Encoder is a helper to encode mojo complex elements into mojo archive format.
59 type Encoder struct {
60 // Buffer containing encoded data.
61 buf []byte
62
63 // Index of the first unclaimed byte in buf.
64 end int
65
66 // Array containing encoded handles.
67 handles []system.UntypedHandle
68
69 // A stack of encoder states matching current one-level value stack
70 // of the encoding data structure.
71 stateStack []encodingState
72
73 // By default encoding is non-deterministic because the encoding of
74 // a mojom map does not specify the order of the keys and values.
75 // If |deterministic| is true then keys and values will be sorted
76 // in ascending key order.
77 deterministic bool
78 }
79
80 func ensureElementBitSizeAndCapacity(state *encodingState, bitSize uint32) error {
81 if state == nil {
82 return fmt.Errorf("empty state stack")
83 }
84 if state.checkElements && state.elementsProcessed >= state.elements {
85 return fmt.Errorf("can't process more than elements defined in h eader(%d)", state.elements)
86 }
87 byteSize := bytesForBits(uint64(state.bitOffset + bitSize))
88 if align(state.offset+byteSize, byteSize) > state.limit {
89 return fmt.Errorf("buffer size limit exceeded")
90 }
91 return nil
92 }
93
94 // claimData claims a block of |size| bytes for a one-level value, resizing
95 // buffer if needed.
96 func (e *Encoder) claimData(size int) {
97 e.end += size
98 if e.end < len(e.buf) {
99 return
100 }
101 newLen := e.end
102 if l := 2 * len(e.buf); newLen < l {
103 newLen = l
104 }
105 tmp := make([]byte, newLen)
106 copy(tmp, e.buf)
107 e.buf = tmp
108 }
109
110 func (e *Encoder) popState() {
111 if len(e.stateStack) != 0 {
112 e.stateStack = e.stateStack[:len(e.stateStack)-1]
113 }
114 }
115
116 func (e *Encoder) pushState(header DataHeader, checkElements bool) {
117 oldEnd := e.end
118 e.claimData(align(int(header.Size), defaultAlignment))
119 elements := uint32(0)
120 if checkElements {
121 elements = header.ElementsOrVersion
122 }
123 e.stateStack = append(e.stateStack, encodingState{
124 offset: oldEnd,
125 limit: e.end,
126 elements: elements,
127 checkElements: checkElements,
128 })
129 }
130
131 // state returns encoder state of the top-level value.
132 func (e *Encoder) state() *encodingState {
133 if len(e.stateStack) == 0 {
134 return nil
135 }
136 return &e.stateStack[len(e.stateStack)-1]
137 }
138
139 // NewEncoder returns a new instance of encoder.
140 func NewEncoder() *Encoder {
141 return &Encoder{}
142 }
143
144 // SetDeterministic sets whether or not this encoder is deterministic.
145 // By default encoding is non-deterministic because the encoding of
146 // a mojom map does not specify the order of the keys and values.
147 // If SetDeterministic(true) is invoked then this encoder will, from then on,
148 // have the property that keys and values will be sorted in ascending key order.
149 // Warning: This causes encoding to be more expensive.
150 func (e *Encoder) SetDeterministic(deterministic bool) {
151 e.deterministic = deterministic
152 }
153
154 func (e *Encoder) Deterministic() bool {
155 return e.deterministic
156 }
157
158 // StartArray starts encoding an array and writes its data header.
159 // Note: it doesn't write a pointer to the encoded array.
160 // Call |Finish()| after writing all array elements.
161 func (e *Encoder) StartArray(length, elementBitSize uint32) {
162 dataSize := dataHeaderSize + bytesForBits(uint64(length)*uint64(elementB itSize))
163 header := DataHeader{uint32(dataSize), length}
164 e.pushState(header, true)
165 e.writeDataHeader(header)
166 }
167
168 // StartMap starts encoding a map and writes its data header.
169 // Note: it doesn't write a pointer to the encoded map.
170 // Call |Finish()| after writing keys array and values array.
171 func (e *Encoder) StartMap() {
172 e.pushState(mapHeader, false)
173 e.writeDataHeader(mapHeader)
174 }
175
176 // StartStruct starts encoding a struct and writes its data header.
177 // Note: it doesn't write a pointer to the encoded struct.
178 // Call |Finish()| after writing all fields.
179 func (e *Encoder) StartStruct(size, version uint32) {
180 dataSize := dataHeaderSize + int(size)
181 header := DataHeader{uint32(dataSize), version}
182 e.pushState(header, false)
183 e.writeDataHeader(header)
184 }
185
186 // StartNestedUnion starts encoding a nested union.
187 // Note: it doesn't write a pointer or a union header.
188 // Call |Finish()| after writing all fields.
189 func (e *Encoder) StartNestedUnion() {
190 header := DataHeader{uint32(16), uint32(0)}
191 e.pushState(header, false)
192 }
193
194 func (e *Encoder) writeDataHeader(header DataHeader) {
195 binary.LittleEndian.PutUint32(e.buf[e.state().offset:], header.Size)
196 binary.LittleEndian.PutUint32(e.buf[e.state().offset+4:], header.Element sOrVersion)
197 e.state().offset += 8
198 }
199
200 // WriteUnionHeader writes a union header for a non-null union.
201 // (See. WriteNullUnion)
202 func (e *Encoder) WriteUnionHeader(tag uint32) error {
203 if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil {
204 return err
205 }
206 e.state().alignOffsetToBytes()
207 e.state().offset = align(e.state().offset, 8)
208 binary.LittleEndian.PutUint32(e.buf[e.state().offset:], 16)
209 binary.LittleEndian.PutUint32(e.buf[e.state().offset+4:], tag)
210 e.state().offset += 8
211 if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil {
212 return err
213 }
214 return nil
215 }
216
217 // FinishWritingUnionValue should call after the union value has been read in
218 // order to indicate to move the encoder past the union value field.
219 func (e *Encoder) FinishWritingUnionValue() {
220 e.state().offset = align(e.state().offset, 8)
221 e.state().alignOffsetToBytes()
222 }
223
224 // Finish indicates the encoder that you have finished writing elements of
225 // a one-level value.
226 func (e *Encoder) Finish() error {
227 if e.state() == nil {
228 return fmt.Errorf("state stack is empty")
229 }
230 if e.state().checkElements && e.state().elementsProcessed != e.state().e lements {
231 return fmt.Errorf("unexpected number of elements written: define d in header %d, but written %d", e.state().elements, e.state().elementsProcessed )
232 }
233 e.popState()
234 return nil
235 }
236
237 // Data returns an encoded message with attached handles.
238 // Call this method after finishing encoding of a value.
239 func (e *Encoder) Data() ([]byte, []system.UntypedHandle, error) {
240 if len(e.stateStack) != 0 {
241 return nil, nil, fmt.Errorf("can't return data when encoder has non-empty state stack")
242 }
243 return e.buf[:e.end], e.handles, nil
244 }
245
246 // WriteBool writes a bool value.
247 func (e *Encoder) WriteBool(value bool) error {
248 if err := ensureElementBitSizeAndCapacity(e.state(), 1); err != nil {
249 return err
250 }
251 if value {
252 e.buf[e.state().offset] |= 1 << e.state().bitOffset
253 }
254 e.state().skipBits(1)
255 e.state().elementsProcessed++
256 return nil
257 }
258
259 // WriteBool writes an int8 value.
260 func (e *Encoder) WriteInt8(value int8) error {
261 return e.WriteUint8(uint8(value))
262 }
263
264 // WriteUint8 writes an uint8 value.
265 func (e *Encoder) WriteUint8(value uint8) error {
266 if err := ensureElementBitSizeAndCapacity(e.state(), 8); err != nil {
267 return err
268 }
269 e.state().alignOffsetToBytes()
270 e.buf[e.state().offset] = value
271 e.state().skipBytes(1)
272 e.state().elementsProcessed++
273 return nil
274 }
275
276 // WriteInt16 writes an int16 value.
277 func (e *Encoder) WriteInt16(value int16) error {
278 return e.WriteUint16(uint16(value))
279 }
280
281 // WriteUint16 writes an uint16 value.
282 func (e *Encoder) WriteUint16(value uint16) error {
283 if err := ensureElementBitSizeAndCapacity(e.state(), 16); err != nil {
284 return err
285 }
286 e.state().alignOffsetToBytes()
287 e.state().offset = align(e.state().offset, 2)
288 binary.LittleEndian.PutUint16(e.buf[e.state().offset:], value)
289 e.state().skipBytes(2)
290 e.state().elementsProcessed++
291 return nil
292 }
293
294 // WriteInt32 writes an int32 value.
295 func (e *Encoder) WriteInt32(value int32) error {
296 return e.WriteUint32(uint32(value))
297 }
298
299 // WriteUint32 writes an uint32 value.
300 func (e *Encoder) WriteUint32(value uint32) error {
301 if err := ensureElementBitSizeAndCapacity(e.state(), 32); err != nil {
302 return err
303 }
304 e.state().alignOffsetToBytes()
305 e.state().offset = align(e.state().offset, 4)
306 binary.LittleEndian.PutUint32(e.buf[e.state().offset:], value)
307 e.state().skipBytes(4)
308 e.state().elementsProcessed++
309 return nil
310 }
311
312 // WriteInt64 writes an int64 value.
313 func (e *Encoder) WriteInt64(value int64) error {
314 return e.WriteUint64(uint64(value))
315 }
316
317 // WriteUint64 writes an uint64 value.
318 func (e *Encoder) WriteUint64(value uint64) error {
319 if err := ensureElementBitSizeAndCapacity(e.state(), 64); err != nil {
320 return err
321 }
322 e.state().alignOffsetToBytes()
323 e.state().offset = align(e.state().offset, 8)
324 binary.LittleEndian.PutUint64(e.buf[e.state().offset:], value)
325 e.state().skipBytes(8)
326 e.state().elementsProcessed++
327 return nil
328 }
329
330 // WriteFloat32 writes a float32 value.
331 func (e *Encoder) WriteFloat32(value float32) error {
332 return e.WriteUint32(math.Float32bits(value))
333 }
334
335 // WriteFloat64 writes a float64 value.
336 func (e *Encoder) WriteFloat64(value float64) error {
337 return e.WriteUint64(math.Float64bits(value))
338 }
339
340 // WriteNullUnion writes a null union.
341 func (e *Encoder) WriteNullUnion() error {
342 if err := e.WriteUint64(0); err != nil {
343 return err
344 }
345 e.state().elementsProcessed--
346 return e.WriteUint64(0)
347 }
348
349 // WriteNullPointer writes a null pointer.
350 func (e *Encoder) WriteNullPointer() error {
351 return e.WriteUint64(0)
352 }
353
354 // WriteString writes a string value. It doesn't write a pointer to the encoded
355 // string.
356 func (e *Encoder) WriteString(value string) error {
357 bytes := []byte(value)
358 e.StartArray(uint32(len(bytes)), 8)
359 for _, b := range bytes {
360 if err := e.WriteUint8(b); err != nil {
361 return err
362 }
363 }
364 return e.Finish()
365 }
366
367 // WritePointer writes a pointer to first unclaimed byte index.
368 func (e *Encoder) WritePointer() error {
369 e.state().alignOffsetToBytes()
370 e.state().offset = align(e.state().offset, 8)
371 return e.WriteUint64(uint64(e.end - e.state().offset))
372 }
373
374 // WriteInvalidHandle an invalid handle.
375 func (e *Encoder) WriteInvalidHandle() error {
376 return e.WriteInt32(-1)
377 }
378
379 // WriteHandle writes a handle and invalidates the passed handle object.
380 func (e *Encoder) WriteHandle(handle system.Handle) error {
381 if !handle.IsValid() {
382 return fmt.Errorf("can't write an invalid handle")
383 }
384 UntypedHandle := handle.ToUntypedHandle()
385 e.handles = append(e.handles, UntypedHandle)
386 return e.WriteUint32(uint32(len(e.handles) - 1))
387 }
388
389 // WriteInvalidInterface writes an invalid interface.
390 func (e *Encoder) WriteInvalidInterface() error {
391 if err := e.WriteInvalidHandle(); err != nil {
392 return err
393 }
394 e.state().elementsProcessed--
395 return e.WriteUint32(0)
396 }
397
398 // WriteInterface writes an interface and invalidates the passed handle object.
399 func (e *Encoder) WriteInterface(handle system.Handle) error {
400 if err := e.WriteHandle(handle); err != nil {
401 return err
402 }
403 e.state().elementsProcessed--
404 // Set the version field to 0 for now.
405 return e.WriteUint32(0)
406 }
407
408 // SortMapKeys will sort the slice pointed to by |slicePointer|
409 // if |slicePointer| is a pointer to a slice of a type that
410 // may be the key of a Mojo map. Otherwise SortMapKeys will do nothing.
411 func SortMapKeys(slicePointer interface{}) {
412 switch slicePointer := slicePointer.(type) {
413 case *[]bool:
414 sort.Sort(boolSlice(*slicePointer))
415 case *[]float32:
416 sort.Sort(float32Slice(*slicePointer))
417 case *[]float64:
418 sort.Float64s(*slicePointer)
419 case *[]int:
420 sort.Ints(*slicePointer)
421 case *[]int8:
422 sort.Sort(int8Slice(*slicePointer))
423 case *[]int16:
424 sort.Sort(int16Slice(*slicePointer))
425 case *[]int32:
426 sort.Sort(int32Slice(*slicePointer))
427 case *[]int64:
428 sort.Sort(int64Slice(*slicePointer))
429 case *[]string:
430 sort.Strings(*slicePointer)
431 case *[]uint8:
432 sort.Sort(uint8Slice(*slicePointer))
433 case *[]uint16:
434 sort.Sort(uint16Slice(*slicePointer))
435 case *[]uint32:
436 sort.Sort(uint32Slice(*slicePointer))
437 case *[]uint64:
438 sort.Sort(uint64Slice(*slicePointer))
439 default:
440 // Note(rudominer) Currently enums may not be used as map keys b ut
441 // that may change in the future in which case we should handle them
442 // here.
443 }
444 }
445
446 // boolSlice
447 type boolSlice []bool
448
449 func (s boolSlice) Len() int {
450 return len(s)
451 }
452
453 func (s boolSlice) Less(i, j int) bool {
454 return s[i] && !s[j]
455 }
456
457 func (s boolSlice) Swap(i, j int) {
458 s[i], s[j] = s[j], s[i]
459 }
460
461 // float32Slice
462 type float32Slice []float32
463
464 func (s float32Slice) Len() int {
465 return len(s)
466 }
467
468 func (s float32Slice) Less(i, j int) bool {
469 return s[i] < s[j]
470 }
471
472 func (s float32Slice) Swap(i, j int) {
473 s[i], s[j] = s[j], s[i]
474 }
475
476 // int8Slice
477 type int8Slice []int8
478
479 func (s int8Slice) Len() int {
480 return len(s)
481 }
482
483 func (s int8Slice) Less(i, j int) bool {
484 return s[i] < s[j]
485 }
486
487 func (s int8Slice) Swap(i, j int) {
488 s[i], s[j] = s[j], s[i]
489 }
490
491 // int16Slice
492 type int16Slice []int16
493
494 func (s int16Slice) Len() int {
495 return len(s)
496 }
497
498 func (s int16Slice) Less(i, j int) bool {
499 return s[i] < s[j]
500 }
501
502 func (s int16Slice) Swap(i, j int) {
503 s[i], s[j] = s[j], s[i]
504 }
505
506 // int32Slice
507 type int32Slice []int32
508
509 func (s int32Slice) Len() int {
510 return len(s)
511 }
512
513 func (s int32Slice) Less(i, j int) bool {
514 return s[i] < s[j]
515 }
516
517 func (s int32Slice) Swap(i, j int) {
518 s[i], s[j] = s[j], s[i]
519 }
520
521 // int64Slice
522 type int64Slice []int64
523
524 func (s int64Slice) Len() int {
525 return len(s)
526 }
527
528 func (s int64Slice) Less(i, j int) bool {
529 return s[i] < s[j]
530 }
531
532 func (s int64Slice) Swap(i, j int) {
533 s[i], s[j] = s[j], s[i]
534 }
535
536 // uint8Slice
537 type uint8Slice []uint8
538
539 func (s uint8Slice) Len() int {
540 return len(s)
541 }
542
543 func (s uint8Slice) Less(i, j int) bool {
544 return s[i] < s[j]
545 }
546
547 func (s uint8Slice) Swap(i, j int) {
548 s[i], s[j] = s[j], s[i]
549 }
550
551 // uint16Slice
552 type uint16Slice []uint16
553
554 func (s uint16Slice) Len() int {
555 return len(s)
556 }
557
558 func (s uint16Slice) Less(i, j int) bool {
559 return s[i] < s[j]
560 }
561
562 func (s uint16Slice) Swap(i, j int) {
563 s[i], s[j] = s[j], s[i]
564 }
565
566 // uint32Slice
567 type uint32Slice []uint32
568
569 func (s uint32Slice) Len() int {
570 return len(s)
571 }
572
573 func (s uint32Slice) Less(i, j int) bool {
574 return s[i] < s[j]
575 }
576
577 func (s uint32Slice) Swap(i, j int) {
578 s[i], s[j] = s[j], s[i]
579 }
580
581 // uint64Slice
582 type uint64Slice []uint64
583
584 func (s uint64Slice) Len() int {
585 return len(s)
586 }
587
588 func (s uint64Slice) Less(i, j int) bool {
589 return s[i] < s[j]
590 }
591
592 func (s uint64Slice) Swap(i, j int) {
593 s[i], s[j] = s[j], s[i]
594 }
OLDNEW
« no previous file with comments | « mojo/public/go/bindings/decoder.go ('k') | mojo/public/go/bindings/interface.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698