#![allow(clippy::float_cmp)] use std::sync::atomic::{AtomicUsize, Ordering}; mod particles; use self::particles::{Particle, ParticleVec, ParticleSlice, ParticleSliceMut}; #[test] fn const_ref() { let particle = Particle::new(String::from("Cl"), 0.0); let reference = particle.as_ref(); let ptr = reference.as_ptr(); unsafe { assert_eq!(ptr.as_ref().unwrap().name, "Cl"); assert_eq!(*ptr.as_ref().unwrap().mass, 0.0); } } #[test] fn mut_ref() { let mut particle = Particle::new(String::from("Cl"), 0.0); let mut reference = particle.as_mut(); let ptr = reference.as_mut_ptr(); unsafe { *ptr.as_mut().unwrap().name = String::from("Fe"); *ptr.as_mut().unwrap().mass = 42.0; } let ptr = reference.as_ptr(); unsafe { assert_eq!(ptr.as_ref().unwrap().name, "Fe"); assert_eq!(*ptr.as_ref().unwrap().mass, 42.0); } } #[test] fn slice() { let mut particles = ParticleVec::new(); particles.push(Particle::new(String::from("Na"), 1.0)); particles.push(Particle::new(String::from("Zn"), 2.0)); particles.push(Particle::new(String::from("Fe"), 3.0)); let slice = particles.as_slice(); let ptr = slice.as_ptr(); unsafe { assert_eq!(ptr.as_ref().unwrap().name, "Na"); assert_eq!(*ptr.as_ref().unwrap().mass, 1.0); } unsafe { let slice = ParticleSlice::from_raw_parts(ptr, 2); assert_eq!(slice.len(), 2); assert_eq!(slice.name[0], "Na"); assert_eq!(slice.name[1], "Zn"); assert_eq!(slice.mass[0], 1.0); assert_eq!(slice.mass[1], 2.0); } } #[test] fn slice_mut() { let mut particles = ParticleVec::new(); particles.push(Particle::new(String::from("Na"), 1.0)); particles.push(Particle::new(String::from("Zn"), 2.0)); particles.push(Particle::new(String::from("Fe"), 3.0)); let mut slice = particles.as_mut_slice(); let ptr = slice.as_mut_ptr(); unsafe { *ptr.as_mut().unwrap().name = String::from("Fe"); *ptr.as_mut().unwrap().mass = 42.0; } assert_eq!(slice.name[0], "Fe"); assert_eq!(slice.mass[0], 42.0); unsafe { let slice = ParticleSliceMut::from_raw_parts_mut(ptr, 2); for mass in slice.mass { *mass = -1.0; } } assert_eq!(slice.mass[0], -1.0); assert_eq!(slice.mass[1], -1.0); assert_eq!(slice.mass[2], 3.0); } #[test] fn vec() { let mut particles = ParticleVec::new(); particles.push(Particle::new(String::from("Na"), 1.0)); particles.push(Particle::new(String::from("Zn"), 2.0)); particles.push(Particle::new(String::from("Fe"), 3.0)); let len = particles.len(); let capacity = particles.capacity(); let ptr = particles.as_mut_ptr(); std::mem::forget(particles); unsafe { *ptr.as_mut().unwrap().name = String::from("Fe"); *ptr.as_mut().unwrap().mass = 42.0; } let particles = unsafe { ParticleVec::from_raw_parts(ptr, len, capacity) }; assert_eq!(particles.len(), len); assert_eq!(particles.capacity(), capacity); assert_eq!(particles.name[0], "Fe"); assert_eq!(particles.mass[0], 42.0); assert_eq!(particles.name[1], "Zn"); assert_eq!(particles.mass[1], 2.0); assert_eq!(particles.name[2], "Fe"); assert_eq!(particles.mass[2], 3.0); } #[derive(Clone, soa_derive::StructOfArray)] #[soa_derive(Clone)] struct CountOnDrop { data: usize, } static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); impl Drop for CountOnDrop { fn drop(&mut self) { DROP_COUNTER.fetch_add(1, Ordering::SeqCst); } } #[test] fn write() { { let mut vec = CountOnDropVec::new(); vec.push(CountOnDrop { data: 0 }); let ptr = vec.as_mut_ptr(); unsafe { // this does not drop the already existing value in the vec ptr.write(CountOnDrop { data: 4 }); } assert_eq!(vec.data[0], 4); } // std::mem::forget(vec); assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 1); }