github.com/bodgit/sevenzip@v1.5.1/internal/lzma/reader.go (about) 1 package lzma 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "io" 8 9 "github.com/ulikunitz/xz/lzma" 10 ) 11 12 type readCloser struct { 13 c io.Closer 14 r io.Reader 15 } 16 17 func (rc *readCloser) Close() error { 18 var err error 19 if rc.c != nil { 20 err = rc.c.Close() 21 rc.c, rc.r = nil, nil 22 } 23 24 return err 25 } 26 27 func (rc *readCloser) Read(p []byte) (int, error) { 28 if rc.r == nil { 29 return 0, errors.New("lzma: Read after Close") 30 } 31 32 return rc.r.Read(p) 33 } 34 35 // NewReader returns a new LZMA io.ReadCloser. 36 func NewReader(p []byte, s uint64, readers []io.ReadCloser) (io.ReadCloser, error) { 37 if len(readers) != 1 { 38 return nil, errors.New("lzma: need exactly one reader") 39 } 40 41 h := bytes.NewBuffer(p) 42 _ = binary.Write(h, binary.LittleEndian, s) 43 44 lr, err := lzma.NewReader(multiReader(h, readers[0])) 45 if err != nil { 46 return nil, err 47 } 48 49 return &readCloser{ 50 c: readers[0], 51 r: lr, 52 }, nil 53 } 54 55 func multiReader(b *bytes.Buffer, rc io.ReadCloser) io.Reader { 56 mr := io.MultiReader(b, rc) 57 58 if br, ok := rc.(io.ByteReader); ok { 59 return &multiByteReader{ 60 b: b, 61 br: br, 62 mr: mr, 63 } 64 } 65 66 return mr 67 } 68 69 type multiByteReader struct { 70 b *bytes.Buffer 71 br io.ByteReader 72 mr io.Reader 73 } 74 75 func (m *multiByteReader) ReadByte() (byte, error) { 76 if m.b.Len() > 0 { 77 return m.b.ReadByte() 78 } 79 80 return m.br.ReadByte() 81 } 82 83 func (m *multiByteReader) Read(p []byte) (n int, err error) { 84 return m.mr.Read(p) 85 }