// Copyright 2021 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

// byteSliceRemoveBytes removes a random chunk of bytes from b.
func byteSliceRemoveBytes( *mutator,  []byte) []byte {
	if len() <= 1 {
		return nil
	}
	 := .rand(len())
	 :=  + .chooseLen(len()-)
	copy([:], [:])
	 = [:len()-(-)]
	return 
}

// byteSliceInsertRandomBytes inserts a chunk of random bytes into b at a random
// position.
func byteSliceInsertRandomBytes( *mutator,  []byte) []byte {
	 := .rand(len() + 1)
	 := .chooseLen(1024)
	if len()+ >= cap() {
		return nil
	}
	 = [:len()+]
	copy([+:], [:])
	for  := 0;  < ; ++ {
		[+] = byte(.rand(256))
	}
	return 
}

// byteSliceDuplicateBytes duplicates a chunk of bytes in b and inserts it into
// a random position.
func byteSliceDuplicateBytes( *mutator,  []byte) []byte {
	if len() <= 1 {
		return nil
	}
	 := .rand(len())
	 := .rand(len())
	for  ==  {
		 = .rand(len())
	}
	 := .chooseLen(len() - )
	// Use the end of the slice as scratch space to avoid doing an
	// allocation. If the slice is too small abort and try something
	// else.
	if len()+(*2) >= cap() {
		return nil
	}
	 := len()
	// Increase the size of b to fit the duplicated block as well as
	// some extra working space
	 = [:+(*2)]
	// Copy the block of bytes we want to duplicate to the end of the
	// slice
	copy([+:], [:+])
	// Shift the bytes after the splice point n positions to the right
	// to make room for the new block
	copy([+:+], [:])
	// Insert the duplicate block into the splice point
	copy([:], [+:])
	 = [:+]
	return 
}

// byteSliceOverwriteBytes overwrites a chunk of b with another chunk of b.
func byteSliceOverwriteBytes( *mutator,  []byte) []byte {
	if len() <= 1 {
		return nil
	}
	 := .rand(len())
	 := .rand(len())
	for  ==  {
		 = .rand(len())
	}
	 := .chooseLen(len() -  - 1)
	copy([:], [:+])
	return 
}

// byteSliceBitFlip flips a random bit in a random byte in b.
func byteSliceBitFlip( *mutator,  []byte) []byte {
	if len() == 0 {
		return nil
	}
	 := .rand(len())
	[] ^= 1 << uint(.rand(8))
	return 
}

// byteSliceXORByte XORs a random byte in b with a random value.
func byteSliceXORByte( *mutator,  []byte) []byte {
	if len() == 0 {
		return nil
	}
	 := .rand(len())
	// In order to avoid a no-op (where the random value matches
	// the existing value), use XOR instead of just setting to
	// the random value.
	[] ^= byte(1 + .rand(255))
	return 
}

// byteSliceSwapByte swaps two random bytes in b.
func byteSliceSwapByte( *mutator,  []byte) []byte {
	if len() <= 1 {
		return nil
	}
	 := .rand(len())
	 := .rand(len())
	for  ==  {
		 = .rand(len())
	}
	[], [] = [], []
	return 
}

// byteSliceArithmeticUint8 adds/subtracts from a random byte in b.
func byteSliceArithmeticUint8( *mutator,  []byte) []byte {
	if len() == 0 {
		return nil
	}
	 := .rand(len())
	 := byte(.rand(35) + 1)
	if .r.bool() {
		[] += 
	} else {
		[] -= 
	}
	return 
}

// byteSliceArithmeticUint16 adds/subtracts from a random uint16 in b.
func byteSliceArithmeticUint16( *mutator,  []byte) []byte {
	if len() < 2 {
		return nil
	}
	 := uint16(.rand(35) + 1)
	if .r.bool() {
		 = 0 - 
	}
	 := .rand(len() - 1)
	 := .randByteOrder()
	.PutUint16([:], .Uint16([:])+)
	return 
}

// byteSliceArithmeticUint32 adds/subtracts from a random uint32 in b.
func byteSliceArithmeticUint32( *mutator,  []byte) []byte {
	if len() < 4 {
		return nil
	}
	 := uint32(.rand(35) + 1)
	if .r.bool() {
		 = 0 - 
	}
	 := .rand(len() - 3)
	 := .randByteOrder()
	.PutUint32([:], .Uint32([:])+)
	return 
}

