diff --git a/rust-ffi-demo/demo.c b/rust-ffi-demo/demo.c index 0526cab..da80835 100644 --- a/rust-ffi-demo/demo.c +++ b/rust-ffi-demo/demo.c @@ -35,12 +35,16 @@ int main() { storybook_advance_nooption(book); break; case (FOOTER_CHOICES): - int n = storybook_get_num_choices(book); - for (int i = 1; i <= n; i++) { - Choice* choice = storybook_get_choice(book, i); - printf("%d) %s\n", choice->option, choice->flavor); - storybook_free_choice(choice); + ChoiceList *list = storybook_get_choices(book); + for (ChoiceList *curr = list; curr; curr = curr->next) { + const StatCheck *sk = curr->choice.statcheck; + if (sk) { + printf("\e[0;31m"); + } + printf("%d) %s", curr->choice.option, curr->choice.flavor); + printf("\n\e[0m"); } + storybook_free_choices(list); uint32_t option; printf("Make a choice: "); scanf("%d", &option); diff --git a/src/rust-base/cbindgen.toml b/src/rust-base/cbindgen.toml index 75bd6b4..e139077 100644 --- a/src/rust-base/cbindgen.toml +++ b/src/rust-base/cbindgen.toml @@ -1,4 +1,6 @@ language = "C" +sys_includes = ["stdbool.h", "stdint.h"] +include_guard = "STORYBOOK_H" [export.rename] diff --git a/src/rust-base/src/lib.rs b/src/rust-base/src/lib.rs index 90be838..75d427d 100644 --- a/src/rust-base/src/lib.rs +++ b/src/rust-base/src/lib.rs @@ -185,6 +185,14 @@ pub mod ffi { pub struct Choice { option: usize, flavor: *const c_char, + statcheck: *const StatCheck, + statchange: *const StatChange, + } + + #[repr(C)] + pub struct ChoiceList { + choice: Choice, + next: *mut ChoiceList, } #[repr(C)] @@ -205,6 +213,42 @@ pub mod ffi { Choice { option: choice.option, flavor: CString::new(choice.flavor.clone()).unwrap().into_raw(), + statcheck: match &choice.stat_check { + Some(statcheck) => { + let statcheck = StatCheck::new(&statcheck); + let statcheck = Box::from(statcheck); + Box::into_raw(statcheck) + } + None => std::ptr::null(), + }, + statchange: match &choice.stat_change { + Some(statchange) => { + let statchange = StatChange::new(&statchange); + let statchange = Box::from(statchange); + Box::into_raw(statchange) + + }, + None => std::ptr::null(), + }, + } + } + } + + impl StatCheck { + pub fn new(statcheck: &super::StatCheck) -> Self { + StatCheck { + stat: CString::new(statcheck.stat.clone()).unwrap().into_raw(), + value: statcheck.value, + rel: statcheck.rel as c_char, + } + } + } + + impl StatChange { + pub fn new(statchange: &super::StatChange) -> Self { + StatChange { + stat: CString::new(statchange.stat.clone()).unwrap().into_raw(), + addend: statchange.addend, } } } @@ -272,6 +316,7 @@ pub mod ffi { book.advance_nooption(); } + #[no_mangle] pub extern fn storybook_advance_option(book: *mut Book, option: usize) { let book = get_book_from_ref(book); @@ -279,34 +324,33 @@ pub mod ffi { } #[no_mangle] - pub extern fn storybook_get_num_choices(book: *mut Book) -> usize { + pub extern fn storybook_get_choices (book: *mut Book) -> *mut ChoiceList { let book = get_book_from_ref(book); let footer = &book.get_current().footer; if let super::Footer::Choices(choices) = footer { - choices.len() + let mut list = std::ptr::null_mut(); + let mut choices = choices.iter().collect::>(); + choices.sort_by_key(|(&o, _)| o); + for (_, choice) in choices.into_iter().rev() { + let choice = Choice::new(choice); + let node = Box::from(ChoiceList { + choice, + next: list, + }); + list = Box::into_raw(node); + } + return list } else { - panic!("Requested num choices but page is not choices."); + panic!("Requested choices but page is not choices."); } } #[no_mangle] - pub extern fn storybook_get_choice(book: *mut Book, n: usize) -> *mut Choice { - let book = get_book_from_ref(book); - let footer = &book.get_current().footer; - if let super::Footer::Choices(choices) = footer { - let choice = choices.get(&n).expect("Requested option isn't present in choices."); - let choice = Choice::new(choice); - let choice = Box::from(choice); - Box::into_raw(choice) - } else { - panic!("Requested a choice but page is not choices."); - } - } - - #[no_mangle] - pub extern fn storybook_free_choice(choice: *mut Choice) { + pub extern fn storybook_free_choices(mut list: *mut ChoiceList) { unsafe { - Box::from_raw(choice); + while !list.is_null() { + list = Box::from_raw(list).next; + } } } }