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

// CFB (Cipher Feedback) Mode.

package cipher

import (
	
	
)

type cfb struct {
	b       Block
	next    []byte
	out     []byte
	outUsed int

	decrypt bool
}

func ( *cfb) (,  []byte) {
	if len() < len() {
		panic("crypto/cipher: output smaller than input")
	}
	if alias.InexactOverlap([:len()], ) {
		panic("crypto/cipher: invalid buffer overlap")
	}
	for len() > 0 {
		if .outUsed == len(.out) {
			.b.Encrypt(.out, .next)
			.outUsed = 0
		}

		if .decrypt {
			// We can precompute a larger segment of the
			// keystream on decryption. This will allow
			// larger batches for xor, and we should be
			// able to match CTR/OFB performance.
			copy(.next[.outUsed:], )
		}
		 := subtle.XORBytes(, , .out[.outUsed:])
		if !.decrypt {
			copy(.next[.outUsed:], )
		}
		 = [:]
		 = [:]
		.outUsed += 
	}
}

// NewCFBEncrypter returns a [Stream] which encrypts with cipher feedback mode,
// using the given [Block]. The iv must be the same length as the [Block]'s block
// size.
func ( Block,  []byte) Stream {
	return newCFB(, , false)
}

// NewCFBDecrypter returns a [Stream] which decrypts with cipher feedback mode,
// using the given [Block]. The iv must be the same length as the [Block]'s block
// size.
func ( Block,  []byte) Stream {
	return newCFB(, , true)
}

func newCFB( Block,  []byte,  bool) Stream {
	 := .BlockSize()
	if len() !=  {
		// stack trace will indicate whether it was de or encryption
		panic("cipher.newCFB: IV length must equal block size")
	}
	 := &cfb{
		b:       ,
		out:     make([]byte, ),
		next:    make([]byte, ),
		outUsed: ,
		decrypt: ,
	}
	copy(.next, )

	return 
}