extern crate proc_macro;
pub fn sel_expression(selector: &str) -> String {
format!(
r#"
{{
#[inline(never)] unsafe fn codegen_workaround() -> ::objr::bindings::Sel {{
#[link_section = "__TEXT,__objc_methname,cstring_literals"]
static L_OBJC_METH_VAR_NAME_: [u8; {len}] = *b"{selector}\0";
#[link_section = "__DATA,__objc_selrefs,literal_pointers,no_dead_strip"]
static L_OBJC_SELECTOR_REFERENCES_: &'static [u8; {len}] = &L_OBJC_METH_VAR_NAME_;
//don't let the optimizer look at the value we just set, since it will be fixedup by dyld
let read_volatile: &'static [u8; {len}] = ::core::ptr::read_volatile(&L_OBJC_SELECTOR_REFERENCES_ );
::objr::bindings::Sel::from_ptr( unsafe{{ std::mem::transmute(read_volatile) }} )
}}
codegen_workaround()
}}"#
,selector=selector,len=selector.len() + 1)
}
pub fn make_fn_partial(fn_name: &str) -> String {
format!("unsafe fn {fn_name}() -> ::objr::bindings::Sel",fn_name=fn_name)
}
pub fn sel_to_rust_name(selector: &str) -> String {
let mut rust_build = String::new();
let mut seen_colon_count: u8 = 0;
for char in selector.chars() {
match char {
':' => {
rust_build.push('_');
seen_colon_count+=1;
}
other => { rust_build.push(other);}
}
}
if seen_colon_count > 1 {
rust_build.pop();
}
rust_build
}
#[test]
fn build_selector() {
assert_eq!(sel_to_rust_name("height"), "height");
assert_eq!(sel_to_rust_name("height:"), "height_");
assert_eq!(sel_to_rust_name("height:width:"), "height_width");
}