{{ self::swift_doc_block(cls.doc, "") }}public final class {{ cls.name }} {
    let handle: UnsafeMutableRawPointer

    init(handle: UnsafeMutableRawPointer) {
        self.handle = handle
    }
{%- for ctor in cls.constructors %}
{%- if ctor.is_designated() %}

{{ self::swift_doc_block(ctor.doc(), "    ") }}    public init{% if ctor.is_optional() %}?{% endif %}({% for p in ctor.params() %}{{ p.signature() }}{% if !loop.last %}, {% endif %}{% endfor %}){% if ctor.is_fallible() %} throws{% endif %} {
{%- for param in ctor.params() %}
{%- if let Some(wrapper) = param.wrapper_code() %}
        {{ wrapper }}
{%- endif %}
{%- endfor %}
{%- if ctor.is_optional() %}
        let ptr = {% for w in ctor.annotated_closure_wrappers() %}{{ w }} {% endfor %}{{ ctor.call_expr() }}{% for _ in ctor.closure_wrappers() %} }{% endfor %}
        guard let ptr = ptr else {
            return nil
        }
{%- elif ctor.is_fallible() %}
        let ptr = {% for w in ctor.annotated_closure_wrappers() %}{{ w }} {% endfor %}{{ ctor.call_expr() }}{% for _ in ctor.closure_wrappers() %} }{% endfor %}
        guard let ptr = ptr else {
            throw FfiError(message: takeLastErrorMessage())
        }
{%- else %}
        let ptr = {% for w in ctor.annotated_closure_wrappers() %}{{ w }} {% endfor %}{{ ctor.call_expr() }}{% for _ in ctor.closure_wrappers() %} }{% endfor %}!
{%- endif %}
        self.handle = ptr
    }
{%- else if ctor.is_factory() %}

{{ self::swift_doc_block(ctor.doc(), "    ") }}    public static func {{ ctor.name().unwrap() }}(){% if ctor.is_fallible() %} throws{% endif %} -> {{ cls.name }}{% if ctor.is_optional() %}?{% endif %} {
{%- if ctor.is_optional() %}
        guard let ptr = {{ ctor.ffi_symbol() }}() else {
            return nil
        }
{%- elif ctor.is_fallible() %}
        guard let ptr = {{ ctor.ffi_symbol() }}() else {
            throw FfiError(message: takeLastErrorMessage())
        }
{%- else %}
        let ptr = {{ ctor.ffi_symbol() }}()!
{%- endif %}
        return {{ cls.name }}(handle: ptr)
    }
{%- else if ctor.is_convenience() %}

{{ self::swift_doc_block(ctor.doc(), "    ") }}    public convenience init{% if ctor.is_optional() %}?{% endif %}({% for p in ctor.params() %}{{ p.signature() }}{% if !loop.last %}, {% endif %}{% endfor %}){% if ctor.is_fallible() %} throws{% endif %} {
{%- for param in ctor.params() %}
{%- if let Some(wrapper) = param.wrapper_code() %}
        {{ wrapper }}
{%- endif %}
{%- endfor %}
{%- if ctor.is_optional() %}
        let ptr = {% for w in ctor.annotated_closure_wrappers() %}{{ w }} {% endfor %}{{ ctor.call_expr() }}{% for _ in ctor.closure_wrappers() %} }{% endfor %}
        guard let ptr = ptr else {
            return nil
        }
{%- elif ctor.is_fallible() %}
        let ptr = {% for w in ctor.annotated_closure_wrappers() %}{{ w }} {% endfor %}{{ ctor.call_expr() }}{% for _ in ctor.closure_wrappers() %} }{% endfor %}
        guard let ptr = ptr else {
            throw FfiError(message: takeLastErrorMessage())
        }
{%- else %}
        let ptr = {% for w in ctor.annotated_closure_wrappers() %}{{ w }} {% endfor %}{{ ctor.call_expr() }}{% for _ in ctor.closure_wrappers() %} }{% endfor %}!
{%- endif %}
        self.init(handle: ptr)
    }
{%- endif %}
{%- endfor %}

    deinit {
        {{ cls.ffi_free }}(handle)
    }
{%- for method in cls.methods %}

