Cinn
Cinn

Reputation: 4517

Zlib compression between Swift and Go

My Swift application communicates to a server written in Go. I'd like the data transferred to be compressed using Zlib, but it appears that the compression results are different from Swift and Go.

Here is the Go version:

sourceString := "A-t-elle besoin d'autres preuves ? Acceptez-la pour le plaisir. J'ai tant fait que de la cueillir, Et c'est presque une fleur-des-veuves."

// Compression
var b bytes.Buffer
writer := zlib.NewWriter(&b)
writer.Write([]byte(sourceString))
writer.Close()

// Base 64
b64 := base64.StdEncoding.EncodeToString(b.Bytes())

fmt.Println(b64)

It gives the following (Go Playground):

eJwczb2tg0AQReFWbkbylhaeCJy4i/FykUYaLev5IXD1Fs6Pzre1bDQjXoxTB/ZFKp2B6ayLgX9svXMmP80E8yyHEdNEQ33FcxFFykgcool3ETthgl5UM/U/PBJ9YeS9jDuoQRzG8rYz2vVz1m8AAAD//++yMFQ=

Now using the following Swift code (based on this article):

let sourceString = "A-t-elle besoin d'autres preuves ? Acceptez-la pour le plaisir. J'ai tant fait que de la cueillir, Et c'est presque une fleur-des-veuves."

var sourceBuffer = Array(sourceString.utf8)

let destinationBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: sourceString.count)

let algorithm = COMPRESSION_ZLIB

let compressedSize = compression_encode_buffer(destinationBuffer, sourceString.count, &sourceBuffer, sourceString.count, nil, algorithm)

if compressedSize == 0 {
    fatalError("Encoding failed.")
}

// EDIT after @Steffen Ullrich answer
// let encodedString = String(cString: destinationBuffer)
// let encodedStringb64 = Data(encodedString.utf8).base64EncodedString()

let encodedData = NSData(bytesNoCopy: destinationBuffer, length: compressedSize)
let encodedStringb64 = encodedData.base64EncodedString()

print(encodedStringb64)

We get:

H̶e̶+̶/̶v̶T̶E̶O̶7̶7̶+̶9̶M̶A̶x̶D̶0̶a̶t̶w̶7̶7̶+̶9̶U̶u̶+̶/̶v̶Q̶p̶F̶7̶7̶+̶9̶L̶O̶+̶/̶v̶e̶+̶/̶v̶e̶+̶/̶v̶T̶D̶v̶v̶7̶0̶=̶ Hc0xDsMwDEPRq3DzUucKRYYsvYXqMIAAwXFtKUNPX6cTlwf+NXumGfHmOLViTxLeOdA645r7xFoKm/ObTdDO6Ji6mejQvuCVROFSHYeo4xPETkxZgmqm/YHNURKH35fjBlGJwxg97xz5+neWHw==

As you can see it is very different, what am i doing wrong here?

Upvotes: 0

Views: 393

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123531

I'm not familiar with Swift but the Go code returns a zlib (RFC 1950) compressed string while according to the documentation from Apple the Swift code should at most return a deflate compressed string (RFC 1951), i.e. like the zlib compressed but without the 2 byte zlib header.

With that knowledge the string returned from the Go code can be properly decompressed while the string returned from Swift can not. The difference in size is also obvious which lets me assume that something was cut off. It looks like you treat the compressed data destinationBuffer as a cString, which means that any \0-byte inside the string will be treated as the end of the string. It is likely that such \0 byte exists as the result of compression and that the string got cut off there, i.e. that your output shows only part of the real destinationBuffer. (EDIT: the last part does not apply anymore since the OP changed the question with a proper result).

Upvotes: 1

Related Questions