package websocket

import (
	
	
)

// maskGo applies the WebSocket masking algorithm to p
// with the given key.
// See https://tools.ietf.org/html/rfc6455#section-5.3
//
// The returned value is the correctly rotated key to
// to continue to mask/unmask the message.
//
// It is optimized for LittleEndian and expects the key
// to be in little endian.
//
// See https://github.com/golang/go/issues/31586
func maskGo( []byte,  uint32) uint32 {
	if len() >= 8 {
		 := uint64()<<32 | uint64()

		// At some point in the future we can clean these unrolled loops up.
		// See https://github.com/golang/go/issues/31586#issuecomment-487436401

		// Then we xor until b is less than 128 bytes.
		for len() >= 128 {
			 := binary.LittleEndian.Uint64()
			binary.LittleEndian.PutUint64(, ^)
			 = binary.LittleEndian.Uint64([8:16])
			binary.LittleEndian.PutUint64([8:16], ^)
			 = binary.LittleEndian.Uint64([16:24])
			binary.LittleEndian.PutUint64([16:24], ^)
			 = binary.LittleEndian.Uint64([24:32])
			binary.LittleEndian.PutUint64([24:32], ^)
			 = binary.LittleEndian.Uint64([32:40])
			binary.LittleEndian.PutUint64([32:40], ^)
			 = binary.LittleEndian.Uint64([40:48])
			binary.LittleEndian.PutUint64([40:48], ^)
			 = binary.LittleEndian.Uint64([48:56])
			binary.LittleEndian.PutUint64([48:56], ^)
			 = binary.LittleEndian.Uint64([56:64])
			binary.LittleEndian.PutUint64([56:64], ^)
			 = binary.LittleEndian.Uint64([64:72])
			binary.LittleEndian.PutUint64([64:72], ^)
			 = binary.LittleEndian.Uint64([72:80])
			binary.LittleEndian.PutUint64([72:80], ^)
			 = binary.LittleEndian.Uint64([80:88])
			binary.LittleEndian.PutUint64([80:88], ^)
			 = binary.LittleEndian.Uint64([88:96])
			binary.LittleEndian.PutUint64([88:96], ^)
			 = binary.LittleEndian.Uint64([96:104])
			binary.LittleEndian.PutUint64([96:104], ^)
			 = binary.LittleEndian.Uint64([104:112])
			binary.LittleEndian.PutUint64([104:112], ^)
			 = binary.LittleEndian.Uint64([112:120])
			binary.LittleEndian.PutUint64([112:120], ^)
			 = binary.LittleEndian.Uint64([120:128])
			binary.LittleEndian.PutUint64([120:128], ^)
			 = [128:]
		}

		// Then we xor until b is less than 64 bytes.
		for len() >= 64 {
			 := binary.LittleEndian.Uint64()
			binary.LittleEndian.PutUint64(, ^)
			 = binary.LittleEndian.Uint64([8:16])
			binary.LittleEndian.PutUint64([8:16], ^)
			 = binary.LittleEndian.Uint64([16:24])
			binary.LittleEndian.PutUint64([16:24], ^)
			 = binary.LittleEndian.Uint64([24:32])
			binary.LittleEndian.PutUint64([24:32], ^)
			 = binary.LittleEndian.Uint64([32:40])
			binary.LittleEndian.PutUint64([32:40], ^)
			 = binary.LittleEndian.Uint64([40:48])
			binary.LittleEndian.PutUint64([40:48], ^)
			 = binary.LittleEndian.Uint64([48:56])
			binary.LittleEndian.PutUint64([48:56], ^)
			 = binary.LittleEndian.Uint64([56:64])
			binary.LittleEndian.PutUint64([56:64], ^)
			 = [64:]
		}

		// Then we xor until b is less than 32 bytes.
		for len() >= 32 {
			 := binary.LittleEndian.Uint64()
			binary.LittleEndian.PutUint64(, ^)
			 = binary.LittleEndian.Uint64([8:16])
			binary.LittleEndian.PutUint64([8:16], ^)
			 = binary.LittleEndian.Uint64([16:24])
			binary.LittleEndian.PutUint64([16:24], ^)
			 = binary.LittleEndian.Uint64([24:32])
			binary.LittleEndian.PutUint64([24:32], ^)
			 = [32:]
		}

		// Then we xor until b is less than 16 bytes.
		for len() >= 16 {
			 := binary.LittleEndian.Uint64()
			binary.LittleEndian.PutUint64(, ^)
			 = binary.LittleEndian.Uint64([8:16])
			binary.LittleEndian.PutUint64([8:16], ^)
			 = [16:]
		}

		// Then we xor until b is less than 8 bytes.
		for len() >= 8 {
			 := binary.LittleEndian.Uint64()
			binary.LittleEndian.PutUint64(, ^)
			 = [8:]
		}
	}

	// Then we xor until b is less than 4 bytes.
	for len() >= 4 {
		 := binary.LittleEndian.Uint32()
		binary.LittleEndian.PutUint32(, ^)
		 = [4:]
	}

	// xor remaining bytes.
	for  := range  {
		[] ^= byte()
		 = bits.RotateLeft32(, -8)
	}

	return 
}