add tests and expose types

This commit is contained in:
Brendan Hansknecht 2022-10-18 23:35:15 -07:00
parent 58f4afd9f0
commit 24cd78fe7e
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
4 changed files with 98 additions and 5 deletions

View file

@ -19,9 +19,9 @@ mod storage;
pub use roc_box::RocBox; pub use roc_box::RocBox;
pub use roc_dict::RocDict; pub use roc_dict::RocDict;
pub use roc_list::RocList; pub use roc_list::{RocList, SendSafeRocList};
pub use roc_set::RocSet; pub use roc_set::RocSet;
pub use roc_str::{InteriorNulError, RocStr}; pub use roc_str::{InteriorNulError, RocStr, SendSafeRocStr};
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

@ -121,6 +121,15 @@ impl<T> RocList<T> {
} }
} }
// Marks a list as readonly. This means that it will be leaked.
// For constants passed in from platform to application, this may be reasonable.
// Marked unsafe because it should not be used lightly.
pub unsafe fn set_readonly(&self) {
if let Some((_, storage)) = self.elements_and_storage() {
storage.set(Storage::Readonly);
}
}
/// Note that there is no way to convert directly to a Vec. /// Note that there is no way to convert directly to a Vec.
/// ///
/// This is because RocList values are not allocated using the system allocator, so /// This is because RocList values are not allocated using the system allocator, so

View file

@ -123,6 +123,16 @@ impl RocStr {
} }
} }
// Marks a str as readonly. This means that it will be leaked.
// For constants passed in from platform to application, this may be reasonable.
// Marked unsafe because it should not be used lightly.
pub unsafe fn set_readonly(&self) {
match self.as_enum_ref() {
RocStrInnerRef::HeapAllocated(roc_list) => unsafe { roc_list.set_readonly() },
RocStrInnerRef::SmallString(_) => {}
}
}
/// Note that there is no way to convert directly to a String. /// Note that there is no way to convert directly to a String.
/// ///
/// This is because RocStr values are not allocated using the system allocator, so /// This is because RocStr values are not allocated using the system allocator, so

View file

@ -59,7 +59,7 @@ pub unsafe extern "C" fn roc_memset(dst: *mut c_void, c: i32, n: usize) -> *mut
#[cfg(test)] #[cfg(test)]
mod test_roc_std { mod test_roc_std {
use roc_std::{RocBox, RocDec, RocList, RocResult, RocStr}; use roc_std::{RocBox, RocDec, RocList, RocResult, RocStr, SendSafeRocList, SendSafeRocStr};
fn roc_str_byte_representation(string: &RocStr) -> [u8; RocStr::SIZE] { fn roc_str_byte_representation(string: &RocStr) -> [u8; RocStr::SIZE] {
unsafe { core::mem::transmute_copy(string) } unsafe { core::mem::transmute_copy(string) }
@ -126,7 +126,7 @@ mod test_roc_std {
roc_str.reserve(42); roc_str.reserve(42);
assert_gte!(roc_str.capacity(), 42); assert_eq!(roc_str.capacity() >= 42, true);
} }
#[test] #[test]
@ -135,7 +135,7 @@ mod test_roc_std {
roc_str.reserve(5000); roc_str.reserve(5000);
assert_gte!(roc_str.capacity(), 5000); assert_eq!(roc_str.capacity() >= 5000, true);
} }
#[test] #[test]
@ -296,6 +296,80 @@ mod test_roc_std {
let example = RocDec::from_str("1234.5678").unwrap(); let example = RocDec::from_str("1234.5678").unwrap();
assert_eq!(format!("{}", example), "1234.5678"); assert_eq!(format!("{}", example), "1234.5678");
} }
#[test]
fn safe_send_no_copy() {
let x = RocStr::from("This is a long string but still unique. Yay!!!");
assert_eq!(x.is_unique(), true);
let safe_x = SendSafeRocStr::from(x);
let new_x = RocStr::from(safe_x);
assert_eq!(new_x.is_unique(), true);
assert_eq!(
new_x.as_str(),
"This is a long string but still unique. Yay!!!"
);
}
#[test]
fn safe_send_requires_copy() {
let x = RocStr::from("This is a long string but still unique. Yay!!!");
let y = x.clone();
let z = y.clone();
assert_eq!(x.is_unique(), false);
assert_eq!(y.is_unique(), false);
assert_eq!(z.is_unique(), false);
let safe_x = SendSafeRocStr::from(x);
let new_x = RocStr::from(safe_x);
assert_eq!(new_x.is_unique(), true);
assert_eq!(y.is_unique(), false);
assert_eq!(z.is_unique(), false);
assert_eq!(
new_x.as_str(),
"This is a long string but still unique. Yay!!!"
);
}
#[test]
fn safe_send_small_str() {
let x = RocStr::from("short");
let y = x.clone();
let z = y.clone();
assert_eq!(x.is_unique(), true);
assert_eq!(y.is_unique(), true);
assert_eq!(z.is_unique(), true);
let safe_x = SendSafeRocStr::from(x);
let new_x = RocStr::from(safe_x);
assert_eq!(new_x.is_unique(), true);
assert_eq!(y.is_unique(), true);
assert_eq!(z.is_unique(), true);
assert_eq!(new_x.as_str(), "short");
}
#[test]
fn empty_list_is_unique() {
let roc_list = RocList::<RocStr>::empty();
assert_eq!(roc_list.is_unique(), true);
}
#[test]
fn readonly_list_is_sendsafe() {
let x = RocList::from_slice(&[1, 2, 3, 4, 5]);
unsafe { x.set_readonly() };
assert_eq!(x.is_readonly(), true);
let y = x.clone();
let z = y.clone();
let safe_x = SendSafeRocList::from(x);
let new_x = RocList::from(safe_x);
assert_eq!(new_x.is_readonly(), true);
assert_eq!(y.is_readonly(), true);
assert_eq!(z.is_readonly(), true);
assert_eq!(new_x.as_slice(), &[1, 2, 3, 4, 5]);
}
} }
#[cfg(test)] #[cfg(test)]