Skip to content

Commit

Permalink
Spport querying setting values as ArrayString (#76)
Browse files Browse the repository at this point in the history
This allows you to query the value of a setting value as an
`ArrayString`, which is a string that is backed by an array. This has
the advantage that it doesn't not need an allocator, but you need to
specify a maximum length.
  • Loading branch information
CryZe committed Nov 6, 2023
1 parent 3c4a007 commit 9563a92
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
33 changes: 30 additions & 3 deletions src/runtime/settings/value.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use core::mem::MaybeUninit;

use crate::runtime::sys;
use arrayvec::ArrayString;

use crate::{runtime::sys, Error};

use super::Map;

Expand Down Expand Up @@ -66,8 +68,8 @@ impl Value {
// that the buffer is valid UTF-8.
unsafe {
let mut len = 0;
let sucess = sys::setting_value_get_string(self.0, core::ptr::null_mut(), &mut len);
if len == 0 && !sucess {
let success = sys::setting_value_get_string(self.0, core::ptr::null_mut(), &mut len);
if len == 0 && !success {
return None;
}
let mut buf = alloc::vec::Vec::with_capacity(len);
Expand All @@ -77,6 +79,31 @@ impl Value {
Some(alloc::string::String::from_utf8_unchecked(buf))
}
}

/// Returns the value as an array backed string if it is a string. Returns
/// an error if the string is too long. The constant `N` determines the
/// maximum length of the string in bytes.
#[inline]
pub fn get_array_string<const N: usize>(&self) -> Option<Result<ArrayString<N>, Error>> {
// SAFETY: The handle is valid. We provide a pointer to our buffer and
// the length of the buffer. If the function fails, we check the length
// and if it's 0, then that indicates that the value is not a string and
// we return None. Otherwise we return an error. If the function
// succeeds, we set the length of the buffer to the returned length and
// return the string. The function also guarantees that the buffer is
// valid UTF-8.
unsafe {
let mut buf = ArrayString::<N>::new();
let mut len = N;
let success =
sys::setting_value_get_string(self.0, buf.as_bytes_mut().as_mut_ptr(), &mut len);
if !success {
return if len == 0 { None } else { Some(Err(Error {})) };
}
buf.set_len(len);
Some(Ok(buf))
}
}
}

impl Drop for Value {
Expand Down
1 change: 0 additions & 1 deletion src/runtime/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,6 @@ extern "C" {
/// UTF-8 and is not nul-terminated. No matter what happens, you still
/// retain ownership of the setting value, which means you still need to
/// free it.
#[cfg(feature = "alloc")]
pub fn setting_value_get_string(
value: SettingValue,
buf_ptr: *mut u8,
Expand Down

0 comments on commit 9563a92

Please sign in to comment.