{{ self::swift_doc_block(method.doc, "    ") }}    public{% if method.is_mutating() %} mutating{% elif method.is_static %} static{% endif %} func {{ method.name }}({% for p in method.params %}{{ p.signature() }}{% if !loop.last %}, {% endif %}{% endfor %}){% if method.mode.is_async() %} async throws{% if let Some(result) = method.mode.async_result() %}{% if let Some(ret) = result.swift_type() %} -> {{ ret }}{% endif %}{% endif %}{% else %}{% if method.returns.is_throws() %} throws{% endif %}{% if let Some(ret) = method.returns.swift_type() %} -> {{ ret }}{% endif %}{% endif %} {
{%- match method.mode %}
{%- when SwiftCallMode::Async { start, poll, complete, cancel, free, result } %}
{%- for param in method.params %}
{%- if let Some(wrapper) = param.wrapper_code() %}
        {{ wrapper }}
{%- endif %}
{%- endfor %}
        let futureHandle = {% for w in method.closure_wrappers() %}{{ w }} {% endfor %}{{ method.start_call_expr() }}{% for _ in method.closure_wrappers() %} }{% endfor %}

{%- if result.is_direct() || result.is_unit() %}
{%- if result.is_direct() %}
        let rawResult = try await boltffiAsyncCallDirect(
            futureHandle: futureHandle,
            pollFn: {{ poll }},
            completeFn: {{ complete }},
            cancelFn: {{ cancel }},
            freeFn: {{ free }}
        )
{%- if let Some(expr) = result.direct_return_expr("rawResult") %}
        return {{ expr }}
{%- endif %}
{%- else %}
        return try await boltffiAsyncCallDirect(
            futureHandle: futureHandle,
            pollFn: {{ poll }},
            completeFn: {{ complete }},
            cancelFn: {{ cancel }},
            freeFn: {{ free }}
        )
{%- endif %}
{%- elif result.is_direct_buffer() %}
        return try await boltffiAsyncCall(
            futureHandle: futureHandle,
            pollFn: {{ poll }},
            completeFn: {{ complete }},
            cancelFn: {{ cancel }},
            freeFn: {{ free }}
        ) { buf, status in
            guard status.code == 0 else { {{ prefix }}_free_buf(buf); throw FfiError(message: "FFI failed in async completion with code \(status.code)") }
            defer { {{ prefix }}_free_buf(buf) }
{%- if result.direct_buffer_is_data() %}
            guard buf.len > 0, let ptr = buf.ptr else { return Data() }
            return Data(bytes: ptr, count: Int(buf.len))
{%- else %}
            guard buf.len > 0, let ptr = buf.ptr else { return [] }
            let count = Int(buf.len) / MemoryLayout<{{ result.direct_buffer_element_type().unwrap() }}>.stride
            let rawPtr = UnsafeRawPointer(ptr).assumingMemoryBound(to: {{ result.direct_buffer_element_type().unwrap() }}.self)
{%- if let Some(mapping) = result.direct_buffer_composite_mapping() %}
            return (0..<count).map { i in
                let _raw = rawPtr[i]
                return {{ mapping.swift_record_type }}({% for f in mapping.fields %}{{ f.swift_name }}: _raw.{{ f.c_name }}{% if !loop.last %}, {% endif %}{% endfor %})
            }
{%- elif let Some(enum_name) = result.direct_buffer_enum_mapping() %}
            return Array(UnsafeBufferPointer(start: UnsafeRawPointer(rawPtr).assumingMemoryBound(to: {{ enum_name }}.self), count: count))
{%- else %}
            return Array(UnsafeBufferPointer(start: rawPtr, count: count))
{%- endif %}
{%- endif %}
        }
{%- else %}
        return try await boltffiAsyncCall(
            futureHandle: futureHandle,
            pollFn: {{ poll }},
            completeFn: {{ complete }},
            cancelFn: {{ cancel }},
            freeFn: {{ free }}
        ) { buf, status in
            guard status.code == 0 else { {{ prefix }}_free_buf(buf); throw FfiError(message: "FFI failed in async completion with code \(status.code)") }
{%- if result.throws() %}
            defer { {{ prefix }}_free_buf(buf) }
            return try boltffiDecodeOwnedBuf(buf.ptr, Int(buf.len)) { reader in {{ result.reader_decode_expr().unwrap() }} }
{%- else %}
            defer { {{ prefix }}_free_buf(buf) }
            return boltffiDecodeOwnedBuf(buf.ptr, Int(buf.len)) { reader in {{ result.reader_decode_expr().unwrap() }} }
{%- endif %}
        }
{%- endif %}
{%- when SwiftCallMode::Sync { symbol } %}
{%- for param in method.params %}
{%- if let Some(wrapper) = param.wrapper_code() %}
        {{ wrapper }}
{%- endif %}
{%- endfor %}
{%- if let Some(rs) = method.value_self %}
{%- if let Some(wrapper) = rs.wrapper_code %}
        {{ wrapper }}
{%- endif %}
{%- endif %}
{%- for open in method.sync_closure_opens() %}
{{ open }}
{%- endfor %}
{%- if method.returns.is_void() %}
{{ method.method_body_indent() }}{{ method.sync_call_expr() }}
{%- elif method.returns.is_direct_buffer() %}
{{ method.method_body_indent() }}let buf = {{ method.sync_call_expr() }}
{{ method.method_body_indent() }}defer { {{ prefix }}_free_buf(buf) }
{%- if method.returns.direct_buffer_is_data() %}
{{ method.method_body_indent() }}guard buf.len > 0, let ptr = buf.ptr else { return Data() }
{{ method.method_body_indent() }}return Data(bytes: ptr, count: Int(buf.len))
{%- else %}
{{ method.method_body_indent() }}guard buf.len > 0, let ptr = buf.ptr else { return [] }
{{ method.method_body_indent() }}let count = Int(buf.len) / MemoryLayout<{{ method.returns.direct_buffer_element_type().unwrap() }}>.stride
{{ method.method_body_indent() }}let rawPtr = UnsafeRawPointer(ptr).assumingMemoryBound(to: {{ method.returns.direct_buffer_element_type().unwrap() }}.self)
{%- if let Some(mapping) = method.returns.direct_buffer_composite_mapping() %}
{{ method.method_body_indent() }}return (0..<count).map { i in
{{ method.method_body_indent() }}    let _raw = rawPtr[i]
{{ method.method_body_indent() }}    return {{ mapping.swift_record_type }}({% for f in mapping.fields %}{{ f.swift_name }}: _raw.{{ f.c_name }}{% if !loop.last %}, {% endif %}{% endfor %})
{{ method.method_body_indent() }}}
{%- elif let Some(enum_name) = method.returns.direct_buffer_enum_mapping() %}
{{ method.method_body_indent() }}return Array(UnsafeBufferPointer(start: UnsafeRawPointer(rawPtr).assumingMemoryBound(to: {{ enum_name }}.self), count: count))
{%- else %}
{{ method.method_body_indent() }}return Array(UnsafeBufferPointer(start: rawPtr, count: count))
{%- endif %}
{%- endif %}
{%- elif method.returns.is_wire_encoded() %}
{{ method.method_body_indent() }}let buf = {{ method.sync_call_expr() }}
{{ method.method_body_indent() }}defer { {{ prefix }}_free_buf(buf) }
{%- if let Some(reader_expr) = method.returns.reader_decode_expr() %}
{%- if method.is_mutating() %}
{{ method.method_body_indent() }}self = boltffiDecodeOwnedBuf(buf.ptr, Int(buf.len)) { reader in {{ reader_expr }} }
{%- elif method.returns.is_throws() %}
{{ method.method_body_indent() }}return try boltffiDecodeOwnedBuf(buf.ptr, Int(buf.len)) { reader in {{ reader_expr }} }
{%- else %}
{{ method.method_body_indent() }}return boltffiDecodeOwnedBuf(buf.ptr, Int(buf.len)) { reader in {{ reader_expr }} }
{%- endif %}
{%- elif let Some(decode_expr) = method.returns.decode_expr() %}
{{ method.method_body_indent() }}let wire = WireBuffer(ptr: buf.ptr!, len: Int(buf.len))
{%- if method.is_mutating() %}
{{ method.method_body_indent() }}self = {{ decode_expr }}
{%- else %}
{{ method.method_body_indent() }}return {{ decode_expr }}
{%- endif %}
{%- endif %}
{%- elif method.returns.is_throws() %}
{{ method.method_body_indent() }}fatalError("throwing methods not yet implemented in IR backend")
{%- elif let Some((class_name, nullable)) = method.returns.handle_info() %}
{%- if nullable %}
{{ method.method_body_indent() }}guard let ptr = {{ method.sync_call_expr() }} else { return nil }
{{ method.method_body_indent() }}return {{ class_name }}(handle: ptr)
{%- else %}
{{ method.method_body_indent() }}let ptr = {{ method.sync_call_expr() }}!
{{ method.method_body_indent() }}return {{ class_name }}(handle: ptr)
{%- endif %}
{%- elif let Some((protocol_name, nullable)) = method.returns.callback_info() %}
{{ method.method_body_indent() }}let callback = {{ method.sync_call_expr() }}
{%- if nullable %}
{{ method.method_body_indent() }}guard callback.handle != 0 else { return nil }
{%- endif %}
{{ method.method_body_indent() }}return {{ protocol_name }}Bridge.wrap(callback)
{%- elif method.returns.is_composite() %}
{%- if let Some(convert_expr) = method.returns.composite_convert_expr("_raw") %}
{{ method.method_body_indent() }}let _raw = {{ method.sync_call_expr() }}
{%- if method.is_mutating() %}
{{ method.method_body_indent() }}self = {{ convert_expr }}
{%- else %}
{{ method.method_body_indent() }}return {{ convert_expr }}
{%- endif %}
{%- endif %}
{%- elif method.returns.is_c_style_enum() %}
{{ method.method_body_indent() }}return {{ method.returns.c_style_enum_type().unwrap() }}(rawValue: {{ method.sync_call_expr() }})!
{%- else %}
{{ method.method_body_indent() }}return {{ method.sync_call_expr() }}
{%- endif %}
{%- for close in method.sync_closure_closes() %}
{{ close }}
{%- endfor %}
{%- endmatch %}
    }
{%- endfor %}
{% for stream in cls.streams %}

