crossplane
116 строк · 2.8 Кб
1/*
2Copyright 2022 The Crossplane Authors.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17package xpkg
18
19import (
20"compress/gzip"
21"io"
22)
23
24var _ io.ReadCloser = &gzipReadCloser{}
25
26// gzipReadCloser reads compressed contents from a file.
27type gzipReadCloser struct {
28rc io.ReadCloser
29gzip *gzip.Reader
30}
31
32// GzipReadCloser constructs a new gzipReadCloser from the passed file.
33func GzipReadCloser(rc io.ReadCloser) (io.ReadCloser, error) {
34r, err := gzip.NewReader(rc)
35if err != nil {
36return nil, err
37}
38return &gzipReadCloser{
39rc: rc,
40gzip: r,
41}, nil
42}
43
44// Read calls the underlying gzip reader's Read method.
45func (g *gzipReadCloser) Read(p []byte) (n int, err error) {
46return g.gzip.Read(p)
47}
48
49// Close first closes the gzip reader, then closes the underlying closer.
50func (g *gzipReadCloser) Close() error {
51if err := g.gzip.Close(); err != nil {
52_ = g.rc.Close()
53return err
54}
55return g.rc.Close()
56}
57
58var _ io.ReadCloser = &teeReadCloser{}
59
60// teeReadCloser is a TeeReader that also closes the underlying writer.
61type teeReadCloser struct {
62w io.WriteCloser
63r io.ReadCloser
64t io.Reader
65}
66
67// TeeReadCloser constructs a teeReadCloser from the passed reader and writer.
68func TeeReadCloser(r io.ReadCloser, w io.WriteCloser) io.ReadCloser {
69return &teeReadCloser{
70w: w,
71r: r,
72t: io.TeeReader(r, w),
73}
74}
75
76// Read calls the underlying TeeReader Read method.
77func (t *teeReadCloser) Read(b []byte) (int, error) {
78return t.t.Read(b)
79}
80
81// Close closes the underlying ReadCloser, then the Writer for the TeeReader.
82func (t *teeReadCloser) Close() error {
83if err := t.r.Close(); err != nil {
84_ = t.w.Close()
85return err
86}
87return t.w.Close()
88}
89
90var _ io.ReadCloser = &joinedReadCloser{}
91
92// joinedReadCloster joins a reader and a closer. It is typically used in the
93// context of a ReadCloser being wrapped by a Reader.
94type joinedReadCloser struct {
95r io.Reader
96c io.Closer
97}
98
99// JoinedReadCloser constructs a new joinedReadCloser from the passed reader and
100// closer.
101func JoinedReadCloser(r io.Reader, c io.Closer) io.ReadCloser {
102return &joinedReadCloser{
103r: r,
104c: c,
105}
106}
107
108// Read calls the underlying reader Read method.
109func (r *joinedReadCloser) Read(b []byte) (int, error) {
110return r.r.Read(b)
111}
112
113// Close closes the closer for the JoinedReadCloser.
114func (r *joinedReadCloser) Close() error {
115return r.c.Close()
116}
117