// byteSliceArithmeticUint64 adds/subtracts from a random uint64 in b.
func byteSliceArithmeticUint64( *mutator,  []byte) []byte {
	if len() < 8 {
		return nil
	}
	 := uint64(.rand(35) + 1)
	if .r.bool() {
		 = 0 - 
	}
	 := .rand(len() - 7)
	 := .randByteOrder()
	.PutUint64([:], .Uint64([:])+)
	return 
}

// byteSliceOverwriteInterestingUint8 overwrites a random byte in b with an interesting
// value.
func byteSliceOverwriteInterestingUint8( *mutator,  []byte) []byte {
	if len() == 0 {
		return nil
	}
	 := .rand(len())
	[] = byte(interesting8[.rand(len(interesting8))])
	return 
}

// byteSliceOverwriteInterestingUint16 overwrites a random uint16 in b with an interesting
// value.
func byteSliceOverwriteInterestingUint16( *mutator,  []byte) []byte {
	if len() < 2 {
		return nil
	}
	 := .rand(len() - 1)
	 := uint16(interesting16[.rand(len(interesting16))])
	.randByteOrder().PutUint16([:], )
	return 
}

// byteSliceOverwriteInterestingUint32 overwrites a random uint16 in b with an interesting
// value.
func byteSliceOverwriteInterestingUint32( *mutator,  []byte) []byte {
	if len() < 4 {
		return nil
	}
	 := .rand(len() - 3)
	 := uint32(interesting32[.rand(len(interesting32))])
	.randByteOrder().PutUint32([:], )
	return 
}

// byteSliceInsertConstantBytes inserts a chunk of constant bytes into a random position in b.
func byteSliceInsertConstantBytes( *mutator,  []byte) []byte {
	if len() <= 1 {
		return nil
	}
	 := .rand(len())
	// TODO(rolandshoemaker,katiehockman): 4096 was mainly picked
	// randomly. We may want to either pick a much larger value
	// (AFL uses 32768, paired with a similar impl to chooseLen
	// which biases towards smaller lengths that grow over time),
	// or set the max based on characteristics of the corpus
	// (libFuzzer sets a min/max based on the min/max size of
	// entries in the corpus and then picks uniformly from
	// that range).
	 := .chooseLen(4096)
	if len()+ >= cap() {
		return nil
	}
	 = [:len()+]
	copy([+:], [:])
	 := byte(.rand(256))
	for  := ;  < +; ++ {
		[] = 
	}
	return 
}

// byteSliceOverwriteConstantBytes overwrites a chunk of b with constant bytes.
func byteSliceOverwriteConstantBytes( *mutator,  []byte) []byte {
	if len() <= 1 {
		return nil
	}
	 := .rand(len())
	 := .chooseLen(len() - )
	 := byte(.rand(256))
	for  := ;  < +; ++ {
		[] = 
	}
	return 
}

// byteSliceShuffleBytes shuffles a chunk of bytes in b.
func byteSliceShuffleBytes( *mutator,  []byte) []byte {
	if len() <= 1 {
		return nil
	}
	 := .rand(len())
	 := .chooseLen(len() - )
	if  <= 2 {
		return nil
	}
	// Start at the end of the range, and iterate backwards
	// to dst, swapping each element with another element in
	// dst:dst+n (Fisher-Yates shuffle).
	for  :=  - 1;  > 0; -- {
		 := .rand( + 1)
		[+], [+] = [+], [+]
	}
	return 
}

// byteSliceSwapBytes swaps two chunks of bytes in b.
func byteSliceSwapBytes( *mutator,  []byte) []byte {
	if len() <= 1 {
		return nil
	}
	 := .rand(len())
	 := .rand(len())
	for  ==  {
		 = .rand(len())
	}
	// Choose the random length as len(b) - max(src, dst)
	// so that we don't attempt to swap a chunk that extends
	// beyond the end of the slice
	 := 
	if  >  {
		 = 
	}
	 := .chooseLen(len() -  - 1)
	// Check that neither chunk intersect, so that we don't end up
	// duplicating parts of the input, rather than swapping them
	if  >  && + >=  ||  >  && + >=  {
		return nil
	}
	// Use the end of the slice as scratch space to avoid doing an
	// allocation. If the slice is too small abort and try something
	// else.
	if len()+ >= cap() {
		return nil
	}
	 := len()
	 = [:+]
	copy([:], [:+])
	copy([:], [:+])
	copy([:], [:])
	 = [:]
	return 
}