diff --git a/ctru-rs/examples/software-keyboard.rs b/ctru-rs/examples/software-keyboard.rs index 1d24a7d6..d76c7547 100644 --- a/ctru-rs/examples/software-keyboard.rs +++ b/ctru-rs/examples/software-keyboard.rs @@ -5,8 +5,6 @@ use ctru::applets::swkbd::{Button, CallbackResult, SoftwareKeyboard}; use ctru::prelude::*; -use std::ffi::CString; - fn main() { let apt = Apt::new().unwrap(); let mut hid = Hid::new().unwrap(); @@ -21,17 +19,16 @@ fn main() { // Custom filter callback to handle the given input. // Using this callback it's possible to integrate the applet // with custom error messages when the input is incorrect. - keyboard.set_filter_callback(Some(Box::new(|str| { - // The string is guaranteed to contain valid Unicode text, so we can safely unwrap and use it as a normal `&str`. - if str.to_str().unwrap().contains("boo") { + keyboard.set_filter_callback(Some(|text| { + if text.contains("boo") { return ( CallbackResult::Retry, - Some(CString::new("Ah, you scared me!").unwrap()), + Some(String::from("Ah, you scared me!")), ); } (CallbackResult::Ok, None) - }))); + })); println!("Press A to enter some text or press Start to exit."); diff --git a/ctru-rs/src/applets/swkbd.rs b/ctru-rs/src/applets/swkbd.rs index 41d40cd2..4b7667f5 100644 --- a/ctru-rs/src/applets/swkbd.rs +++ b/ctru-rs/src/applets/swkbd.rs @@ -9,18 +9,18 @@ use ctru_sys::{self, SwkbdState}; use bitflags::bitflags; use libc; -use std::ffi::{CStr, CString}; +use std::ffi::CString; use std::fmt::Display; use std::iter::once; use std::str; -type CallbackFunction = dyn Fn(&CStr) -> (CallbackResult, Option); +type CallbackFunction = fn(&str) -> (CallbackResult, Option); /// Configuration structure to setup the Software Keyboard applet. #[doc(alias = "SwkbdState")] pub struct SoftwareKeyboard { state: Box, - callback: Option>, + callback: Option, error_message: Option, } @@ -399,24 +399,23 @@ impl SoftwareKeyboard { /// # fn main() { /// # /// use std::borrow::Cow; - /// use std::ffi::CString; /// use ctru::applets::swkbd::{SoftwareKeyboard, CallbackResult}; /// /// let mut keyboard = SoftwareKeyboard::default(); /// - /// keyboard.set_filter_callback(Some(Box::new(|str| { - /// if str.to_str().unwrap().contains("boo") { + /// keyboard.set_filter_callback(Some(|text| { + /// if text.contains("boo") { /// return ( /// CallbackResult::Retry, - /// Some(CString::new("Ah, you scared me!").unwrap()), + /// Some(String::from("Ah, you scared me!")), /// ); /// } /// /// (CallbackResult::Ok, None) - /// }))); + /// })); /// # /// # } - pub fn set_filter_callback(&mut self, callback: Option>) { + pub fn set_filter_callback(&mut self, callback: Option) { self.callback = callback; } @@ -425,30 +424,32 @@ impl SoftwareKeyboard { user: *mut libc::c_void, pp_message: *mut *const libc::c_char, text: *const libc::c_char, - _text_size: libc::size_t, + text_size: libc::size_t, ) -> ctru_sys::SwkbdCallbackResult { - let this: *mut SoftwareKeyboard = user.cast(); + let this = unsafe { &mut *user.cast::() }; - unsafe { - // Reset any leftover error message. - (*this).error_message = None; + // Reset any leftover error message. + this.error_message = None; - let text = CStr::from_ptr(text); + unsafe { + let text = std::str::from_utf8_unchecked(std::slice::from_raw_parts(text, text_size)); let result = { // Run the callback if still available. - if let Some(callback) = &mut (*this).callback { - let (res, cstr) = callback(text); + if let Some(callback) = this.callback { + let (result, error_message) = callback(text); // Due to how `libctru` operates, the user is expected to keep the error message alive until // the end of the Software Keyboard prompt. We ensure that happens by saving it within the configuration. - (*this).error_message = cstr; + if let Some(error_message) = error_message { + let error_message = CString::from_vec_unchecked(error_message.into_bytes()); + + *pp_message = error_message.as_ptr(); - if let Some(newstr) = &(*this).error_message { - *pp_message = newstr.as_ptr(); + this.error_message = Some(error_message); } - res + result } else { CallbackResult::Ok }