add readonly roc list and roc str to roc_std

This commit is contained in:
Brendan Hansknecht 2024-12-10 20:03:08 -08:00
parent 0e162a767d
commit 98cde41439
No known key found for this signature in database
GPG key ID: A199D0660F95F948
3 changed files with 105 additions and 3 deletions

View file

@ -18,8 +18,8 @@ mod roc_str;
mod storage; mod storage;
pub use roc_box::RocBox; pub use roc_box::RocBox;
pub use roc_list::{RocList, SendSafeRocList}; pub use roc_list::{RocList, SendSafeRocList, ReadOnlyRocList};
pub use roc_str::{InteriorNulError, RocStr, SendSafeRocStr}; pub use roc_str::{InteriorNulError, RocStr, SendSafeRocStr, ReadOnlyRocStr};
pub use storage::Storage; pub use storage::Storage;
// A list of C functions that are being imported // A list of C functions that are being imported

View file

@ -172,7 +172,7 @@ where
/// There is no way to tell how many references it has and if it is safe to free. /// There is no way to tell how many references it has and if it is safe to free.
/// As such, only values that should have a static lifetime for the entire application run /// As such, only values that should have a static lifetime for the entire application run
/// should be considered for marking read-only. /// should be considered for marking read-only.
pub unsafe fn set_readonly(&self) { pub unsafe fn set_readonly(&mut self) {
if let Some((_, storage)) = self.elements_and_storage() { if let Some((_, storage)) = self.elements_and_storage() {
storage.set(Storage::Readonly); storage.set(Storage::Readonly);
} }
@ -916,6 +916,64 @@ where
} }
} }
#[repr(transparent)]
pub struct ReadOnlyRocList<T>(RocList<T>)
where
T: RocRefcounted;
unsafe impl<T> Send for ReadOnlyRocList<T> where T: Send + RocRefcounted {}
unsafe impl<T> Sync for ReadOnlyRocList<T> where T: Sync + RocRefcounted {}
impl<T> RocRefcounted for ReadOnlyRocList<T>
where
T: RocRefcounted,
{
fn inc(&mut self) {
}
fn dec(&mut self) {
}
fn is_refcounted() -> bool {
true
}
}
impl<T> Clone for ReadOnlyRocList<T>
where
T: Clone + RocRefcounted,
{
fn clone(&self) -> Self {
ReadOnlyRocList(self.0.clone())
}
}
impl<T> From<RocList<T>> for ReadOnlyRocList<T>
where
T: Clone + RocRefcounted,
{
fn from(mut l: RocList<T>) -> Self {
if l.is_unique() {
unsafe {l.set_readonly()};
}
if l.is_readonly() {
ReadOnlyRocList(l)
} else {
// This is not unique, do a deep copy.
ReadOnlyRocList::from(RocList::from_slice(&l))
}
}
}
impl<T> From<ReadOnlyRocList<T>> for RocList<T>
where
T: RocRefcounted,
{
fn from(l: ReadOnlyRocList<T>) -> Self {
l.0
}
}
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
struct RocListVisitor<T> struct RocListVisitor<T>
where where

View file

@ -824,6 +824,50 @@ impl RocRefcounted for RocStr {
} }
} }
#[repr(transparent)]
pub struct ReadOnlyRocStr(RocStr);
unsafe impl Send for ReadOnlyRocStr {}
unsafe impl Sync for ReadOnlyRocStr {}
impl RocRefcounted for ReadOnlyRocStr {
fn inc(&mut self) {
}
fn dec(&mut self) {
}
fn is_refcounted() -> bool {
true
}
}
impl Clone for ReadOnlyRocStr {
fn clone(&self) -> Self {
ReadOnlyRocStr(self.0.clone())
}
}
impl From<RocStr> for ReadOnlyRocStr {
fn from(mut s: RocStr) -> Self {
if s.is_unique() {
unsafe {s.set_readonly()};
}
if s.is_readonly() {
ReadOnlyRocStr(s)
} else {
// This is not readonly or unique, do a deep copy.
ReadOnlyRocStr::from(RocStr::from(s.as_str()))
}
}
}
impl From<ReadOnlyRocStr> for RocStr {
fn from(s: ReadOnlyRocStr) -> Self {
s.0
}
}
#[repr(C)] #[repr(C)]
struct BigString { struct BigString {
elements: NonNull<u8>, elements: NonNull<u8>,