package main

import (
	"crypto/rand"
	"log"
	"math"
	"math/big"
	"os"
	"text/template"
)

var Template = template.Must(template.New("hash_value").Parse(
	"// Generated by `go run scripts/generate_transformation.go`" + `

use num_traits::{PrimInt, Unsigned};

pub trait HashValue: Unsigned + PrimInt {
    const TRANSFORMATION: [Self; 256];
}

impl HashValue for u32 {
    const TRANSFORMATION: [Self; 256] = [
	{{ range .U32 }}
		{{ printf "0x%0.8x," . }}
	{{- end }}
	];
}

impl HashValue for u64 {
    const TRANSFORMATION: [Self; 256] = [
	{{ range .U64 }}
		{{ printf "0x%0.16x," . }}
	{{- end }}
	];
}
`))

type RandValues struct {
	U32 []uint32
	U64 []uint64
}

func main() {
	randValues := RandValues{
		U32: make([]uint32, 256),
		U64: make([]uint64, 256),
	}
	var max big.Int
	max.SetUint64(math.MaxUint64)
	for i := 0; i < 256; i++ {
		bigRand, err := rand.Int(rand.Reader, &max)
		if err != nil {
			log.Fatal("Cannot calculate uint64 random number", err)
		}
		as64bit := bigRand.Uint64()
		as32bit := uint32(as64bit & math.MaxUint32)
		randValues.U32[i] = as32bit
		randValues.U64[i] = as64bit
	}
	Template.ExecuteTemplate(os.Stdout, "hash_value", randValues)
}
