| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- // Sources/protoc-gen-swift/MessageStorageClassGenerator.swift - Message storage class logic
- //
- // Copyright (c) 2014 - 2016 Apple Inc. and the project authors
- // Licensed under Apache License v2.0 with Runtime Library Exception
- //
- // See LICENSE.txt for license information:
- // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
- //
- // -----------------------------------------------------------------------------
- ///
- /// Code generation for the private storage class used inside copy-on-write
- /// messages.
- ///
- // -----------------------------------------------------------------------------
- import Foundation
- import SwiftProtobuf
- import SwiftProtobufPluginLibrary
- /// Generates the `_StorageClass` used for messages that employ copy-on-write
- /// logic for some of their fields.
- class MessageStorageClassGenerator {
- private let fields: [any FieldGenerator]
- /// Creates a new `MessageStorageClassGenerator`.
- init(fields: [any FieldGenerator]) {
- self.fields = fields
- }
- /// Visibility of the storage within the Message.
- var storageVisibility: String {
- "fileprivate"
- }
- /// If the storage wants to manually implement equality.
- var storageProvidesEqualTo: Bool { false }
- /// Generates the full code for the storage class.
- ///
- /// - Parameter p: The code printer.
- func generateTypeDeclaration(printer p: inout CodePrinter) {
- p.print("fileprivate class _StorageClass {")
- p.withIndentation { p in
- generateStoredProperties(printer: &p)
- // Generate a default instance to be used so the heap allocation is
- // delayed until mutation is needed. This is the largest savings when
- // the message is used as a field in another message as it causes
- // returning the default to not require that heap allocation, i.e. -
- // readonly usage never causes the allocation.
- p.print(
- """
- // This property is used as the initial default value for new instances of the type.
- // The type itself is protecting the reference to its storage via CoW semantics.
- // This will force a copy to be made of this reference when the first mutation occurs;
- // hence, it is safe to mark this as `nonisolated(unsafe)`.
- static nonisolated(unsafe) let defaultInstance = _StorageClass()
- private init() {}
- """
- )
- generateClone(printer: &p)
- }
- p.print("}")
- }
- /// Generated the uniqueStorage() implementation.
- func generateUniqueStorage(printer p: inout CodePrinter) {
- p.print("\(storageVisibility) mutating func _uniqueStorage() -> _StorageClass {")
- p.withIndentation { p in
- p.print("if !isKnownUniquelyReferenced(&_storage) {")
- p.printIndented("_storage = _StorageClass(copying: _storage)")
- p.print(
- "}",
- "return _storage"
- )
- }
- p.print("}")
- }
- func generatePreTraverse(printer p: inout CodePrinter) {
- // Nothing
- }
- /// Generates the stored properties for the storage class.
- ///
- /// - Parameter p: The code printer.
- private func generateStoredProperties(printer p: inout CodePrinter) {
- for f in fields {
- f.generateStorage(printer: &p)
- }
- }
- /// Generates the `init(copying:)` method of the storage class.
- ///
- /// - Parameter p: The code printer.
- private func generateClone(printer p: inout CodePrinter) {
- p.print("init(copying source: _StorageClass) {")
- p.withIndentation { p in
- for f in fields {
- f.generateStorageClassClone(printer: &p)
- }
- }
- p.print("}")
- }
- }
- /// Custom generator for storage of an google.protobuf.Any.
- class AnyMessageStorageClassGenerator: MessageStorageClassGenerator {
- override var storageVisibility: String { "internal" }
- override var storageProvidesEqualTo: Bool { true }
- override func generateTypeDeclaration(printer p: inout CodePrinter) {
- // Just need an alias to the hand coded Storage.
- p.print("typealias _StorageClass = AnyMessageStorage")
- }
- override func generatePreTraverse(printer p: inout CodePrinter) {
- p.print("try _storage.preTraverse()")
- }
- }
|