use core::pin::Pin;
use rkyv::archived_value;
use rkyv::ser::Serializer;
use rkyv::ArchiveUnsized;
use rkyv::SerializeUnsized;
use xous::{Error, MemoryMessage, Result, CID};
#[derive(Copy, Clone)]
pub struct String<const N: usize> {
bytes: [u8; N],
len: u32, }
impl<const N: usize> String<N> {
pub fn new() -> String<N> { String { bytes: [0; N], len: 0 } }
pub fn volatile_clear(&mut self) {
let b = self.bytes.as_mut_ptr();
for i in 0..N {
unsafe {
b.add(i).write_volatile(core::mem::zeroed());
}
}
self.len = 0; core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
}
pub fn from_str<T>(src: T) -> String<N>
where
T: AsRef<str>,
{
let src = src.as_ref();
let mut s = Self::new();
for (&src_byte, dest_byte) in src.as_bytes().iter().zip(&mut s.bytes) {
*dest_byte = src_byte;
}
s.len = s.bytes.len().min(src.as_bytes().len()) as u32;
if s.as_str().is_err() {
s.len = 0;
}
s
}
pub fn as_bytes(&self) -> [u8; N] { self.bytes }
pub fn as_str(&self) -> core::result::Result<&str, core::str::Utf8Error> {
core::str::from_utf8(&self.bytes[0..self.len as usize])
}
pub fn len(&self) -> usize { self.len as usize }
pub fn is_empty(&self) -> bool { self.len == 0 }
pub fn from_message(message: &MemoryMessage) -> core::result::Result<String<N>, core::str::Utf8Error> {
let buf = unsafe { crate::Buffer::from_memory_message(message) };
let bytes = Pin::new(buf.as_ref());
let value = unsafe { archived_value::<String<N>>(&bytes, message.id as usize) };
let s = String::<N>::from_str(value.as_str());
Ok(s)
}
pub fn lend(
&self,
connection: CID,
) -> core::result::Result<Result, Error> {
let mut writer = rkyv::ser::serializers::BufferSerializer::new(crate::Buffer::new(N));
let pos = writer.serialize_value(self).expect("xous::String -- couldn't archive self");
let xous_buffer = writer.into_inner();
xous_buffer.lend(connection, pos as u32)
}
pub fn send(
self,
connection: CID,
) -> core::result::Result<Result, Error> {
let mut writer = rkyv::ser::serializers::BufferSerializer::new(crate::Buffer::new(N));
let pos = writer.serialize_value(&self).expect("xous::String -- couldn't archive self");
let xous_buffer = writer.into_inner();
xous_buffer.send(connection, pos as u32)
}
pub fn clear(&mut self) {
self.len = 0;
self.bytes = [0; N];
}
pub fn to_str(&self) -> &str { unsafe { core::str::from_utf8_unchecked(&self.bytes[0..self.len()]) } }
pub fn pop(&mut self) -> Option<char> {
if self.is_empty() {
return None;
}
let tempbytes: [u8; N] = self.bytes;
let tempstr = &(*unsafe { core::str::from_utf8_unchecked(&tempbytes[0..self.len()]) });
self.len = 0;
self.bytes = [0; N];
let mut char_iter = tempstr.chars();
let mut maybe_c = char_iter.next();
loop {
match maybe_c {
Some(c) => {
let next_c = char_iter.next();
match next_c {
Some(_thing) => {
self.push(c).unwrap(); maybe_c = next_c;
}
None => return next_c,
}
}
None => {
return None; }
}
}
}
pub fn push(&mut self, ch: char) -> core::result::Result<usize, Error> {
match ch.len_utf8() {
1 => {
if self.len() < self.bytes.len() {
self.bytes[self.len()] = ch as u8;
self.len += 1;
Ok(1)
} else {
Err(Error::OutOfMemory)
}
}
_ => {
let mut bytes: usize = 0;
let mut data: [u8; 4] = [0; 4];
let subslice = ch.encode_utf8(&mut data);
if self.len() + subslice.len() < self.bytes.len() {
for c in subslice.bytes() {
self.bytes[self.len()] = c;
self.len += 1;
bytes += 1;
}
Ok(bytes)
} else {
Err(Error::OutOfMemory)
}
}
}
}
pub fn append(&mut self, s: &str) -> core::result::Result<usize, Error> {
let mut bytes_added = 0;
for ch in s.chars() {
if let Ok(bytes) = self.push(ch) {
bytes_added += bytes;
} else {
return Err(Error::OutOfMemory);
}
}
Ok(bytes_added)
}
pub fn push_byte(&mut self, b: u8) -> core::result::Result<(), Error> {
if self.len() < self.bytes.len() {
self.bytes[self.len()] = b;
self.len += 1;
Ok(())
} else {
Err(Error::OutOfMemory)
}
}
}
impl<const N: usize> Default for String<N> {
fn default() -> Self { Self::new() }
}
impl<const N: usize> core::fmt::Display for String<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", self.to_str()) }
}
impl<const N: usize> core::fmt::Write for String<N> {
fn write_str(&mut self, s: &str) -> core::result::Result<(), core::fmt::Error> {
for c in s.bytes() {
if self.len() < self.bytes.len() {
self.bytes[self.len()] = c;
self.len += 1;
}
}
Ok(())
}
}
impl<const N: usize> core::fmt::Debug for String<N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", self.to_str()) }
}
impl<const N: usize> core::convert::AsRef<str> for String<N> {
fn as_ref(&self) -> &str { self.to_str() }
}
impl<const N: usize> PartialEq for String<N> {
fn eq(&self, other: &Self) -> bool {
self.bytes[..self.len as usize] == other.bytes[..other.len as usize] && self.len == other.len
}
}
impl<const N: usize> Eq for String<N> {}
#[repr(C)]
pub struct ArchivedString {
ptr: rkyv::RelPtr<str>,
}
impl ArchivedString {
pub fn as_str(&self) -> &str {
unsafe {
&*self.ptr.as_ptr()
}
}
}
pub struct StringResolver {
bytes_pos: usize,
_metadata_resolver: rkyv::MetadataResolver<str>,
}
impl<const N: usize> rkyv::Archive for String<N> {
type Archived = ArchivedString;
type Resolver = StringResolver;
fn resolve(&self, pos: usize, resolver: Self::Resolver) -> Self::Archived {
Self::Archived {
ptr: unsafe {
self.as_str().unwrap().resolve_unsized(
pos + rkyv::offset_of!(Self::Archived, ptr),
resolver.bytes_pos,
(),
)
},
}
}
}
impl<S: rkyv::ser::Serializer + ?Sized, const N: usize> rkyv::Serialize<S> for String<N> {
fn serialize(&self, serializer: &mut S) -> core::result::Result<Self::Resolver, S::Error> {
Ok(StringResolver {
bytes_pos: self.as_str().unwrap().serialize_unsized(serializer)?,
_metadata_resolver: self.as_str().unwrap().serialize_metadata(serializer)?,
})
}
}
use rkyv::Fallible;
impl<D: Fallible + ?Sized, const N: usize> rkyv::Deserialize<String<N>, D> for ArchivedString {
fn deserialize(&self, _deserializer: &mut D) -> core::result::Result<String<N>, D::Error> {
Ok(String::<N>::from_str(self.as_str()))
}
}
pub struct XousDeserializer;
impl rkyv::Fallible for XousDeserializer {
type Error = xous::Error;
}