use std::num::NonZero;
use crate::Env;
pub struct CommitToken {
env_ident: NonZero<usize>,
}
impl CommitToken {
pub(crate) fn new<T>(env: &Env<T>) -> CommitToken {
CommitToken { env_ident: env.env_mut_ptr().addr() }
}
pub(crate) fn env_ident(&self) -> NonZero<usize> {
self.env_ident
}
}
pub trait OnCommit {
type Committed;
fn on_commit(self, token: &CommitToken) -> Self::Committed;
}
impl OnCommit for () {
type Committed = ();
fn on_commit(self, _token: &CommitToken) -> Self::Committed {}
}
impl<A: OnCommit> OnCommit for Option<A> {
type Committed = Option<A::Committed>;
fn on_commit(self, token: &CommitToken) -> Self::Committed {
self.map(|a| a.on_commit(token))
}
}
impl<T: OnCommit, E> OnCommit for Result<T, E> {
type Committed = Result<T::Committed, E>;
fn on_commit(self, token: &CommitToken) -> Self::Committed {
self.map(|t| t.on_commit(token))
}
}
impl<T: OnCommit, const N: usize> OnCommit for [T; N] {
type Committed = [T::Committed; N];
fn on_commit(self, token: &CommitToken) -> Self::Committed {
self.map(|t| t.on_commit(token))
}
}
macro_rules! impl_on_commit_for_tuple {
( $( $name:ident )+ ) => {
impl<$($name: OnCommit),+> OnCommit for ($($name,)+) {
type Committed = ($($name::Committed,)+);
#[allow(non_snake_case)]
fn on_commit(self, token: &crate::CommitToken) -> Self::Committed {
let ($($name,)+) = self;
($($name.on_commit(token),)+)
}
}
};
}
impl_on_commit_for_tuple! { A }
impl_on_commit_for_tuple! { A B }
impl_on_commit_for_tuple! { A B C }
impl_on_commit_for_tuple! { A B C D }
impl_on_commit_for_tuple! { A B C D E }
impl_on_commit_for_tuple! { A B C D E F }
impl_on_commit_for_tuple! { A B C D E F G }
impl_on_commit_for_tuple! { A B C D E F G H }
impl_on_commit_for_tuple! { A B C D E F G H I }
impl_on_commit_for_tuple! { A B C D E F G H I J }
impl_on_commit_for_tuple! { A B C D E F G H I J K }
impl_on_commit_for_tuple! { A B C D E F G H I J K L }