Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 1 | /* |
| 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 | |
| 20 | package thrift |
| 21 | |
| 22 | import ( |
| 23 | "compress/zlib" |
John Boiles | 5785279 | 2018-01-05 14:37:05 -0800 | [diff] [blame] | 24 | "context" |
Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 25 | "io" |
Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 26 | ) |
| 27 | |
| 28 | // TZlibTransportFactory is a factory for TZlibTransport instances |
| 29 | type TZlibTransportFactory struct { |
Yuri Khrustalev | 39310da | 2017-09-25 23:22:33 +0300 | [diff] [blame] | 30 | level int |
| 31 | factory TTransportFactory |
Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 32 | } |
| 33 | |
| 34 | // TZlibTransport is a TTransport implementation that makes use of zlib compression. |
| 35 | type 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 Celasun | 8da0e72 | 2017-06-02 14:33:32 +0200 | [diff] [blame] | 42 | func (p *TZlibTransportFactory) GetTransport(trans TTransport) (TTransport, error) { |
Yuri Khrustalev | 39310da | 2017-09-25 23:22:33 +0300 | [diff] [blame] | 43 | 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 Celasun | 8da0e72 | 2017-06-02 14:33:32 +0200 | [diff] [blame] | 51 | return NewTZlibTransport(trans, p.level) |
Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | // NewTZlibTransportFactory constructs a new instance of NewTZlibTransportFactory |
| 55 | func NewTZlibTransportFactory(level int) *TZlibTransportFactory { |
Yuri Khrustalev | 39310da | 2017-09-25 23:22:33 +0300 | [diff] [blame] | 56 | return &TZlibTransportFactory{level: level, factory: nil} |
| 57 | } |
| 58 | |
| 59 | // NewTZlibTransportFactory constructs a new instance of TZlibTransportFactory |
| 60 | // as a wrapper over existing transport factory |
| 61 | func NewTZlibTransportFactoryWithFactory(level int, factory TTransportFactory) *TZlibTransportFactory { |
| 62 | return &TZlibTransportFactory{level: level, factory: factory} |
Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 63 | } |
| 64 | |
| 65 | // NewTZlibTransport constructs a new instance of TZlibTransport |
| 66 | func NewTZlibTransport(trans TTransport, level int) (*TZlibTransport, error) { |
| 67 | w, err := zlib.NewWriterLevel(trans, level) |
| 68 | if err != nil { |
Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 69 | 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. |
| 80 | func (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 Boiles | 5785279 | 2018-01-05 14:37:05 -0800 | [diff] [blame] | 93 | func (z *TZlibTransport) Flush(ctx context.Context) error { |
Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 94 | if err := z.writer.Flush(); err != nil { |
| 95 | return err |
| 96 | } |
John Boiles | 5785279 | 2018-01-05 14:37:05 -0800 | [diff] [blame] | 97 | return z.transport.Flush(ctx) |
Jens Geyer | c6b991f | 2015-08-07 23:41:09 +0200 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | // IsOpen returns true if the transport is open |
| 101 | func (z *TZlibTransport) IsOpen() bool { |
| 102 | return z.transport.IsOpen() |
| 103 | } |
| 104 | |
| 105 | // Open opens the transport for communication |
| 106 | func (z *TZlibTransport) Open() error { |
| 107 | return z.transport.Open() |
| 108 | } |
| 109 | |
| 110 | func (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. |
| 124 | func (z *TZlibTransport) RemainingBytes() uint64 { |
| 125 | return z.transport.RemainingBytes() |
| 126 | } |
| 127 | |
| 128 | func (z *TZlibTransport) Write(p []byte) (int, error) { |
| 129 | return z.writer.Write(p) |
| 130 | } |
Yuxuan 'fishy' Wang | c4d1c0d | 2020-12-16 17:10:48 -0800 | [diff] [blame] | 131 | |
| 132 | // SetTConfiguration implements TConfigurationSetter for propagation. |
| 133 | func (z *TZlibTransport) SetTConfiguration(conf *TConfiguration) { |
| 134 | PropagateTConfiguration(z.transport, conf) |
| 135 | } |
| 136 | |
| 137 | var _ TConfigurationSetter = (*TZlibTransport)(nil) |