123 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
| // Copyright 2025 The Prometheus Authors
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| // http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| package compression
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 
 | |
| 	"github.com/golang/snappy"
 | |
| )
 | |
| 
 | |
| // Type represents a valid compression type supported by this package.
 | |
| type Type = string
 | |
| 
 | |
| const (
 | |
| 	// None represents no compression case.
 | |
| 	// None is the default when Type is empty.
 | |
| 	None Type = "none"
 | |
| 	// Snappy represents snappy block format.
 | |
| 	Snappy Type = "snappy"
 | |
| 	// Zstd represents "speed" mode of Zstd (Zstandard https://facebook.github.io/zstd/).
 | |
| 	// This is roughly equivalent to the default Zstandard mode (level 3).
 | |
| 	Zstd Type = "zstd"
 | |
| )
 | |
| 
 | |
| func Types() []Type { return []Type{None, Snappy, Zstd} }
 | |
| 
 | |
| // Encode returns the encoded form of src for the given compression type.
 | |
| // For None or empty message the encoding is not attempted.
 | |
| //
 | |
| // The buf allows passing various buffer implementations that make encoding more
 | |
| // efficient. See NewSyncEncodeBuffer and NewConcurrentEncodeBuffer for further
 | |
| // details. For non-zstd compression types, it is valid to pass nil buf.
 | |
| //
 | |
| // Encode is concurrency-safe, however note the concurrency limits for the
 | |
| // buffer of your choice.
 | |
| func Encode(t Type, src []byte, buf EncodeBuffer) (ret []byte, err error) {
 | |
| 	if len(src) == 0 || t == "" || t == None {
 | |
| 		return src, nil
 | |
| 	}
 | |
| 	if t == Snappy {
 | |
| 		// If MaxEncodedLen is less than 0 the record is too large to be compressed.
 | |
| 		if snappy.MaxEncodedLen(len(src)) < 0 {
 | |
| 			return src, fmt.Errorf("compression: Snappy can't encode such a large message: %v", len(src))
 | |
| 		}
 | |
| 		var b []byte
 | |
| 		if buf != nil {
 | |
| 			b = buf.get()
 | |
| 			defer func() {
 | |
| 				buf.set(ret)
 | |
| 			}()
 | |
| 		}
 | |
| 
 | |
| 		// The snappy library uses `len` to calculate if we need a new buffer.
 | |
| 		// In order to allocate as few buffers as possible make the length
 | |
| 		// equal to the capacity.
 | |
| 		b = b[:cap(b)]
 | |
| 		return snappy.Encode(b, src), nil
 | |
| 	}
 | |
| 	if t == Zstd {
 | |
| 		if buf == nil {
 | |
| 			return nil, errors.New("zstd requested but EncodeBuffer was not provided")
 | |
| 		}
 | |
| 		b := buf.get()
 | |
| 		defer func() {
 | |
| 			buf.set(ret)
 | |
| 		}()
 | |
| 
 | |
| 		return buf.zstdEncBuf().EncodeAll(src, b[:0]), nil
 | |
| 	}
 | |
| 	return nil, fmt.Errorf("unsupported compression type: %s", t)
 | |
| }
 | |
| 
 | |
| // Decode returns the decoded form of src for the given compression type.
 | |
| //
 | |
| // The buf allows passing various buffer implementations that make decoding more
 | |
| // efficient. See NewSyncDecodeBuffer and NewConcurrentDecodeBuffer for further
 | |
| // details. For non-zstd compression types, it is valid to pass nil buf.
 | |
| //
 | |
| // Decode is concurrency-safe, however note the concurrency limits for the
 | |
| // buffer of your choice.
 | |
| func Decode(t Type, src []byte, buf DecodeBuffer) (ret []byte, err error) {
 | |
| 	if len(src) == 0 || t == "" || t == None {
 | |
| 		return src, nil
 | |
| 	}
 | |
| 	if t == Snappy {
 | |
| 		var b []byte
 | |
| 		if buf != nil {
 | |
| 			b = buf.get()
 | |
| 			defer func() {
 | |
| 				buf.set(ret)
 | |
| 			}()
 | |
| 		}
 | |
| 		// The snappy library uses `len` to calculate if we need a new buffer.
 | |
| 		// In order to allocate as few buffers as possible make the length
 | |
| 		// equal to the capacity.
 | |
| 		b = b[:cap(b)]
 | |
| 		return snappy.Decode(b, src)
 | |
| 	}
 | |
| 	if t == Zstd {
 | |
| 		if buf == nil {
 | |
| 			return nil, errors.New("zstd requested but DecodeBuffer was not provided")
 | |
| 		}
 | |
| 		b := buf.get()
 | |
| 		defer func() {
 | |
| 			buf.set(ret)
 | |
| 		}()
 | |
| 		return buf.zstdDecBuf().DecodeAll(src, b[:0])
 | |
| 	}
 | |
| 	return nil, fmt.Errorf("unsupported compression type: %s", t)
 | |
| }
 |