dope_core/driver/storage/
cleanup.rs1use std::{convert, mem};
2
3use dope_sys::memory;
4
5use crate::{
6 Resources,
7 driver::{life::native::create, storage},
8};
9
10pub struct Cleanup(State<Resources, create::Failure>);
12
13impl Cleanup {
14 pub(in crate::driver) fn new<S: Into<Resources>>(state: S) -> Self {
15 Self(State::new(state))
16 }
17
18 pub fn try_close(
20 &mut self,
21 report: impl FnMut(storage::Failure),
22 ) -> Result<storage::Failure, storage::Failure> {
23 self.0
24 .try_close(report, storage::Failure::from, storage::Failure::from)
25 }
26
27 pub fn primary(&self) -> storage::Failure {
28 self.0.primary(storage::Failure::from)
29 }
30
31 pub fn cleanup(&self) -> Option<storage::Failure> {
33 self.0.failure(storage::Failure::from)
34 }
35}
36
37pub(super) enum State<R, P> {
39 Owner(R),
40 Primary(P),
41}
42
43impl<R, P> State<R, P> {
44 pub(super) fn new<S: Into<R>>(state: S) -> Self {
45 Self::Owner(state.into())
46 }
47}
48
49impl<R: memory::Cleanup<P>, P: Copy> State<R, P> {
50 pub(super) fn try_close<T, E>(
51 &mut self,
52 mut report: impl FnMut(E),
53 primary: impl FnOnce(P) -> T,
54 failure: impl Fn(R::Error) -> E,
55 ) -> Result<T, E> {
56 let retained = self.primary(convert::identity);
57 match mem::replace(self, Self::Primary(retained)) {
58 Self::Primary(value) => Ok(primary(value)),
59 Self::Owner(owner) => match owner.try_close(|error| report(failure(error))) {
60 Ok(value) => {
61 *self = Self::Primary(value);
62 Ok(primary(value))
63 }
64 Err(owner) => {
65 let error = owner.failure();
66 *self = Self::Owner(owner);
67 Err(failure(error))
68 }
69 },
70 }
71 }
72
73 pub(super) fn primary<T>(&self, map: impl FnOnce(P) -> T) -> T {
74 map(match self {
75 Self::Owner(owner) => owner.primary(),
76 Self::Primary(primary) => *primary,
77 })
78 }
79
80 pub(super) fn failure<E>(&self, map: impl FnOnce(R::Error) -> E) -> Option<E> {
81 match self {
82 Self::Owner(owner) => Some(map(owner.failure())),
83 Self::Primary(_) => None,
84 }
85 }
86}