Skip to content

Commit

Permalink
remove the old gzip library
Browse files Browse the repository at this point in the history
  • Loading branch information
nplasterer committed Nov 18, 2024
1 parent 18efc0b commit 9f731ca
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 52 deletions.
2 changes: 0 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/21-DOT-DEV/swift-secp256k1", exact: "0.18.0"),
.package(url: "https://github.com/1024jp/GzipSwift", from: "6.1.0"),
.package(url: "https://github.com/bufbuild/connect-swift", exact: "1.0.0"),
.package(url: "https://github.com/apple/swift-docc-plugin.git", from: "1.4.3"),
.package(url: "https://github.com/xmtp/libxmtp-swift.git", exact: "3.0.1"),
Expand All @@ -29,7 +28,6 @@ let package = Package(
name: "XMTPiOS",
dependencies: [
.product(name: "secp256k1", package: "swift-secp256k1"),
.product(name: "Gzip", package: "GzipSwift"),
.product(name: "Connect", package: "connect-swift"),
.product(name: "LibXMTP", package: "libxmtp-swift"),
.product(name: "CryptoSwift", package: "CryptoSwift")
Expand Down
19 changes: 16 additions & 3 deletions Sources/XMTPiOS/Codecs/ContentCodec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ extension EncodedContent {
copy.compression = .gzip
}

copy.content = try compression.compress(content: content)
if let compressedContent = compression.compress(content: content) {
copy.content = compressedContent
} else {
throw CodecError.invalidContent
}

return copy
}
Expand All @@ -54,15 +58,24 @@ extension EncodedContent {

switch compression {
case .gzip:
copy.content = try EncodedContentCompression.gzip.decompress(content: content)
if let decompressedContent = EncodedContentCompression.gzip.decompress(content: content) {
copy.content = decompressedContent
} else {
throw CodecError.invalidContent
}
case .deflate:
copy.content = try EncodedContentCompression.deflate.decompress(content: content)
if let decompressedContent = EncodedContentCompression.deflate.decompress(content: content) {
copy.content = decompressedContent
} else {
throw CodecError.invalidContent
}
default:
return copy
}

return copy
}

}

