github.com/bodgit/sevenzip@v1.5.1/internal/delta/reader.go (about)

     1  package delta
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  )
     7  
     8  const (
     9  	stateSize = 256
    10  )
    11  
    12  type readCloser struct {
    13  	rc    io.ReadCloser
    14  	state [stateSize]byte
    15  	delta int
    16  }
    17  
    18  func (rc *readCloser) Close() (err error) {
    19  	if rc.rc != nil {
    20  		err = rc.rc.Close()
    21  		rc.rc = nil
    22  	}
    23  
    24  	return
    25  }
    26  
    27  func (rc *readCloser) Read(p []byte) (int, error) {
    28  	if rc.rc == nil {
    29  		return 0, errors.New("delta: Read after Close")
    30  	}
    31  
    32  	n, err := rc.rc.Read(p)
    33  	if err != nil {
    34  		return n, err
    35  	}
    36  
    37  	var (
    38  		buffer [stateSize]byte
    39  		j      int
    40  	)
    41  
    42  	copy(buffer[:], rc.state[:rc.delta])
    43  
    44  	for i := 0; i < n; {
    45  		for j = 0; j < rc.delta && i < n; i++ {
    46  			p[i] = buffer[j] + p[i]
    47  			buffer[j] = p[i]
    48  			j++
    49  		}
    50  	}
    51  
    52  	if j == rc.delta {
    53  		j = 0
    54  	}
    55  
    56  	copy(rc.state[:], buffer[j:rc.delta])
    57  	copy(rc.state[rc.delta-j:], buffer[:j])
    58  
    59  	return n, nil
    60  }
    61  
    62  // NewReader returns a new Delta io.ReadCloser.
    63  func NewReader(p []byte, _ uint64, readers []io.ReadCloser) (io.ReadCloser, error) {
    64  	if len(readers) != 1 {
    65  		return nil, errors.New("delta: need exactly one reader")
    66  	}
    67  
    68  	if len(p) != 1 {
    69  		return nil, errors.New("delta: not enough properties")
    70  	}
    71  
    72  	return &readCloser{
    73  		rc:    readers[0],
    74  		delta: int(p[0] + 1),
    75  	}, nil
    76  }