1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/.
 */

//! High-level memory management.
use crate::{Memory, MemoryBuilder, Trail, TrailBuilder};
use std::fmt;

/// Representation of how something is stored on the trail.
///
/// Objects can be stored on the trail in backtrackable or non-backtrackable memory, represented by
/// [`Backtrackable`](Backtrackable) and [`NonBacktrackable`](NonBacktrackable), respectively. Both
/// of these structs implement `StorageMode`. See the documentation for [`Trail`](Trail) for the
/// difference between backtrackable and non-backtrackable storage.
pub trait StorageMode: fmt::Debug + Default {
    /// Returns the associated `MemoryBuilder` from a `TrailBuilder`.
    fn builder_mut(builder: &mut TrailBuilder) -> &mut MemoryBuilder;

    /// Returns the associated `Memory` from a `Trail`.
    fn memory(trail: &Trail) -> &Memory;

    /// Returns the associated `Memory` from a `Trail` mutably.
    fn memory_mut(trail: &mut Trail) -> &mut Memory;
}

/// Objects stored on the trail in backtrackable memory.
///
/// Instead of using `Backtrackable` directly, it's often easier to use the type definitions
/// [`BacktrackableValue`](crate::BacktrackableValue) and
/// [`BacktrackableArray`](crate::NonBacktrackableArray).
///
/// # Examples
///
/// ```
/// use contrail::{BacktrackableValue, TrailBuilder};
///
/// let mut builder = TrailBuilder::new();
/// let backtrackable_counter = BacktrackableValue::new(&mut builder, 0);
/// let mut trail = builder.finish();
///
/// assert_eq!(backtrackable_counter.get(&trail), 0);
///
/// trail.new_level();
///
/// backtrackable_counter.update(&mut trail, |x| x + 1);
///
/// assert_eq!(backtrackable_counter.get(&trail), 1);
///
/// trail.backtrack();
///
/// assert_eq!(backtrackable_counter.get(&trail), 0);
/// ```
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Backtrackable;

impl StorageMode for Backtrackable {
    #[inline]
    fn builder_mut(builder: &mut TrailBuilder) -> &mut MemoryBuilder {
        &mut builder.backtrackable_mem
    }

    #[inline]
    fn memory(trail: &Trail) -> &Memory {
        &trail.backtrackable_mem
    }

    #[inline]
    fn memory_mut(trail: &mut Trail) -> &mut Memory {
        &mut trail.backtrackable_mem
    }
}

/// Objects stored on the trail in stable memory.
///
/// Instead of using `NonBacktrackable` directly, it's often easier to use the type definitions
/// [`NonBacktrackableValue`](crate::NonBacktrackableValue) and
/// [`NonBacktrackableArray`](crate::NonBacktrackableArray).
///
/// # Examples
///
/// ```
/// use contrail::{NonBacktrackableValue, TrailBuilder};
///
/// let mut builder = TrailBuilder::new();
/// let non_backtrackable_counter = NonBacktrackableValue::new(&mut builder, 0);
/// let mut trail = builder.finish();
///
/// assert_eq!(non_backtrackable_counter.get(&trail), 0);
///
/// trail.new_level();
///
/// non_backtrackable_counter.update(&mut trail, |x| x + 1);
///
/// assert_eq!(non_backtrackable_counter.get(&trail), 1);
///
/// trail.backtrack();
///
/// assert_eq!(non_backtrackable_counter.get(&trail), 1);
/// ```
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct NonBacktrackable;

impl StorageMode for NonBacktrackable {
    #[inline]
    fn builder_mut(builder: &mut TrailBuilder) -> &mut MemoryBuilder {
        &mut builder.non_backtrackable_mem
    }

    #[inline]
    fn memory(trail: &Trail) -> &Memory {
        &trail.non_backtrackable_mem
    }

    #[inline]
    fn memory_mut(trail: &mut Trail) -> &mut Memory {
        &mut trail.non_backtrackable_mem
    }
}