{%- match stream.mode %}
{%- when SwiftStreamMode::Async %}
    public func {{ stream.name }}() -> _Concurrency.AsyncStream<{{ stream.item_type }}> {
        _Concurrency.AsyncStream<{{ stream.item_type }}>(bufferingPolicy: .unbounded) { continuation in
            guard let subscription = {{ stream.subscribe }}(self.handle) else {
                continuation.finish()
                return
            }
            let context = WireStreamContextBase(
                subscription: subscription, batchSize: 16,
                drainAvailableItems: { subscription, batchSize in
{%- match stream.item_delivery %}
{%- when SwiftStreamItemDelivery::WireEncoded { .. } %}
                    boltffiDrainWireStreamBatch(
                        subscription: subscription,
                        batchSize: batchSize,
                        popBatch: {{ stream.pop_batch }},
                        freeBuf: {{ stream.free_buf }}
                    ) { reader in
                        let count = Int(reader.readU32())
                        for _ in 0..<count {
                            let item = {{ stream.item_delivery.reader_decode_expr().unwrap() }}
                            _ = continuation.yield(item)
                        }
                    }
{%- when SwiftStreamItemDelivery::Direct { c_element_type, .. } %}
                    boltffiDrainDirectStreamBatch(
                        subscription: subscription,
                        batchSize: batchSize,
                        popBatch: {{ stream.pop_batch }}
                    ) { rawItems in
                        for rawItem in rawItems {
                            let item = {{ stream.item_delivery.direct_item_expr("rawItem").unwrap() }}
                            _ = continuation.yield(item)
                        }
                    }
{%- endmatch %}
                },
                poll: {{ stream.poll }},
                unsubscribe: {{ stream.unsubscribe }},
                freeFn: {{ stream.free }},
                atomicCas: {{ stream.atomic_cas }},
                finish: { continuation.finish() }
            )
            continuation.onTermination = { @Sendable _ in context.requestTermination() }
            context.start()
        }
    }
{%- when SwiftStreamMode::Batch { class_name, method_name_pascal } %}
    public func {{ stream.name }}() -> {{ class_name }}{{ method_name_pascal }}Subscription {
        {{ class_name }}{{ method_name_pascal }}Subscription(
            handle: {{ stream.subscribe }}(self.handle),
            readBatch: { subscription, batchSize in
{%- match stream.item_delivery %}
{%- when SwiftStreamItemDelivery::WireEncoded { .. } %}
                boltffiReadWireStreamBatch(
                    subscription: subscription,
                    batchSize: batchSize,
                    popBatch: {{ stream.pop_batch }},
                    freeBuf: {{ stream.free_buf }}
                ) { reader in
                    let count = Int(reader.readU32())
                    var result: [{{ stream.item_type }}] = []
                    result.reserveCapacity(count)
                    for _ in 0..<count {
                        let item = {{ stream.item_delivery.reader_decode_expr().unwrap() }}
                        result.append(item)
                    }
                    return result
                }
{%- when SwiftStreamItemDelivery::Direct { c_element_type, .. } %}
                return boltffiReadDirectStreamBatch(
                    subscription: subscription,
                    batchSize: batchSize,
                    popBatch: {{ stream.pop_batch }}
                ) { rawItems in
                    rawItems.map { rawItem in
                    {{ stream.item_delivery.direct_item_expr("rawItem").unwrap() }}
                    }
                }
{%- endmatch %}
            },
            wait: {{ stream.wait }},
            unsubscribe: {{ stream.unsubscribe }},
            freeFn: {{ stream.free }}
        )
    }
{%- when SwiftStreamMode::Callback { class_name, method_name_pascal } %}
    public func {{ stream.name }}(callback: @escaping ({{ stream.item_type }}) -> Void) -> {{ class_name }}{{ method_name_pascal }}Cancellable {
        guard let subscription = {{ stream.subscribe }}(self.handle) else {
            return {{ class_name }}{{ method_name_pascal }}Cancellable {}
        }

        final class CallbackContext: @unchecked Sendable {
            let subscription: SubscriptionHandle
            let batchSize: UInt
            let drainAvailableItems: (SubscriptionHandle, UInt) -> Bool
            let unsubscribe: (SubscriptionHandle?) -> Void
            let freeFn: (SubscriptionHandle?) -> Void
            let atomicCas: (UnsafeMutablePointer<UInt8>?, UInt8, UInt8) -> Bool
            let callback: ({{ stream.item_type }}) -> Void
            private var lifecycleTag: UInt8 = 0
            private var callbackTag: UInt8 = 0

            init(
                subscription: SubscriptionHandle, batchSize: UInt,
                drainAvailableItems: @escaping (SubscriptionHandle, UInt) -> Bool,
                poll: @escaping (SubscriptionHandle?, UInt64, StreamContinuationCallback?) -> Void,
                unsubscribe: @escaping (SubscriptionHandle?) -> Void,
                freeFn: @escaping (SubscriptionHandle?) -> Void,
                atomicCas: @escaping (UnsafeMutablePointer<UInt8>?, UInt8, UInt8) -> Bool,
                callback: @escaping ({{ stream.item_type }}) -> Void
            ) {
                self.subscription = subscription; self.batchSize = batchSize
                self.drainAvailableItems = drainAvailableItems; self.unsubscribe = unsubscribe
                self.freeFn = freeFn; self.atomicCas = atomicCas
                self.callback = callback
            }

            func start() { registerPoll() }

            func requestTermination() {
                let started = withUnsafeMutablePointer(to: &lifecycleTag) { atomicCas($0, 0, 1) }
                if started { unsubscribe(subscription); _ = withUnsafeMutablePointer(to: &lifecycleTag) { atomicCas($0, 1, 2) } }
                attemptFinalize()
            }

            private func attemptFinalize() {
                guard (withUnsafeMutablePointer(to: &callbackTag) { atomicCas($0, 0, 0) }) else { return }
                guard (withUnsafeMutablePointer(to: &lifecycleTag) { atomicCas($0, 2, 3) }) else { return }
                freeFn(subscription)
            }

            private func schedulePoll() { _Concurrency.Task { [self] in await _Concurrency.Task.yield(); registerPoll() } }

            private func registerPoll() {
                guard (withUnsafeMutablePointer(to: &lifecycleTag) { atomicCas($0, 0, 0) }) else { attemptFinalize(); return }
                let data = UInt64(UInt(bitPattern: Unmanaged.passRetained(self).toOpaque()))
                {{ stream.poll }}(subscription, data) { data, result in
                    Unmanaged<CallbackContext>.fromOpaque(UnsafeRawPointer(bitPattern: UInt(data))!).takeRetainedValue().handlePoll(result)
                }
            }

            private func handlePoll(_ pollResult: Int8) {
                let isClosed = pollResult == StreamPollResult.closed.rawValue
                guard (withUnsafeMutablePointer(to: &callbackTag) { atomicCas($0, 0, 1) }) else { attemptFinalize(); return }
                defer { _ = withUnsafeMutablePointer(to: &callbackTag) { atomicCas($0, 1, 0) }; attemptFinalize() }
                guard (withUnsafeMutablePointer(to: &lifecycleTag) { atomicCas($0, 0, 0) }) else { return }
                while drainAvailableItems(subscription, batchSize) {}
                if isClosed { requestTermination(); return }
                guard (withUnsafeMutablePointer(to: &lifecycleTag) { atomicCas($0, 0, 0) }) else { return }
                schedulePoll()
            }
        }

        let context = CallbackContext(
            subscription: subscription, batchSize: 16,
            drainAvailableItems: { subscription, batchSize in
{%- match stream.item_delivery %}
{%- when SwiftStreamItemDelivery::WireEncoded { .. } %}
                boltffiDrainWireStreamBatch(
                    subscription: subscription,
                    batchSize: batchSize,
                    popBatch: {{ stream.pop_batch }},
                    freeBuf: {{ stream.free_buf }}
                ) { reader in
                    let count = Int(reader.readU32())
                    for _ in 0..<count {
                        let item = {{ stream.item_delivery.reader_decode_expr().unwrap() }}
                        callback(item)
                    }
                }
{%- when SwiftStreamItemDelivery::Direct { c_element_type, .. } %}
                boltffiDrainDirectStreamBatch(
                    subscription: subscription,
                    batchSize: batchSize,
                    popBatch: {{ stream.pop_batch }}
                ) { rawItems in
                    for rawItem in rawItems {
                        let item = {{ stream.item_delivery.direct_item_expr("rawItem").unwrap() }}
                        callback(item)
                    }
                }
{%- endmatch %}
            },
            poll: {{ stream.poll }},
            unsubscribe: {{ stream.unsubscribe }},
            freeFn: {{ stream.free }},
            atomicCas: {{ stream.atomic_cas }},
            callback: callback
        )
        context.start()
        return {{ class_name }}{{ method_name_pascal }}Cancellable { context.requestTermination() }
    }
{%- endmatch %}
{%- endfor %}
}
{%- for stream in cls.streams %}
{%- match stream.mode %}
{%- when SwiftStreamMode::Batch { class_name, method_name_pascal } %}

