Serialization.swift 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Copyright 2020, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. import NIO
  17. import NIOFoundationCompat
  18. import SwiftProtobuf
  19. public protocol MessageSerializer {
  20. associatedtype Input
  21. /// Serializes `input` into a `ByteBuffer` allocated using the provided `allocator`.
  22. ///
  23. /// - Parameters:
  24. /// - input: The element to serialize.
  25. /// - allocator: A `ByteBufferAllocator`.
  26. @inlinable
  27. func serialize(_ input: Input, allocator: ByteBufferAllocator) throws -> ByteBuffer
  28. }
  29. public protocol MessageDeserializer {
  30. associatedtype Output
  31. /// Deserializes `byteBuffer` to produce a single `Output`.
  32. ///
  33. /// - Parameter byteBuffer: The `ByteBuffer` to deserialize.
  34. @inlinable
  35. func deserialize(byteBuffer: ByteBuffer) throws -> Output
  36. }
  37. // MARK: Protobuf
  38. public struct ProtobufSerializer<Message: SwiftProtobuf.Message>: MessageSerializer {
  39. @inlinable
  40. public init() {}
  41. @inlinable
  42. public func serialize(_ message: Message, allocator: ByteBufferAllocator) throws -> ByteBuffer {
  43. // Serialize the message.
  44. let serialized = try message.serializedData()
  45. // Allocate enough space and an extra 5 leading bytes. This a minor optimisation win: the length
  46. // prefixed message writer can re-use the leading 5 bytes without needing to allocate a new
  47. // buffer and copy over the serialized message.
  48. var buffer = allocator.buffer(capacity: serialized.count + 5)
  49. buffer.writeRepeatingByte(0, count: 5)
  50. buffer.moveReaderIndex(forwardBy: 5)
  51. // Now write the serialized message.
  52. buffer.writeContiguousBytes(serialized)
  53. return buffer
  54. }
  55. }
  56. public struct ProtobufDeserializer<Message: SwiftProtobuf.Message>: MessageDeserializer {
  57. @inlinable
  58. public init() {}
  59. @inlinable
  60. public func deserialize(byteBuffer: ByteBuffer) throws -> Message {
  61. var buffer = byteBuffer
  62. // '!' is okay; we can always read 'readableBytes'.
  63. let data = buffer.readData(length: buffer.readableBytes)!
  64. return try Message(serializedData: data)
  65. }
  66. }
  67. // MARK: GRPCPayload
  68. public struct GRPCPayloadSerializer<Message: GRPCPayload>: MessageSerializer {
  69. @inlinable
  70. public init() {}
  71. @inlinable
  72. public func serialize(_ message: Message, allocator: ByteBufferAllocator) throws -> ByteBuffer {
  73. // Reserve 5 leading bytes. This a minor optimisation win: the length prefixed message writer
  74. // can re-use the leading 5 bytes without needing to allocate a new buffer and copy over the
  75. // serialized message.
  76. var buffer = allocator.buffer(repeating: 0, count: 5)
  77. let readerIndex = buffer.readerIndex
  78. let writerIndex = buffer.writerIndex
  79. // Serialize the payload into the buffer.
  80. try message.serialize(into: &buffer)
  81. // Ensure 'serialize(into:)' didn't do anything strange.
  82. assert(buffer.readerIndex == readerIndex, "serialize(into:) must not move the readerIndex")
  83. assert(
  84. buffer.writerIndex >= writerIndex,
  85. "serialize(into:) must not move the writerIndex backwards"
  86. )
  87. assert(
  88. buffer.getBytes(at: readerIndex, length: 5) == Array(repeating: 0, count: 5),
  89. "serialize(into:) must not write over existing written bytes"
  90. )
  91. // 'read' the first 5 bytes so that the buffer's readable bytes are only the bytes of the
  92. // serialized message.
  93. buffer.moveReaderIndex(forwardBy: 5)
  94. return buffer
  95. }
  96. }
  97. public struct GRPCPayloadDeserializer<Message: GRPCPayload>: MessageDeserializer {
  98. @inlinable
  99. public init() {}
  100. @inlinable
  101. public func deserialize(byteBuffer: ByteBuffer) throws -> Message {
  102. var buffer = byteBuffer
  103. return try Message(serializedByteBuffer: &buffer)
  104. }
  105. }
  106. // MARK: - Any Serializer/Deserializer
  107. internal struct AnySerializer<Input>: MessageSerializer {
  108. private let _serialize: (Input, ByteBufferAllocator) throws -> ByteBuffer
  109. init<Serializer: MessageSerializer>(wrapping other: Serializer) where Serializer.Input == Input {
  110. self._serialize = other.serialize(_:allocator:)
  111. }
  112. internal func serialize(_ input: Input, allocator: ByteBufferAllocator) throws -> ByteBuffer {
  113. return try self._serialize(input, allocator)
  114. }
  115. }
  116. internal struct AnyDeserializer<Output>: MessageDeserializer {
  117. private let _deserialize: (ByteBuffer) throws -> Output
  118. init<Deserializer: MessageDeserializer>(
  119. wrapping other: Deserializer
  120. ) where Deserializer.Output == Output {
  121. self._deserialize = other.deserialize(byteBuffer:)
  122. }
  123. internal func deserialize(byteBuffer: ByteBuffer) throws -> Output {
  124. return try self._deserialize(byteBuffer)
  125. }
  126. }