blob: d09160e027ca64182e6f3d6c593cb8f31950ee89 [file] [log] [blame]
package mojovdl
import (
"encoding/binary"
"v.io/v23/vdl"
)
// for struct
type fieldsTarget struct {
vdlType *vdl.Type
block bytesRef
}
func (fe fieldsTarget) StartField(name string) (key, field vdl.Target, _ error) {
fieldType, fieldIndex := fe.vdlType.FieldByName(name)
byteOffset, bitOffset := offsetInStruct(fieldIndex, fe.vdlType)
numBits := baseTypeSizeBits(fieldType.Type)
refSize := (numBits + 7) / 8
newRef := fe.block.Slice(byteOffset, byteOffset+refSize)
return nil, target{
currentBitOffset: bitOffset,
current: newRef,
}, nil
}
func (fieldsTarget) FinishField(key, field vdl.Target) error {
return nil
}
type unionFieldsTarget struct {
vdlType *vdl.Type
block bytesRef
}
func (ufe unionFieldsTarget) StartField(name string) (key, field vdl.Target, _ error) {
fld, index := ufe.vdlType.FieldByName(name)
binary.LittleEndian.PutUint32(ufe.block.Bytes(), 16)
binary.LittleEndian.PutUint32(ufe.block.Bytes()[4:], uint32(index))
valueSlice := ufe.block.Slice(8, 16)
if fld.Type.Kind() == vdl.Union {
// nested union, create a pointer to the body
nestedUnionBlock := ufe.block.allocator.Allocate(8, 0)
offset := nestedUnionBlock.AsPointer(valueSlice)
binary.LittleEndian.PutUint64(valueSlice.Bytes(), uint64(offset))
return nil, target{
currentBitOffset: 0,
current: nestedUnionBlock.SignedSlice(-8, 8),
}, nil
}
return nil, target{
currentBitOffset: 0,
current: valueSlice,
}, nil
}
func (unionFieldsTarget) FinishField(key, field vdl.Target) error {
return nil
}
// doubles as set target
type listTarget struct {
incrementSize uint32
block bytesRef
nextPosition uint32
}
func (lt *listTarget) StartElem(index int) (elem vdl.Target, _ error) {
// TODO(bprosnitz) Index is ignored -- we should probably remove this from Target.
sliceBlock := lt.block.Slice(lt.nextPosition, lt.nextPosition+lt.incrementSize)
lt.nextPosition += lt.incrementSize
return target{
current: sliceBlock,
}, nil
}
func (lt *listTarget) StartKey() (key vdl.Target, _ error) {
return lt.StartElem(0)
}
func (listTarget) FinishElem(elem vdl.Target) error {
return nil
}
func (listTarget) FinishKey(key vdl.Target) error {
return nil
}
type bitListTarget struct {
block bytesRef
nextBitPosition uint32
}
func (blt *bitListTarget) StartElem(index int) (elem vdl.Target, _ error) {
bitPos := blt.nextBitPosition
blt.nextBitPosition++
byteIndex := bitPos / 8
sliceBlock := blt.block.Slice(byteIndex, byteIndex+1)
return target{
currentBitOffset: uint8(bitPos % 8),
current: sliceBlock,
}, nil
}
func (blt *bitListTarget) StartKey() (key vdl.Target, _ error) {
return blt.StartElem(0)
}
func (bitListTarget) FinishElem(elem vdl.Target) error {
return nil
}
func (bitListTarget) FinishKey(key vdl.Target) error {
return nil
}
type mapTarget struct {
listTarget vdl.ListTarget
setTarget vdl.SetTarget
}
func (mt *mapTarget) StartKey() (key vdl.Target, _ error) {
return mt.setTarget.StartKey()
}
func (mt *mapTarget) FinishKeyStartField(key vdl.Target) (field vdl.Target, _ error) {
return mt.listTarget.StartElem(0)
}
func (mapTarget) FinishField(key, field vdl.Target) error {
return nil
}