public final class {{ class_name }}{{ method_name_pascal }}Subscription {
    private let handle: SubscriptionHandle?
    private let readBatchFn: (SubscriptionHandle, UInt) -> [{{ stream.item_type }}]
    private let waitFn: (SubscriptionHandle, UInt32) -> Int32
    private let unsubscribeFn: (SubscriptionHandle?) -> Void
    private let freeFn: (SubscriptionHandle?) -> Void
    private var isUnsubscribed = false

    init(
        handle: SubscriptionHandle?,
        readBatch: @escaping (SubscriptionHandle, UInt) -> [{{ stream.item_type }}],
        wait: @escaping (SubscriptionHandle, UInt32) -> Int32,
        unsubscribe: @escaping (SubscriptionHandle?) -> Void,
        freeFn: @escaping (SubscriptionHandle?) -> Void
    ) {
        self.handle = handle
        self.readBatchFn = readBatch
        self.waitFn = wait
        self.unsubscribeFn = unsubscribe
        self.freeFn = freeFn
    }

    deinit {
        freeFn(handle)
    }

    public func popBatch(maxCount: UInt = 16) -> [{{ stream.item_type }}] {
        guard let h = handle else { return [] }
        return readBatchFn(h, maxCount)
    }

    public func wait(timeout: UInt32) -> Int32 {
        guard let h = handle else { return -1 }
        return waitFn(h, timeout)
    }

    public func unsubscribe() {
        guard !isUnsubscribed else { return }
        isUnsubscribed = true
        unsubscribeFn(handle)
    }
}
{%- when SwiftStreamMode::Callback { class_name, method_name_pascal } %}

public final class {{ class_name }}{{ method_name_pascal }}Cancellable {
    private var isCancelled = false
    private let cancelAction: () -> Void

    init(onCancel: @escaping () -> Void = {}) {
        self.cancelAction = onCancel
    }

    deinit {
        cancel()
    }

    public func cancel() {
        guard !isCancelled else { return }
        isCancelled = true
        cancelAction()
    }
}
{%- when SwiftStreamMode::Async %}
{%- endmatch %}
{%- endfor %}
