alexeyxo / protobuf-swift

Google ProtocolBuffers for Apple Swift
http://protobuf.io/#swift
Apache License 2.0
940 stars 138 forks source link

ProtoBuf3.0-Swift2.0 builder to NSData, Data missing... #134

Closed whoooami closed 8 years ago

whoooami commented 8 years ago

Version of protoc (protoc --version)

3.0

Version of ProtocolBuffers.framework

ProtoBuf3.0-Swift2.0

.proto file to reproduce

message UserLoginIN {
    int32 id = 1;
    string username = 2;
    string password = 3;
    string key = 4;
    string addon = 5;
}

Description

    var data:NSData = NSData()
    let loginIn = UserLoginIn.Builder()
    loginIn.setId(0x03)
        .setUsername("nothing")
        .setPassword("123456")

    do {
        try data = loginIn.build().data()
        print(NSString(data: data, encoding: NSUTF8StringEncoding)) 
    } catch {
        print(error)
    }
    client.writeData(data, withTimeout: 0, tag: 0)
    client.readDataWithTimeout(10, tag: 0)

print(NSString(data: data, encoding: NSUTF8StringEncoding)) only print Optional (nothing123456) missing field id 3 not Optional (3nothing123456), I want know why? When I use netty protobuf of java send to netty server, the same data struct and same data I receive the array is [8, 3, 18, 7, 110, 111, 116, 104, 105, 110, 103, 26, 6, 49, 50, 51, 52, 53, 54], but when I use AsyncSocket and protobuf-swift of swift, I receive array [3, 18, 7, 110, 111, 116, 104, 105], why? @alecthomas @eventualbuddha @mpruett @NachoSoto @tamird please help! thank you!

alexeyxo commented 8 years ago

In the Protocol Buffers, binary data has not be converted in utf8 string. Int32 value in Protocol Buffers has a variable size.

whoooami commented 8 years ago

OK! Thanks! But When I write it to NSData, it seems failed. because data.length = 0?

` var data:NSData = NSData() let loginIn = UserLoginIn.Builder() loginIn.setId(Int32(3)) .setUsername("nothing") .setPassword("123456")

do {
    let loginInBuild = try loginIn.build()
    print(try loginInBuild.encode())
    let length = loginInBuild.serializedSize()
    let msg:NSMutableData = NSMutableData(length: Int(length + length.computeInt32SizeNoTag()))!

    let stream = CodedOutputStream(data: msg)
    try loginInBuild.writeToCodedOutputStream(stream)

    try stream.writeRawData(data)
    print(NSString(data: data, encoding: NSUTF8StringEncoding))
    print("\(data.length) \(loginInBuild.serializedSize())") // this output: 0 19 why?
} catch {
    print(error)
}`

Could you help me with this? Thanks! @alexeyxo

alexeyxo commented 8 years ago

Example from UnitTest:

 func testWriteWholeMessage()
    {
        do {
            let message = try TestUtilities.allSet()

            let rawBytes = message.data()
            let goldenData = TestUtilities.goldenData()
            XCTAssertTrue(rawBytes == goldenData, "")

        // Try different block sizes.

            var blockSize:Int32 = 1
            while blockSize <= 256 {
                let rawOutput = openMemoryStream()
                let output:CodedOutputStream = CodedOutputStream(output:rawOutput, bufferSize:Int32(blockSize))
                try message.writeToCodedOutputStream(output)
                try output.flush()
                let actual = rawOutput.propertyForKey(NSStreamDataWrittenToMemoryStreamKey) as! NSData
                XCTAssertTrue(rawBytes == actual, "")
                blockSize *= 2
            }
        }
        catch
        {
            XCTFail("Fail testWriteLittleEndian")
        }

    }