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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use super::GenerationCounterT;

#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub struct GenerationIndex(GenerationCounterT);

pub struct Generation<T> {
    generation_index: GenerationIndex,
    value: Option<T>,
}

impl<T> Generation<T> {
    pub fn new() -> Self {
        Generation {
            generation_index: GenerationIndex(0),
            value: None,
        }
    }

    pub fn get(&self, generation: GenerationIndex) -> Option<&T> {
        //println!("get self: {} param: {}", self.generation_index.0, generation.0);

        let value = self.value.as_ref()?;
        if self.generation_index == generation {
            Some(value)
        } else {
            None
        }
    }

    pub fn get_mut(&mut self, generation: GenerationIndex) -> Option<&mut T> {
        //println!("get self: {} param: {}", self.generation_index.0, generation.0);

        let value = self.value.as_mut()?;
        if self.generation_index == generation {
            Some(value)
        } else {
            None
        }
    }

    pub fn allocate(&mut self, value: T) -> GenerationIndex {
        assert!(
            self.value.is_none(),
            "Can only allocate a generation if it's not already allocated"
        );
        self.value = Some(value);

        //println!("allocate generation {}", self.generation_index.0);
        self.generation_index
    }

    pub fn free(&mut self, generation_index: GenerationIndex) {
        assert!(
            self.value.is_some(),
            "Can only free a generation if it's not already freed"
        );
        assert!(
            self.generation_index == generation_index,
            "Can not free a generation with incorrect generation_index"
        );
        self.value = None;
        self.generation_index.0 += 1;
        //println!("free generation {}", self.generation_index.0);
    }

    pub fn is_none(&self) -> bool {
        self.value.is_none()
    }

    pub fn peek(&self) -> Option<&T> {
        self.value.as_ref()
    }

    pub fn peek_mut(&mut self) -> Option<&mut T> {
        self.value.as_mut()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generation_get() {
        // Generations starts unallocated
        let mut value = Generation::new();
        assert!(value.get(GenerationIndex(0)).is_none());

        // Once it's allocated, the first gen index will work to access it
        let generation_index0 = value.allocate(0);
        assert!(value.get(generation_index0).is_some());

        // Now that it's free, the generation won't work
        value.free(generation_index0);
        assert!(value.get(generation_index0).is_none());

        // Allocate again, the new index works and the old one doesn't
        let generation_index1 = value.allocate(0);
        assert!(value.get(generation_index0).is_none());
        assert!(value.get(generation_index1).is_some());
    }

    #[test]
    fn test_generation_get_mut() {
        // Generations starts unallocated
        let mut value = Generation::new();
        assert!(value.get_mut(GenerationIndex(0)).is_none());

        // Once it's allocated, the first gen index will work to access it
        let generation_index0 = value.allocate(0);
        assert!(value.get_mut(generation_index0).is_some());

        // Now that it's free, the generation won't work
        value.free(generation_index0);
        assert!(value.get_mut(generation_index0).is_none());

        // Allocate again, the new index works and the old one doesn't
        let generation_index1 = value.allocate(0);
        assert!(value.get_mut(generation_index0).is_none());
        assert!(value.get_mut(generation_index1).is_some());
    }

    #[test]
    #[should_panic(expected = "Can only allocate a generation if it's not already allocated")]
    fn test_double_allocate() {
        let mut value = Generation::new();
        value.allocate(0);
        value.allocate(0);
    }

    #[test]
    #[should_panic(expected = "Can only free a generation if it's not already freed")]
    fn test_double_free() {
        let mut value = Generation::new();
        let index = value.allocate(0);

        value.free(index);
        value.free(index);
    }

    #[test]
    #[should_panic(expected = "Can not free a generation with incorrect generation_index")]
    fn test_free_wrong_index() {
        let mut value = Generation::new();
        let index = value.allocate(0);

        value.free(index);
        value.allocate(0);
        value.free(index);
    }
}