Skip to content

Commit

Permalink
Add Message binary decoding support from ContiguousBytes.
Browse files Browse the repository at this point in the history
ContiguousBytes should allow other libraries that have their own "buffer"
types to directly decode things without having to copy the payloads into
a Data first.

- Add a new init.
- Add a new merge.
- Redirect the Data interfaces thru the ContiguousBytes interfaces.
  • Loading branch information
thomasvl committed Nov 18, 2019
1 parent 007b10a commit 7f8daf3
Showing 1 changed file with 76 additions and 0 deletions.
76 changes: 76 additions & 0 deletions Sources/SwiftProtobuf/Message+BinaryAdditions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,39 @@ extension Message {
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
self.init()
#if swift(>=5.0)
try merge(contiguousBytes: data, extensions: extensions, partial: partial, options: options)
#else
try merge(serializedData: data, extensions: extensions, partial: partial, options: options)
#endif
}

#if swift(>=5.0)
/// Creates a new message by decoding the given `ContiguousBytes` value
/// containing a serialized message in Protocol Buffer binary format.
///
/// - Parameters:
/// - contiguousBytes: The binary-encoded message data to decode.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - options: The BinaryDecodingOptions to use.
/// - Throws: `BinaryDecodingError` if decoding fails.
public init(
contiguousBytes bytes: ContiguousBytes,
extensions: ExtensionMap? = nil,
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
self.init()
try merge(contiguousBytes: bytes, extensions: extensions, partial: partial, options: options)
}
#endif // #if swift(>=5.0)

/// Updates the message by decoding the given `Data` value containing a
/// serialized message in Protocol Buffer binary format into the receiver.
///
Expand All @@ -107,6 +137,9 @@ extension Message {
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
#if swift(>=5.0)
try merge(contiguousBytes: data, extensions: extensions, partial: partial, options: options)
#else
if !data.isEmpty {
try data.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
if let baseAddress = body.baseAddress, body.count > 0 {
Expand All @@ -122,5 +155,48 @@ extension Message {
if !partial && !isInitialized {
throw BinaryDecodingError.missingRequiredFields
}
#endif // swift(>=5.0)
}

#if swift(>=5.0)
/// Updates the message by decoding the given `ContiguousBytes` value
/// containing a serialized message in Protocol Buffer binary format into the
/// receiver.
///
/// - Note: If this method throws an error, the message may still have been
/// partially mutated by the binary data that was decoded before the error
/// occurred.
///
/// - Parameters:
/// - contiguousBytes: The binary-encoded message data to decode.
/// - extensions: An `ExtensionMap` used to look up and decode any
/// extensions in this message or messages nested within this message's
/// fields.
/// - partial: If `false` (the default), this method will check
/// `Message.isInitialized` before encoding to verify that all required
/// fields are present. If any are missing, this method throws
/// `BinaryEncodingError.missingRequiredFields`.
/// - options: The BinaryDecodingOptions to use.
/// - Throws: `BinaryDecodingError` if decoding fails.
public mutating func merge(
contiguousBytes bytes: ContiguousBytes,
extensions: ExtensionMap? = nil,
partial: Bool = false,
options: BinaryDecodingOptions = BinaryDecodingOptions()
) throws {
try bytes.withUnsafeBytes { (body: UnsafeRawBufferPointer) in
if let baseAddress = body.baseAddress, body.count > 0 {
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
var decoder = BinaryDecoder(forReadingFrom: pointer,
count: body.count,
options: options,
extensions: extensions)
try decoder.decodeFullMessage(message: &self)
}
}
if !partial && !isInitialized {
throw BinaryDecodingError.missingRequiredFields
}
}
#endif // swift(>=5.0)
}

0 comments on commit 7f8daf3

Please sign in to comment.