github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/third_party/code.google.com/p/go.crypto/openpgp/packet/reader.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package packet
     6  
     7  import (
     8  	"camlistore.org/third_party/code.google.com/p/go.crypto/openpgp/errors"
     9  	"io"
    10  )
    11  
    12  // Reader reads packets from an io.Reader and allows packets to be 'unread' so
    13  // that they result from the next call to Next.
    14  type Reader struct {
    15  	q       []Packet
    16  	readers []io.Reader
    17  }
    18  
    19  // Next returns the most recently unread Packet, or reads another packet from
    20  // the top-most io.Reader. Unknown packet types are skipped.
    21  func (r *Reader) Next() (p Packet, err error) {
    22  	if len(r.q) > 0 {
    23  		p = r.q[len(r.q)-1]
    24  		r.q = r.q[:len(r.q)-1]
    25  		return
    26  	}
    27  
    28  	for len(r.readers) > 0 {
    29  		p, err = Read(r.readers[len(r.readers)-1])
    30  		if err == nil {
    31  			return
    32  		}
    33  		if err == io.EOF {
    34  			r.readers = r.readers[:len(r.readers)-1]
    35  			continue
    36  		}
    37  		if _, ok := err.(errors.UnknownPacketTypeError); !ok {
    38  			return nil, err
    39  		}
    40  	}
    41  
    42  	return nil, io.EOF
    43  }
    44  
    45  // Push causes the Reader to start reading from a new io.Reader. When an EOF
    46  // error is seen from the new io.Reader, it is popped and the Reader continues
    47  // to read from the next most recent io.Reader.
    48  func (r *Reader) Push(reader io.Reader) {
    49  	r.readers = append(r.readers, reader)
    50  }
    51  
    52  // Unread causes the given Packet to be returned from the next call to Next.
    53  func (r *Reader) Unread(p Packet) {
    54  	r.q = append(r.q, p)
    55  }
    56  
    57  func NewReader(r io.Reader) *Reader {
    58  	return &Reader{
    59  		q:       nil,
    60  		readers: []io.Reader{r},
    61  	}
    62  }