Skip to content

Commit 8153da2

Browse files
committed
initial commit
0 parents  commit 8153da2

39 files changed

+4339
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Cargo.lock
2+
/target
3+
*~
4+
\#*\#

Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
authors = ["Michael Sippel <micha@fragmental.art>"]
3+
edition = "2018"
4+
name = "r3vi"
5+
version = "0.1.0"
6+
7+
[dependencies]
8+
cgmath = { version = "0.18.0", features = ["serde"] }
9+
serde = { version = "1.0", features = ["derive"] }
10+
bincode = "1.3.3"
11+
serde_json = "*"
12+
13+
[dependencies.async-std]
14+
version = "1.9.0"
15+
features = ["unstable", "attributes"]

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# r3vi
2+
3+
Rust Runtime for Reactive View-Projections
4+
5+
Using **r3vi** you can define *Projections*, i.e. transformations on *Views* that are
6+
updated *reactively* on changes in the source-view.
7+
These updates are performed incrementally using fine-granuar diffs.
8+
9+
*Views* are abstract accessor-interfaces that also define the update protocol (the diff).
10+
*Observers* can register to observe a *View* and are notified with the according diff-message
11+
whenever the view changes.
12+
*Projections* are transformations from one view into antoher.
13+
They are made of the target view and an observer that observes the source view.
14+
15+
R3vi provides basic data-structures and projections to build projectional pipelines
16+
with an interface similar to native rust iterators.
17+
18+
19+
## Examples
20+
21+
```rust
22+
use r3vi::buffer::vec::*;
23+
24+
let mut buffer = VecBuffer::<i32>::new();
25+
buffer.push(3);
26+
27+
let projected_port = buffer.get_port()
28+
.to_sequence() // make SequenceView from Vec
29+
.map(|x| x + 10)
30+
.filter(|x| x > 10);
31+
32+
let projected_view = projected_port.get_view();
33+
34+
assert_eq!(projected_view.get(&0), Some(13));
35+
36+
buffer.push(5); // maps to 15
37+
buffer.push(-9); // maps to 1, is eliminated by filter
38+
buffer.push(1); // maps to 11
39+
40+
assert_eq!(projected_view.get(&1), Some(15));
41+
assert_eq!(projected_view.get(&2), Some(11));
42+
43+
```

src/buffer/grid_hashmap.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
2+
use {
3+
std::{
4+
sync::Arc,
5+
collections::HashMap,
6+
hash::Hash
7+
},
8+
std::sync::RwLock,
9+
crate::{
10+
core::{
11+
Observer,
12+
ObserverBroadcast,
13+
View,
14+
InnerViewPort
15+
},
16+
index::{IndexArea, IndexView}
17+
}
18+
};
19+
20+
21+
struct GridBuffer<Item> {
22+
data: HashMap<Point2<i16>, Item>,
23+
limit: Point2<i16>
24+
}
25+
26+
impl<Item> View for GridBuffer<Item>
27+
where Item: Clone + Send + Sync + 'static
28+
{
29+
type Msg = IndexArea<Point2<i16>>;
30+
}
31+
32+
impl<Item> IndexView<Point2<i16>> for GridBufferView<Item>
33+
where Item: Clone + Send + Sync + 'static
34+
{
35+
type Item = Item;
36+
37+
fn get(&self, key: &Point2<i16>) -> Option<Self::Item> {
38+
self.data.get(key).cloned()
39+
}
40+
41+
fn area(&self) -> IndexArea<Point2<i16>> {
42+
IndexArea::Range(
43+
Point2::new(0, 0)
44+
..= self.limit
45+
)
46+
}
47+
}
48+
49+
pub struct GridBufferController<Item>
50+
where Item: Clone + Send + Sync + 'static
51+
{
52+
data: Arc<RwLock<HashMap<Point2<i16>, Item>>>,
53+
cast: Arc<RwLock<ObserverBroadcast<dyn IndexView<Point2<i16>, Item = Item>>>>
54+
}
55+
56+
impl<Key, Item> GridBuffer<Key, Item>
57+
where Key: Clone + Hash + Eq + Send + Sync + 'static,
58+
Item: Clone + Send + Sync + 'static
59+
{
60+
pub fn new(port: InnerViewPort<dyn IndexView<Point2<i16>, Item = Item>>) -> Self {
61+
let data = Arc::new(RwLock::new(HashMap::<Point2<i16>, Item>::new()));
62+
port.set_view(Some(Arc::new(GridBufferView(data.clone()))));
63+
64+
GridBuffer {
65+
data,
66+
cast: port.get_broadcast()
67+
}
68+
}
69+
70+
pub fn insert(&mut self, key: Point2<i16>, item: Item) {
71+
self.data.write().unwrap().insert(key.clone(), item);
72+
73+
if
74+
75+
self.cast.notify(&IndexArea::Set(vec![ key ]));
76+
}
77+
78+
pub fn insert_iter<T>(&mut self, iter: T)
79+
where T: IntoIterator<Item = (Point2<i16>, Item)> {
80+
for (key, item) in iter {
81+
self.insert(key, item);
82+
}
83+
}
84+
85+
pub fn remove(&mut self, key: Point2<i16>) {
86+
self.data.write().unwrap().remove(&key);
87+
self.cast.notify(&IndexArea::Set(vec![ key ]));
88+
}
89+
}
90+

