• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

alexeyxo/protobuf-swift: Google ProtocolBuffers for Apple Swift

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

alexeyxo/protobuf-swift

开源软件地址(OpenSource Url):

https://github.com/alexeyxo/protobuf-swift

开源编程语言(OpenSource Language):

Swift 97.2%

开源软件介绍(OpenSource Introduction):

Protocol Buffers for Swift

Build Status Carthage compatible Version Platform

An implementation of Protocol Buffers in Swift.

Protocol Buffers are a way of encoding structured data in an efficient yet extensible format. This project is based on an implementation of Protocol Buffers from Google. See the Google protobuf project for more information.

Required Protocol Buffers 3.0

How To Install Protobuf Compiler on Linux(Ubuntu 14.04)

1.wget https://github.com/google/protobuf/archive/v3.2.0.tar.gz

2.tar xzf v3.2.0.tar.gz

3.cd protobuf-3.2.0/

4.sudo apt-get install autoreconf automake libtool make

5../autogen.sh

6../configure CXXFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib

7.sudo make && sudo make install

8.cd .. && wget https://github.com/alexeyxo/protobuf-swift/archive/3.0.9.tar.gz && tar xzf 3.0.9.tar.gz && cd protobuf-swift-3.0.9

9../script/build.sh && swift build

How To Install Protobuf Compiler from Homebrew

1.ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2.brew install protobuf-swift

How To Install Protobuf Compiler

1.ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2.brew install automake

3.brew install libtool

4.brew install protobuf

5.git clone [email protected]:alexeyxo/protobuf-swift.git

6../scripts/build.sh

Add ./src/ProtocolBuffers/ProtocolBuffers.xcodeproj in your project.

Cocoapods

Podfile:

use_frameworks!
pod 'ProtocolBuffers-Swift'

Installation via Carthage

Cartfile:

github "alexeyxo/protobuf-swift"

Compile ".proto" files.

protoc  person.proto --swift_out="./"

Serializing

syntax = "proto2";
message Person {
    required int32 id = 1;
    required string name = 2;
    optional string email = 3;
}
let personBuilder = Person.Builder()
personBuilder.id = 123
personBuilder.name = "Bob"
personBuilder.email = "[email protected]"
let person = try! personBuilder.build()
print(person)

person.data() //return NSData

Chaining

syntax = "proto2";
message Perfomance
{
  required int32 ints = 1;
  required int64 ints64 = 2;
  required double doubles = 3;
  required float floats  = 4;
  optional string str  = 5;
  optional bytes bytes  = 6;
  optional string description = 7;
}
var originalBuilder = ProtoPerfomance.Builder()
originalBuilder.setInts(Int32(32))
               .setInts64(Int64(64))
               .setDoubles(Double(12.12))
               .setFloats(Float(123.123))
               .setStr("string")
let original = originalBuilder.build()

Sub Builders

syntax = "proto2";
message Foo {
  optional int32 val = 1;
  // some other fields.
}

message Bar {
  optional Foo foo = 1;
  // some other fields.
}

message Baz {
  optional Bar bar = 1;
  // some other fields.
}
var builder = baz.toBuilder()
builder.getBarBuilder().getFooBuilder().setVal(10)
baz = builder.build()

Maps(ProtocolBuffers 3.0)

syntax = "proto3";
message MapMessageValue
{
    int32 valueInMapMessage = 1;
}

message MessageContainsMap
{

  enum EnumMapValue
  {
    FirstValueEnum = 0;
    SecondValueEnum = 1;
  }

  map<int32,int32> map_int32_int32= 1;
  map<int64,int64> map_int64_int64= 2;
  map<string,string> map_string_string = 3;
  map<string,bytes> map_string_bytes = 4;
  map<string,MapMessageValue> map_string_message = 5;
  map<int32,EnumMapValue> map_int32_enum = 6;

}
final internal class MessageContainsMap : GeneratedMessage, GeneratedMessageProtocol, Hashable {
    ...
    private(set) var mapInt32Int32:Dictionary<Int32,Int32> = Dictionary<Int32,Int32>()
    private(set) var mapInt64Int64:Dictionary<Int64,Int64> = Dictionary<Int64,Int64>()

    private(set) var mapStringString:Dictionary<String,String> = Dictionary<String,String>()
    private(set) var mapStringBytes:Dictionary<String,NSData> = Dictionary<String,NSData>()
    private(set) var mapInt32Enum:Dictionary<Int32,MessageContainsMap.EnumMapValue> = Dictionary<Int32,MessageContainsMap.EnumMapValue>()
    ...
}

JSON(proto3)

let personBuilder = Person.builder()
personBuilder.id = 123
personBuilder.name = "Bob"
personBuilder.email = "[email protected]"
let person = personBuilder.build()
let jsonData = person.toJSON() //return NSData
let jsonDictionaryObject:Dictionary<String,AnyObject> = person.encode()
let personFromJson = Person.fromJSON(jsonData) //Person

Deserializing

var person = Person.parseFromData(bytes) // from NSData

Using Oneof

syntax = "proto3";
message SubMessage {
    string str = 1;
}

message SampleMessage {
  oneof test_oneof {
     string name = 4;
     int32 id = 5;
     SubMessage mes = 6;
  }
}
var sm = SampleMessage.Builder()
sm.name = "Alex"
sm.id = 123
println(ss.build()) //->  id: 123

Nested Types

syntax = "proto3";
message SearchResponse {
    message Result {
        string url = 1;
        string title = 2;
        repeated string snippets = 3;
    }
    repeated Result result = 1;
}
var builderResult = SearchResponse.Result.Builder()
builderResult.url = "http://protobuf.axo.io"
builderResult.title = "Protocol Bufers Apple Swift"
var searchRespons = SearchResponse.builder()
searchRespons.result += [builderResult.build()]
println(searchRespons.build())

