// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This benchmark tests JSON encoding and decoding performance.

package go1

import (
	"bytes"
	"compress/bzip2"
	"encoding/base64"
	"encoding/json"
	"io"
	"testing"
)

var (
	jsonbytes = makeJsonBytes()
	jsondata  = makeJsonData()
)

func makeJsonBytes() []byte {
	var r io.Reader
	r = bytes.NewReader(bytes.Replace(jsonbz2_base64, []byte{'\n'}, nil, -1))
	r = base64.NewDecoder(base64.StdEncoding, r)
	r = bzip2.NewReader(r)
	b, err := io.ReadAll(r)
	if err != nil {
		panic(err)
	}
	return b
}

func makeJsonData() JSONResponse {
	var v JSONResponse
	if err := json.Unmarshal(jsonbytes, &v); err != nil {
		panic(err)
	}
	return v
}

type JSONResponse struct {
	Tree     *JSONNode `json:"tree"`
	Username string    `json:"username"`
}

type JSONNode struct {
	Name     string      `json:"name"`
	Kids     []*JSONNode `json:"kids"`
	CLWeight float64     `json:"cl_weight"`
	Touches  int         `json:"touches"`
	MinT     int64       `json:"min_t"`
	MaxT     int64       `json:"max_t"`
	MeanT    int64       `json:"mean_t"`
}

func jsondec() {
	var r JSONResponse
	if err := json.Unmarshal(jsonbytes, &r); err != nil {
		panic(err)
	}
	_ = r
}

func jsonenc() {
	buf, err := json.Marshal(&jsondata)
	if err != nil {
		panic(err)
	}
	_ = buf
}

func BenchmarkJSONEncode(b *testing.B) {
	b.SetBytes(int64(len(jsonbytes)))
	for i := 0; i < b.N; i++ {
		jsonenc()
	}
}

func BenchmarkJSONDecode(b *testing.B) {
	b.SetBytes(int64(len(jsonbytes)))
	for i := 0; i < b.N; i++ {
		jsondec()
	}
}
