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
//! Logic for recursive counters in a document for titles and other
//! counted items.

use std::fmt;

/// The struct that manages the counters for the document.
#[derive(Clone, Default)]
pub struct Counters {
    /// The counters.
    pub counters: Vec<usize>,
}

impl Counters {
    /// Creates a new empty counters.
    pub fn new() -> Counters {
        Counters { counters: vec![0] }
    }

    /// Increases the corresponding counter and returns it if it is correct.
    ///
    /// The counters of the subsections will be reinitialized.
    ///
    /// # Example
    ///
    /// ```
    /// # use spandex::document::counters::Counters;
    /// let mut counters = Counters::new();
    /// counters.increment(0);
    /// assert_eq!(counters.counter(0), 1);
    /// assert_eq!(counters.counter(1), 0);
    /// assert_eq!(counters.counter(2), 0);
    /// counters.increment(1);
    /// assert_eq!(counters.counter(1), 1);
    /// counters.increment(1);
    /// assert_eq!(counters.counter(1), 2);
    /// counters.increment(0);
    /// assert_eq!(counters.counter(0), 2);
    /// assert_eq!(counters.counter(1), 0);
    /// println!("{}", counters);
    /// ```
    pub fn increment(&mut self, counter_id: usize) -> usize {
        self.counters.resize(counter_id + 1, 0);
        self.counters[counter_id] += 1;
        self.counters[counter_id]
    }

    /// Returns a specific value of a counter.
    pub fn counter(&self, counter_id: usize) -> usize {
        match self.counters.get(counter_id) {
            Some(i) => *i,
            None => 0,
        }
    }
}

impl fmt::Display for Counters {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(
            fmt,
            "{}",
            self.counters
                .iter()
                .map(std::string::ToString::to_string)
                .collect::<Vec<_>>()
                .join(".")
        )
    }
}