// Copyright 2009 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 base64 implements base64 encoding as specified by RFC 4648.
package base64

import (
	"bytes";
	"io";
	"os";
	"strconv";
)

/*
 * Encodings
 */

// An Encoding is a radix 64 encoding/decoding scheme, defined by a
// 64-character alphabet.  The most common encoding is the "base64"
// encoding defined in RFC 4648 and used in MIME (RFC 2045) and PEM
// (RFC 1421).  RFC 4648 also defines an alternate encoding, which is
// the standard encoding with - and _ substituted for + and /.
type Encoding struct {
	encode		string;
	decodeMap	[256]byte;
}

const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"

// NewEncoding returns a new Encoding defined by the given alphabet,
// which must be a 64-byte string.
func NewEncoding(encoder string) *Encoding {
	e := new(Encoding);
	e.encode = encoder;
	for i := 0; i < len(e.decodeMap); i++ {
		e.decodeMap[i] = 0xFF;
	}
	for i := 0; i < len(encoder); i++ {
		e.decodeMap[encoder[i]] = byte(i);
	}
	return e;
}

// StdEncoding is the standard base64 encoding, as defined in
// RFC 4648.
var StdEncoding = NewEncoding(encodeStd)

// URLEncoding is the alternate base64 encoding defined in RFC 4648.
// It is typically used in URLs and file names.
var URLEncoding = NewEncoding(encodeURL)

/*
 * Encoder
 */

// Encode encodes src using the encoding enc, writing
// EncodedLen(len(src)) bytes to dst.
//
// The encoding pads the output to a multiple of 4 bytes,
// so Encode is not appropriate for use on individual blocks
// of a large data stream.  Use NewEncoder() instead.
func (enc *Encoding) Encode(src, dst []byte) {
	if len(src) == 0 {
		return;
	}

	for len(src) > 0 {
		dst[0] = 0;
		dst[1] = 0;
		dst[2] = 0;
		dst[3] = 0;

		// Unpack 4x 6-bit source blocks into a 4 byte
		// destination quantum
		switch len(src) {
		default:
			dst[3] |= src[2]&0x3F;
			dst[2] |= src[2]>>6;
			fallthrough;
		case 2:
			dst[2] |= (src[1]<<2)&0x3F;
			dst[1] |= src[1]>>4;
			fallthrough;
		case 1:
			dst[1] |= (src[0]<<4)&0x3F;
			dst[0] |= src[0]>>2;
		}

		// Encode 6-bit blocks using the base64 alphabet
		for j := 0; j < 4; j++ {
			dst[j] = enc.encode[dst[j]];
		}

		// Pad the final quantum
		if len(src) < 3 {
			dst[3] = '=';
			if len(src) < 2 {
				dst[2] = '=';
			}
			break;
		}

		src = src[3:len(src)];
		dst = dst[4:len(dst)];
	}
}

type encoder struct {
	err	os.Error;
	enc	*Encoding;
	w	io.Writer;
	buf	[3]byte;	// buffered data waiting to be encoded
	nbuf	int;		// number of bytes in buf
	out	[1024]byte;	// output buffer
}

func (e *encoder) Write(p []byte) (n int, err os.Error) {
	if e.err != nil {
		return 0, e.err;
	}

	// Leading fringe.
	if e.nbuf > 0 {
		var i int;
		for i = 0; i < len(p) && e.nbuf < 3; i++ {
			e.buf[e.nbuf] = p[i];
			e.nbuf++;
		}
		n += i;
		p = p[i:len(p)];
		if e.nbuf < 3 {
			return;
		}
		e.enc.Encode(&e.buf, &e.out);
		if _, e.err = e.w.Write(e.out[0:4]); e.err != nil {
			return n, e.err;
		}
		e.nbuf = 0;
	}

	// Large interior chunks.
	for len(p) >= 3 {
		nn := len(e.out)/4*3;
		if nn > len(p) {
			nn = len(p);
		}
		nn -= nn%3;
		if nn > 0 {
			e.enc.Encode(p[0:nn], &e.out);
			if _, e.err = e.w.Write(e.out[0 : nn/3*4]); e.err != nil {
				return n, e.err;
			}
		}
		n += nn;
		p = p[nn:len(p)];
	}

	// Trailing fringe.
	for i := 0; i < len(p); i++ {
		e.buf[i] = p[i];
	}
	e.nbuf = len(p);
	n += len(p);
	return;
}

// Close flushes any pending output from the encoder.
// It is an error to call Write after calling Close.
func (e *encoder) Close() os.Error {
	// If there's anything left in the buffer, flush it out
	if e.err == nil && e.nbuf > 0 {
		e.enc.Encode(e.buf[0 : e.nbuf], &e.out);
		e.nbuf = 0;
		_, e.err = e.w.Write(e.out[0:4]);
	}
	return e.err;
}

