oop_inheritance/
lib.rs

1/*!
2This crate provides object-oriented inheritance using Nodes.
3
4A Node consits of a set of components and a Node can have other
5children nodes.
6
7# Defining classes
8
9Use the [`class!`] invocation for defining class.
10
11# Components
12
13```
14use oop_inheritance::*;
15
16let something = Node::new();
17
18// Set a component
19something.set::<f64>(10);
20
21// `Option<Arc<f64>>`
22something.get::<f64>();
23```
24
25# Children
26
27```ignore
28something.add_child(&another_thing);
29```
30
31# Node paths
32
33Since Nodes are in hierarchy, every Node that has a name may be found when
34using the `.resolve_path` method. However, there are special segments of an Node path that do not resolve
35by name, which may be useful in some contexts:
36
37- `.first` resolves to the first child of an Node;
38- `.last` resolves to the last child of an Node;
39- `..` resolves to the parent.
40
41```
42let last_sibling: Option<Node> = node.resolve_path("../.last");
43```
44*/
45
46use std::{
47    any::Any,
48    sync::{Arc, RwLock, Weak},
49    hash::Hash, fmt::{Debug, Display}, error::Error,
50};
51
52use by_address::ByAddress;
53
54type Component = Arc<dyn Any + Send + Sync>;
55
56#[doc(hidden)]
57pub use oop_inheritance_proc::class_extends;
58
59pub use oop_inheritance_proc::class;
60
61pub mod util;
62
63use self::util::VectorExtensions;
64
65fn default<T: Default>() -> T {
66    T::default()
67}
68
69/// Represents an node as a type managed by reference-counting.
70pub struct Node {
71    inner: Arc<NodeInner>,
72}
73
74impl Debug for Node {
75    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76        write!(f, "Node")
77    }
78}
79
80impl Hash for Node {
81    /// Hashes the node by reference.
82    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
83        ByAddress(Arc::clone(&self.inner)).hash(state)
84    }
85}
86
87impl PartialEq for Node {
88    /// Compares nodes by reference.
89    /// > **Note**: This method does not compare the nodes by content.
90    fn eq(&self, other: &Self) -> bool {
91        Arc::ptr_eq(&self.inner, &other.inner)
92    }
93}
94
95impl Eq for Node {}
96
97impl Clone for Node {
98    /// Clones the node by reference.
99    /// > **Note**: This method does not clone the node by content.
100    fn clone(&self) -> Self {
101        Self { inner: Arc::clone(&self.inner) }
102    }
103}
104
105impl AsRef<Node> for Node {
106    fn as_ref(&self) -> &Node {
107        self
108    }
109}
110
111impl Node {
112    pub fn new() -> Node {
113        Self {
114            inner: Arc::new(NodeInner {
115                name: RwLock::new(None),
116                parent: RwLock::new(default()),
117                components: RwLock::new(vec![]),
118                children: RwLock::new(vec![]),
119            })
120        }
121    }
122
123    /// Downgrades the node reference into a weak reference.
124    pub fn downgrade_ref(&self) -> WeakNodeRef {
125        WeakNodeRef(Arc::downgrade(&self.inner))
126    }
127
128    /// Checks whether node has a specified component.
129    pub fn has<T>(&self) -> bool
130        where T: Any + Send + Sync
131    {
132        self.get::<T>().is_some()
133    }
134
135    /// Retrieves a component from the node.
136    pub fn get<T>(&self) -> Option<Arc<T>>
137        where T: Any + Send + Sync
138    {
139        for component in self.inner.components.read().unwrap().iter() {
140            if let Ok(c) = Arc::downcast::<T>(Arc::clone(component)) {
141                return Some(c);
142            }
143        }
144        None
145    }
146
147    /// Overrides a component of the node. This method is chainable.
148    pub fn set<T>(&self, value: T) -> Self
149        where T: Any + Send + Sync
150    {
151        self.delete::<T>();
152        self.inner.components.write().unwrap().push(Arc::new(value));
153        self.clone()
154    }
155
156    /// Deletes a component of the node.
157    /// Returns `true` if any component was deleted;
158    /// otherwise returns `false`.
159    pub fn delete<T>(&self) -> bool
160        where T: Any + Send + Sync
161    {
162        let mut i = 0;
163        let mut components = vec![];
164        for component in self.inner.components.read().unwrap().iter() {
165            components.push(Arc::clone(component));
166        }
167        for component in components {
168            if Arc::downcast::<T>(Arc::clone(&component)).is_ok() {
169                self.inner.components.write().unwrap().remove(i);
170                return true;
171            }
172            i += 1;
173        }
174        false
175    }
176    
177    pub fn parent(&self) -> Option<Node> {
178        self.inner.parent.read().unwrap().upgrade()
179    }
180
181    pub fn children(&self) -> Vec<Node> {
182        let mut c = vec![];
183        for child in self.inner.children.read().unwrap().iter() {
184            c.push(child.clone());
185        }
186        c
187    }
188
189    pub fn child_at(&self, index: usize) -> Option<Node> {
190        if index < self.num_children() { Some(self.inner.children.read().unwrap()[index].clone()) } else { None }
191    }
192
193    /// Returns the number of children.
194    pub fn num_children(&self) -> usize {
195        self.inner.children.read().unwrap().len()
196    }
197
198    fn is_child_of(&self, child: &Node) -> bool {
199        if let Some(p) = self.parent() {
200            if &p == child {
201                return true;
202            }
203        }
204        for i in 0..child.num_children() {
205            let child = child.child_at(i).unwrap();
206            if self.is_child_of(&child) {
207                return true;
208            }
209        }
210        false
211    }
212
213    /// Adds a child node to the end of the children collection.
214    /// If `child` is already child of an node, it is removed and then added
215    /// as part of this node.
216    pub fn add_child(&self, child: impl AsRef<Node>) {
217        let child = child.as_ref();
218        child.remove_from_parent();
219
220        // Do not allow circular children
221        assert!(!self.is_child_of(child), "Adding circular child.");
222
223        *child.inner.parent.write().unwrap() = self.downgrade_ref();
224        self.inner.children.write().unwrap().push(child.clone());
225    }
226
227    /// Adds a child node at the index `index` of the children collection.
228    /// If `child` is already child of an node, it is removed and then added
229    /// as part of this node.
230    /// 
231    /// # Panics
232    /// 
233    /// This method panics if `index` is out of bounds.
234    pub fn add_child_at(&self, index: usize, child: impl AsRef<Node>) {
235        let child = child.as_ref();
236        child.remove_from_parent();
237        assert!(index < self.num_children(), "Specified index is out of bounds.");
238
239        // Do not allow circular children
240        assert!(!self.is_child_of(child), "Adding circular child.");
241
242        *child.inner.parent.write().unwrap() = self.downgrade_ref();
243        self.inner.children.write().unwrap().insert(index, child.clone());
244    }
245
246    /// Adds a sequence of children to the end of the children collection.
247    /// This is equivalent to iterating the sequence and invoking `add_child()`
248    /// with every child.
249    pub fn add_children(&self, children: impl IntoIterator<Item = impl AsRef<Node>>) {
250        for child in children.into_iter() {
251            self.add_child(child.as_ref());
252        }
253    }
254
255    /// Swaps two children.
256    /// 
257    /// # Panics
258    /// 
259    /// Panics if any of the specified nodes is not part of the node.
260    pub fn swap_children(&self, child_1: impl AsRef<Node>, child_2: impl AsRef<Node>) {
261        let child_1 = child_1.as_ref();
262        let child_2 = child_2.as_ref();
263        let indices = [self.inner.children.read().unwrap().index_of(child_1), self.inner.children.read().unwrap().index_of(child_2)];
264        assert!(indices.iter().all(|i| i.is_some()), "Some of the specified indices are out of bounds.");
265        self.inner.children.write().unwrap().swap(indices[0].unwrap(), indices[1].unwrap());
266    }
267
268    /// Swaps two children.
269    /// 
270    /// # Panics
271    /// 
272    /// Panics if any of the specified indices is out of bounds.
273    pub fn swap_children_by_indices(&self, child_1: usize, child_2: usize) {
274        assert!([child_1, child_2].iter().all(|&i| i < self.num_children()), "Some of the specified indices are out of bounds.");
275        self.inner.children.write().unwrap().swap(child_1, child_2);
276    }
277
278    /// Removes a child. Returns `true` if the child has been removed, or `false` otherwise.
279    pub fn remove_child(&self, child: impl AsRef<Node>) -> bool {
280        let child = child.as_ref();
281        let i = self.inner.children.read().unwrap().index_of(child);
282        if let Some(i) = i {
283            self.inner.children.write().unwrap().remove(i);
284            *child.inner.parent.write().unwrap() = default();
285            true
286        } else {
287            false
288        }
289    }
290
291    /// Removes all children nodes from the node.
292    pub fn remove_children(&self) {
293        for child in self.children() {
294            *child.inner.parent.write().unwrap() = default();
295        }
296        self.inner.children.write().unwrap().clear();
297    }
298
299    /// Removes the node from its parent. Returns `true` if the child has been removed, or `false` otherwise.
300    pub fn remove_from_parent(&self) -> bool {
301        if let Some(p) = self.parent() { p.remove_child(self) } else { false }
302    }
303
304    /// The name of the node as used in Node paths.
305    pub fn name(&self) -> Option<String> {
306        self.inner.name.read().unwrap().clone()
307    }
308
309    /// The name of the node as used in Node paths.
310    pub fn set_name(&self, name: Option<String>) {
311        *self.inner.name.write().unwrap() = name;
312    }
313
314    /**
315    Resolves an Node path. An Node path is resolved as follows:
316
317    1. Let *segments* be the splitting of the path by the slash character (`/`).
318    2. Let *r* be the initial node.
319    3. For every segment *s*:
320        1. If `s == ".first"`, let *r* be the first child of *r* or otherwise `None`.
321        2. If `s == ".last"`, let *r* be the last child of *r* or otherwise `None`.
322        3. If `s == ".."`, let *r* be the parent of *r* or otherwise `None`.
323        4. If *s* is non-empty, let *r* be a child of *r* such that `child.name() == s` or otherwise `None`.
324    4. Return *r*
325    */
326    pub fn resolve_path(&self, path: &str) -> Option<Node> {
327        let segments = path.split('/');
328        let mut r: Option<Node> = Some(self.clone());
329        for s in segments {
330            if r.is_none() {
331                break;
332            }
333            match s {
334                ".first" => {
335                    r = r.unwrap().children().first().map(|c| c.clone());
336                },
337                ".last" => {
338                    r = r.unwrap().children().last().map(|c| c.clone());
339                },
340                ".." => {
341                    r = r.unwrap().parent();
342                },
343                "" => {
344                    // Empty
345                },
346                _ => {
347                    r = r.unwrap().children().iter().find(|c| c.name().as_ref().map(|cn| cn.as_ref()) == Some(s)).map(|c| c.clone());
348                },
349            }
350        }
351        r
352    }
353
354    /// Indicates whether an Node is of a certain Node subtype.
355    pub fn is<T: TryFrom<Self, Error = ClassError>>(&self) -> bool {
356        T::try_from(self.clone()).is_ok()
357    }
358
359    /// Attempts to convert this Node reference into a `T` reference.
360    pub fn to<T: TryFrom<Self, Error = ClassError>>(&self) -> Result<T, ClassError> {
361        T::try_from(self.clone())
362    }
363}
364
365struct NodeInner {
366    name: RwLock<Option<String>>,
367    parent: RwLock<WeakNodeRef>,
368    components: RwLock<Vec<Component>>,
369    children: RwLock<Vec<Node>>,
370}
371
372/// Represents a weak reference to an node.
373pub struct WeakNodeRef(Weak<NodeInner>);
374
375impl WeakNodeRef {
376    /// Returns a `WeakNodeRef` reference that upgrades to no
377    /// strong reference.
378    pub fn empty() -> Self {
379        Self(Weak::new())
380    }
381
382    /// Attempts to upgrade a weak reference into a strong reference.
383    pub fn upgrade(&self) -> Option<Node> {
384        if let Some(r) = self.0.upgrade() { Some(Node { inner: r }) } else { None }
385    }
386}
387
388impl Debug for WeakNodeRef {
389    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
390        write!(f, "WeakNodeRef")
391    }
392}
393
394impl Default for WeakNodeRef {
395    fn default() -> Self {
396        Self::empty()
397    }
398}
399
400impl PartialEq for WeakNodeRef {
401    /// Compares nodes by reference.
402    fn eq(&self, other: &Self) -> bool {
403        Weak::ptr_eq(&self.0, &other.0)
404    }
405}
406
407impl Eq for WeakNodeRef {}
408
409impl Clone for WeakNodeRef {
410    fn clone(&self) -> Self {
411        Self(self.0.clone())
412    }
413}
414
415/// Represents an error originated from Node subclass relationships.
416/// For example, this error might occur as result of a failed conversion.
417pub struct ClassError {
418    message: String,
419}
420
421impl ClassError {
422    pub fn new(message: &str) -> Self {
423        Self { message: message.into() }
424    }
425}
426
427impl Display for ClassError {
428    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
429        write!(f, "{}", self.message)
430    }
431}
432
433impl Debug for ClassError {
434    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
435        <Self as Display>::fmt(self, f)
436    }
437}
438
439impl Error for ClassError {}
440
441#[cfg(test)]
442mod tests {
443    use crate::*;
444
445    #[test]
446    fn test_components() {
447        let node = Node::new();
448        node.set(10.0);
449        assert_eq!(10.0, *node.get::<f64>().unwrap());
450
451        node.delete::<f64>();
452        assert!(node.get::<f64>().is_none());
453    }
454
455    #[test]
456    fn test_hierarchy() {
457        let topmost = Node::new();
458        let child_1 = Node::new();
459        child_1.set_name(Some("child1".into()));
460        topmost.add_child(&child_1);
461        assert_eq!("child1".to_owned(), topmost.resolve_path(".last").unwrap().name().unwrap());
462        assert_eq!(topmost.resolve_path(".last").unwrap(), child_1);
463    }
464
465    #[test]
466    fn test_class_extends() {
467        struct A(Node);
468
469        class_extends!(A < Node, use AComponent, crate);
470        
471        impl A {
472            fn new() -> Self {
473                Self(Node::new().set(AComponent))
474            }
475        }
476
477        struct AComponent;
478
479        struct B(A);
480
481        class_extends!(B < A < Node, use BComponent, crate);
482
483        impl B {
484            fn new() -> Self {
485                Self(A::new().set(BComponent).try_into().unwrap())
486            }
487        }
488
489        struct BComponent;
490
491        let r = B::new();
492        let r_e: Node = r.clone().into();
493        let _: A = r.into();
494        assert!(r_e.is::<B>());
495
496        let r = Node::new();
497        assert!(!r.is::<A>());
498    }
499
500    #[test]
501    fn test_class() {
502        class! {
503            use oop_inheritance = crate;
504            struct A: Node {
505                x: f64 = 0.0,
506            }
507            fn constructor(x: f64) {
508                super();
509                this.set_x(x);
510            }
511        }
512
513        let o = A::new(10.0);
514        assert_eq!(o.x(), 10.0);
515
516        class! {
517            use oop_inheritance = crate;
518            struct B: A < Node {
519                y: A = A::new(15.0),
520                ref z: f64 = 0.0,
521            }
522            fn constructor() {
523                super(0.0);
524            }
525        }
526
527        let o = B::new();
528        assert_eq!(o.y().x(), 15.0);
529    }
530}