blob: 259943a627c1995f1950df33d0322330376bbe1c [file] [log] [blame]
Jens Geyerc6b991f2015-08-07 23:41:09 +02001/*
2* Licensed to the Apache Software Foundation (ASF) under one
3* or more contributor license agreements. See the NOTICE file
4* distributed with this work for additional information
5* regarding copyright ownership. The ASF licenses this file
6* to you under the Apache License, Version 2.0 (the
7* "License"); you may not use this file except in compliance
8* with the License. You may obtain a copy of the License at
9*
10* http://www.apache.org/licenses/LICENSE-2.0
11*
12* Unless required by applicable law or agreed to in writing,
13* software distributed under the License is distributed on an
14* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15* KIND, either express or implied. See the License for the
16* specific language governing permissions and limitations
17* under the License.
18 */
19
20package thrift
21
22import (
23 "compress/zlib"
John Boiles57852792018-01-05 14:37:05 -080024 "context"
Jens Geyerc6b991f2015-08-07 23:41:09 +020025 "io"
Jens Geyerc6b991f2015-08-07 23:41:09 +020026)
27
28// TZlibTransportFactory is a factory for TZlibTransport instances
29type TZlibTransportFactory struct {
Yuri Khrustalev39310da2017-09-25 23:22:33 +030030 level int
31 factory TTransportFactory
Jens Geyerc6b991f2015-08-07 23:41:09 +020032}
33
34// TZlibTransport is a TTransport implementation that makes use of zlib compression.
35type TZlibTransport struct {
36 reader io.ReadCloser
37 transport TTransport
38 writer *zlib.Writer
39}
40
41// GetTransport constructs a new instance of NewTZlibTransport
D. Can Celasun8da0e722017-06-02 14:33:32 +020042func (p *TZlibTransportFactory) GetTransport(trans TTransport) (TTransport, error) {
Yuri Khrustalev39310da2017-09-25 23:22:33 +030043 if p.factory != nil {
44 // wrap other factory
45 var err error
46 trans, err = p.factory.GetTransport(trans)
47 if err != nil {
48 return nil, err
49 }
50 }
D. Can Celasun8da0e722017-06-02 14:33:32 +020051 return NewTZlibTransport(trans, p.level)
Jens Geyerc6b991f2015-08-07 23:41:09 +020052}
53
54// NewTZlibTransportFactory constructs a new instance of NewTZlibTransportFactory
55func NewTZlibTransportFactory(level int) *TZlibTransportFactory {
Yuri Khrustalev39310da2017-09-25 23:22:33 +030056 return &TZlibTransportFactory{level: level, factory: nil}
57}
58
59// NewTZlibTransportFactory constructs a new instance of TZlibTransportFactory
60// as a wrapper over existing transport factory
61func NewTZlibTransportFactoryWithFactory(level int, factory TTransportFactory) *TZlibTransportFactory {
62 return &TZlibTransportFactory{level: level, factory: factory}
Jens Geyerc6b991f2015-08-07 23:41:09 +020063}
64
65// NewTZlibTransport constructs a new instance of TZlibTransport
66func NewTZlibTransport(trans TTransport, level int) (*TZlibTransport, error) {
67 w, err := zlib.NewWriterLevel(trans, level)
68 if err != nil {
Jens Geyerc6b991f2015-08-07 23:41:09 +020069 return nil, err
70 }
71
72 return &TZlibTransport{
73 writer: w,
74 transport: trans,
75 }, nil
76}
77
78// Close closes the reader and writer (flushing any unwritten data) and closes
79// the underlying transport.
80func (z *TZlibTransport) Close() error {
81 if z.reader != nil {
82 if err := z.reader.Close(); err != nil {
83 return err
84 }
85 }
86 if err := z.writer.Close(); err != nil {
87 return err
88 }
89 return z.transport.Close()
90}
91
92// Flush flushes the writer and its underlying transport.
John Boiles57852792018-01-05 14:37:05 -080093func (z *TZlibTransport) Flush(ctx context.Context) error {
Jens Geyerc6b991f2015-08-07 23:41:09 +020094 if err := z.writer.Flush(); err != nil {
95 return err
96 }
John Boiles57852792018-01-05 14:37:05 -080097 return z.transport.Flush(ctx)
Jens Geyerc6b991f2015-08-07 23:41:09 +020098}
99
100// IsOpen returns true if the transport is open
101func (z *TZlibTransport) IsOpen() bool {
102 return z.transport.IsOpen()
103}
104
105// Open opens the transport for communication
106func (z *TZlibTransport) Open() error {
107 return z.transport.Open()
108}
109
110func (z *TZlibTransport) Read(p []byte) (int, error) {
111 if z.reader == nil {
112 r, err := zlib.NewReader(z.transport)
113 if err != nil {
114 return 0, NewTTransportExceptionFromError(err)
115 }
116 z.reader = r
117 }
118
119 return z.reader.Read(p)
120}
121
122// RemainingBytes returns the size in bytes of the data that is still to be
123// read.
124func (z *TZlibTransport) RemainingBytes() uint64 {
125 return z.transport.RemainingBytes()
126}
127
128func (z *TZlibTransport) Write(p []byte) (int, error) {
129 return z.writer.Write(p)
130}
Yuxuan 'fishy' Wangc4d1c0d2020-12-16 17:10:48 -0800131
132// SetTConfiguration implements TConfigurationSetter for propagation.
133func (z *TZlibTransport) SetTConfiguration(conf *TConfiguration) {
134 PropagateTConfiguration(z.transport, conf)
135}
136
137var _ TConfigurationSetter = (*TZlibTransport)(nil)