// NewEncoder returns a new base64 stream encoder.  Data written to
// the returned writer will be encoded using enc and then written to w.
// Base64 encodings operate in 4-byte blocks; when finished
// writing, the caller must Close the returned encoder to flush any
// partially written blocks.
func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser {
	return &encoder{enc: enc, w: w};
}

// EncodedLen returns the length in bytes of the base64 encoding
// of an input buffer of length n.
func (enc *Encoding) EncodedLen(n int) int {
	return (n+2)/3*4;
}

/*
 * Decoder
 */

type CorruptInputError int64

func (e CorruptInputError) String() string {
	return "illegal base64 data at input byte" + strconv.Itoa64(int64(e));
}

// decode is like Decode but returns an additional 'end' value, which
// indicates if end-of-message padding was encountered and thus any
// additional data is an error.  decode also assumes len(src)%4==0,
// since it is meant for internal use.
func (enc *Encoding) decode(src, dst []byte) (n int, end bool, err os.Error) {
	for i := 0; i < len(src)/4 && !end; i++ {
		// Decode quantum using the base64 alphabet
		var dbuf [4]byte;
		dlen := 4;

	dbufloop:
		for j := 0; j < 4; j++ {
			in := src[i*4 + j];
			if in == '=' && j >= 2 && i == len(src)/4 - 1 {
				// We've reached the end and there's
				// padding
				if src[i*4 + 3] != '=' {
					return n, false, CorruptInputError(i*4 + 2);
				}
				dlen = j;
				end = true;
				break dbufloop;
			}
			dbuf[j] = enc.decodeMap[in];
			if dbuf[j] == 0xFF {
				return n, false, CorruptInputError(i*4 + j);
			}
		}

		// Pack 4x 6-bit source blocks into 3 byte destination
		// quantum
		switch dlen {
		case 4:
			dst[i*3 + 2] = dbuf[2]<<6 | dbuf[3];
			fallthrough;
		case 3:
			dst[i*3 + 1] = dbuf[1]<<4 | dbuf[2]>>2;
			fallthrough;
		case 2:
			dst[i*3 + 0] = dbuf[0]<<2 | dbuf[1]>>4;
		}
		n += dlen-1;
	}

	return n, end, nil;
}

// Decode decodes src using the encoding enc.  It writes at most
// DecodedLen(len(src)) bytes to dst and returns the number of bytes
// written.  If src contains invalid base64 data, it will return the
// number of bytes successfully written and CorruptInputError.
func (enc *Encoding) Decode(src, dst []byte) (n int, err os.Error) {
	if len(src)%4 != 0 {
		return 0, CorruptInputError(len(src)/4*4);
	}

	n, _, err = enc.decode(src, dst);
	return;
}

type decoder struct {
	err	os.Error;
	enc	*Encoding;
	r	io.Reader;
	end	bool;		// saw end of message
	buf	[1024]byte;	// leftover input
	nbuf	int;
	out	[]byte;	// leftover decoded output
	outbuf	[1024/4*3]byte;
}

func (d *decoder) Read(p []byte) (n int, err os.Error) {
	if d.err != nil {
		return 0, d.err;
	}

	// Use leftover decoded output from last read.
	if len(d.out) > 0 {
		n = bytes.Copy(p, d.out);
		d.out = d.out[n:len(d.out)];
		return n, nil;
	}

	// Read a chunk.
	nn := len(p)/3*4;
	if nn < 4 {
		nn = 4;
	}
	if nn > len(d.buf) {
		nn = len(d.buf);
	}
	nn, d.err = io.ReadAtLeast(d.r, d.buf[d.nbuf : nn], 4 - d.nbuf);
	d.nbuf += nn;
	if d.nbuf < 4 {
		return 0, d.err;
	}

	// Decode chunk into p, or d.out and then p if p is too small.
	nr := d.nbuf / 4 * 4;
	nw := d.nbuf / 4 * 3;
	if nw > len(p) {
		nw, d.end, d.err = d.enc.decode(d.buf[0:nr], &d.outbuf);
		d.out = d.outbuf[0:nw];
		n = bytes.Copy(p, d.out);
		d.out = d.out[n:len(d.out)];
	} else {
		n, d.end, d.err = d.enc.decode(d.buf[0:nr], p);
	}
	d.nbuf -= nr;
	for i := 0; i < d.nbuf; i++ {
		d.buf[i] = d.buf[i+nr];
	}

	if d.err == nil {
		d.err = err;
	}
	return n, d.err;
}

// NewDecoder constructs a new base64 stream decoder.
func NewDecoder(enc *Encoding, r io.Reader) io.Reader {
	return &decoder{enc: enc, r: r};
}

// DecodeLen returns the maximum length in bytes of the decoded data
// corresponding to n bytes of base64-encoded data.
func (enc *Encoding) DecodedLen(n int) int {
	return n/4*3;
}
