bink/
cstory.rs

1use std::{
2    ffi::{CStr, CString},
3    os::raw::c_char,
4    rc::Rc,
5};
6
7use bladeink::{choice::Choice, story::Story};
8
9use crate::{BINK_FAIL, BINK_FAIL_NULL_POINTER, BINK_OK};
10
11#[allow(clippy::not_unsafe_ptr_arg_deref)]
12#[no_mangle]
13pub extern "C" fn bink_story_new(
14    story: *mut *mut Story,
15    json_string: *const c_char,
16    err_msg: *mut *mut c_char,
17) -> u32 {
18    if story.is_null() || err_msg.is_null() {
19        return BINK_FAIL_NULL_POINTER;
20    }
21
22    unsafe {
23        *story = std::ptr::null_mut();
24        *err_msg = std::ptr::null_mut();
25    }
26
27    let c_str: &CStr = unsafe { CStr::from_ptr(json_string) };
28    let str_slice: &str = c_str.to_str().unwrap();
29
30    let result = Story::new(str_slice);
31
32    match result {
33        Ok(s) => unsafe {
34            *story = Box::into_raw(Box::new(s));
35            BINK_OK
36        },
37        Err(e) => unsafe {
38            *err_msg = CString::new(e.to_string()).unwrap().into_raw();
39            BINK_FAIL
40        },
41    }
42}
43
44#[allow(clippy::not_unsafe_ptr_arg_deref)]
45#[no_mangle]
46pub extern "C" fn bink_story_free(story: *mut Story) {
47    if !story.is_null() {
48        unsafe {
49            drop(Box::from_raw(story));
50        }
51    }
52}
53
54#[allow(clippy::not_unsafe_ptr_arg_deref)]
55#[no_mangle]
56pub extern "C" fn bink_story_can_continue(story: *mut Story, can_continue: *mut bool) -> u32 {
57    if story.is_null() {
58        return BINK_FAIL_NULL_POINTER;
59    }
60
61    let story: &mut Story = unsafe { &mut *story };
62
63    unsafe {
64        *can_continue = story.can_continue();
65    }
66
67    BINK_OK
68}
69
70#[allow(clippy::not_unsafe_ptr_arg_deref)]
71#[no_mangle]
72pub extern "C" fn bink_story_cont(
73    story: *mut Story,
74    line: *mut *mut c_char,
75    err_msg: *mut *mut c_char,
76) -> u32 {
77    if story.is_null() {
78        return BINK_FAIL_NULL_POINTER;
79    }
80
81    let story: &mut Story = unsafe { &mut *story };
82
83    let result = story.cont();
84
85    match result {
86        Ok(l) => unsafe {
87            *line = CString::new(l).unwrap().into_raw();
88            BINK_OK
89        },
90        Err(e) => unsafe {
91            *err_msg = CString::new(e.to_string()).unwrap().into_raw();
92            BINK_FAIL
93        },
94    }
95}
96
97#[allow(clippy::not_unsafe_ptr_arg_deref)]
98#[no_mangle]
99pub extern "C" fn bink_story_get_current_choices(
100    story: *mut Story,
101    choices: *mut *mut Vec<Rc<Choice>>,
102    len: *mut usize,
103) -> u32 {
104    if story.is_null() {
105        return BINK_FAIL_NULL_POINTER;
106    }
107
108    let story: &mut Story = unsafe { &mut *story };
109
110    let result = Box::new(story.get_current_choices());
111
112    unsafe {
113        *len = result.len();
114        *choices = Box::into_raw(result);
115    }
116
117    BINK_OK
118}
119
120#[allow(clippy::not_unsafe_ptr_arg_deref)]
121#[no_mangle]
122pub extern "C" fn bink_story_choose_choice_index(story: *mut Story, choice_index: usize) -> u32 {
123    if story.is_null() {
124        return BINK_FAIL_NULL_POINTER;
125    }
126
127    let story: &mut Story = unsafe { &mut *story };
128
129    let result = story.choose_choice_index(choice_index);
130
131    match result {
132        Ok(_) => BINK_OK,
133        Err(_) => BINK_FAIL,
134    }
135}
136
137#[allow(clippy::not_unsafe_ptr_arg_deref)]
138#[no_mangle]
139pub extern "C" fn bink_story_get_current_tags(
140    story: *mut Story,
141    tags: *mut *mut Vec<String>,
142    len: *mut usize,
143) -> u32 {
144    if story.is_null() {
145        return BINK_FAIL_NULL_POINTER;
146    }
147
148    let story: &mut Story = unsafe { &mut *story };
149
150    let result = story.get_current_tags();
151
152    match result {
153        Ok(result) => unsafe {
154            *len = result.len();
155            *tags = Box::into_raw(Box::new(result));
156        },
157        Err(_) => return BINK_FAIL,
158    }
159
160    BINK_OK
161}