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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//! This module exposes data structures composed of [Word]s.
//! 
//! The [ProduceConsume] trait helps create function which can accept any stack or queue-like structure.
//!
//! The [WordStack], [WordQueue] and [Array] structures help process operations with memory. 

use std::collections::VecDeque;
use std::ops::{Index, IndexMut};
use std::slice::Iter;
use std::vec::IntoIter;

use crate::data::atomic::Word;
use crate::data::identification::{Address, Area, Cursor, Identifier};


/// Common trait for data structure usable as a producer-consumer medium.
pub trait ProduceConsume<T> {
    /// Produce a value.
    ///
    /// This method adds a value into the object.
    fn produce(&mut self, data: T);

    /// Consume a value.
    ///
    /// This method moves out a value from the object.
    fn consume(&mut self) -> Option<T>;
    fn len(&self) -> usize;
    fn is_empty(&self) -> bool;
}


/// Describes a contiguous area in memory composed of [Word]s.
#[derive(Clone, Debug, Default)]
pub struct Array {
    data: Vec<Word>,
}

impl Array {
    /// Creates a new array composed of zeros.
    pub fn new(size: usize) -> Self {
        let mut array = Self { data: Vec::new() };
        array.data.resize(size, Word::default());
        array
    }

    /// Creates a new array from a slice of [Word]s.
    pub fn from(arr: &[Word]) -> Self {
        Self { data: arr.to_vec() }
    }

    /// Gets a subset of the current array.
    pub fn sub(&self, ignore_start: Address, ignore_end: Address) -> Self {
        Self::from(&self.as_slice()[ignore_start.to_usize()..(self.len() - ignore_end.to_usize())])
    }

    /// Gets a subset of the current array with its end trimmed.
    pub fn sub_from_start(&self, ignore_end: Address) -> Self { self.sub(Address::default(), ignore_end) }

    /// Gets a subset of the current array with its start trimmed.
    pub fn sub_from_end(&self, ignore_start: Address) -> Self { self.sub(ignore_start, Address::default()) }

    /// Returns `([..cesure], [cesure..])`.
    pub fn split(&self, cesure: Address) -> (Array, Array) {
        let mut first = Array::new(0);
        let mut second = Array::new(0);
        let mut index = Address::default();
        while let Some(word) = self.next(&mut index) {
            if index < cesure {
                first.push(word);
            } else {
                second.push(word);
            }
        }
        (first, second)
    }

    /// Returns a slice that shares the raw [Word]s data.
    pub fn as_slice(&self) -> &[Word] { &self.data }

    /// Returns a slice that shares the raw [Word]s data.
    pub fn as_mut_slice(&mut self) -> &mut [Word] { &mut self.data }

    /// Returns Some(Word) at the corresponding index.
    pub fn next(&self, index: &mut Address) -> Option<Word> {
        let output = self.data.get(index.to_usize()).cloned();
        index.increment();
        output
    }

    /// Returns an iterator that gives immutable references to the elements in the collection in sequence.
    pub fn iter(&self) -> Iter<Word> { self.data.iter() }

    /// Returns the number of words in the array.
    pub fn len(&self) -> usize { self.data.len() }

    /// Returns true if the array contains no elements.
    pub fn is_empty(&self) -> bool { self.data.is_empty() }

    /// Appends an element to the end of the array.
    pub fn push(&mut self, value: Word) { self.data.push(value); }

    /// Inserts an element to the array at a specific position.
    ///
    /// Assumes that 'address' can be converted to a position in the array.
    pub fn insert(&mut self, address: Address, value: Word) { self.data.insert(address.to_usize(), value); }

    /// Removes and returns the element at position 'index' in the array.
    ///
    /// Assumes that 'index' can be converted to a valid position in the array.
    pub fn remove(&mut self, index: Address) -> Word { self.data.remove(index.to_usize()) }

    /// Merges the current array with a borrowed array.
    pub fn merge(&mut self, with: &Array) {
        self.data.extend_from_slice(with.as_slice());
    }

    /// Extract an array covering a whole area.
    pub fn extract(&self, area: Area) -> Array { self.sub(area.start(), area.end()) }

    /// Extract one word inside an area from the array.
    pub fn extract_word(&self, area: Area, cursor: Address) -> Word { self[area.constraint(cursor)] }

    /// Extract one word from a cursor reference and advances it.
    pub fn next_word(&self, cursor: Cursor) -> (Word, Cursor) {
        let data = self[cursor.area.constraint(cursor.pointer)];
        let cursor = Cursor { area: cursor.area, pointer: cursor.next() };
        (data, cursor)
    }
}

impl IntoIterator for Array {
    type Item = Word;
    type IntoIter = IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter { self.data.into_iter() }
}

impl Index<Address> for Array {
    type Output = Word;
    fn index(&self, index: Address) -> &Self::Output { &self.data[index.to_usize()] }
}

impl IndexMut<Address> for Array {
    fn index_mut(&mut self, index: Address) -> &mut Self::Output { &mut self.data[index.to_usize()] }
}

/// Describes a queue (First In-First Out) composed of [Word]s.
#[derive(Clone, Debug, Default)]
pub struct WordQueue {
    raw: VecDeque<Word>,
}

impl WordQueue {
    /// Creates an empty queue.
    pub fn new() -> Self { Self::default() }
}

impl ProduceConsume<Word> for WordQueue {
    /// Adds a word at the end of the queue.
    fn produce(&mut self, word: Word) { self.raw.push_back(word); }

    /// Removes and returns an item from the end of the queue.
    fn consume(&mut self) -> Option<Word> { self.raw.pop_front() }

    /// Returns the queue length.
    fn len(&self) -> usize { self.raw.len() }

    /// Returns true if the queue has a zero length.
    fn is_empty(&self) -> bool { self.len() == 0 }
}

/// Describes a stack (Last In-First Out) composed of [Word]s.
#[derive(Clone, Debug, Default)]
pub struct WordStack {
    raw: Vec<Word>,
}

impl WordStack {
    /// Creates an empty stack.
    pub fn new() -> Self { Self::default() }
}

impl ProduceConsume<Word> for WordStack {
    fn produce(&mut self, word: Word) { self.raw.push(word); }
    fn consume(&mut self) -> Option<Word> { self.raw.pop() }
    fn len(&self) -> usize { self.raw.len() }
    fn is_empty(&self) -> bool { self.len() == 0 }
}