|
|
|
@ -66,10 +66,15 @@ impl List {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
|
self.as_slice().len()
|
|
|
|
|
// SAFETY: Slice is immediately discarded.
|
|
|
|
|
unsafe { self.as_slice() }.len()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn as_slice(&self) -> &[Obj] {
|
|
|
|
|
// SAFETY: Slice itself is guaranteed to stay valid. However, its contents
|
|
|
|
|
// may be mutated in MicroPython or by another copy of this list.
|
|
|
|
|
// Caller is responsible for only keeping the slice around for as long as it is
|
|
|
|
|
// not mutated.
|
|
|
|
|
pub unsafe fn as_slice(&self) -> &[Obj] {
|
|
|
|
|
unsafe {
|
|
|
|
|
// SAFETY: mp_obj_list_get() does not mutate the list.
|
|
|
|
|
let list = self.as_mut_obj();
|
|
|
|
@ -81,7 +86,10 @@ impl List {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn as_mut_slice(&mut self) -> &mut [Obj] {
|
|
|
|
|
// SAFETY: Returned slice may be mutated in MicroPython or by another copy of
|
|
|
|
|
// this list. Caller is responsible for ensuring uniqueness of the mutable
|
|
|
|
|
// borrow.
|
|
|
|
|
pub unsafe fn as_mut_slice(&mut self) -> &mut [Obj] {
|
|
|
|
|
unsafe {
|
|
|
|
|
// SAFETY: self is borrowed mutably.
|
|
|
|
|
let list = self.as_mut_obj();
|
|
|
|
@ -92,6 +100,22 @@ impl List {
|
|
|
|
|
core::slice::from_raw_parts_mut(items_ptr, len)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get(&self, index: usize) -> Result<Obj, Error> {
|
|
|
|
|
// SAFETY: Slice is immediately discarded.
|
|
|
|
|
unsafe { self.as_slice() }
|
|
|
|
|
.get(index)
|
|
|
|
|
.copied()
|
|
|
|
|
.ok_or(Error::IndexError)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set(&mut self, index: usize, value: Obj) -> Result<(), Error> {
|
|
|
|
|
// SAFETY: Slice is immediately discarded.
|
|
|
|
|
unsafe { self.as_mut_slice() }
|
|
|
|
|
.get_mut(index)
|
|
|
|
|
.map(|slot| *slot = value)
|
|
|
|
|
.ok_or(Error::IndexError)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<Gc<List>> for Obj {
|
|
|
|
@ -155,6 +179,32 @@ mod tests {
|
|
|
|
|
assert_eq!(list.len(), vec.len());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn list_get_set() {
|
|
|
|
|
unsafe { mpy_init() };
|
|
|
|
|
|
|
|
|
|
let vec: Vec<u16, 17> = (0..17).collect();
|
|
|
|
|
let mut gc_list = List::from_iter(vec.iter().copied()).unwrap();
|
|
|
|
|
let list = unsafe { Gc::as_mut(&mut gc_list) };
|
|
|
|
|
|
|
|
|
|
for (i, value) in vec.iter().copied().enumerate() {
|
|
|
|
|
assert_eq!(value, list.get(i).unwrap().try_into().unwrap());
|
|
|
|
|
list.set(i, Obj::from(value + 1)).unwrap();
|
|
|
|
|
assert_eq!(value + 1, list.get(i).unwrap().try_into().unwrap());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut buf = IterBuf::new();
|
|
|
|
|
let iter = Iter::try_from_obj_with_buf(gc_list.into(), &mut buf).unwrap();
|
|
|
|
|
let retrieved_vec: Vec<u16, 17> = iter
|
|
|
|
|
.map(TryInto::try_into)
|
|
|
|
|
.collect::<Result<Vec<u16, 17>, Error>>()
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
for i in 0..retrieved_vec.len() {
|
|
|
|
|
assert_eq!(retrieved_vec[i], vec[i] + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn list_as_slice() {
|
|
|
|
|
unsafe { mpy_init() };
|
|
|
|
@ -162,7 +212,7 @@ mod tests {
|
|
|
|
|
let vec: Vec<u16, 17> = (13..13 + 17).collect();
|
|
|
|
|
let list = List::from_iter(vec.iter().copied()).unwrap();
|
|
|
|
|
|
|
|
|
|
let slice = list.as_slice();
|
|
|
|
|
let slice = unsafe { list.as_slice() };
|
|
|
|
|
assert_eq!(slice.len(), vec.len());
|
|
|
|
|
for i in 0..slice.len() {
|
|
|
|
|
assert_eq!(vec[i], slice[i].try_into().unwrap());
|
|
|
|
@ -176,7 +226,7 @@ mod tests {
|
|
|
|
|
let vec: Vec<u16, 5> = (0..5).collect();
|
|
|
|
|
let mut list = List::from_iter(vec.iter().copied()).unwrap();
|
|
|
|
|
|
|
|
|
|
let slice = unsafe { Gc::<List>::as_mut(&mut list) }.as_mut_slice();
|
|
|
|
|
let slice = unsafe { Gc::as_mut(&mut list).as_mut_slice() };
|
|
|
|
|
assert_eq!(slice.len(), vec.len());
|
|
|
|
|
assert_eq!(vec[0], slice[0].try_into().unwrap());
|
|
|
|
|
|
|
|
|
|