Skip to content

Commit 7507caf

Browse files
authored
Removed DataCompression dependency from SPM & CocoaPods (#905)
1 parent 5721c12 commit 7507caf

File tree

7 files changed

+244
-34
lines changed

7 files changed

+244
-34
lines changed

NOTICE

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
OpenTelemetry-Swift
2+
Copyright 2025 OpenTelemetry Authors
3+
4+
This product includes portions derived from "DataCompression"
5+
Copyright © 2016 Markus Wanke
6+
Licensed under the Apache License, Version 2.0
7+
https://github.com/mw99/DataCompression

OpenTelemetry-Swift-Protocol-Exporter-Http.podspec

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ Pod::Spec.new do |spec|
2121
spec.dependency 'OpenTelemetry-Swift-Api', spec.version.to_s
2222
spec.dependency 'OpenTelemetry-Swift-Sdk', spec.version.to_s
2323
spec.dependency 'OpenTelemetry-Swift-Protocol-Exporter-Common', spec.version.to_s
24-
spec.dependency 'DataCompression', '3.8.0'
2524
spec.dependency 'SwiftProtobuf', '~> 1.28'
2625
spec.pod_target_xcconfig = { "OTHER_SWIFT_FLAGS" => "-module-name OpenTelemetryProtocolExporterHttp -package-name opentelemetry_swift_exporter_http" }
2726

Package.resolved

Lines changed: 0 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ let package = Package(
3333
.package(url: "https://github.com/grpc/grpc-swift.git", exact: "1.26.1"),
3434
.package(url: "https://github.com/apple/swift-protobuf.git", from: "1.30.0"),
3535
.package(url: "https://github.com/apple/swift-log.git", from: "1.6.3"),
36-
.package(url: "https://github.com/apple/swift-metrics.git", from: "2.7.0"),
37-
.package(url: "https://github.com/mw99/DataCompression", from: "3.9.0")
36+
.package(url: "https://github.com/apple/swift-metrics.git", from: "2.7.0")
3837
],
3938
targets: [
4039
.target(
@@ -77,12 +76,7 @@ let package = Package(
7776
name: "OpenTelemetryProtocolExporterHttp",
7877
dependencies: [
7978
.product(name: "OpenTelemetrySdk", package: "opentelemetry-swift-core"),
80-
"OpenTelemetryProtocolExporterCommon",
81-
.product(
82-
name: "DataCompression",
83-
package: "DataCompression",
84-
condition: .when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .visionOS])
85-
)
79+
"OpenTelemetryProtocolExporterCommon"
8680
],
8781
path: "Sources/Exporters/OpenTelemetryProtocolHttp"
8882
),
@@ -142,11 +136,6 @@ let package = Package(
142136
dependencies: [
143137
"OpenTelemetryProtocolExporterGrpc",
144138
"OpenTelemetryProtocolExporterHttp",
145-
.product(
146-
name: "DataCompression",
147-
package: "DataCompression",
148-
condition: .when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .visionOS])
149-
),
150139
.product(name: "NIO", package: "swift-nio"),
151140
.product(name: "NIOHTTP1", package: "swift-nio"),
152141
.product(name: "NIOTestUtils", package: "swift-nio")
@@ -343,11 +332,6 @@ extension Package {
343332
.product(name: "OpenTelemetrySdk", package: "opentelemetry-swift-core"),
344333
"OpenTelemetryProtocolExporterHttp", .product(name: "StdoutExporter", package: "opentelemetry-swift-core"),
345334
"ZipkinExporter", "ResourceExtension", "SignPostIntegration",
346-
.product(
347-
name: "DataCompression",
348-
package: "DataCompression",
349-
condition: .when(platforms: [.macOS, .iOS, .watchOS, .tvOS, .visionOS])
350-
)
351335
],
352336
path: "Examples/OTLP HTTP Exporter",
353337
exclude: ["README.md", "collector-config.yaml", "docker-compose.yaml", "prometheus.yaml", "images"]
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// Portions derived from "DataCompression" (Apache-2.0)
2+
// https://github.com/mw99/DataCompression/
3+
//
4+
// Copyright 2016, Markus Wanke
5+
//
6+
// Modifications for OpenTelemetry-Swift: namespacing, limited algorithms and internal visibility.
7+
8+
#if canImport(Compression)
9+
import Compression
10+
import Foundation
11+
12+
fileprivate extension Data {
13+
func withUnsafeBytes<ResultType, ContentType>(
14+
_ body: (UnsafePointer<ContentType>) throws -> ResultType
15+
) rethrows -> ResultType
16+
{
17+
return try self.withUnsafeBytes({ (rawBufferPointer: UnsafeRawBufferPointer) -> ResultType in
18+
return try body(rawBufferPointer.bindMemory(to: ContentType.self).baseAddress!)
19+
})
20+
}
21+
}
22+
23+
extension Data {
24+
/// Compresses the data using the zlib deflate algorithm.
25+
/// - returns: raw deflated data according to [RFC-1951](https://tools.ietf.org/html/rfc1951).
26+
/// - note: Fixed at compression level 5 (best trade off between speed and time)
27+
func deflate() -> Data?
28+
{
29+
return self.withUnsafeBytes { (sourcePtr: UnsafePointer<UInt8>) -> Data? in
30+
let config = (operation: COMPRESSION_STREAM_ENCODE, algorithm: COMPRESSION_ZLIB)
31+
return perform(config, source: sourcePtr, sourceSize: count)
32+
}
33+
}
34+
35+
/// Compresses the data using the deflate algorithm and makes it comply to the gzip stream format.
36+
/// - returns: deflated data in gzip format [RFC-1952](https://tools.ietf.org/html/rfc1952)
37+
/// - note: Fixed at compression level 5 (best trade off between speed and time)
38+
func gzip() -> Data?
39+
{
40+
var header = Data([0x1f, 0x8b, 0x08, 0x00]) // magic, magic, deflate, noflags
41+
42+
var unixtime = UInt32(Date().timeIntervalSince1970).littleEndian
43+
header.append(Data(bytes: &unixtime, count: MemoryLayout<UInt32>.size))
44+
45+
header.append(contentsOf: [0x00, 0x03]) // normal compression level, unix file type
46+
47+
let deflated = self.withUnsafeBytes { (sourcePtr: UnsafePointer<UInt8>) -> Data? in
48+
let config = (operation: COMPRESSION_STREAM_ENCODE, algorithm: COMPRESSION_ZLIB)
49+
return perform(config, source: sourcePtr, sourceSize: count, preload: header)
50+
}
51+
52+
guard var result = deflated else { return nil }
53+
54+
// append checksum
55+
var crc32: UInt32 = self.crc32().checksum.littleEndian
56+
result.append(Data(bytes: &crc32, count: MemoryLayout<UInt32>.size))
57+
58+
// append size of original data
59+
var isize: UInt32 = UInt32(truncatingIfNeeded: count).littleEndian
60+
result.append(Data(bytes: &isize, count: MemoryLayout<UInt32>.size))
61+
62+
return result
63+
}
64+
65+
/// Calculate the Crc32 checksum of the data.
66+
/// - returns: Crc32 checksum type. Can still be further advanced.
67+
func crc32() -> Crc32
68+
{
69+
var res = Crc32()
70+
res.advance(withChunk: self)
71+
return res
72+
}
73+
74+
fileprivate typealias DataCompressionConfig = (
75+
operation: compression_stream_operation,
76+
algorithm: compression_algorithm
77+
)
78+
79+
fileprivate func perform(
80+
_ config: DataCompressionConfig,
81+
source: UnsafePointer<UInt8>,
82+
sourceSize: Int,
83+
preload: Data = Data()) -> Data?
84+
{
85+
guard config.operation == COMPRESSION_STREAM_ENCODE || sourceSize > 0 else { return nil }
86+
87+
let streamBase = UnsafeMutablePointer<compression_stream>.allocate(capacity: 1)
88+
defer { streamBase.deallocate() }
89+
var stream = streamBase.pointee
90+
91+
let status = compression_stream_init(&stream, config.operation, config.algorithm)
92+
guard status != COMPRESSION_STATUS_ERROR else { return nil }
93+
defer { compression_stream_destroy(&stream) }
94+
95+
var result = preload
96+
var flags: Int32 = Int32(COMPRESSION_STREAM_FINALIZE.rawValue)
97+
let blockLimit = 64 * 1024
98+
var bufferSize = Swift.max(sourceSize, 64)
99+
100+
if sourceSize > blockLimit {
101+
bufferSize = blockLimit
102+
if config.algorithm == COMPRESSION_LZFSE && config.operation != COMPRESSION_STREAM_ENCODE {
103+
// This fixes a bug in Apples lzfse decompressor. it will sometimes fail randomly when the input gets
104+
// splitted into multiple chunks and the flag is not 0. Even though it should always work with FINALIZE...
105+
flags = 0
106+
}
107+
}
108+
109+
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)
110+
defer { buffer.deallocate() }
111+
112+
stream.dst_ptr = buffer
113+
stream.dst_size = bufferSize
114+
stream.src_ptr = source
115+
stream.src_size = sourceSize
116+
117+
while true {
118+
switch compression_stream_process(&stream, flags) {
119+
case COMPRESSION_STATUS_OK:
120+
guard stream.dst_size == 0 else { return nil }
121+
result.append(buffer, count: stream.dst_ptr - buffer)
122+
stream.dst_ptr = buffer
123+
stream.dst_size = bufferSize
124+
125+
if flags == 0 && stream.src_size == 0 { // part of the lzfse bugfix above
126+
flags = Int32(COMPRESSION_STREAM_FINALIZE.rawValue)
127+
}
128+
129+
case COMPRESSION_STATUS_END:
130+
result.append(buffer, count: stream.dst_ptr - buffer)
131+
return result
132+
133+
default:
134+
return nil
135+
}
136+
}
137+
}
138+
}
139+
140+
/// Struct based type representing a Crc32 checksum.
141+
public struct Crc32: CustomStringConvertible {
142+
private static let zLibCrc32: ZLibCrc32FuncPtr? = loadCrc32fromZLib()
143+
144+
public init() {}
145+
146+
// C convention function pointer type matching the signature of `libz::crc32`
147+
private typealias ZLibCrc32FuncPtr = @convention(c) (
148+
_ cks: UInt32,
149+
_ buf: UnsafePointer<UInt8>,
150+
_ len: UInt32
151+
) -> UInt32
152+
153+
/// Raw checksum. Updated after a every call to `advance(withChunk:)`
154+
public var checksum: UInt32 = 0
155+
156+
/// Advance the current checksum with a chunk of data. Designed t be called multiple times.
157+
/// - parameter chunk: data to advance the checksum
158+
public mutating func advance(withChunk chunk: Data)
159+
{
160+
if let fastCrc32 = Crc32.zLibCrc32 {
161+
checksum = chunk.withUnsafeBytes({ (ptr: UnsafePointer<UInt8>) -> UInt32 in
162+
return fastCrc32(checksum, ptr, UInt32(chunk.count))
163+
})
164+
}
165+
else {
166+
checksum = slowCrc32(start: checksum, data: chunk)
167+
}
168+
}
169+
170+
/// Formatted checksum.
171+
public var description: String
172+
{
173+
return String(format: "%08x", checksum)
174+
}
175+
176+
/// Load `crc32()` from '/usr/lib/libz.dylib' if libz is installed.
177+
/// - returns: A function pointer to crc32() of zlib or nil if zlib can't be found
178+
private static func loadCrc32fromZLib() -> ZLibCrc32FuncPtr?
179+
{
180+
guard let libz = dlopen("/usr/lib/libz.dylib", RTLD_NOW) else { return nil }
181+
guard let fptr = dlsym(libz, "crc32") else { return nil }
182+
return unsafeBitCast(fptr, to: ZLibCrc32FuncPtr.self)
183+
}
184+
185+
/// Rudimentary fallback implementation of the crc32 checksum. This is only a backup used
186+
/// when zlib can't be found under '/usr/lib/libz.dylib'.
187+
/// - returns: crc32 checksum (4 byte)
188+
private func slowCrc32(start: UInt32, data: Data) -> UInt32
189+
{
190+
return ~data.reduce(~start) { (crc: UInt32, next: UInt8) -> UInt32 in
191+
let tableOffset = (crc ^ UInt32(next)) & 0xff
192+
return lookUpTable[Int(tableOffset)] ^ crc >> 8
193+
}
194+
}
195+
196+
/// Lookup table for faster crc32 calculation.
197+
/// table source: http://web.mit.edu/freebsd/head/sys/libkern/crc32.c
198+
private let lookUpTable: [UInt32] = [
199+
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
200+
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
201+
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
202+
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
203+
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
204+
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
205+
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
206+
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
207+
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
208+
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
209+
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
210+
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
211+
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
212+
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
213+
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
214+
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
215+
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
216+
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
217+
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
218+
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
219+
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
220+
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
221+
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
222+
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
223+
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
224+
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
225+
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
226+
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
227+
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
228+
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
229+
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
230+
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
231+
]
232+
}
233+
234+
#endif

Sources/Exporters/OpenTelemetryProtocolHttp/OtlpHttpExporterBase.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
// SPDX-License-Identifier: Apache-2.0
44
//
55

6-
#if canImport(Compression)
7-
import DataCompression
8-
#endif
96
import Foundation
107
import OpenTelemetryProtocolExporterCommon
118
import SwiftProtobuf

Tests/ExportersTests/OpenTelemetryProtocol/OtlpHTTPExporterBaseTests.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
//
55

66
#if canImport(Compression)
7-
import DataCompression
8-
97
import Foundation
108
#if canImport(FoundationNetworking)
119
import FoundationNetworking
@@ -138,4 +136,4 @@
138136
return testData
139137
}
140138
}
141-
#endif
139+
#endif

0 commit comments

Comments
 (0)