use super::*;
use crate::abi;
use crate::resolve;
use core::ffi::c_void;
use crate::mangle;
mangle::result_types! {
pub(crate) TOOLBAR_ITEM_T = ty("ToolbarItem").of(vec![Type::Void, ty("AnyView")]);
pub(crate) TOOLBAR_TUPLE_T = ty("TupleToolbarContent").of(vec![ty("ToolbarItem").of(vec![Type::Void, ty("AnyView")])]);
pub(crate) TOOLBAR_ITEM_ID_T = ty("ToolbarItem").of(vec![Type::Verbatim("SS".into()), ty("AnyView")]);
pub(crate) TOOLBAR_TUPLE_ID_T = ty("TupleToolbarContent").of(vec![ty("ToolbarItem").of(vec![Type::Verbatim("SS".into()), ty("AnyView")])]);
}
mangle::modifier_types! {
pub(crate) TOOLBAR_T = ty("ToolbarModifier").of(vec![Type::Void, ty("TupleToolbarContent").of(vec![ty("ToolbarItem").of(vec![Type::Void, ty("AnyView")])])]);
}
swift_statics! {
pub enum ToolbarItemPlacement {
Automatic = c"$s7SwiftUI20ToolbarItemPlacementV9automaticACvgZ",
CancellationAction = c"$s7SwiftUI20ToolbarItemPlacementV18cancellationActionACvgZ",
ConfirmationAction = c"$s7SwiftUI20ToolbarItemPlacementV18confirmationActionACvgZ",
DestructiveAction = c"$s7SwiftUI20ToolbarItemPlacementV17destructiveActionACvgZ",
Keyboard = c"$s7SwiftUI20ToolbarItemPlacementV8keyboardACvgZ",
Navigation = c"$s7SwiftUI20ToolbarItemPlacementV10navigationACvgZ",
PrimaryAction = c"$s7SwiftUI20ToolbarItemPlacementV13primaryActionACvgZ",
Principal = c"$s7SwiftUI20ToolbarItemPlacementV9principalACvgZ",
SecondaryAction = c"$s7SwiftUI20ToolbarItemPlacementV15secondaryActionACvgZ",
Status = c"$s7SwiftUI20ToolbarItemPlacementV6statusACvgZ",
}
}
#[repr(C)]
pub(crate) struct BytesPayload {
pub(crate) data: *const u8,
pub(crate) len: usize,
}
pub(crate) unsafe extern "C" fn emit_bytes(out: *mut u8, payload: *mut c_void) {
let p = unsafe { &*(payload as *const BytesPayload) };
unsafe { core::ptr::copy_nonoverlapping(p.data, out, p.len) };
}
pub fn toolbar(view: &ViewHandle, content: &ViewHandle) -> ViewHandle {
toolbar_placed(view, ToolbarItemPlacement::Automatic, content)
}
pub fn toolbar_placed(
view: &ViewHandle,
placement: ToolbarItemPlacement,
content: &ViewHandle,
) -> ViewHandle {
unsafe {
let placement_meta = abi::metadata0(resolve::toolbar_placement_ma());
let mut placement =
static_getter_indirect(placement.resolved(), placement_meta, 0);
let item_ctx = Box::leak(Box::new(abi::ClosureCtx::new(
emit_tuple,
Child::leak(content, Content::Erased),
))) as *mut abi::ClosureCtx;
let (item_meta, _, item_size) = {
let m = abi::resolve_type_by_mangled_name(&TOOLBAR_ITEM_T);
assert!(!m.is_null(), "ToolbarItem<(), AnyView> metadata");
(m, (), abi::type_bytes(m))
};
let mut item = vec![0u8; item_size];
core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_item_init(),
in("x0") placement.as_mut_ptr(),
in("x1") abi::swift_closure_thunk as *const c_void,
in("x2") item_ctx,
in("x3") resolve::anyview_meta(),
in("x4") resolve::anyview_wt(),
in("x8") item.as_mut_ptr(),
lateout("x5") _, lateout("x6") _, lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
clobber_abi("C"),
);
let item_tc_wt =
abi::get_view_wt_for_proto(item_meta, resolve::toolbar_content_proto());
assert!(!item_tc_wt.is_null(), "ToolbarItem: ToolbarContent");
let tuple_meta = abi::resolve_type_by_mangled_name(&TOOLBAR_TUPLE_T);
assert!(!tuple_meta.is_null(), "TupleToolbarContent metadata");
let mut tuple = vec![0u8; abi::type_bytes(tuple_meta)];
core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_build_block(),
in("x0") item.as_mut_ptr(),
in("x1") item_meta,
in("x2") item_tc_wt,
in("x8") tuple.as_mut_ptr(),
lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _,
lateout("x7") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
lateout("x21") _, clobber_abi("C"),
);
let tuple_tc_wt =
abi::get_view_wt_for_proto(tuple_meta, resolve::toolbar_content_proto());
assert!(!tuple_tc_wt.is_null(), "TupleToolbarContent: ToolbarContent");
let leaked = Box::leak(tuple.into_boxed_slice());
let bytes = Box::leak(Box::new(BytesPayload {
data: leaked.as_ptr(),
len: leaked.len(),
}));
let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
emit_bytes,
bytes as *mut BytesPayload as *mut c_void,
))) as *mut abi::ClosureCtx;
let (_, _, size) = TOOLBAR_T.applied_to(view.meta);
let mut result = vec![0u8; size];
let this = view.value_ptr();
core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_fn(),
in("x0") abi::swift_closure_thunk as *const c_void,
in("x1") ctx,
in("x2") view.meta,
in("x3") tuple_meta,
in("x4") content.wt,
in("x5") tuple_tc_wt,
in("x8") result.as_mut_ptr(),
in("x20") this,
lateout("x6") _, lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
wrap_modified(result, &TOOLBAR_T, view)
}
}
pub fn toolbar_customizable(
view: &ViewHandle,
toolbar_id: &str,
item_id: &str,
shows_by_default: bool,
content: &ViewHandle,
) -> ViewHandle {
toolbar_customizable_placed(
view,
toolbar_id,
item_id,
ToolbarItemPlacement::Automatic,
shows_by_default,
content,
)
}
pub fn toolbar_customizable_placed(
view: &ViewHandle,
toolbar_id: &str,
item_id: &str,
placement: ToolbarItemPlacement,
shows_by_default: bool,
content: &ViewHandle,
) -> ViewHandle {
unsafe {
let placement_meta = abi::metadata0(resolve::toolbar_placement_ma());
let mut placement =
static_getter_indirect(placement.resolved(), placement_meta, 0);
let item_ctx = Box::leak(Box::new(abi::ClosureCtx::new(
emit_tuple,
Child::leak(content, Content::Erased),
))) as *mut abi::ClosureCtx;
let item_meta = abi::resolve_type_by_mangled_name(&TOOLBAR_ITEM_ID_T);
assert!(!item_meta.is_null(), "ToolbarItem<String, AnyView> metadata");
let mut item = vec![0u8; abi::type_bytes(item_meta)];
let id = abi::swift_string(item_id);
core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_item_id_init(),
in("x0") u64::from_le_bytes(id[..8].try_into().expect("id lo")),
in("x1") u64::from_le_bytes(id[8..].try_into().expect("id hi")),
in("x2") placement.as_mut_ptr(),
in("x3") u64::from(shows_by_default),
in("x4") abi::swift_closure_thunk as *const c_void,
in("x5") item_ctx,
in("x6") resolve::anyview_meta(),
in("x7") resolve::anyview_wt(),
in("x8") item.as_mut_ptr(),
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x20") _, lateout("x21") _,
clobber_abi("C"),
);
let item_tc_wt = abi::get_view_wt_for_proto(item_meta, resolve::toolbar_content_proto());
assert!(!item_tc_wt.is_null(), "ToolbarItem<String, _>: ToolbarContent");
let tuple_meta = abi::resolve_type_by_mangled_name(&TOOLBAR_TUPLE_ID_T);
assert!(!tuple_meta.is_null(), "TupleToolbarContent<ToolbarItem<String, _>> metadata");
let mut tuple = vec![0u8; abi::type_bytes(tuple_meta)];
core::arch::asm!("blr {f}", f = in(reg) resolve::toolbar_build_block(),
in("x0") item.as_mut_ptr(),
in("x1") item_meta,
in("x2") item_tc_wt,
in("x8") tuple.as_mut_ptr(),
lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _,
lateout("x7") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
lateout("x21") _, clobber_abi("C"),
);
let tuple_custom_wt = abi::get_view_wt_for_proto(
tuple_meta,
resolve::customizable_toolbar_content_proto(),
);
assert!(
!tuple_custom_wt.is_null(),
"TupleToolbarContent<ToolbarItem<String, _>>: CustomizableToolbarContent"
);
let leaked = Box::leak(tuple.into_boxed_slice());
let bytes = Box::leak(Box::new(BytesPayload {
data: leaked.as_ptr(),
len: leaked.len(),
}));
let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
emit_bytes,
bytes as *mut BytesPayload as *mut c_void,
))) as *mut abi::ClosureCtx;
let tid = abi::swift_string(toolbar_id);
super::generic1_modifier_ints(
resolve::toolbar_id_fn(),
resolve::toolbar_id_oret(),
view,
tuple_meta,
tuple_custom_wt,
&[
u64::from_le_bytes(tid[..8].try_into().expect("toolbar id lo")),
u64::from_le_bytes(tid[8..].try_into().expect("toolbar id hi")),
abi::swift_closure_thunk as *const c_void as u64,
ctx as u64,
],
[0.0; 4],
)
}
}
#[cfg(not(target_os = "macos"))]
swift_statics! {
pub enum ContentToolbarPlacement {
NavigationSplitView = c"$s7SwiftUI23ContentToolbarPlacementV19navigationSplitViewACvgZ",
TabViewAccessory = c"$s7SwiftUI23ContentToolbarPlacementV16tabViewAccessoryACvgZ",
TabViewSidebar = c"$s7SwiftUI23ContentToolbarPlacementV14tabViewSidebarACvgZ",
}
}
#[cfg(not(target_os = "macos"))]
pub fn content_toolbar(
view: &ViewHandle,
placement: ContentToolbarPlacement,
content: &ViewHandle,
) -> ViewHandle {
unsafe {
let placement_meta = abi::metadata0(resolve::content_toolbar_placement_ma());
assert!(!placement_meta.is_null(), "ContentToolbarPlacement metadata");
let mut placement =
static_getter_indirect(placement.resolved(), placement_meta, 0);
let ctx = Box::leak(Box::new(abi::ClosureCtx::new(
emit_tuple,
Child::leak(content, Content::Erased),
))) as *mut abi::ClosureCtx;
let subst = [
view.meta,
resolve::anyview_meta(),
view.wt,
resolve::anyview_wt(),
];
let (meta, wt, size) =
super::opaque_result_type(resolve::content_toolbar_oret(), &subst);
let mut result = vec![0u8; size];
let this = view.value_ptr();
core::arch::asm!("blr {f}", f = in(reg) resolve::content_toolbar_fn(),
in("x0") placement.as_mut_ptr(),
in("x1") abi::swift_closure_thunk as *const c_void,
in("x2") ctx,
in("x3") view.meta,
in("x4") resolve::anyview_meta(),
in("x5") view.wt,
in("x6") resolve::anyview_wt(),
in("x8") result.as_mut_ptr(),
in("x20") this,
lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
wrap_owned(result, meta, wt)
}
}