// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Code generated by go generate; DO NOT EDIT.

package inspect

import (
	"fmt"
	"math"
	"unsafe"
)

// The BlockOrder type represents the order of an allocation returned by the buddy allocator.
type BlockOrder uint64

const (
{{- range $index, $value := .BlockOrders }}
	// Order{{- $index }} is a constant representing allocations of order {{ $index -}}.
	Order{{- $index }} {{ if eq $index 0 }}= BlockOrder(iota){{ end }}
{{ end }}
)

// nOrders contains the number of allocation orders.
const nOrders = uint({{ len .BlockOrders }})

var orderSize = []BlockOrder{ {{- range $index, $value := .BlockOrders }}{{ $value -}}, {{ end -}} }

// Size returns the usable size of an allocation for the given order.
func (o BlockOrder) Size() uint64 {
	return uint64(orderSize[o])
}

func (o BlockOrder) String() string {
	switch o {
{{- range $index, $value := .BlockOrders }}
	case Order{{- $index }}:
		return "{{ $index }} [{{ $value }} bytes]"
{{ end -}}
	}

	return "INVALID"
}

// The BlockType type represents the type of a block returned by the buddy allocator.
type BlockType uint64

const (
{{- range $index, $value := .BlockTypes }}
	{{- if ne $value.Name "Block" }}
	// {{ $value.Name -}}Type is the type value for blocks of type {{ $value.Name -}}.
	{{ $value.Name -}}Type {{ if eq $index 1 }}= BlockType(iota){{ end }}
	{{ end -}}
{{ end -}}
)

func (t BlockType) String() string {
	switch t {
{{- range $index, $value := .BlockTypes }}
	{{- if ne $value.Name "Block" }}
	case {{ $value.Name -}}Type:
		return "{{ $value.Name -}}Type"
	{{ end -}}
{{ end -}}
	}

	return "INVALID"
}

// Block is an opaque type representing any region returned by the buddy allocator.
type Block struct {
	header  uint64
	payload uint64
}

{{ range $bti, $bt := .BlockTypes }}
// As{{- $bt.Name }} converts the Block to a {{ $bt.Name -}}.
func (b *Block) As{{- $bt.Name }}() *{{- $bt.Name}} {
	return (*{{- $bt.Name }})(unsafe.Pointer(b))
}
{{ end }}

func (b *Block) zeroPayload(size uint64, off uintptr) {
	p := uintptr(unsafe.Pointer(&b.payload)) + off
	for i := uint64(0); i < size; i++ {
		*(*byte)(unsafe.Pointer(p+uintptr(i))) = 0
	}
}

func (b *Block) Free(order BlockOrder, nextFree BlockIndex) {
	b.header = (uint64(order) & 0xf) | ((uint64(nextFree)&0xfffffff)<<8)
}

func (b Block) String() string {
	return fmt.Sprintf("Header: %x, Payload: %x, Type: %s, Order: %s\n", b.header, b.payload, b.GetType(), b.GetOrder())
}

{{ range $bti, $bt := .BlockTypes }}
	{{ if ne $bt.Name "Block" }}
// The {{ $bt.Name }} type represents a block of type {{ $bt.Name -}}.
type {{ $bt.Name }} Block
	{{ end }}

// SetHeader sets the header fields for {{ $bt.Name -}}.
func (b *{{- $bt.Name }}) SetHeader({{- range $hi, $hf := $bt.AllHeaders -}}{{ if ne $hi 0 }}, {{ end -}}{{ $hf.Name }} {{ $hf.Type }}{{- end -}}) {
	b.header = uint64({{ range $hi, $hf := $bt.AllHeaders -}}{{ if ne $hi 0 }} | {{ end }}((uint64({{ $hf.Name }}) << {{ $hf.BitStart }}) & {{ $hf.Mask }}){{ end }})
}

	{{ range $hi, $hf := $bt.AllHeaders }}
// Get{{- $hf.Name }} returns the {{ $hf.Name }} field in the {{ $bt.Name -}}.
func (b *{{- $bt.Name }}) Get{{- $hf.Name }}() {{ $hf.Type }} {
	return {{ $hf.Type }}((b.header & {{ $hf.Mask }}) >> {{ $hf.BitStart }})
}

// Set{{- $hf.Name }} sets the {{ $hf.Name }} field in the {{ $bt.Name -}}.
		{{- if eq $hf.Name "Type" }}
func (b *{{- $bt.Name }}) Set{{- $hf.Name }}(v BlockType) {
		{{ else if eq $hf.Name "Order" }}
func (b *{{- $bt.Name }}) Set{{- $hf.Name }}(v BlockOrder) {
		{{ else }}
func (b *{{- $bt.Name }}) Set{{- $hf.Name }}(v {{ $hf.Type -}}) {
		{{ end -}}
	mask := uint64({{- $hf.Mask -}})
	b.header &= ^mask
	b.header |= ((uint64(v)<<{{ $hf.BitStart }})&mask)
}
	{{ end }}

	{{ range $hi, $hf := $bt.PayloadFields }}
// Get{{- $hf.Name }} returns the {{ $hf.Name }} field in the {{ $bt.Name -}}.
func (b *{{- $bt.Name }}) Get{{- $hf.Name }}() {{ $hf.Type }} {
		{{- if eq $hf.Type "float64" }}
	return math.Float64frombits(((b.payload & {{ $hf.Mask }}) >> {{ $hf.BitStart }}))
		{{ else }}
	return {{ $hf.Type }}((b.payload & {{ $hf.Mask }}) >> {{ $hf.BitStart }})
		{{ end -}}
}

// Set{{- $hf.Name }} sets the {{ $hf.Name }} field in the {{ $bt.Name -}}.
		{{- if eq $hf.Type "float64" }}
func (b *{{- $bt.Name }}) Set{{- $hf.Name }}(f {{ $hf.Type -}}) {
	v := math.Float64bits(f)
		{{ else }}
func (b *{{- $bt.Name }}) Set{{- $hf.Name }}(v {{ $hf.Type -}}) {
		{{ end -}}
	mask := uint64({{ $hf.Mask }})
	b.payload &= ^mask
	b.payload |= ((uint64(v)<<{{ $hf.BitStart }})&mask)
}
	{{ end }}

	{{ if ne $bt.PayloadOffset 0 }}
func (b *{{- $bt.Name }}) SetPayload(data []byte) {
	p := uintptr(unsafe.Pointer(b)) + {{ $bt.PayloadOffset }}
	for i, v := range data {
		*(*byte)(unsafe.Pointer(p + uintptr(i))) = v
	}
}
	{{ end }}
{{ end }}
