osiris_data/data/
composite.rs

1//! This module exposes data structures composed of [Word]s.
2//!
3//! The [ProduceConsume] trait helps create function which can accept any stack or queue-like structure.
4//!
5//! The [WordStack], [WordQueue] and [Array] structures help process operations with memory. 
6
7use std::collections::VecDeque;
8use std::ops::{Index, IndexMut};
9use std::slice::Iter;
10use std::vec::IntoIter;
11
12use crate::data::atomic::Word;
13use crate::data::identification::{Address, Area, Cursor, Identifier};
14
15
16/// Common trait for data structure usable as a producer-consumer medium.
17pub trait ProduceConsume<T> {
18    /// Produce a value.
19    ///
20    /// This method adds a value into the object.
21    fn produce(&mut self, data: T);
22
23    /// Consume a value.
24    ///
25    /// This method moves out a value from the object.
26    fn consume(&mut self) -> Option<T>;
27    fn len(&self) -> usize;
28    fn is_empty(&self) -> bool;
29}
30
31
32/// Describes a contiguous area in memory composed of [Word]s.
33#[derive(Clone, Debug, Default)]
34pub struct Array {
35    data: Vec<Word>,
36}
37
38impl Array {
39    /// Creates a new array composed of zeros.
40    pub fn new(size: usize) -> Self {
41        let mut array = Self { data: Vec::new() };
42        array.data.resize(size, Word::default());
43        array
44    }
45
46    /// Creates a new array from a slice of [Word]s.
47    pub fn from(arr: &[Word]) -> Self {
48        Self { data: arr.to_vec() }
49    }
50
51    /// Gets a subset of the current array.
52    pub fn sub(&self, ignore_start: Address, ignore_end: Address) -> Self {
53        Self::from(&self.as_slice()[ignore_start.to_usize()..(self.len() - ignore_end.to_usize())])
54    }
55
56    /// Gets a subset of the current array with its end trimmed.
57    pub fn sub_from_start(&self, ignore_end: Address) -> Self { self.sub(Address::default(), ignore_end) }
58
59    /// Gets a subset of the current array with its start trimmed.
60    pub fn sub_from_end(&self, ignore_start: Address) -> Self { self.sub(ignore_start, Address::default()) }
61
62    /// Returns `([..cesure], [cesure..])`.
63    pub fn split(&self, cesure: Address) -> (Array, Array) {
64        let mut first = Array::new(0);
65        let mut second = Array::new(0);
66        let mut index = Address::default();
67        while let Some(word) = self.next(&mut index) {
68            if index < cesure {
69                first.push(word);
70            } else {
71                second.push(word);
72            }
73        }
74        (first, second)
75    }
76
77    /// Returns a slice that shares the raw [Word]s data.
78    pub fn as_slice(&self) -> &[Word] { &self.data }
79
80    /// Returns a slice that shares the raw [Word]s data.
81    pub fn as_mut_slice(&mut self) -> &mut [Word] { &mut self.data }
82
83    /// Returns Some(Word) at the corresponding index.
84    pub fn next(&self, index: &mut Address) -> Option<Word> {
85        let output = self.data.get(index.to_usize()).cloned();
86        index.increment();
87        output
88    }
89
90    /// Returns an iterator that gives immutable references to the elements in the collection in sequence.
91    pub fn iter(&self) -> Iter<Word> { self.data.iter() }
92
93    /// Returns the number of words in the array.
94    pub fn len(&self) -> usize { self.data.len() }
95
96    /// Returns true if the array contains no elements.
97    pub fn is_empty(&self) -> bool { self.data.is_empty() }
98
99    /// Appends an element to the end of the array.
100    pub fn push(&mut self, value: Word) { self.data.push(value); }
101
102    /// Inserts an element to the array at a specific position.
103    ///
104    /// Assumes that 'address' can be converted to a position in the array.
105    pub fn insert(&mut self, address: Address, value: Word) { self.data.insert(address.to_usize(), value); }
106
107    /// Removes and returns the element at position 'index' in the array.
108    ///
109    /// Assumes that 'index' can be converted to a valid position in the array.
110    pub fn remove(&mut self, index: Address) -> Word { self.data.remove(index.to_usize()) }
111
112    /// Merges the current array with a borrowed array.
113    pub fn merge(&mut self, with: &Array) {
114        self.data.extend_from_slice(with.as_slice());
115    }
116
117    /// Extract an array covering a whole area.
118    pub fn extract(&self, area: Area) -> Array { self.sub(area.start(), area.end()) }
119
120    /// Extract one word inside an area from the array.
121    pub fn extract_word(&self, area: Area, cursor: Address) -> Word { self[area.constraint(cursor)] }
122
123    /// Extract one word from a cursor reference and advances it.
124    pub fn next_word(&self, mut cursor: Cursor) -> (Word, Cursor) {
125        let data = self[cursor.area.constraint(cursor.current())];
126        cursor.advance();
127        (data, cursor)
128    }
129}
130
131impl IntoIterator for Array {
132    type Item = Word;
133    type IntoIter = IntoIter<Self::Item>;
134
135    fn into_iter(self) -> Self::IntoIter { self.data.into_iter() }
136}
137
138impl Index<Address> for Array {
139    type Output = Word;
140    fn index(&self, index: Address) -> &Self::Output { &self.data[index.to_usize()] }
141}
142
143impl IndexMut<Address> for Array {
144    fn index_mut(&mut self, index: Address) -> &mut Self::Output { &mut self.data[index.to_usize()] }
145}
146
147/// Describes a queue (First In-First Out) composed of [Word]s.
148#[derive(Clone, Debug, Default)]
149pub struct WordQueue {
150    raw: VecDeque<Word>,
151}
152
153impl WordQueue {
154    /// Creates an empty queue.
155    pub fn new() -> Self { Self::default() }
156}
157
158impl ProduceConsume<Word> for WordQueue {
159    /// Adds a word at the end of the queue.
160    fn produce(&mut self, word: Word) { self.raw.push_back(word); }
161
162    /// Removes and returns an item from the end of the queue.
163    fn consume(&mut self) -> Option<Word> { self.raw.pop_front() }
164
165    /// Returns the queue length.
166    fn len(&self) -> usize { self.raw.len() }
167
168    /// Returns true if the queue has a zero length.
169    fn is_empty(&self) -> bool { self.len() == 0 }
170}
171
172/// Describes a stack (Last In-First Out) composed of [Word]s.
173#[derive(Clone, Debug, Default)]
174pub struct WordStack {
175    raw: Vec<Word>,
176}
177
178impl WordStack {
179    /// Creates an empty stack.
180    pub fn new() -> Self { Self::default() }
181}
182
183impl ProduceConsume<Word> for WordStack {
184    fn produce(&mut self, word: Word) { self.raw.push(word); }
185    fn consume(&mut self) -> Option<Word> { self.raw.pop() }
186    fn len(&self) -> usize { self.raw.len() }
187    fn is_empty(&self) -> bool { self.len() == 0 }
188}