flo_animation/traits/
editable.rs1use super::edit::*;
2
3use std::ops::{Deref, DerefMut};
4
5pub trait Editable<T: ?Sized> {
9 fn edit(&self) -> Option<Editor<T>>;
13
14 fn read(&self) -> Option<Reader<T>>;
18}
19
20pub struct Reader<'a, T: ?Sized+'a> {
24 target: Box<'a+Deref<Target=T>>
25}
26
27pub struct Editor<'a, T: ?Sized+'a> {
31 target: Box<'a+DerefMut<Target=T>>,
33}
34
35impl<'a, T: ?Sized+'a> Reader<'a, T> {
36 pub fn new<Owner: 'a+Deref<Target=T>>(target: Owner) -> Reader<'a, T> {
40 Reader { target: Box::new(target) }
41 }
42}
43
44impl<'a, T: ?Sized+'a> Editor<'a, T> {
45 pub fn new<Owner: 'a+DerefMut<Target=T>>(target: Owner) -> Editor<'a, T> {
49 Editor { target: Box::new(target) }
50 }
51}
52
53impl<'a, T: ?Sized+'a> Deref for Reader<'a, T> {
54 type Target = T;
55
56 fn deref(&self) -> &T {
57 self.target.deref()
58 }
59}
60
61impl<'a, T: ?Sized+'a> Deref for Editor<'a, T> {
62 type Target = T;
63
64 fn deref(&self) -> &T {
65 self.target.deref()
66 }
67}
68
69impl<'a, T: ?Sized+'a> DerefMut for Editor<'a, T> {
70 fn deref_mut(&mut self) -> &mut T {
71 self.target.deref_mut()
72 }
73}
74
75impl<T: ?Sized> Editable<T> for () {
76 fn edit(&self) -> Option<Editor<T>> { None }
77 fn read(&self) -> Option<Reader<T>> { None }
78}
79
80pub fn open_read<'a, EditorType: ?Sized>(editable: &'a Editable<EditorType>) -> Option<Reader<'a, EditorType>> {
84 editable.read()
85}
86
87pub fn open_edit<'a, EditorType: ?Sized>(editable: &'a Editable<EditorType>) -> Option<Editor<'a, EditorType>> {
91 editable.edit()
92}
93
94pub trait PerformEdits<Edit> {
98 fn perform_edits<Iter: IntoIterator<Item=Edit>>(&self, edits: Iter);
99 fn set_pending(&self, pending: &[Edit]);
100 fn commit_pending(&self);
101}
102
103impl<Edit, T: Editable<PendingEditLog<Edit>>> PerformEdits<Edit> for T {
104 #[inline]
105 fn perform_edits<Iter: IntoIterator<Item=Edit>>(&self, edits: Iter) {
106 let mut editor = open_edit::<PendingEditLog<Edit>>(self).unwrap();
107
108 let edits: Vec<_> = edits.into_iter().collect();
109
110 editor.set_pending(&edits);
111 editor.commit_pending();
112 }
113
114 #[inline]
115 fn set_pending(&self, edits: &[Edit]) {
116 let mut editor = open_edit::<PendingEditLog<Edit>>(self).unwrap();
117
118 editor.set_pending(edits);
119 }
120
121 #[inline]
122 fn commit_pending(&self) {
123 let mut editor = open_edit::<PendingEditLog<Edit>>(self).unwrap();
124
125 editor.commit_pending();
126 }
127}
128
129#[cfg(test)]
130mod test {
131 use super::*;
132 use std::sync::*;
133
134 #[test]
135 fn can_create_reader_for_mutex() {
136 let mutex = Mutex::new(1);
137
138 {
139 let reader = {
141 let locked = mutex.lock().unwrap();
142 Reader::new(locked)
143 };
144
145 assert!(*reader == 1);
147 }
148 }
149
150 #[test]
151 fn can_create_editor_for_mutex() {
152 let mutex = Mutex::new(1);
153
154 {
155 let mut editor = {
157 let locked = mutex.lock().unwrap();
158 Editor::new(locked)
159 };
160
161 assert!(*editor == 1);
163 *editor = 2;
164 }
165
166 assert!(*mutex.lock().unwrap() == 2);
168 }
169
170 struct TestEditable;
171
172 impl Editable<i32> for TestEditable {
173 fn edit(&self) -> Option<Editor<i32>> { None }
174 fn read(&self) -> Option<Reader<i32>> { None }
175 }
176
177 impl Editable<bool> for TestEditable {
178 fn edit(&self) -> Option<Editor<bool>> { None }
179 fn read(&self) -> Option<Reader<bool>> { None }
180 }
181
182 #[test]
183 fn can_have_multiple_editable_items() {
184 let test = TestEditable;
185 let edit_i32:Option<Editor<i32>> = test.edit();
186 let edit_bool = open_edit::<bool>(&test);
187
188 assert!(edit_i32.is_none());
189 assert!(edit_bool.is_none());
190 }
191}