FieldTag.swift 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // Sources/SwiftProtobuf/FieldTag.swift - Describes a binary field tag
  2. //
  3. // Copyright (c) 2014 - 2016 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. /// Types related to binary encoded tags (field numbers and wire formats).
  12. ///
  13. // -----------------------------------------------------------------------------
  14. /// Encapsulates the number and wire format of a field, which together form the
  15. /// "tag".
  16. ///
  17. /// This type also validates tags in that it will never allow a tag with an
  18. /// improper field number (such as zero) or wire format (such as 6 or 7) to
  19. /// exist. In other words, a `FieldTag`'s properties never need to be tested
  20. /// for validity because they are guaranteed correct at initialization time.
  21. package struct FieldTag: RawRepresentable {
  22. package typealias RawValue = UInt32
  23. /// The raw numeric value of the tag, which contains both the field number and
  24. /// wire format.
  25. package let rawValue: UInt32
  26. /// The field number component of the tag.
  27. package var fieldNumber: Int {
  28. Int(rawValue >> 3)
  29. }
  30. /// The wire format component of the tag.
  31. package var wireFormat: WireFormat {
  32. // This force-unwrap is safe because there are only two initialization
  33. // paths: one that takes a WireFormat directly (and is guaranteed valid at
  34. // compile-time), or one that takes a raw value but which only lets valid
  35. // wire formats through.
  36. WireFormat(rawValue: UInt8(rawValue & 7))!
  37. }
  38. /// A helper property that returns the number of bytes required to
  39. /// varint-encode this tag.
  40. package var encodedSize: Int {
  41. Varint.encodedSize(of: rawValue)
  42. }
  43. /// Creates a new tag from its raw numeric representation.
  44. ///
  45. /// Note that if the raw value given here is not a valid tag (for example, it
  46. /// has an invalid wire format), this initializer will fail.
  47. package init?(rawValue: UInt32) {
  48. // Verify that the field number and wire format are valid and fail if they
  49. // are not.
  50. guard rawValue & ~0x07 != 0,
  51. let _ = WireFormat(rawValue: UInt8(rawValue % 8))
  52. else {
  53. return nil
  54. }
  55. self.rawValue = rawValue
  56. }
  57. /// Creates a new tag by composing the given field number and wire format.
  58. package init(fieldNumber: Int, wireFormat: WireFormat) {
  59. self.rawValue = UInt32(truncatingIfNeeded: fieldNumber) << 3 | UInt32(wireFormat.rawValue)
  60. }
  61. }