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
/// The lifespan of an entity.
#[derive(Debug, Clone, Copy)]
pub enum Lifespan {
    Ephemeral(Span),
    Immortal,
}

impl Lifespan {
    /// Returns true only if there is lifespan left. It will always return true
    /// if immortal.
    pub fn is_alive(&self) -> bool {
        match self {
            Lifespan::Ephemeral(span) => span.length() > 0,
            Lifespan::Immortal => true,
        }
    }

    /// Shorten the lifespan by a single unit of span, it has no effect if
    /// immortal. Returns the Lifespan left.
    pub fn shorten(&mut self) -> &Self {
        self.shorten_by(Span::with_length(1))
    }

    /// Lengthen the lifespan by a single unit of span, it has no effect if
    /// immortal. Returns the Lifespan left.
    pub fn lengthen(&mut self) -> &Self {
        self.lengthen_by(Span::with_length(1))
    }

    /// Shorten the lifespan by the given amount of span, it has no effect if
    /// immortal. Returns the Lifespan left.
    pub fn shorten_by(&mut self, amount: Span) -> &Self {
        if let Lifespan::Ephemeral(span) = self {
            span.shorten_by(amount.into());
        }
        self
    }

    /// Lengthen the lifespan by the given amount of span, it has no effect if
    /// immortal. Returns the Lifespan left.
    pub fn lengthen_by(&mut self, amount: Span) -> &Self {
        if let Lifespan::Ephemeral(span) = self {
            span.lengthen_by(amount.into());
        }
        self
    }

    /// Replaces the lifespan with a new empty one, by effectively representing
    /// the death of the entity. This method will have an effect also on an
    /// immortal lifespan.
    pub fn clear(&mut self) {
        *self = Lifespan::Ephemeral(Span::empty())
    }
}

/// The window of time span as seen by an entity, represented as discrete number
/// of steps left before the entity dies.
#[derive(Debug, Clone, Copy)]
pub struct Span {
    length: u64,
}

impl From<u64> for Span {
    fn from(length: u64) -> Self {
        Self { length }
    }
}

impl From<Span> for u64 {
    fn from(span: Span) -> Self {
        span.length
    }
}

impl Span {
    /// Constructs a new Span of the given length.
    pub fn with_length(length: u64) -> Self {
        Self { length }
    }

    /// Constructs an empty lifespan.
    pub fn empty() -> Self {
        Self { length: 0 }
    }

    /// Gets the length of this Span.
    pub fn length(self) -> u64 {
        self.length
    }

    /// Shorten the span by the given length of span.
    pub fn shorten_by(&mut self, length: u64) {
        self.length = self.length.saturating_sub(length);
    }

    /// Lengthen the span by the given length of span.
    pub fn lengthen_by(&mut self, length: u64) {
        self.length = self.length.saturating_add(length);
    }

    /// Shorten the span by a single unit of span.
    pub fn shorten(&mut self) {
        self.shorten_by(1);
    }

    /// Lengthen the span by a single unit of span.
    pub fn lengthen(&mut self) {
        self.lengthen_by(1);
    }

    /// Reset the span to 0.
    pub fn clear(&mut self) {
        self.length = 0;
    }
}