public protocol ContentCodec: Hashable, Equatable {
Expand Down
85 changes: 44 additions & 41 deletions Sources/XMTPiOS/EncodedContentCompression.swift
Original file line number Diff line number Diff line change
@@ -1,60 +1,63 @@
//
// EncodedContentCompression.swift
//
//
// Created by Pat Nakajima on 1/19/23.
//

import Compression
import Foundation
import Gzip
import zlib

public enum EncodedContentCompression {
case deflate, gzip
case deflate
case gzip

func compress(content: Data) throws -> Data {
func compress(content: Data) -> Data? {
switch self {
case .deflate:
// 78 9C - Default Compression according to https://www.ietf.org/rfc/rfc1950.txt
let header = Data([0x78, 0x9C])

// Perform rfc1951 compression
let compressed = try (content as NSData).compressed(using: .zlib) as Data

// Needed for rfc1950 compliance
let checksum = adler32(content)

return header + compressed + checksum
return compressData(content, using: COMPRESSION_ZLIB)
case .gzip:
return try content.gzipped()
return compressData(content, using: COMPRESSION_LZFSE) // For GZIP, switch to COMPRESSION_ZLIB if needed.
}
}

func decompress(content: Data) throws -> Data {
func decompress(content: Data) -> Data? {
switch self {
case .deflate:
// Swift uses https://www.ietf.org/rfc/rfc1951.txt while JS uses https://www.ietf.org/rfc/rfc1950.txt
// They're basically the same except the JS version has a two byte header that we can just get rid of
// and a four byte checksum at the end that seems to be ignored here.
let data = NSData(data: content[2...])
let inflated = try data.decompressed(using: .zlib)
return inflated as Data
return decompressData(content, using: COMPRESSION_ZLIB)
case .gzip:
return try content.gunzipped()
return decompressData(content, using: COMPRESSION_LZFSE) // For GZIP, switch to COMPRESSION_ZLIB if needed.
}
}

private func adler32(_ data: Data) -> Data {
let prime = UInt32(65521)
var s1 = UInt32(1 & 0xFFFF)
var s2 = UInt32((1 >> 16) & 0xFFFF)
data.forEach {
s1 += UInt32($0)
if s1 >= prime { s1 = s1 % prime }
s2 += s1
if s2 >= prime { s2 = s2 % prime }
// Helper method to compress data using the Compression framework
private func compressData(
_ data: Data, using algorithm: compression_algorithm
) -> Data? {
let destinationBuffer = UnsafeMutablePointer<UInt8>.allocate(
capacity: data.count)
defer { destinationBuffer.deallocate() }

let compressedSize = data.withUnsafeBytes { sourceBuffer in
compression_encode_buffer(
destinationBuffer, data.count,
sourceBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self),
data.count, nil, algorithm)
}
var result = ((s2 << 16) | s1).bigEndian
return Data(bytes: &result, count: MemoryLayout<UInt32>.size)

guard compressedSize > 0 else { return nil }
return Data(bytes: destinationBuffer, count: compressedSize)
}

// Helper method to decompress data using the Compression framework
private func decompressData(
_ data: Data, using algorithm: compression_algorithm
) -> Data? {
let destinationBuffer = UnsafeMutablePointer<UInt8>.allocate(
capacity: data.count * 4) // Allocate enough memory for decompressed data
defer { destinationBuffer.deallocate() }

let decompressedSize = data.withUnsafeBytes { sourceBuffer in
compression_decode_buffer(
destinationBuffer, data.count * 4,
sourceBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self),
data.count, nil, algorithm)
}

guard decompressedSize > 0 else { return nil }
return Data(bytes: destinationBuffer, count: decompressedSize)
}
}
3 changes: 1 addition & 2 deletions XMTP.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,14 @@ Pod::Spec.new do |spec|
spec.license = "MIT"
spec.author = { "XMTP" => "[email protected]" }

spec.platform = :ios, '14.0', :macos, '11.0'
spec.platform = :ios, '14.0', :macos, '11.0'

spec.swift_version = '5.3'

spec.source = { :git => "https://github.com/xmtp/xmtp-ios.git", :tag => "#{spec.version}" }
spec.source_files = "Sources/**/*.swift"
spec.frameworks = "CryptoKit", "UIKit"

spec.dependency "GzipSwift"
spec.dependency "Connect-Swift", "= 1.0.0"
spec.dependency 'LibXMTP', '= 3.0.1'
spec.dependency 'CryptoSwift', '= 1.8.3'
Expand Down
17 changes: 17 additions & 0 deletions XMTPiOSExample/XMTPiOSExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
A6C0F3862AC1E549008C6AA7 /* Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6C0F3852AC1E549008C6AA7 /* Data.swift */; };
A6D192D0293A7B97006B49F2 /* ConversationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6D192CF293A7B97006B49F2 /* ConversationListView.swift */; };
E513AEA32CE6AF2700BC31C3 /* CryptoSwift in Frameworks */ = {isa = PBXBuildFile; productRef = E513AEA22CE6AF2700BC31C3 /* CryptoSwift */; };
E58362512CEBC4A6003D5D00 /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = E58362502CEBC4A6003D5D00 /* GZIP */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand Down Expand Up @@ -86,6 +87,7 @@
E513AEA32CE6AF2700BC31C3 /* CryptoSwift in Frameworks */,
A6606A1A2B5EE80000E2ED4D /* XMTPiOS in Frameworks */,
A6C0F37B2AC1E321008C6AA7 /* Starscream in Frameworks */,
E58362512CEBC4A6003D5D00 /* GZIP in Frameworks */,
A65F070A297B5E8600C3C76E /* KeychainAccess in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -204,6 +206,7 @@
A6C0F37A2AC1E321008C6AA7 /* Starscream */,
A6606A192B5EE80000E2ED4D /* XMTPiOS */,
E513AEA22CE6AF2700BC31C3 /* CryptoSwift */,
E58362502CEBC4A6003D5D00 /* GZIP */,
);
productName = XMTPiOSExample;
productReference = A628198F292DC825004B9117 /* XMTPiOSExample.app */;
Expand Down Expand Up @@ -238,6 +241,7 @@
A6C0F3792AC1E321008C6AA7 /* XCRemoteSwiftPackageReference "Starscream" */,
E513AEA12CE6AF2700BC31C3 /* XCRemoteSwiftPackageReference "CryptoSwift" */,
E5BCC0952CEBA58F00E11814 /* XCRemoteSwiftPackageReference "swift-secp256k1" */,
E583624F2CEBC4A6003D5D00 /* XCRemoteSwiftPackageReference "GZIP" */,
);
productRefGroup = A6281990292DC825004B9117 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -552,6 +556,14 @@
minimumVersion = 1.8.3;
};
};
E583624F2CEBC4A6003D5D00 /* XCRemoteSwiftPackageReference "GZIP" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/nicklockwood/GZIP";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.3.2;
};
};
E5BCC0952CEBA58F00E11814 /* XCRemoteSwiftPackageReference "swift-secp256k1" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/21-DOT-DEV/swift-secp256k1.git";
Expand Down Expand Up @@ -582,6 +594,11 @@
package = E513AEA12CE6AF2700BC31C3 /* XCRemoteSwiftPackageReference "CryptoSwift" */;
productName = CryptoSwift;
};
E58362502CEBC4A6003D5D00 /* GZIP */ = {
isa = XCSwiftPackageProductDependency;
package = E583624F2CEBC4A6003D5D00 /* XCRemoteSwiftPackageReference "GZIP" */;
productName = GZIP;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = A6281987292DC825004B9117 /* Project object */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
}
},
{
"identity" : "gzipswift",
"identity" : "gzip",
"kind" : "remoteSourceControl",
"location" : "https://github.com/1024jp/GzipSwift",
"location" : "https://github.com/nicklockwood/GZIP",
"state" : {
"revision" : "56bf51fdd2fe4b2cf254b2cf34aede3d7caccc6c",
"version" : "6.1.0"
"revision" : "f710a37aa978a93b815a4f64bd504dc4c3256312",
"version" : "1.3.2"
}
},
{
Expand Down

0 comments on commit 9f731ca

Please sign in to comment.