_MessageLayout.swift 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. // Sources/SwiftProtobuf/_MessageLayout.swift - Table-driven message layout
  2. //
  3. // Copyright (c) 2014 - 2025 Apple Inc. and the project authors
  4. // Licensed under Apache License v2.0 with Runtime Library Exception
  5. //
  6. // See LICENSE.txt for license information:
  7. // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
  8. //
  9. // -----------------------------------------------------------------------------
  10. ///
  11. /// The in-memory layout description for the fields of a table-driven message.
  12. ///
  13. // -----------------------------------------------------------------------------
  14. import Foundation
  15. /// Defines the in-memory layout of the storage for a message.
  16. ///
  17. /// This type is public because it needs to be referenced and initialized from generated messages.
  18. /// Clients should not access it directly.
  19. ///
  20. /// ## Encoded Layout
  21. ///
  22. /// The message layout is encoded in UTF-8-compatible form as a `StaticString`. Unlike `_NameMap`,
  23. /// which uses variable-width sequences of "instructions", the message layout is represented as a
  24. /// fixed size "header" followed by a sequence of fixed size field layout descriptors. This allows
  25. /// for fast lookup of those fields (constant time in some cases, falling back to binary search
  26. /// when needed).
  27. ///
  28. /// ### General integer encoding
  29. ///
  30. /// Since the string must be valid UTF-8, it is simplest to restrict all bytes in the string to
  31. /// 7-bit ASCII (0x00...0x7F). Therefore, we encode larger integers in a fixed base-128 format;
  32. /// no continuation bit is used (the MSB is always 0) and the layout specification determines the
  33. /// expected width of any encoded integers. For example, if we were encoding 16-bit integers, we
  34. /// would need 3 bytes, because 65536 would be encoded as 00000011 01111111 01111111.
  35. ///
  36. /// ### Message layout header
  37. ///
  38. /// The **message layout header** describes properties of the entire message:
  39. ///
  40. /// ```
  41. /// +---------+--------------+-------------+----------------+-------------------------+-------------------+
  42. /// | Bytes 0 | Bytes 1-3 | Bytes 4-6 | Bytes 7-9 | Bytes 10-12 | Byte 13-15 |
  43. /// | Version | Message size | Field count | Required count | Explicit presence count | Density threshold |
  44. /// +---------+--------------+-------------+----------------+-------------------------+-------------------+
  45. /// ```
  46. /// * Byte 0: A `UInt8` that describes the version of the layout. Currently, this is always 0.
  47. /// This value allows for future enhancements to be made to the layout but preserving backward
  48. /// compatibility.
  49. /// * Bytes 1-3: The size of the message in bytes, as a base-128 integer. 64KB is an upper bound
  50. /// on message size imposed in practice by µpb, since it uses a `uint16_t` to represent field
  51. /// offsets in their own mini-tables.
  52. /// * Bytes 4-6: The number of fields defined by the message, as a base-128 integer.
  53. /// 65536 is an upper bound imposed in practice by the core protobuf implementation
  54. /// (https://github.com/protocolbuffers/protobuf/commit/90824aaa69000452bff5ad8db3240215a3b9a595)
  55. /// since larger messages would overflow various data structures.
  56. /// * Bytes 7-9: The number of required fields defined by the message, as a base-128 integer.
  57. /// * Bytes 10-12: The number of fields that have explicit presence, as a base-128 integer. Note
  58. /// that this will always be greater than or equal to the required count, because required
  59. /// fields also have explicit presence.
  60. /// * Bytes 13-15: The largest field number `N` for which all fields in the range `1..<N` are
  61. /// inhabited, as a base-128 integer. We only need three bytes to represent this because the
  62. /// largest possible number is 65537; otherwise, it would imply that the message had more than
  63. /// 65536 fields in violation of the bound above.
  64. ///
  65. /// ### Field layouts
  66. ///
  67. /// After the header above, starting at byte offset 13, is a sequence of encoded field layouts.
  68. /// Each field layout is 13 bytes long and they are written in field number order. Each entry
  69. /// encodes the following information:
  70. ///
  71. /// ```
  72. /// +---------------------+-----------+-----------+------------------+------------+
  73. /// | Bytes 0-4 | Bytes 5-7 | Bytes 8-9 | Bytes 10-11 | Byte 12 |
  74. /// | Field number & mode | Offset | Presence | Trampoline index | Field type |
  75. /// +---------------------+-----------+-----------+------------------+------------+
  76. /// ```
  77. ///
  78. /// * Bytes 0-4: A packed value where the low 33-bits are a base-128 integer that encodes the
  79. /// 29-bit field number, and the remaining bits of byte 4 represent the field mode.
  80. /// * Bytes 5-7: The byte offset of the field in in-memory storage, as a base-128 integer. To
  81. /// match µpb's layout constraints, this value will never be larger than 2^16 - 1.
  82. /// * Bytes 8-9: Information about the field's presence. Specifically,
  83. /// * If this field is a member of a `oneof`, then the bitwise inverse of this value is the
  84. /// byte offset into in-memory storage where the field number of the populated `oneof`
  85. /// field is stored.
  86. /// * Otherwise, the value is the index of the has-bit used to store the presence of the
  87. /// field.
  88. /// * Bytes 10-11: For message/group/enum fields, an opaque index as a base-128 integer used to
  89. /// perform operations on submessage or enum fields that require the concrete type hint.
  90. /// * Byte 12: The type of the field.
  91. @_spi(ForGeneratedCodeOnly) public struct _MessageLayout: @unchecked Sendable {
  92. // Using `UnsafeRawBufferPointer` requires that we declare the `Sendable` conformance as
  93. // `@unchecked`. Clearly this is safe because the pointer obtained from a `StaticString` is an
  94. // immortal compile-time constant and we only read from it.
  95. /// The encoded layout of the fields of the message.
  96. private let layout: UnsafeRawBufferPointer
  97. /// The function type for the generated function that is called to deinitialize a field whose
  98. /// type is a message, array of messages, or array of enums.
  99. public typealias TrampolineDeinitializer = (
  100. _ token: TrampolineToken,
  101. _ field: FieldLayout,
  102. _ storage: _MessageStorage
  103. ) -> Void
  104. /// The function type for the generated function that is called to copy a field whose type is a
  105. /// message, array of messages, or array of enums.
  106. public typealias TrampolineCopier = (
  107. _ token: TrampolineToken,
  108. _ field: FieldLayout,
  109. _ source: _MessageStorage,
  110. _ destination: _MessageStorage
  111. ) -> Void
  112. /// The function type for the generated function that is called to test for equality two fields
  113. /// whose types are a message, array of messages, or array of enums.
  114. public typealias TrampolineEquater = (
  115. _ token: TrampolineToken,
  116. _ field: FieldLayout,
  117. _ lhs: _MessageStorage,
  118. _ rhs: _MessageStorage
  119. ) -> Bool
  120. /// The function type for the generated function that is called to test if a field whose type
  121. /// is a message or array of messages is initialized.
  122. public typealias SubmessageInitializedChecker = (
  123. _ token: TrampolineToken,
  124. _ field: FieldLayout,
  125. _ storage: _MessageStorage
  126. ) -> Bool
  127. /// The function type for the generated function that is called to perform an arbitrary
  128. /// operation on the storage of a field whose type is a message or array of messages.
  129. public typealias SubmessageStoragePerformer = (
  130. _ token: TrampolineToken,
  131. _ field: FieldLayout,
  132. _ storage: _MessageStorage,
  133. _ operation: TrampolineFieldOperation,
  134. _ perform: (_MessageStorage) throws -> Bool
  135. ) throws -> Bool
  136. /// The function type for the generated function that is called to perform an arbitrary
  137. /// operation on the raw values of a singular or repeated enum field.
  138. public typealias RawEnumValuesPerformer = (
  139. _ token: TrampolineToken,
  140. _ field: FieldLayout,
  141. _ storage: _MessageStorage,
  142. _ operation: TrampolineFieldOperation,
  143. _ perform: (inout Int32) throws -> Bool,
  144. _ onInvalidValue: (Int32) -> Void
  145. ) throws -> Void
  146. /// The function that is called to deinitialize a field whose type is a message (singular or
  147. /// repeated) or a repeated enum field.
  148. let deinitializeField: TrampolineDeinitializer
  149. /// The function that is called to copy a field whose type is a message (singular or repeated)
  150. /// or a repeated enum field.
  151. let copyField: TrampolineCopier
  152. /// The function that is called to test a field whose type is a message, array of messages, or
  153. /// array of enums for equality.
  154. let areFieldsEqual: TrampolineEquater
  155. /// The function that is called to perform an arbitrary operation on the storage of a submessage
  156. /// field.
  157. let performOnSubmessageStorage: SubmessageStoragePerformer
  158. /// The function that is called to perform an arbitrary operation on the raw values of an enum
  159. /// field.
  160. let performOnRawEnumValues: RawEnumValuesPerformer
  161. /// Creates a new message layout and submessage operations from the given values.
  162. ///
  163. /// This initializer is public because generated messages need to call it.
  164. public init(
  165. layout: StaticString,
  166. deinitializeField: @escaping TrampolineDeinitializer,
  167. copyField: @escaping TrampolineCopier,
  168. areFieldsEqual: @escaping TrampolineEquater,
  169. performOnSubmessageStorage: @escaping SubmessageStoragePerformer,
  170. performOnRawEnumValues: @escaping RawEnumValuesPerformer
  171. ) {
  172. precondition(
  173. layout.hasPointerRepresentation,
  174. "The layout string should have a pointer-based representation; this is a generator bug"
  175. )
  176. self.layout = UnsafeRawBufferPointer(start: layout.utf8Start, count: layout.utf8CodeUnitCount)
  177. self.deinitializeField = deinitializeField
  178. self.copyField = copyField
  179. self.areFieldsEqual = areFieldsEqual
  180. self.performOnSubmessageStorage = performOnSubmessageStorage
  181. self.performOnRawEnumValues = performOnRawEnumValues
  182. precondition(version == 0, "This runtime only supports version 0 message layouts")
  183. precondition(
  184. self.layout.count == messageLayoutHeaderSize + self.fieldCount * fieldLayoutSize,
  185. """
  186. The layout size in bytes was not consistent with the number of fields \
  187. (got \(self.layout.count), expected \(messageLayoutHeaderSize + self.fieldCount * fieldLayoutSize)); \
  188. this is a generator bug
  189. """
  190. )
  191. }
  192. /// Creates a new message layout from the given layout string.
  193. ///
  194. /// Layouts created with this initalizer must have no submessage fields because the invalid
  195. /// submessage operation placeholder will be used.
  196. ///
  197. /// This initializer is public because generated messages need to call it.
  198. public init(layout: StaticString) {
  199. self.init(
  200. layout: layout,
  201. deinitializeField: { _, _, _ in
  202. preconditionFailure("This should have been unreachable; this is a generator bug")
  203. },
  204. copyField: { _, _, _, _ in
  205. preconditionFailure("This should have been unreachable; this is a generator bug")
  206. },
  207. areFieldsEqual: { _, _, _, _ in
  208. preconditionFailure("This should have been unreachable; this is a generator bug")
  209. },
  210. performOnSubmessageStorage: { _, _, _, _, _ in
  211. preconditionFailure("This should have been unreachable; this is a generator bug")
  212. },
  213. performOnRawEnumValues: { _, _, _, _, _, _ in
  214. preconditionFailure("This should have been unreachable; this is a generator bug")
  215. }
  216. )
  217. }
  218. }
  219. extension _MessageLayout {
  220. /// The version of the layout data.
  221. ///
  222. /// Currently, the runtime only supports version 0. If the layout needs to change in a breaking
  223. /// way, the generator should increment the version and the runtime implementation should detect
  224. /// the new version while maintaining the ability to read the older layouts.
  225. private var version: UInt8 {
  226. layout.load(fromByteOffset: 0, as: UInt8.self)
  227. }
  228. /// The size of the message in bytes.
  229. var size: Int {
  230. fixed3ByteBase128(in: layout, atByteOffset: 1)
  231. }
  232. /// The number of non-extension fields defined by the message.
  233. var fieldCount: Int {
  234. fixed3ByteBase128(in: layout, atByteOffset: 4)
  235. }
  236. /// The number of required fields defined by the message.
  237. ///
  238. /// Required fields have their has-bits arranged first in storage so that the runtime can
  239. /// efficiently compute whether the message is definitely not initialized.
  240. var requiredCount: Int {
  241. fixed3ByteBase128(in: layout, atByteOffset: 7)
  242. }
  243. /// The number of fields defined by the message that have explicit presence.
  244. ///
  245. /// Fields with explicit presence have their has-bits arranged after the required has-bits but
  246. /// before those with implicit presence so that we can determine the nature of a field's
  247. /// presence without increasing the size of field layouts.
  248. var explicitPresenceCount: Int {
  249. fixed3ByteBase128(in: layout, atByteOffset: 10)
  250. }
  251. /// The largest field number `N` for which all fields in the range `1..<N` are inhabited.
  252. ///
  253. /// Looking up the field layout for a field below `N` can be done via constant-time random
  254. /// access; fields numbered `N` or higher must be found via binary search.
  255. var denseBelow: UInt32 {
  256. UInt32(fixed3ByteBase128(in: layout, atByteOffset: 13))
  257. }
  258. /// Returns a value indicating whether or not the given field is required.
  259. func isFieldRequired(_ field: FieldLayout) -> Bool {
  260. let raw = field.rawPresence
  261. return 0 <= raw && raw < requiredCount
  262. }
  263. /// Returns a value indicating whether ot not the given field has explicit presence.
  264. func fieldHasPresence(_ field: FieldLayout) -> Bool {
  265. let raw = field.rawPresence
  266. return 0 <= raw && raw < explicitPresenceCount
  267. }
  268. }
  269. /// The size, in bytes, of the header the describes the overall message layout.
  270. private var messageLayoutHeaderSize: Int { 16 }
  271. /// The size, in bytes, of an encoded field layout in the static string representation.
  272. private var fieldLayoutSize: Int { 13 }
  273. extension _MessageLayout {
  274. /// Iterates over the field layouts in the layout string.
  275. struct FieldIterator: IteratorProtocol {
  276. var current: Slice<UnsafeRawBufferPointer>
  277. init(layout: UnsafeRawBufferPointer) {
  278. self.current = layout.dropFirst(messageLayoutHeaderSize)
  279. }
  280. mutating func next() -> FieldLayout? {
  281. guard !current.isEmpty else { return nil }
  282. defer { current = current.dropFirst(fieldLayoutSize) }
  283. return FieldLayout(slice: current.prefix(fieldLayoutSize))
  284. }
  285. }
  286. /// Returns a sequence that represents the layout descriptions of the fields in the message,
  287. /// in field number order.
  288. var fields: some Sequence<FieldLayout> { IteratorSequence(FieldIterator(layout: self.layout)) }
  289. /// Returns the layout for the field with the given number in the message, or nil if the field
  290. /// is not defined.
  291. @usableFromInline subscript(fieldNumber number: UInt32) -> FieldLayout? {
  292. if number < denseBelow {
  293. let index = messageLayoutHeaderSize + (Int(number) - 1) * fieldLayoutSize
  294. return FieldLayout(slice: layout[index..<(index + fieldLayoutSize)])
  295. }
  296. var low = Int(denseBelow - 1)
  297. var high = fieldCount - 1
  298. while high >= low {
  299. let mid = (high + low) / 2
  300. let index = messageLayoutHeaderSize + mid * fieldLayoutSize
  301. let field = FieldLayout(slice: layout[index..<(index + fieldLayoutSize)])
  302. if number == field.fieldNumber {
  303. return field
  304. }
  305. if field.fieldNumber < number {
  306. low = mid + 1
  307. } else {
  308. high = mid - 1
  309. }
  310. }
  311. return nil
  312. }
  313. }
  314. extension _MessageLayout {
  315. /// An opaque token that is used to ask a message for the metatype of one of its submessage
  316. /// or enum fields.
  317. public struct TrampolineToken: Sendable, Equatable {
  318. /// The index that identifies the submessage or enum type being requested.
  319. public let index: Int
  320. }
  321. }
  322. /// The nature of the operation that is being performed by `performOnSubmessageStorage` or
  323. /// `performOnEnumRawValues`.
  324. @_spi(ForGeneratedCodeOnly) public enum TrampolineFieldOperation {
  325. /// The submessage's storage or enum's raw value is being read.
  326. case read
  327. /// The submessage's storage or enum's raw value is being mutated.
  328. ///
  329. /// For submessages, the value should be created if it is not already present. If already
  330. /// present, the storage should be made unique before the mutation.
  331. case mutate
  332. /// The submessage's array storage or enum's array value is having a new value appended to it.
  333. ///
  334. /// The array should be created if it is not already present.
  335. case append
  336. }
  337. /// Provides access to the properties of a field's layout based on a slice of the raw message
  338. /// layout string.
  339. @_spi(ForGeneratedCodeOnly) public struct FieldLayout {
  340. /// Describes the presence information of a field, translated from its raw bytecode
  341. /// representation.
  342. enum Presence: Sendable, Equatable {
  343. /// The byte offset and mask of the has-bit for this field that is not a oneof member.
  344. case hasBit(byteOffset: Int, mask: UInt8)
  345. /// The byte offset of the 32-bit integer that holds the field number of the currently set
  346. /// oneof member.
  347. case oneOfMember(Int)
  348. fileprivate init(rawValue: Int) {
  349. // The raw value needs to be treated as a 14-bit signed integer where the MSB (bit 13)
  350. // acts as the sign bit. Therefore, we need to check the range of the value to
  351. // determine if it's a oneof (0x2000...0x3fff) or not (0x0000...0x1fff), then
  352. // sign-extend it to 16 bits so that we can correctly take its inverse.
  353. if rawValue >= 0x2000 {
  354. self = .oneOfMember(Int(~(UInt16(rawValue) | 0xc000)))
  355. } else {
  356. self = .hasBit(byteOffset: rawValue >> 3, mask: 1 << UInt8(rawValue & 7))
  357. }
  358. }
  359. }
  360. /// The rebased slice of `_MessageLayout.fields` that describes the layout of this field.
  361. private let buffer: UnsafeRawBufferPointer
  362. /// The number of the field whose layout is being described.
  363. var fieldNumber: UInt32 {
  364. // The layout ensures that there will always be at least 8 bytes that we can read here, so
  365. // we can do a single memory read and mask off what we don't need.
  366. let rawBits = UInt64(littleEndian: buffer.loadUnaligned(fromByteOffset: 0, as: UInt64.self))
  367. return UInt32(
  368. truncatingIfNeeded: (rawBits & 0x00_0000_007f)
  369. | ((rawBits & 0x00_0000_7f00) >> 1)
  370. | ((rawBits & 0x00_007f_0000) >> 2)
  371. | ((rawBits & 0x00_7f00_0000) >> 3)
  372. | ((rawBits & 0x01_0000_0000) >> 4)
  373. )
  374. }
  375. /// The offset, in bytes, where this field's value is stored in in-memory storage.
  376. @usableFromInline var offset: Int {
  377. fixed3ByteBase128(in: buffer, atByteOffset: 5)
  378. }
  379. /// The raw presence value.
  380. ///
  381. /// For `oneof` fields, this is the bitwise inverse of the _byte_ offset in storage where the
  382. /// populated `oneof` member's field number is stored. For non-`oneof` fields, this is the index
  383. /// of the has-bit for this field.
  384. var rawPresence: Int {
  385. fixed2ByteBase128(in: buffer, atByteOffset: 8)
  386. }
  387. /// The presence information for this field.
  388. ///
  389. /// This value is an enum that provides structured access to the information based on whether it
  390. /// is a `oneof` member or a regular field.
  391. var presence: Presence {
  392. Presence(rawValue: rawPresence)
  393. }
  394. /// The index that is used when requesting the metatype of this field from its containing
  395. /// message.
  396. var submessageIndex: Int {
  397. fixed2ByteBase128(in: buffer, atByteOffset: 10)
  398. }
  399. /// The raw type of the field as it is represented on the wire.
  400. var rawFieldType: RawFieldType {
  401. RawFieldType(rawValue: buffer.load(fromByteOffset: 12, as: UInt8.self))
  402. }
  403. /// Mode properties of the field.
  404. var fieldMode: FieldMode {
  405. FieldMode(rawValue: buffer.load(fromByteOffset: 4, as: UInt8.self) & 0x1e)
  406. }
  407. /// The wire format used by this field.
  408. var wireFormat: WireFormat {
  409. switch rawFieldType {
  410. case .bool: return .varint
  411. case .bytes: return .lengthDelimited
  412. case .double: return .fixed64
  413. case .enum: return .varint
  414. case .fixed32: return .fixed32
  415. case .fixed64: return .fixed64
  416. case .float: return .fixed32
  417. case .group: return .startGroup
  418. case .int32: return .varint
  419. case .int64: return .varint
  420. case .message: return .lengthDelimited
  421. case .sfixed32: return .fixed32
  422. case .sfixed64: return .fixed64
  423. case .sint32: return .varint
  424. case .sint64: return .varint
  425. case .string: return .lengthDelimited
  426. case .uint32: return .varint
  427. case .uint64: return .varint
  428. default: preconditionFailure("Unreachable")
  429. }
  430. }
  431. /// The in-memory stride of a value of this field's type on the current platform.
  432. @usableFromInline var scalarStride: Int {
  433. switch rawFieldType {
  434. case .double: return MemoryLayout<Double>.stride
  435. case .float: return MemoryLayout<Float>.stride
  436. case .int64, .sfixed64, .sint64: return MemoryLayout<Int64>.stride
  437. case .uint64, .fixed64: return MemoryLayout<UInt64>.stride
  438. case .int32, .sfixed32, .sint32, .enum: return MemoryLayout<Int32>.stride
  439. case .fixed32, .uint32: return MemoryLayout<UInt32>.stride
  440. case .bool: return MemoryLayout<Bool>.stride
  441. case .string: return MemoryLayout<String>.stride
  442. case .group, .message: return MemoryLayout<_MessageStorage>.stride
  443. case .bytes: return MemoryLayout<Data>.stride
  444. default: preconditionFailure("Unreachable")
  445. }
  446. }
  447. /// Creates a new field layout from the given slice of a message's field layout string.
  448. fileprivate init(slice: Slice<UnsafeRawBufferPointer>) {
  449. self.buffer = UnsafeRawBufferPointer(rebasing: slice)
  450. }
  451. }
  452. /// The type of a field as it is represented on the wire.
  453. package struct RawFieldType: RawRepresentable, Equatable, Hashable, Sendable {
  454. package static let double = Self(rawValue: 1)
  455. package static let float = Self(rawValue: 2)
  456. package static let int64 = Self(rawValue: 3)
  457. package static let uint64 = Self(rawValue: 4)
  458. package static let int32 = Self(rawValue: 5)
  459. package static let fixed64 = Self(rawValue: 6)
  460. package static let fixed32 = Self(rawValue: 7)
  461. package static let bool = Self(rawValue: 8)
  462. package static let string = Self(rawValue: 9)
  463. package static let group = Self(rawValue: 10)
  464. package static let message = Self(rawValue: 11)
  465. package static let bytes = Self(rawValue: 12)
  466. package static let uint32 = Self(rawValue: 13)
  467. package static let `enum` = Self(rawValue: 14)
  468. package static let sfixed32 = Self(rawValue: 15)
  469. package static let sfixed64 = Self(rawValue: 16)
  470. package static let sint32 = Self(rawValue: 17)
  471. package static let sint64 = Self(rawValue: 18)
  472. package let rawValue: UInt8
  473. package init(rawValue: UInt8) {
  474. self.rawValue = rawValue
  475. }
  476. }
  477. /// Note that the least-significant bit of this value is not used because this value is packed
  478. /// into the high byte of the field number, which uses that bit.
  479. package struct FieldMode: RawRepresentable, Equatable, Hashable, Sendable {
  480. /// Describes the cardinality of a field (whether it represents a scalar value, an array of
  481. /// values, or a mapping between values).
  482. package struct Cardinality: RawRepresentable, Equatable, Hashable, Sendable {
  483. package static let scalar = Self(rawValue: 0b000_0000)
  484. package static let array = Self(rawValue: 0b000_0010)
  485. package static let map = Self(rawValue: 0b000_0100)
  486. package let rawValue: UInt8
  487. package init(rawValue: UInt8) {
  488. self.rawValue = rawValue
  489. }
  490. }
  491. /// The cardinality of a field.
  492. package var cardinality: Cardinality {
  493. get { .init(rawValue: rawValue & 0b000_0110) }
  494. set { self = .init(rawValue: rawValue & ~0b000_0110 | newValue.rawValue) }
  495. }
  496. /// Indicates whether or not the field uses packed representation on the wire by default.
  497. package var isPacked: Bool {
  498. get { rawValue & 0b000_1000 != 0 }
  499. set { self = .init(rawValue: rawValue & ~0b000_1000 | (newValue ? 0b000_1000 : 0)) }
  500. }
  501. /// Indicates whether or not the field is an extension field.
  502. package var isExtension: Bool {
  503. get { rawValue & 0b001_0000 != 0 }
  504. set { self = .init(rawValue: rawValue & ~0b001_0000 | (newValue ? 0b001_0000 : 0)) }
  505. }
  506. package let rawValue: UInt8
  507. package init(rawValue: UInt8) {
  508. self.rawValue = rawValue
  509. }
  510. }
  511. /// Returns the up-to-14-bit unsigned integer that has been base-128 encoded at the given byte
  512. /// offset in the buffer.
  513. @_alwaysEmitIntoClient @inline(__always)
  514. private func fixed2ByteBase128(in buffer: UnsafeRawBufferPointer, atByteOffset byteOffset: Int) -> Int {
  515. let rawBits = UInt16(littleEndian: buffer.loadUnaligned(fromByteOffset: byteOffset, as: UInt16.self))
  516. return Int((rawBits & 0x007f) | ((rawBits & 0x7f00) >> 1))
  517. }
  518. /// Returns the up-to-21-bit unsigned integer that has been base-128 encoded at the given byte
  519. /// offset in the buffer.
  520. @_alwaysEmitIntoClient @inline(__always)
  521. private func fixed3ByteBase128(in buffer: UnsafeRawBufferPointer, atByteOffset byteOffset: Int) -> Int {
  522. let lowBits = UInt16(littleEndian: buffer.loadUnaligned(fromByteOffset: byteOffset, as: UInt16.self))
  523. let highBits = buffer.loadUnaligned(fromByteOffset: byteOffset, as: UInt8.self)
  524. return Int((lowBits & 0x00007f) | ((lowBits & 0x007f00) >> 1)) | Int((highBits << 16))
  525. }