feat(core/rust): introduce StrBuffer

it is a variant of Buffer specifically for accepting python `str`
pull/2220/head
matejcik 2 years ago committed by matejcik
parent 2ced50ed16
commit 785dc7f4d7

@ -72,6 +72,7 @@ fn generate_micropython_bindings() {
.allowlist_var("MP_BUFFER_READ")
.allowlist_var("MP_BUFFER_WRITE")
.allowlist_var("MP_BUFFER_RW")
.allowlist_var("mp_type_str")
// dict
.allowlist_type("mp_obj_dict_t")
.allowlist_function("mp_obj_new_dict")

@ -1,7 +1,7 @@
use core::{
convert::TryFrom,
ops::{Deref, DerefMut},
ptr, slice,
ptr, slice, str,
};
use crate::{error::Error, micropython::obj::Obj};
@ -132,6 +132,50 @@ impl AsMut<[u8]> for BufferMut {
}
}
/// Represents an immutable UTF-8 string stored on the MicroPython heap and
/// owned by a `str` object.
///
/// # Safety
///
/// In most cases, it is unsound to store `StrBuffer` values in a GC-unreachable
/// location, such as static data. It is also unsound to let the contents be
/// modified while a reference to them is being held.
#[derive(Default)]
pub struct StrBuffer(Buffer);
impl TryFrom<Obj> for StrBuffer {
type Error = Error;
fn try_from(obj: Obj) -> Result<Self, Self::Error> {
if obj.is_qstr() || unsafe { ffi::mp_type_str.is_type_of(obj) } {
Ok(Self(Buffer::try_from(obj)?))
} else {
Err(Error::TypeError)
}
}
}
impl Deref for StrBuffer {
type Target = str;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl AsRef<str> for StrBuffer {
fn as_ref(&self) -> &str {
// SAFETY: MicroPython ensures that values of type `str` are UTF-8
unsafe { str::from_utf8_unchecked(self.0.as_ref()) }
}
}
impl From<&'static str> for StrBuffer {
fn from(val: &'static str) -> Self {
Self(Buffer::from(val.as_bytes()))
}
}
fn get_buffer_info(obj: Obj, flags: u32) -> Result<ffi::mp_buffer_info_t, Error> {
let mut bufinfo = ffi::mp_buffer_info_t {
buf: ptr::null_mut(),
@ -183,3 +227,10 @@ impl crate::trace::Trace for Buffer {
self.as_ref().trace(t)
}
}
#[cfg(feature = "ui_debug")]
impl crate::trace::Trace for StrBuffer {
fn trace(&self, t: &mut dyn crate::trace::Tracer) {
self.as_ref().trace(t)
}
}

Loading…
Cancel
Save