// Copyright 2020 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 fuzz

import (
	
	
	
	
)

type mutator struct {
	r       mutatorRand
	scratch []byte // scratch slice to avoid additional allocations
}

func newMutator() *mutator {
	return &mutator{r: newPcgRand()}
}

func ( *mutator) ( int) int {
	return .r.intn()
}

func ( *mutator) () binary.ByteOrder {
	if .r.bool() {
		return binary.LittleEndian
	}
	return binary.BigEndian
}

// chooseLen chooses length of range mutation in range [1,n]. It gives
// preference to shorter ranges.
func ( *mutator) ( int) int {
	switch  := .rand(100); {
	case  < 90:
		return .rand(min(8, )) + 1
	case  < 99:
		return .rand(min(32, )) + 1
	default:
		return .rand() + 1
	}
}

// mutate performs several mutations on the provided values.
func ( *mutator) ( []any,  int) {
	// TODO(katiehockman): pull some of these functions into helper methods and
	// test that each case is working as expected.
	// TODO(katiehockman): perform more types of mutations for []byte.

	// maxPerVal will represent the maximum number of bytes that each value be
	// allowed after mutating, giving an equal amount of capacity to each line.
	// Allow a little wiggle room for the encoding.
	 := /len() - 100

	// Pick a random value to mutate.
	// TODO: consider mutating more than one value at a time.
	 := .rand(len())
	switch v := [].(type) {
	case int:
		[] = int(.mutateInt(int64(), maxInt))
	case int8:
		[] = int8(.mutateInt(int64(), math.MaxInt8))
	case int16:
		[] = int16(.mutateInt(int64(), math.MaxInt16))
	case int64:
		[] = .mutateInt(, maxInt)
	case uint:
		[] = uint(.mutateUInt(uint64(), maxUint))
	case uint16:
		[] = uint16(.mutateUInt(uint64(), math.MaxUint16))
	case uint32:
		[] = uint32(.mutateUInt(uint64(), math.MaxUint32))
	case uint64:
		[] = .mutateUInt(, maxUint)
	case float32:
		[] = float32(.mutateFloat(float64(), math.MaxFloat32))
	case float64:
		[] = .mutateFloat(, math.MaxFloat64)
	case bool:
		if .rand(2) == 1 {
			[] = ! // 50% chance of flipping the bool
		}
	case rune: // int32
		[] = rune(.mutateInt(int64(), math.MaxInt32))
	case byte: // uint8
		[] = byte(.mutateUInt(uint64(), math.MaxUint8))
	case string:
		if len() >  {
			panic(fmt.Sprintf("cannot mutate bytes of length %d", len()))
		}
		if cap(.scratch) <  {
			.scratch = append(make([]byte, 0, ), ...)
		} else {
			.scratch = .scratch[:len()]
			copy(.scratch, )
		}
		.mutateBytes(&.scratch)
		[] = string(.scratch)
	case []byte:
		if len() >  {
			panic(fmt.Sprintf("cannot mutate bytes of length %d", len()))
		}
		if cap(.scratch) <  {
			.scratch = append(make([]byte, 0, ), ...)
		} else {
			.scratch = .scratch[:len()]
			copy(.scratch, )
		}
		.mutateBytes(&.scratch)
		[] = .scratch
	default:
		panic(fmt.Sprintf("type not supported for mutating: %T", []))
	}
}

func ( *mutator) (,  int64) int64 {
	var  int64
	for {
		 = 100
		switch .rand(2) {
		case 0:
			// Add a random number
			if  >=  {
				continue
			}
			if  > 0 && - <  {
				// Don't let v exceed maxValue
				 =  - 
			}
			 += int64(1 + .rand(int()))
			return 
		case 1:
			// Subtract a random number
			if  <= - {
				continue
			}
			if  < 0 && + <  {
				// Don't let v drop below -maxValue
				 =  + 
			}
			 -= int64(1 + .rand(int()))
			return 
		}
	}
}

func ( *mutator) (,  uint64) uint64 {
	var  uint64
	for {
		 = 100
		switch .rand(2) {
		case 0:
			// Add a random number
			if  >=  {
				continue
			}
			if  > 0 && - <  {
				// Don't let v exceed maxValue
				 =  - 
			}

			 += uint64(1 + .rand(int()))
			return 
		case 1:
			// Subtract a random number
			if  <= 0 {
				continue
			}
			if  <  {
				// Don't let v drop below 0
				 = 
			}
			 -= uint64(1 + .rand(int()))
			return 
		}
	}
}

func ( *mutator) (,  float64) float64 {
	var  float64
	for {
		switch .rand(4) {
		case 0:
			// Add a random number
			if  >=  {
				continue
			}
			 = 100
			if  > 0 && - <  {
				// Don't let v exceed maxValue
				 =  - 
			}
			 += float64(1 + .rand(int()))
			return 
		case 1:
			// Subtract a random number
			if  <= - {
				continue
			}
			 = 100
			if  < 0 && + <  {
				// Don't let v drop below -maxValue
				 =  + 
			}
			 -= float64(1 + .rand(int()))
			return 
		case 2:
			// Multiply by a random number
			 := math.Abs()
			if  == 0 ||  >=  {
				continue
			}
			 = 10
			if / <  {
				// Don't let v go beyond the minimum or maximum value
				 =  / 
			}
			 *= float64(1 + .rand(int()))
			return 
		case 3:
			// Divide by a random number
			if  == 0 {
				continue
			}
			 /= float64(1 + .rand(10))
			return 
		}
	}
}

type byteSliceMutator func(*mutator, []byte) []byte

var byteSliceMutators = []byteSliceMutator{
	byteSliceRemoveBytes,
	byteSliceInsertRandomBytes,
	byteSliceDuplicateBytes,
	byteSliceOverwriteBytes,
	byteSliceBitFlip,
	byteSliceXORByte,
	byteSliceSwapByte,
	byteSliceArithmeticUint8,
	byteSliceArithmeticUint16,
	byteSliceArithmeticUint32,
	byteSliceArithmeticUint64,
	byteSliceOverwriteInterestingUint8,
	byteSliceOverwriteInterestingUint16,
	byteSliceOverwriteInterestingUint32,
	byteSliceInsertConstantBytes,
	byteSliceOverwriteConstantBytes,
	byteSliceShuffleBytes,
	byteSliceSwapBytes,
}

func ( *mutator) ( *[]byte) {
	 := *
	defer func() {
		if unsafe.SliceData(*) != unsafe.SliceData() {
			panic("data moved to new address")
		}
		* = 
	}()

	for {
		 := byteSliceMutators[.rand(len(byteSliceMutators))]
		if  := (, );  != nil {
			 = 
			return
		}
	}
}

var (
	interesting8  = []int8{-128, -1, 0, 1, 16, 32, 64, 100, 127}
	interesting16 = []int16{-32768, -129, 128, 255, 256, 512, 1000, 1024, 4096, 32767}
	interesting32 = []int32{-2147483648, -100663046, -32769, 32768, 65535, 65536, 100663045, 2147483647}
)

const (
	maxUint = uint64(^uint(0))
	maxInt  = int64(maxUint >> 1)
)

func init() {
	for ,  := range interesting8 {
		interesting16 = append(interesting16, int16())
	}
	for ,  := range interesting16 {
		interesting32 = append(interesting32, int32())
	}
}