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.

package armor

import (
	
	
)

var armorHeaderSep = []byte(": ")
var blockEnd = []byte("\n=")
var newline = []byte("\n")
var armorEndOfLineOut = []byte("-----\n")
writeSlices writes its arguments to the given Writer.
func ( io.Writer,  ...[]byte) ( error) {
	for ,  := range  {
		_,  = .Write()
		if  != nil {
			return 
		}
	}
	return
}
lineBreaker breaks data across several lines, all of the same byte length (except possibly the last). Lines are broken with a single '\n'.
type lineBreaker struct {
	lineLength  int
	line        []byte
	used        int
	out         io.Writer
	haveWritten bool
}

func ( io.Writer,  int) *lineBreaker {
	return &lineBreaker{
		lineLength: ,
		line:       make([]byte, ),
		used:       0,
		out:        ,
	}
}

func ( *lineBreaker) ( []byte) ( int,  error) {
	 = len()

	if  == 0 {
		return
	}

	if .used == 0 && .haveWritten {
		_,  = .out.Write([]byte{'\n'})
		if  != nil {
			return
		}
	}

	if .used+len() < .lineLength {
		.used += copy(.line[.used:], )
		return
	}

	.haveWritten = true
	_,  = .out.Write(.line[0:.used])
	if  != nil {
		return
	}
	 := .lineLength - .used
	.used = 0

	_,  = .out.Write([0:])
	if  != nil {
		return
	}

	_,  = .([:])
	return
}

func ( *lineBreaker) () ( error) {
	if .used > 0 {
		_,  = .out.Write(.line[0:.used])
		if  != nil {
			return
		}
	}

	return
}
encoding keeps track of a running CRC24 over the data which has been written to it and outputs a OpenPGP checksum when closed, followed by an armor trailer. It's built into a stack of io.Writers: encoding -> base64 encoder -> lineBreaker -> out
type encoding struct {
	out       io.Writer
	breaker   *lineBreaker
	b64       io.WriteCloser
	crc       uint32
	blockType []byte
}

func ( *encoding) ( []byte) ( int,  error) {
	.crc = crc24(.crc, )
	return .b64.Write()
}

func ( *encoding) () ( error) {
	 = .b64.Close()
	if  != nil {
		return
	}
	.breaker.Close()

	var  [3]byte
	[0] = byte(.crc >> 16)
	[1] = byte(.crc >> 8)
	[2] = byte(.crc)

	var  [4]byte
	base64.StdEncoding.Encode([:], [:])

	return writeSlices(.out, blockEnd, [:], newline, armorEnd, .blockType, armorEndOfLine)
}
Encode returns a WriteCloser which will encode the data written to it in OpenPGP armor.
func ( io.Writer,  string,  map[string]string) ( io.WriteCloser,  error) {
	 := []byte()
	 = writeSlices(, armorStart, , armorEndOfLineOut)
	if  != nil {
		return
	}

	for ,  := range  {
		 = writeSlices(, []byte(), armorHeaderSep, []byte(), newline)
		if  != nil {
			return
		}
	}

	_,  = .Write(newline)
	if  != nil {
		return
	}

	 := &encoding{
		out:       ,
		breaker:   newLineBreaker(, 64),
		crc:       crc24Init,
		blockType: ,
	}
	.b64 = base64.NewEncoder(base64.StdEncoding, .breaker)
	return , nil