Currently the only way to create a FuriString is via a function like furi_string_alloc that returns an opaque FuriString*. However the underlying m-string does support in-place allocation of string_t:
In-place allocation of string_t allows taking advantage of the short-string optimisation that allocates small strings directly in string_t, rather than always allocating space on the heap.
I believe it would be possible to add a furi_string_init and furi_string_clear function to the SDK that can initialize a stack-allocated FuriString. However this means that a stack-allocated FuriString can't be passed into any function that assumes it can take ownership of a FuriString* (and thus call furi_string_free). It would also require exposing the implementation of FuriString so that the compiler can allocate the correct amount of space.
Anything else?
The reason I'm interested in doing this is that it allows creation of a stack-allocated Rust FuriString type in flipperzero-rs (see discussion here). The type would look approximately like the following (note: may have some syntax errors):
/// Dynamically allocated string.
/// This is a wrapper around the SDK's C `FuriString` type).
#[repr(transparent)]
pub struct FuriString(sys::FuriString);
impl FuriString {
/// Create a new [`FuriString`]
pub fn new() -> FuriString {
// Uninitialized structure
let mut furi_string = MaybeUninit<sys::FuriString> = MaybeUninit::uninit();
unsafe {
// Initialize `sys::FuriString` memory
sys::furi_string_init(furi_string.as_mut_ptr());
}
// Wrap the initialized `sys::FuriString` in a wrapper type
FuriString(unsafe { furi_string.assume_init() })
}
/// Get a pointer to this string that can be used with Flipper Zero SDK APIs.
pub fn to_raw(&self) -> *const sys::FuriString {
&self.0 as &sys::FuriString as *const sys::FuriString
}
// ...
}
impl Drop for FuriString {
fn drop(&mut self) {
unsafe {
// Ensure any dynamic memory allocations are freed
sys::furi_string_clear(self.to_mut_raw());
}
}
}
/// We can trivially get a `&CStr` from a `FuriString`
impl AsRef<CStr> for FuriString {
#[inline]
fn as_ref(&self) -> &CStr {
CStr::from_ptr(unsafe { sys::furi_string_get_cstr(self.to_raw()) })
}
}
Describe the enhancement you're suggesting.
Currently the only way to create a
FuriString
is via a function likefuri_string_alloc
that returns an opaqueFuriString*
. However the underlying m-string does support in-place allocation ofstring_t
:In-place allocation of
string_t
allows taking advantage of the short-string optimisation that allocates small strings directly instring_t
, rather than always allocating space on the heap.I believe it would be possible to add a
furi_string_init
andfuri_string_clear
function to the SDK that can initialize a stack-allocatedFuriString
. However this means that a stack-allocatedFuriString
can't be passed into any function that assumes it can take ownership of aFuriString*
(and thus callfuri_string_free
). It would also require exposing the implementation ofFuriString
so that the compiler can allocate the correct amount of space.Anything else?
The reason I'm interested in doing this is that it allows creation of a stack-allocated Rust
FuriString
type in flipperzero-rs (see discussion here). The type would look approximately like the following (note: may have some syntax errors):