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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
//! # SwiftUI Native — pure Rust, zero Swift source files
//!
//! Constructs SwiftUI views entirely from Rust using:
//! - `dlsym` to resolve symbols from `SwiftUI.framework`
//! - arm64 inline assembly for Swift calling convention
//! - `swift-runtime-sys` for retain/release and string creation
//!
//! ```text
//! ┌────────────┐ dlsym ┌──────────────────────┐
//! │ Rust code │ ──────────► │ SwiftUI.framework │
//! │ (arm64 │ Swift CC │ (Text, Color, etc.) │
//! │ asm) │ ──────────► │ │
//! └────────────┘ └──────────────────────┘
//! ```
//!
//! # Quick start
//!
//! ```no_run
//! use swiftui_native::{prelude::*, swiftui};
//!
//! run(|| swiftui! {
//! VStack(spacing: 8.0) {
//! Text("Hello from pure Rust!").text_style(.large_title)
//! Text("No Swift source files, no bridging header.")
//! }
//! .padding(20.0)
//! });
//! ```
//!
//! [`swiftui!`] is SwiftUI's own syntax; the same tree written as calls is
//! `vstack_spacing(&[…], Some(8.0)).padding(20.0)`, and [`views`] underneath that
//! is the layer where every argument is explicit. All three are the same thing —
//! pick the one that suits the code around it.
//!
//! # Platform
//!
//! arm64 macOS and iOS, device or simulator. Requires the Swift 6.3+ runtime.
//!
//! Almost none of this is platform-specific: SwiftUI's mangled symbols and the
//! Swift calling convention are the same everywhere, so [`views`], [`abi`],
//! [`state`], [`view`] and the rest are shared verbatim. What differs is the
//! host UI framework SwiftUI draws through, and it differs in three places:
//!
//! * [`hosting`] — AppKit has `NSHostingView`, a view. UIKit has only
//! `UIHostingController`, so there the view comes from `.view` and the
//! SwiftUI side lives on the controller.
//! * [`render`] — `cacheDisplayInRect:` has no UIKit counterpart, so iOS
//! rasterises the layer into a CoreGraphics bitmap instead. The window,
//! sheet, popover and compositor captures are AppKit-only.
//! * [`window`] — an `NSWindow` takes a content view and has a title bar; a
//! `UIWindow` takes a root view controller and has neither.
//!
//! # Conforming to SwiftUI's protocols, from Rust
//!
//! Several of SwiftUI's protocols exist to be implemented by the *caller*:
//! `Layout`, `ButtonStyle`, `ViewModifier`, `Shape`, `Transition`,
//! `CustomAnimation`, `NSViewRepresentable`, and the three keyed bags —
//! `EnvironmentKey`, `FocusedValueKey`, `ContainerValueKey`. A Swift program writes a `struct` and
//! the compiler emits a witness table; there is no compiler here, so the witness
//! table is built at run time and registered with
//! [`swift_registerProtocolConformances`](conformance) — after which SwiftUI
//! finds it by the same lookup it uses for its own.
//!
//! What lands in Rust is a closure. [`views::shape_fn`] is handed the rect and
//! draws a path; [`views::ns_view_fn`] makes an `NSView` through the
//! Objective-C runtime and SwiftUI hosts it; [`views::animation_fn`] is handed a time and answers with a
//! fraction, which is then applied to a value whose type Rust never learns, by
//! calling `VectorArithmetic.scale(by:)` through that type's own witness table.
//!
//! Two things make this harder than it sounds, and both are written up where
//! they bite: every such callback uses the *witness-method* convention, which no
//! `extern "C"` signature can express (see [`views::modifier_fn`]'s module); and `Shape`
//! requires `View`, whose `Body` is a type that cannot be built until `Shape`
//! exists (see [`views::shape_fn`]'s module).
//!
//! # Observation
//!
//! `@Observable` works, and the thing that made it look impossible was wrong.
//! `Observation.Observable` is a **marker protocol** with zero requirements, and
//! `ObservationRegistrar` and `withObservationTracking` are fully exported — so
//! the only real obstacle was that an `@Observable` model is a *class* and this
//! crate mints structs.
//!
//! It does not have to be a *Swift* class. `Observable` requires `AnyObject`, an
//! `NSObject` subclass is one, and [`objc::ClassBuilder`] mints those. The piece
//! that was genuinely missing was a conformance record whose type reference is a
//! class rather than a nominal descriptor — `IndirectObjCClass`, one of the four
//! kinds the format already has, which [`conformance::Conformer`] now emits.
//!
//! What that buys is in [`observable`](mod@observable): a model owned by Rust that SwiftUI
//! re-renders on, without a `@State` write anywhere. [`state::StatefulView`] is
//! still there for view-local state; this is for a model that outlives the view.
//!
//! # Declaring your own keys and models
//!
//! An environment key, a container value key, a focused value key and an
//! `@Observable` model are all things Swift declares with a keyword and this
//! crate synthesises at run time. Each is a `static` — one name is one
//! conformance and one key path — so there is a macro per kind that writes the
//! `static` for you:
//!
//! ```no_run
//! # use swiftui_native::{environment_keys, observable, prelude::*};
//! environment_keys! {
//! /// How deeply this row is nested.
//! depth: i64 = 0,
//! /// What to greet the reader with.
//! greeting: String = "hello",
//! }
//!
//! observable! {
//! /// Everything the app's windows share.
//! pub AppModel {
//! count: i64 = 0,
//! name: String = "Ada",
//! }
//! }
//!
//! run(|| {
//! let model = AppModel::shared();
//! environment_reader(move |env| {
//! format!("{}, {} — {} deep", env.value_for(greeting()), model.name.get(), env.value_for(depth()))
//! })
//! .environment_value(depth(), 3)
//! .environment_model(model.as_model())
//! });
//! ```
//!
//! Each property of a model has a key path of its own, so a body that read
//! `count` is rebuilt when `count` changes and left alone when `name` does. See
//! [`environment_keys!`], [`container_keys!`], [`focused_keys!`] and
//! [`observable!`].
//!
//! # Known limitations
//!
//! **Closure contexts are leaked, deliberately.** A `@ViewBuilder` body that
//! SwiftUI stores — a sheet's content, an alert's actions, a context menu's
//! items — is called long after the binding that created it has returned, so
//! its context and a copy of its child are leaked rather than freed. Building
//! such a view once per process costs nothing; rebuilding one every frame
//! leaks every frame. The non-escaping cases (a stack's content, which the
//! initialiser calls before it returns) borrow instead and leak nothing.
//! `examples/parity`'s `rebuild_is_bounded` check measures the non-escaping side:
//! it builds a stack of eleven children a hundred times, divides the growth in
//! resident memory by a hundred, and fails above 4096 bytes per rebuild. The
//! escaping cases are not bounded by anything, which is the point of naming them
//! here.
//!
//! **`ViewHandle::as_ptr` mints a new `AnyView` each call.** It hands back a
//! `+1` box for a callee to consume. Two calls on the same handle return two
//! different boxes, and a caller that takes one without handing it to Swift
//! has leaked it.
//!
//! **A `@ViewBuilder` closure's result type is fixed when the view is built.**
//! `GeometryReader` and `EnvironmentReader` take a Rust closure run per layout,
//! so there is no type to name when the reader is constructed and its content
//! is erased to `AnyView`. Swift's equivalent is fixed by the compiler, so the
//! two build different — equally valid — types there. Everything else builds
//! the same type Swift does, which `examples/parity` checks case by case.
//!
//! **A `Tab`'s content is boxed, and the whole `TabContent` chain with it.**
//! A `Tab` is a `TabContent` rather than a `View`, so what holds it is a
//! `TabView<_, Content: TabContent>`, and every link — the tab, the
//! `TupleTabContent` over several of them, the `TabView` around those — names
//! `Tab<Never, AnyView, DefaultTabLabel>` in its own type. Typing one link and
//! not the rest describes a value of one layout to code reading another; moving
//! them together is a `TabContent` composition of its own. Everything else that
//! knows its children when it is built keeps their types — `Grid`, `GridRow`,
//! `Section` in all four forms, both `NavigationSplitView` shapes, `Picker`,
//! `Gauge`, `ViewThatFits`, `Menu`, `DisclosureGroup`, `List`, `TabView`,
//! `NavigationStack`, `GroupBox`, `Group`, `ControlGroup`, `Form`, `ForEach`,
//! `TimelineView`, `Toggle` and the stacks — which
//! [`views::substitute_args`](views) composes per content rather than naming a
//! fixed instantiation.
//!
//! All of these are verified the same way, against a Swift reference built for
//! the same platform: `examples/parity` on macOS, `examples/ios_parity` in a simulator.
//! `examples/ios_app` runs a SwiftUI application on iOS through either entry
//! point — a runtime-synthesised `App` conformance, or `UIApplicationMain` with
//! a delegate class built through the Objective-C runtime.
/// Runtime synthesis of a Swift view type with real `@State` storage.
// Keep old modules for backward compat
pub use Color;
pub use HostingView;
pub use Rendered;
pub use View;
pub use Window;
/// A `&mut` to a `static mut`, taken through a raw pointer.
///
/// Two lints disagree about how to write this. `&mut STATIC` is rustc's
/// `static_mut_refs`; `&mut *(&raw mut STATIC)` in one expression is clippy's
/// `deref_addrof`, whose suggested fix is the first form. Going through a
/// function is neither, and the obligation is unchanged either way.
///
/// The slots this is used for — a key path's pattern, an async function pointer
/// record — are each written once, by one caller, before anything reads them.
/// That is what makes the exclusive borrow sound, and it is a property of those
/// call sites rather than of this function.
///
/// # Safety
/// No other reference to the static may be live for the returned lifetime.
pub unsafe
pub use ViewHandle;
/// `swiftui! { … }` — SwiftUI's declarative syntax, lowered to this crate's DSL.
///
/// The DSL is already chainable, so what the macro adds is the part Rust has no
/// syntax for: a *body* of children written one after another, with `if`,
/// `match` and `ForEach` inside it.
///
/// A string literal in the macro is a format string, so values go in the text
/// the way Swift's `\(…)` puts them there — `Text("{count} of {total}")`. Field
/// access works too, `Text("{item.name}")`, which `format!` refuses on its own.
///
/// `$name` passes a binding the way Swift passes a projected value —
/// `Toggle("Dark", isOn: $dark)` — and a leading dot names a case anywhere an
/// argument is taken, `VStack(alignment: .leading)`.
///
/// Swift's further trailing closures carry a label, and work here too:
/// `Section { … } header: { … }` and `Button { … } label: { … }`.
///
/// A trailing brace is content for a modifier that takes a view
/// — `.overlay { Text("over") }` — and an action for one that takes a callback,
/// `.on_tap { count += 1 }`. Swift tells those apart by the parameter's type;
/// with no type to ask, the name does: `on_*`, `task` and `refreshable` take
/// actions. Swift's `{ value in … }` names the callback's argument.
///
/// ```no_run
/// # use swiftui_native::{swiftui, prelude::*};
/// # let show_detail = true;
/// # let items = vec![String::from("one"), String::from("two")];
/// # enum Status { Ready(String), Waiting }
/// # let status = Status::Waiting;
/// let view = swiftui! {
/// VStack(spacing: 8.0) {
/// Text("Title").text_style(.large_title)
/// if show_detail {
/// Text("the details")
/// }
/// match status {
/// Status::Ready(name) => Text("ready: {name}"),
/// _ => Text("waiting"),
/// }
/// ForEach(0..3) { i in
/// Text("row {i}")
/// }
/// ForEach(items) { item in
/// Text(item)
/// }
/// }
/// };
/// ```
///
/// See [`swiftui_native_macros`](../swiftui_native_macros/index.html) for what
/// it does and does not translate.
pub use ;