src/buffer/index_hashmap.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
use {
2+
crate::{
3+
view::{
4+
InnerViewPort, OuterViewPort, ViewPort, View,
5+
index::{IndexArea, IndexView},
6+
},
7+
},
8+
std::sync::RwLock,
9+
std::{collections::HashMap, hash::Hash, sync::Arc, ops::{Deref, DerefMut}},
10+
};
11+
12+
pub struct IndexBufferView<Key, Item>(Arc<RwLock<HashMap<Key, Item>>>)
13+
where
14+
Key: Clone + Hash + Eq + Send + Sync + 'static,
15+
Item: Clone + Send + Sync + 'static;
16+
17+
impl<Key, Item> View for IndexBufferView<Key, Item>
18+
where
19+
Key: Clone + Hash + Eq + Send + Sync + 'static,
20+
Item: Clone + Send + Sync + 'static,
21+
{
22+
type Msg = IndexArea<Key>;
23+
}
24+
25+
impl<Key, Item> IndexView<Key> for IndexBufferView<Key, Item>
26+
where
27+
Key: Clone + Hash + Eq + Send + Sync + 'static,
28+
Item: Clone + Send + Sync + 'static,
29+
{
30+
type Item = Item;
31+
32+
fn get(&self, key: &Key) -> Option<Self::Item> {
33+
self.0.read().unwrap().get(key).cloned()
34+
}
35+
36+
fn area(&self) -> IndexArea<Key> {
37+
IndexArea::Set(self.0.read().unwrap().keys().cloned().collect())
38+
}
39+
}
40+
41+
#[derive(Clone)]
42+
pub struct IndexBuffer<Key, Item>
43+
where
44+
Key: Clone + Hash + Eq + Send + Sync + 'static,
45+
Item: Clone + Send + Sync + 'static,
46+
{
47+
data: Arc<RwLock<HashMap<Key, Item>>>,
48+
port: InnerViewPort<dyn IndexView<Key, Item = Item>>,
49+
}
50+
51+
impl<Key, Item> IndexBuffer<Key, Item>
52+
where
53+
Key: Clone + Hash + Eq + Send + Sync + 'static,
54+
Item: Clone + Send + Sync + 'static,
55+
{
56+
pub fn with_port(port: InnerViewPort<dyn IndexView<Key, Item = Item>>) -> Self {
57+
let data = Arc::new(RwLock::new(HashMap::<Key, Item>::new()));
58+
port.set_view(Some(Arc::new(IndexBufferView(data.clone()))));
59+
60+
IndexBuffer {
61+
data,
62+
port
63+
}
64+
}
65+
66+
pub fn new() -> Self {
67+
IndexBuffer::with_port(ViewPort::new().into_inner())
68+
}
69+
70+
pub fn get_port(&self) -> OuterViewPort<dyn IndexView<Key, Item = Item>> {
71+
self.port.0.outer()
72+
}
73+
74+
pub fn get(&self, key: &Key) -> Option<Item> {
75+
self.data.read().unwrap().get(key).cloned()
76+
}
77+
78+
pub fn get_mut(&mut self, key: &Key) -> MutableIndexAccess<Key, Item> {
79+
MutableIndexAccess {
80+
buf: self.clone(),
81+
key: key.clone(),
82+
val: self.get(key)
83+
}
84+
}
85+
86+
pub fn update(&mut self, key: Key, item: Option<Item>) {
87+
if let Some(item) = item {
88+
self.data.write().unwrap().insert(key.clone(), item);
89+
} else {
90+
self.data.write().unwrap().remove(&key);
91+
}
92+
self.port.notify(&IndexArea::Set(vec![key]));
93+
}
94+
95+
pub fn insert(&mut self, key: Key, item: Item) {
96+
self.data.write().unwrap().insert(key.clone(), item);
97+
self.port.notify(&IndexArea::Set(vec![key]));
98+
}
99+
100+
pub fn insert_iter<T>(&mut self, iter: T)
101+
where
102+
T: IntoIterator<Item = (Key, Item)>,
103+
{
104+
for (key, item) in iter {
105+
self.insert(key, item);
106+
}
107+
}
108+
109+
pub fn remove(&mut self, key: Key) {
110+
self.data.write().unwrap().remove(&key);
111+
self.port.notify(&IndexArea::Set(vec![key]));
112+
}
113+
}
114+
115+
//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>
116+
117+
pub struct MutableIndexAccess<Key, Item>
118+
where
119+
Key: Clone + Hash + Eq + Send + Sync + 'static,
120+
Item: Clone + Send + Sync + 'static,
121+
{
122+
buf: IndexBuffer<Key, Item>,
123+
key: Key,
124+
val: Option<Item>,
125+
}
126+
127+
impl<Key, Item> Deref for MutableIndexAccess<Key, Item>
128+
where
129+
Key: Clone + Hash + Eq + Send + Sync + 'static,
130+
Item: Clone + Send + Sync + 'static,
131+
{
132+
type Target = Option<Item>;
133+
134+
fn deref(&self) -> &Option<Item> {
135+
&self.val
136+
}
137+
}
138+
139+
impl<Key, Item> DerefMut for MutableIndexAccess<Key, Item>
140+
where
141+
Key: Clone + Hash + Eq + Send + Sync + 'static,
142+
Item: Clone + Send + Sync + 'static,
143+
{
144+
fn deref_mut(&mut self) -> &mut Self::Target {
145+
&mut self.val
146+
}
147+
}
148+
149+
impl<Key, Item> Drop for MutableIndexAccess<Key, Item>
150+
where
151+
Key: Clone + Hash + Eq + Send + Sync + 'static,
152+
Item: Clone + Send + Sync + 'static,
153+
{
154+
fn drop(&mut self) {
155+
self.buf.update(self.key.clone(), self.val.clone());
156+
}
157+
}
158+

src/buffer/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
pub mod singleton;
3+
pub mod vec;
4+
pub mod index_hashmap;
5+

0 commit comments

Comments
 (0)