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
//! Provides utilities for working with alphabets.
//!
//! Note: This package re-exports the alphabet!() macro defined by the crate [alphabet_macro](https://crates.io/crates/alphabet-macro).

pub use alphabet_macro::alphabet;

/// Allows to iterate over words of an alphabet (i.e. A\* for some alphabet A). This is an infinite iterator.
///
/// The words are sorted lexicographically if the alphabet imposes any particular order on its symbols.
///
/// Note: All alphabets generated by the alphabet!() macro impose an order on their symbols, namely the order in which they were specified in the alphabet contents.
///
/// # Examples
/// ```
/// use alphabet::*;
///
/// alphabet!(BINARY = "01");
/// let mut words = BINARY.iter_words();
/// assert_eq!(words.next().unwrap(), "");
/// assert_eq!(words.next().unwrap(), "0");
/// assert_eq!(words.next().unwrap(), "1");
///
/// // Note that this does not 'count' in binary, it operates on symbols:
/// assert_eq!(words.next().unwrap(), "00");
/// assert_eq!(words.next().unwrap(), "01");
/// assert_eq!(words.next().unwrap(), "10");
/// assert_eq!(words.next().unwrap(), "11");
/// assert_eq!(words.next().unwrap(), "000");
/// ```
pub trait WordIterable {
    /// Obtains an infinite iterator over the words constructible from the implementor.
    ///
    /// # Examples
    /// ```
    /// use alphabet::*;
    ///
    /// alphabet!(SCREAM = "A");
    /// let mut words = SCREAM.iter_words();
    /// assert_eq!(words.next().unwrap(), "");
    /// assert_eq!(words.next().unwrap(), "A");
    /// assert_eq!(words.next().unwrap(), "AA");
    /// assert_eq!(words.next().unwrap(), "AAA");
    /// ```
    fn iter_words(&self) -> detail::WordIterator;
}

impl WordIterable for [char] {
    fn iter_words(&self) -> detail::WordIterator {
        detail::WordIterator::from_vec(self.to_vec())
    }
}

impl WordIterable for Vec<char> {
    fn iter_words(&self) -> detail::WordIterator {
        detail::WordIterator::with_vec(self)
    }
}

mod detail {
    pub struct WordIterator<'a> {
        source: WordSource<'a>,
        counter: Vec<usize>
    }

    impl<'a> WordIterator<'a> {
        pub fn with_vec(v: &'a Vec<char>) -> Self {
            Self {
                source: WordSource::Vector(v),
                counter: Vec::new()
            }
        }

        pub fn from_vec(v: Vec<char>) -> Self {
            Self {
                source: WordSource::Array(v),
                counter: Vec::new()
            }
        }

        fn impl_next(&mut self) -> String {
            if self.counter.len() == 0 {
                self.counter.push(0);
                String::from("")
            } else {
                let result = self.counter_to_string();
                self.increase_counter();
                result
            }
        }

        fn counter_to_string(&self) -> String {
            let mut result = String::with_capacity(self.counter.len());
            for &elem in self.counter.iter().rev() {
                result.push(self.char_at(elem));
            }
            result
        }

        fn increase_counter(&mut self) {
            let maxlen = self.source_len();
            for elem in self.counter.iter_mut() {
                *elem += 1;
                if *elem == maxlen {
                    *elem = 0;
                } else {
                    return
                }
            }
            self.counter.push(0)
        }

        fn source_len(&self) -> usize {
            match &self.source {
                WordSource::Array(v) => v.len(),
                WordSource::Vector(v) => v.len()
            }
        }

        fn char_at(&self, i: usize) -> char {
            match &self.source {
                WordSource::Array(v) => v[i],
                WordSource::Vector(v) => v[i]
            }
        }
    }

    pub enum WordSource<'a> {
        Array(Vec<char>),
        Vector(&'a Vec<char>)
    }

    impl<'a> Iterator for WordIterator<'a> {
        type Item = String;

        fn next(&mut self) -> Option<String> {
            Some(self.impl_next())
        }
    }
}