diff --git a/internal/compression/old-compression.go b/internal/compression/old-compression.go deleted file mode 100644 index eeca6b8..0000000 --- a/internal/compression/old-compression.go +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2026 Safronov Grigorii - * - * Licensed under the CDDL, Version 1.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * You may obtain a copy of the License at - * https://opensource.org/licenses/CDDL-1.0 - */ - -// Файл: internal/compression/compression.go -// Назначение: Реализация сжатия данных с использованием различных алгоритмов. -// Поддерживаемые алгоритмы: Snappy (по умолчанию), LZ4, Zstandard. -// Обеспечивает прозрачное сжатие/распаковку для документов. - -package compression - -import ( - "bytes" - "encoding/binary" - "fmt" - - "github.com/golang/snappy" - "github.com/klauspost/compress/zstd" - "github.com/pierrec/lz4/v4" -) - -// Config представляет конфигурацию сжатия -type Config struct { - Enabled bool // Включено ли сжатие - Algorithm string // Алгоритм сжатия: snappy, lz4, zstd - Level int // Уровень сжатия (1-9) - MinSize int // Минимальный размер для сжатия (байт) -} - -// MagicNumber используется для идентификации сжатых данных -var MagicNumber = []byte{0x46, 0x54, 0x52, 0x53} // "FTRS" - Futriis - -// CompressionType определяет тип сжатия -type CompressionType byte - -const ( - CompressionNone CompressionType = 0x00 - CompressionSnappy CompressionType = 0x01 - CompressionLZ4 CompressionType = 0x02 - CompressionZstd CompressionType = 0x03 -) - -// Compress сжимает данные с использованием указанного алгоритма -func Compress(data []byte, config *Config) ([]byte, error) { - if !config.Enabled { - return data, nil - } - - if len(data) < config.MinSize { - return data, nil - } - - var compressed []byte - var err error - var compType CompressionType - - switch config.Algorithm { - case "snappy": - compressed = snappy.Encode(nil, data) - compType = CompressionSnappy - case "lz4": - buf := bytes.NewBuffer(nil) - lz4Writer := lz4.NewWriter(buf) - - // Установка уровня сжатия для LZ4 - if config.Level > 0 { - // LZ4 уровни: 0-9, где 0=быстрый, 9=максимальное сжатие - compressionLevel := lz4.CompressionLevel(config.Level) - if err := lz4Writer.Apply(lz4.CompressionLevelOption(compressionLevel)); err != nil { - return nil, fmt.Errorf("failed to set LZ4 compression level: %v", err) - } - } - - if _, err := lz4Writer.Write(data); err != nil { - return nil, err - } - if err := lz4Writer.Close(); err != nil { - return nil, err - } - compressed = buf.Bytes() - compType = CompressionLZ4 - case "zstd": - // Для Zstandard используем предустановленные уровни скорости - var encoder *zstd.Encoder - var encoderLevel zstd.EncoderLevel - - // Выбираем уровень сжатия на основе config.Level - switch { - case config.Level <= 1: - encoderLevel = zstd.SpeedFastest - case config.Level <= 3: - encoderLevel = zstd.SpeedDefault - case config.Level <= 6: - encoderLevel = zstd.SpeedBetterCompression - default: - encoderLevel = zstd.SpeedBestCompression - } - - // Создаём энкодер с выбранным уровнем - encoder, err = zstd.NewWriter(nil, zstd.WithEncoderLevel(encoderLevel)) - if err != nil { - return nil, fmt.Errorf("failed to create zstd encoder: %v", err) - } - defer encoder.Close() - - compressed = encoder.EncodeAll(data, nil) - compType = CompressionZstd - default: - return nil, fmt.Errorf("unsupported compression algorithm: %s", config.Algorithm) - } - - // Проверяем, что сжатие действительно уменьшило размер - if len(compressed) >= len(data) { - return data, nil - } - - // Добавляем заголовок: магическое число (4 байта) + тип сжатия (1 байт) + оригинальный размер (8 байт) - header := make([]byte, 4+1+8) - copy(header[0:4], MagicNumber) - header[4] = byte(compType) - binary.LittleEndian.PutUint64(header[5:], uint64(len(data))) - - result := make([]byte, 0, len(header)+len(compressed)) - result = append(result, header...) - result = append(result, compressed...) - - return result, nil -} - -// Decompress распаковывает данные -func Decompress(data []byte) ([]byte, error) { - // Проверяем наличие магического числа - if len(data) < 4+1+8 { - return nil, fmt.Errorf("data too short for compressed format") - } - - // Проверяем магическое число - if !bytes.Equal(data[0:4], MagicNumber) { - return nil, fmt.Errorf("invalid magic number") - } - - compType := CompressionType(data[4]) - originalSize := binary.LittleEndian.Uint64(data[5:13]) - compressedData := data[13:] - - if originalSize == 0 { - return nil, fmt.Errorf("invalid original size") - } - - var decompressed []byte - var err error - - switch compType { - case CompressionSnappy: - decompressed, err = snappy.Decode(nil, compressedData) - if err != nil { - return nil, fmt.Errorf("snappy decode failed: %v", err) - } - case CompressionLZ4: - decompressed = make([]byte, originalSize) - lz4Reader := lz4.NewReader(bytes.NewReader(compressedData)) - n, err := lz4Reader.Read(decompressed) - if err != nil && err.Error() != "EOF" { - return nil, fmt.Errorf("lz4 decode failed: %v", err) - } - if n != int(originalSize) { - // Некоторые данные могли быть прочитаны, но не все - decompressed = decompressed[:n] - } - case CompressionZstd: - decoder, err := zstd.NewReader(nil) - if err != nil { - return nil, fmt.Errorf("failed to create zstd decoder: %v", err) - } - defer decoder.Close() - - decompressed, err = decoder.DecodeAll(compressedData, nil) - if err != nil { - return nil, fmt.Errorf("zstd decode failed: %v", err) - } - case CompressionNone: - return compressedData, nil - default: - return nil, fmt.Errorf("unsupported compression type: %d", compType) - } - - // Проверяем размер распакованных данных - if len(decompressed) != int(originalSize) { - // Не критично, но логируем - _ = len(decompressed) - } - - return decompressed, nil -} - -// DecompressAuto автоматически определяет, сжаты ли данные, и распаковывает при необходимости -func DecompressAuto(data []byte) ([]byte, error) { - // Проверяем, есть ли магическое число (признак сжатых данных) - if len(data) >= 4 && bytes.Equal(data[0:4], MagicNumber) { - return Decompress(data) - } - return data, nil -} - -// IsCompressed проверяет, сжаты ли данные -func IsCompressed(data []byte) bool { - if len(data) < 4 { - return false - } - return bytes.Equal(data[0:4], MagicNumber) -} - -// GetCompressionType возвращает тип сжатия данных -func GetCompressionType(data []byte) CompressionType { - if !IsCompressed(data) || len(data) < 5 { - return CompressionNone - } - return CompressionType(data[4]) -} - -// GetCompressionRatio возвращает коэффициент сжатия -func GetCompressionRatio(original, compressed []byte) float64 { - if len(original) == 0 { - return 1.0 - } - return float64(len(compressed)) / float64(len(original)) -}