Packages

syntax = "proto2";
package FooBar;
message Perfomance
{
  required int32 ints = 1;
  required int64 ints64 = 2;
  required double doubles = 3;
  required float floats  = 4;
  optional string str  = 5;
  optional bytes bytes  = 6;
  optional string description = 7;
}
public extension FooBar {
  ...
  final public class Perfomance : GeneratedMessage, GeneratedMessageProtocol {
    ...
  }

}

Custom Options

import "google/protobuf/descriptor.proto";

package google.protobuf;

enum AccessControl {
  InternalEntities = 0;
  PublicEntities = 1;
}
message SwiftFileOptions {

  optional string class_prefix = 1;
  optional AccessControl entities_access_control = 2 [default = PublicEntities];
  optional bool compile_for_framework = 3 [default = true];
}

message SwiftMessageOptions {
  optional bool generate_error_type = 1 [default = false];
}

message SwiftEnumOptions {
  optional bool generate_error_type = 1 [default = false];
}

extend google.protobuf.FileOptions {
  optional SwiftFileOptions swift_file_options = 5092014;
}

extend google.protobuf.MessageOptions {
  optional SwiftMessageOptions swift_message_options = 5092014;
}

extend google.protobuf.EnumOptions {
  optional SwiftEnumOptions swift_enum_options = 5092015;
}

option (.google.protobuf.swift_file_options).compile_for_framework = false;
option (.google.protobuf.swift_file_options).entities_access_control = PublicEntities;

At now protobuf-swift's compiler is supporting custom options.

  1. Class Prefix
  2. Access Control
  3. Error Types
  4. Compile for framework

If you have use custom options, you need to add:

import 'google/protobuf/swift-descriptor.proto';

in your .proto files.

Class prefix

This option needs to generate class names with prefix.

Example:

import 'google/protobuf/swift-descriptor.proto';

option (.google.protobuf.swift_file_options).class_prefix = "Proto";

message NameWithPrefix
{
  optional string str = 1;
}

Generated class has a name:

final internal class ProtoNameWithPrefix : GeneratedMessage

Access control

option (.google.protobuf.swift_file_options).entities_access_control = PublicEntities;

All generated classes marks as internal by default. If you want mark as public, you can use entities_access_control option.

option (.google.protobuf.swift_file_options).entities_access_control = PublicEntities;

message MessageWithCustomOption
{
  optional string str = 1;
}

Generated class and all fields are marked a public:

final public class MessageWithCustomOption : GeneratedMessage

Generate enum/message conforming to "Error" protocol

option (.google.protobuf.swift_enum_options).generate_error_type = true;

Example

import 'google/protobuf/swift-descriptor.proto';

enum ServiceError {
  option (.google.protobuf.swift_enum_options).generate_error_type = true;
  BadRequest = 0;
  InternalServerError = 1;
}

message UserProfile {
    message Request {
        required string userId = 1;
    }
    message Response {
        optional UserProfile profile = 1;
        optional ServiceError error = 2;
        optional Exception exception = 3;
    }

     message Exception {
        option (.google.protobuf.swift_message_options).generate_error_type = true;
        required int32 errorCode = 1;
        required string errorDescription = 2;
    }
    
    optional string firstName = 1;
    optional string lastName = 2;
    optional string avatarUrl = 3;
}
public enum ServiceError:Error, RawRepresentable, CustomDebugStringConvertible, CustomStringConvertible {
  public typealias RawValue = Int32

  case badRequest
  case internalServerError

  public init?(rawValue: RawValue) {
    switch rawValue {
    case 0: self = .badRequest
    case 1: self = .internalServerError
    default: return nil
    }
  }

  public var rawValue: RawValue {
    switch self {
    case .badRequest: return 0
    case .internalServerError: return 1
    }
  }

  public func throwException() throws {
    throw self
  }

  public var debugDescription:String { return getDescription() }
  public var description:String { return getDescription() }
  private func getDescription() -> String { 
    switch self {
    case .badRequest: return ".badRequest"
    case .internalServerError: return ".internalServerError"
    }
  }
}
func generateException()throws {
    let user = UserProfile.Response.Builder()
    user.error = .internalServerError
    let data = try user.build().data()
    let userError = try UserProfile.Response.parseFrom(data:data)
    if userError.hasError {
        throw userError.error //userError.error.throwException()
    }
}

do {
    try generateException()
} catch let err as ServiceError where err == .internalServerError {
    XCTAssertTrue(true)
} catch {
    XCTAssertTrue(false)
}

func throwExceptionMessage() throws {
  let exception = UserProfile.Exception.Builder()
  exception.errorCode = 403
  exception.errorDescription = "Bad Request"
  let exc = try exception.build()
  let data = try UserProfile.Response.Builder().setException(exc).build().data()
  let userError = try UserProfile.Response.parseFrom(data:data)
  if userError.hasException {
      throw userError.exception
  }
}

do {
    try throwExceptionMessage()
} catch let err as UserProfile.Exception {
    print(err)
    XCTAssertTrue(true)
} catch {
    XCTAssertTrue(false)
}
  

Compile for framework

option (.google.protobuf.swift_file_options).compile_for_framework = false;

This option deletes the string import ProtocolBuffers of the generated files.

If you will need some other options, write me. I will add them.

Utilities (ProtocolBuffers 3.0)

Added well-known type protos (any.proto, empty.proto, timestamp.proto, duration.proto, etc.). Users can import and use these protos just like regular proto files. Addtional runtime support will be added for them in future releases (in the form of utility helper functions, or having them replaced by language specific types in generated code).


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap