// // CompressionUtil.swift // bitchat // // This is free and unencumbered software released into the public domain. // For more information, see // import struct Foundation.Data private import Compression struct CompressionUtil { // Compression threshold - don't compress if data is smaller than this static let compressionThreshold = Constants.compressionThresholdBytes // bytes // Compress data using zlib algorithm (most compatible) static func compress(_ data: Data) -> Data? { // Skip compression for small data guard data.count >= compressionThreshold else { return nil } let maxCompressedSize = data.count + (data.count / 255) + 16 let destinationBuffer = UnsafeMutablePointer.allocate(capacity: maxCompressedSize) defer { destinationBuffer.deallocate() } let compressedSize = data.withUnsafeBytes { sourceBuffer in guard let sourcePtr = sourceBuffer.bindMemory(to: UInt8.self).baseAddress else { return 0 } return compression_encode_buffer( destinationBuffer, data.count, sourcePtr, data.count, nil, COMPRESSION_ZLIB ) } guard compressedSize > 0 && compressedSize < data.count else { return nil } return Data(bytes: destinationBuffer, count: compressedSize) } // Decompress zlib compressed data static func decompress(_ compressedData: Data, originalSize: Int) -> Data? { let destinationBuffer = UnsafeMutablePointer.allocate(capacity: originalSize) defer { destinationBuffer.deallocate() } let decompressedSize = compressedData.withUnsafeBytes { sourceBuffer in guard let sourcePtr = sourceBuffer.bindMemory(to: UInt8.self).baseAddress else { return 0 } return compression_decode_buffer( destinationBuffer, originalSize, sourcePtr, compressedData.count, nil, COMPRESSION_ZLIB ) } guard decompressedSize > 0 else { return nil } return Data(bytes: destinationBuffer, count: decompressedSize) } // Helper to check if compression is worth it static func shouldCompress(_ data: Data) -> Bool { // Don't compress if: // 1. Data is too small // 2. Data appears to be already compressed (high entropy) guard data.count >= compressionThreshold else { return false } // Quick uniqueness check — a high diversity of bytes usually means the // payload is already compressed. We only need to know how many unique // values exist rather than keeping full frequency counts. let uniqueByteCount = Set(data).count let sampleSize = min(data.count, 256) let uniqueByteRatio = Double(uniqueByteCount) / Double(sampleSize) return uniqueByteRatio < 0.9 // Compress if less than 90% unique bytes } }