// Copyright 2022 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.

package benchmarks

// Handlers for benchmarking.

import (
	
	
	
	
	
	
	
)

// A fastTextHandler writes a Record to an io.Writer in a format similar to
// slog.TextHandler, but without quoting or locking. It has a few other
// performance-motivated shortcuts, like writing times as seconds since the
// epoch instead of strings.
//
// It is intended to represent a high-performance Handler that synchronously
// writes text (as opposed to binary).
type fastTextHandler struct {
	w io.Writer
}

func newFastTextHandler( io.Writer) slog.Handler {
	return &fastTextHandler{w: }
}

func ( *fastTextHandler) (context.Context, slog.Level) bool { return true }

func ( *fastTextHandler) ( context.Context,  slog.Record) error {
	 := buffer.New()
	defer .Free()

	if !.Time.IsZero() {
		.WriteString("time=")
		.appendTime(, .Time)
		.WriteByte(' ')
	}
	.WriteString("level=")
	* = strconv.AppendInt(*, int64(.Level), 10)
	.WriteByte(' ')
	.WriteString("msg=")
	.WriteString(.Message)
	.Attrs(func( slog.Attr) bool {
		.WriteByte(' ')
		.WriteString(.Key)
		.WriteByte('=')
		.appendValue(, .Value)
		return true
	})
	.WriteByte('\n')
	,  := .w.Write(*)
	return 
}

func ( *fastTextHandler) ( *buffer.Buffer,  slog.Value) {
	switch .Kind() {
	case slog.KindString:
		.WriteString(.String())
	case slog.KindInt64:
		* = strconv.AppendInt(*, .Int64(), 10)
	case slog.KindUint64:
		* = strconv.AppendUint(*, .Uint64(), 10)
	case slog.KindFloat64:
		* = strconv.AppendFloat(*, .Float64(), 'g', -1, 64)
	case slog.KindBool:
		* = strconv.AppendBool(*, .Bool())
	case slog.KindDuration:
		* = strconv.AppendInt(*, .Duration().Nanoseconds(), 10)
	case slog.KindTime:
		.appendTime(, .Time())
	case slog.KindAny:
		 := .Any()
		switch a := .(type) {
		case error:
			.WriteString(.Error())
		default:
			fmt.Fprint(, )
		}
	default:
		panic(fmt.Sprintf("bad kind: %s", .Kind()))
	}
}

func ( *fastTextHandler) ( *buffer.Buffer,  time.Time) {
	* = strconv.AppendInt(*, .Unix(), 10)
}

func ( *fastTextHandler) ([]slog.Attr) slog.Handler {
	panic("fastTextHandler: With unimplemented")
}

func (*fastTextHandler) (string) slog.Handler {
	panic("fastTextHandler: WithGroup unimplemented")
}

// An asyncHandler simulates a Handler that passes Records to a
// background goroutine for processing.
// Because sending to a channel can be expensive due to locking,
// we simulate a lock-free queue by adding the Record to a ring buffer.
// Omitting the locking makes this little more than a copy of the Record,
// but that is a worthwhile thing to measure because Records are on the large
// side. Since nothing actually reads from the ring buffer, it can handle an
// arbitrary number of Records without either blocking or allocation.
type asyncHandler struct {
	ringBuffer [100]slog.Record
	next       int
}

func newAsyncHandler() *asyncHandler {
	return &asyncHandler{}
}

func (*asyncHandler) (context.Context, slog.Level) bool { return true }

func ( *asyncHandler) ( context.Context,  slog.Record) error {
	.ringBuffer[.next] = .Clone()
	.next = (.next + 1) % len(.ringBuffer)
	return nil
}

func (*asyncHandler) ([]slog.Attr) slog.Handler {
	panic("asyncHandler: With unimplemented")
}

func (*asyncHandler) (string) slog.Handler {
	panic("asyncHandler: WithGroup unimplemented")
}

// A disabledHandler's Enabled method always returns false.
type disabledHandler struct{}

func (disabledHandler) (context.Context, slog.Level) bool  { return false }
func (disabledHandler) (context.Context, slog.Record) error { panic("should not be called") }

func (disabledHandler) ([]slog.Attr) slog.Handler {
	panic("disabledHandler: With unimplemented")
}

func (disabledHandler) (string) slog.Handler {
	panic("disabledHandler: WithGroup unimplemented")
}