mod callbacks;
mod domain;
mod integrator;
mod output;
mod particles;
mod reference;
mod settings;
mod state;
mod tools;
mod traits;
mod transfer;
pub use callbacks::*;
pub use domain::*;
pub use integrator::*;
pub use output::*;
pub use particles::*;
pub use reference::*;
pub use settings::*;
pub use state::*;
pub use tools::*;
pub use traits::*;
pub use transfer::*;
use std::{
alloc::{Layout, alloc},
cell::UnsafeCell,
marker::PhantomPinned,
mem::MaybeUninit,
pin::Pin,
};
use rebound_bind as rb;
use crate::{Error, Result};
pub struct Simulation {
_owned: Pin<Box<_Simulation>>,
}
#[repr(C)]
pub(crate) struct _Simulation {
pub(crate) raw: rb::reb_simulation,
state: UnsafeCell<state::SimulationState>,
_pin: PhantomPinned,
}
impl _Simulation {
fn new() -> Self {
Self {
raw: unsafe { MaybeUninit::<rb::reb_simulation>::zeroed().assume_init() },
state: UnsafeCell::new(state::SimulationState::new()),
_pin: PhantomPinned,
}
}
pub(crate) fn sim_ref(&self) -> SimulationRef<'_> {
SimulationRef::new(self)
}
pub(crate) fn sim_mut(self: Pin<&mut Self>) -> SimulationRefMut<'_> {
SimulationRefMut::new(self)
}
pub(crate) fn state(&self) -> &state::SimulationState {
unsafe { &*self.state.get() }
}
pub(crate) fn with_state_mut<R>(&self, f: impl FnOnce(&mut state::SimulationState) -> R) -> R {
unsafe { f(&mut *self.state.get()) }
}
#[allow(dead_code)]
pub(crate) unsafe fn from_raw<'a>(raw: *const rb::reb_simulation) -> &'a Self {
unsafe { &*raw.cast() }
}
#[allow(dead_code)]
pub(crate) unsafe fn from_raw_mut<'a>(raw: *mut rb::reb_simulation) -> Pin<&'a mut Self> {
unsafe { Pin::new_unchecked(&mut *raw.cast()) }
}
}
impl Default for Simulation {
fn default() -> Self {
Self::try_new().expect("failed to allocate REBOUND simulation")
}
}
impl Drop for Simulation {
fn drop(&mut self) {
let raw = unsafe { &raw mut self._owned_mut().get_unchecked_mut().raw };
unsafe {
rb::reb_simulation_free_pointers(raw);
}
}
}
impl Simulation {
pub fn as_ref(&self) -> SimulationRef<'_> {
self._owned().sim_ref()
}
pub fn as_mut(&mut self) -> SimulationRefMut<'_> {
self._owned_mut().sim_mut()
}
pub(crate) fn _owned(&self) -> &_Simulation {
self._owned.as_ref().get_ref()
}
pub(crate) fn _owned_mut(&mut self) -> Pin<&mut _Simulation> {
self._owned.as_mut()
}
fn new_owned() -> Result<Pin<Box<_Simulation>>> {
let layout = Layout::new::<_Simulation>();
let ptr = unsafe { alloc(layout) as *mut _Simulation };
if ptr.is_null() {
return Err(Error::Allocation);
}
unsafe {
ptr.write(_Simulation::new());
Ok(Box::into_pin(Box::from_raw(ptr)))
}
}
pub fn new() -> Self {
Self::default()
}
pub fn try_new() -> Result<Self> {
let mut owned = Self::new_owned()?;
let raw = unsafe { &raw mut owned.as_mut().get_unchecked_mut().raw };
unsafe {
rb::reb_simulation_init(raw);
}
Ok(Self { _owned: owned })
}
}