package salsa20

import (
	
	

	
)

const BlockSize = 64

type salsaCipher struct {
	key     *[32]byte
	nonce   [8]byte
	x       [BlockSize]byte
	nx      int
	counter uint64
}

func ( *[32]byte,  []byte) cipher.Stream {
	 := new(salsaCipher)

	if len() == 24 {
		var  [32]byte
		var  [16]byte
		copy([:], [:16])
		salsa.HSalsa20(&, &, , &salsa.Sigma)
		copy(.nonce[:], [16:])
		.key = &
	} else if len() == 8 {
		.key = 
		copy(.nonce[:], )
	} else {
		panic("salsa20: nonce must be 8 or 24 bytes")
	}
	return 
}

func ( *salsaCipher) (,  []byte) {
	if len() < len() {
		 = [:len()]
	}
	if .nx > 0 {
		 := xorBytes(, , .x[.nx:])
		.nx += 
		if .nx == BlockSize {
			.nx = 0
		}
		 = [:]
		 = [:]
	}
	if len() > BlockSize {
		 := len() &^ (BlockSize - 1)
		.blocks(, [:])
		 = [:]
		 = [:]
	}
	if len() > 0 {
		.nx = copy(.x[:], )
		for  := .nx;  < len(.x); ++ {
			.x[] = 0
		}
		.blocks(.x[:], .x[:])
		copy(, .x[:.nx])
	}
}

func ( *salsaCipher) (,  []byte) {
	var  [16]byte
	copy([:], .nonce[:])
	binary.LittleEndian.PutUint64([8:], .counter)
	salsa.XORKeyStream(, , &, .key)
	.counter += uint64(len()) / 64
}

func xorBytes(, ,  []byte) int {
	 := len()
	if len() <  {
		 = len()
	}
	for  := 0;  < ; ++ {
		[] = [] ^ []
	}
	return 
}