File: GuestPrelude.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (137 lines) | stat: -rw-r--r-- 5,666 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
let guestPrelude = """
    // DO NOT EDIT.
    //
    // Generated by the wit-overlay-generator

    #if arch(wasm32)
    import WASILibc
    @_implementationOnly import _CabiShims

    fileprivate enum Prelude {
        class LeakBox<Wrapped> {
            let wrapped: Wrapped
            init(wrapped: Wrapped) {
                self.wrapped = wrapped
            }
        }

        static func release(_ buffer: UnsafeMutableRawPointer) {
            buffer.deallocate()
        }

        /// Before calling any exported function, this function must be called to ensure
        /// that the static constructors are called because wasi-libc and Swift runtime
        /// has some ctor works to do.
        static func initializeOnce() {
            enum Static {
                static var _initialized = false
            }
            guard !Static._initialized else { return }
            __wasm_call_ctors()
        }

        static func deallocateList(
            pointer: UInt32, length: UInt32, elementSize: Int,
            deallocateElement: (UnsafeMutableRawPointer) -> Void
        ) {
            guard let basePointer = UnsafeMutableRawPointer(bitPattern: Int(pointer)) else {
                return
            }
            for i in 0..<Int(length) {
                let elementPointer = basePointer.advanced(by: i * elementSize)
                deallocateElement(elementPointer)
            }
            basePointer.deallocate()
        }

        static func deallocateString(pointer: UInt32, length: UInt32) {
            UnsafeMutableRawPointer(bitPattern: Int(pointer))?.deallocate()
        }

        static func liftList<Element>(
            pointer: UInt32, length: UInt32, elementSize: Int,
            loadElement: (UnsafeRawPointer) -> Element
        ) -> [Element] {
            var elements = [Element]()
            elements.reserveCapacity(Int(elementSize))
            let guestPointer = UnsafeRawPointer(bitPattern: Int(pointer))!
            for i in 0..<Int(length) {
                let element = loadElement(guestPointer.advanced(by: i * elementSize))
                elements.append(element)
            }
            return elements
        }

        static func lowerList<Key, Value>(
            _ dictionary: [Key: Value], elementSize: Int, elementAlignment: Int,
            storeElement: ((Key, Value), UnsafeMutableRawPointer) -> Void
        ) -> (pointer: UInt, length: UInt) {
            return lowerList(
                Array(dictionary), elementSize: elementSize,
                elementAlignment: elementAlignment, storeElement: storeElement
            )
        }

        static func lowerList<Element>(
            _ array: [Element], elementSize: Int, elementAlignment: Int,
            storeElement: (Element, UnsafeMutableRawPointer) -> Void
        ) -> (pointer: UInt, length: UInt) {
            let newBuffer = malloc(elementSize * array.count)
            for (i, element) in array.enumerated() {
                storeElement(element, newBuffer!.advanced(by: i * elementSize))
            }
            return (
                newBuffer.map { UInt(bitPattern: $0) } ?? 0, UInt(array.count)
            )
        }

        /// Create a buffer pointer with the given array contents.
        ///
        /// The returned buffer pointer is leaked and not managed by Swift's memory model,
        /// so the caller is responsible for deallocating it after use. It's useful to
        /// dynamically control lifetime of buffer in unstructured way. (e.g. returning
        /// a list/string from an exported function requires a separate cleanup function call
        /// after the caller component reads and copies the content into their memory space,
        /// so callee has to keep the buffer available until the exported cleanup function
        /// is called.)
        static func leakUnderlyingBuffer<Element>(_ array: [Element]) -> UInt {
             precondition(_isPOD(Element.self))
            // TODO: As an optimization, we can reuse the underlying buffer space of `Array`,
            // but the buffer is somehow deallocated even performing unbalanced retain operation.
            // So this function just creates a new buffer and copy the contents of the given array
            // for now.
            //
            // let (owner, pointer): (AnyObject?, UnsafeRawPointer) = _convertConstArrayToPointerArgument(array)
            // Unmanaged.passRetained(owner!)
            // return pointer
            return array.withUnsafeBufferPointer { buffer in
                let rawBuffer = UnsafeRawBufferPointer(buffer)
                let newBuffer = UnsafeMutableRawBufferPointer.allocate(
                    byteCount: rawBuffer.count * MemoryLayout<Element>.size,
                    alignment: MemoryLayout<Element>.alignment
                )
                newBuffer.copyMemory(from: rawBuffer)
                return newBuffer.baseAddress.map { UInt(bitPattern: $0) } ?? 0
            }
        }
    }

    public struct ComponentError<Content>: Error {
        let content: Content

        init(_ content: Content) {
            self.content = content
        }
    }

    extension ComponentError: Equatable where Content: Equatable {}
    extension ComponentError: Hashable where Content: Hashable {}

    // TODO: use `@_expose(wasm)`
    // NOTE: multiple objects in a component can have cabi_realloc definition so use `@_weakLinked` here.
    @_weakLinked
    @_cdecl("cabi_realloc")
    func cabi_realloc(old: UnsafeMutableRawPointer, oldSize: UInt, align: UInt, newSize: UInt) -> UnsafeMutableRawPointer {
        realloc(old, Int(newSize))
    }
    """