blob: f21489daed0d8bf749106b1fd20b0bfc5ed23604 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package transcoder
import (
"fmt"
"v.io/v23/vdl"
)
// an array where the index corresponds to the bit index in the allocation
// and the value is the tag (here representing vdlIndex+1)
type structBitAllocation []int
// allocateStructBits performs the naive allocation of fields in the struct,
// literally laying out all bits in an array - each associated with a tag
// and finding the first spot where a block of the given size fits (given
// alignment constraints)
func allocateStructBits(a structBitAllocation, tag, size int) structBitAllocation {
lenActive := 0
// Scan the given array for a run of |size| empty locations.
// If found, fill that section with tag.
for i, v := range a {
if v == 0 {
lenActive++
} else {
lenActive = 0
}
if i%size == size-1 && lenActive >= size {
for j := i - size + 1; j <= i; j++ {
a[j] = tag
}
return a
}
}
// If there isn't a sufficiently large empty location, allocate a new aligned block.
paddingAmt := size - len(a)%size
if paddingAmt == size {
paddingAmt = 0
}
for i := 0; i < paddingAmt; i++ {
a = append(a, 0)
}
// Now len(a) % size == 0
for i := 0; i < size; i++ {
a = append(a, tag)
}
return a
}
type structLayoutField struct {
vdlStructIndex int // the index in the vdl value of this field
byteOffset uint32 // byte offset from the beginning of the mojom byte array
bitOffset uint8 // bit offset [0,8)
}
// computeStructLayout computes a representation of the fields in a struct, as
// a list ordered by mojom byte field order.
func computeStructLayout(t *vdl.Type) (layout structLayout) {
a := structBitAllocation{}
for i := 0; i < t.NumField(); i++ {
bits := baseTypeSizeBits(t.Field(i).Type)
a = allocateStructBits(a, i+1, int(bits))
}
lastVal := 0
for i, v := range a {
if v != lastVal && v != 0 {
layout = append(layout, structLayoutField{
vdlStructIndex: v - 1,
byteOffset: uint32(i / 8),
bitOffset: uint8(i % 8),
})
lastVal = v
}
}
return
}
type structLayout []structLayoutField
func (s structLayout) MojoOffsetsFromVdlIndex(vdlIndex int) (byteOffset uint32, bitOffset uint8) {
for _, alloc := range s {
if alloc.vdlStructIndex == vdlIndex {
return alloc.byteOffset, alloc.bitOffset
}
}
panic(fmt.Sprintf("unknown vdl index %d (layout %v) -- this should never happen", vdlIndex, s))
}