From 24e2e3f48f9a9e8700189bb23bf47110277ded38 Mon Sep 17 00:00:00 2001 From: Mossa Date: Thu, 29 Feb 2024 10:55:31 +0100 Subject: [PATCH] extendr-api: add `as_str_mut` this might not make sense for NA strings for now, there is a `todo!` --- extendr-api/src/robj/mod.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/extendr-api/src/robj/mod.rs b/extendr-api/src/robj/mod.rs index af5af930b1..6064b5ce2a 100644 --- a/extendr-api/src/robj/mod.rs +++ b/extendr-api/src/robj/mod.rs @@ -593,6 +593,7 @@ impl Robj { unsafe { let charsxp = match self.sexptype() { STRSXP => { + // only allows scalar strings if self.len() != 1 { return None; } @@ -613,6 +614,42 @@ impl Robj { Some(std::str::from_utf8_unchecked(all_bytes)) } } + /// Get a mutable reference to a scalar string type. + /// ``` + /// use extendr_api::prelude::*; + /// test! { + /// let robj1 = Robj::from("xyz"); + /// let robj2 = Robj::from(1); + /// assert_eq!(robj1.as_str(), Some("xyz")); + /// assert_eq!(robj2.as_str(), None); + /// } + /// ``` + pub fn as_str_mut<'a>(&mut self) -> Option<&'a mut str> { + unsafe { + let charsxp = match self.sexptype() { + STRSXP => { + // only allows Scalar strings + if self.len() != 1 { + return None; + } + Some(STRING_ELT(self.get_mut(), 0)) + } + CHARSXP => Some(self.get_mut()), + SYMSXP => Some(PRINTNAME(self.get_mut())), + _ => None, + }; + + let charsxp = charsxp?; + if charsxp == R_NaString { + todo!() + // return Some(<&str>::na()); + } + + let length = Rf_xlength(charsxp); + let all_bytes = std::slice::from_raw_parts_mut(R_CHAR(charsxp) as _, length as _); + Some(std::str::from_utf8_unchecked_mut(all_bytes)) + } + } /// Get a scalar integer. /// ```