github.com/spi-ca/misc@v1.0.1/strutil/chunk.go (about)

     1  package strutil
     2  
     3  import (
     4  	"io"
     5  )
     6  
     7  const pemLineLength = 64
     8  
     9  // LineBreaker is an io.Writer that advances a newline if one line exceeds 64 bytes.
    10  type LineBreaker struct {
    11  	// Out os
    12  	Out  io.Writer
    13  	line [pemLineLength]byte
    14  	used int
    15  }
    16  
    17  var nl = []byte{'\n'}
    18  
    19  // Write writes len(p) bytes from p to the underlying data stream.
    20  // It returns the number of bytes written from p (0 <= n <= len(p))
    21  // and any error encountered that caused the write to stop early.
    22  // Write must return a non-nil error if it returns n < len(p).
    23  // Write must not modify the slice data, even temporarily.
    24  func (l *LineBreaker) Write(b []byte) (n int, err error) {
    25  	if l.used+len(b) < pemLineLength {
    26  		copy(l.line[l.used:], b)
    27  		l.used += len(b)
    28  		return len(b), nil
    29  	}
    30  
    31  	n, err = l.Out.Write(l.line[0:l.used])
    32  	if err != nil {
    33  		return
    34  	}
    35  	excess := pemLineLength - l.used
    36  	l.used = 0
    37  
    38  	n, err = l.Out.Write(b[0:excess])
    39  	if err != nil {
    40  		return
    41  	}
    42  
    43  	n, err = l.Out.Write(nl)
    44  	if err != nil {
    45  		return
    46  	}
    47  
    48  	return l.Out.Write(b[excess:])
    49  }
    50  
    51  // Close flushes any pending output from the writer.
    52  // It is an error to call Write after calling Close.
    53  func (l *LineBreaker) Close() (err error) {
    54  	if l.used > 0 {
    55  		_, err = l.Out.Write(l.line[0:l.used])
    56  		if err != nil {
    57  			return
    58  		}
    59  		_, err = l.Out.Write(nl)
    60  	}
    61  	if err != nil {
    62  		return
    63  	} else if closer, ok := l.Out.(io.Closer); ok {
    64  		err = closer.Close()
    65  	}
    66  	return
    67  }