node_tree 0.15.0

An extendable scene graph made up of autonomous execution services known as nodes organized in a tree of processes. Inspired by Godot!
Documentation
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
//===================================================================================================================================================================================//
//
//  /$$$$$$$$           /$$ /$$$$$$$$ /$$            /$$$ /$$$$$$$$                                  /$$$$$$$           /$$             /$$                      /$$$  
// |__  $$__/          /$$/|__  $$__/|  $$          /$$_/|__  $$__/                                 | $$__  $$         |__/            | $$                     |_  $$ 
//    | $$  /$$$$$$   /$$/    | $$    \  $$        /$$/     | $$  /$$$$$$   /$$$$$$   /$$$$$$       | $$  \ $$ /$$$$$$  /$$ /$$$$$$$  /$$$$$$    /$$$$$$   /$$$$$$\  $$
//    | $$ /$$__  $$ /$$/     | $$     \  $$      | $$      | $$ /$$__  $$ /$$__  $$ /$$__  $$      | $$$$$$$//$$__  $$| $$| $$__  $$|_  $$_/   /$$__  $$ /$$__  $$| $$
//    | $$| $$  \ $$|  $$     | $$      /$$/      | $$      | $$| $$  \__/| $$$$$$$$| $$$$$$$$      | $$____/| $$  \ $$| $$| $$  \ $$  | $$    | $$$$$$$$| $$  \__/| $$
//    | $$| $$  | $$ \  $$    | $$     /$$/       |  $$     | $$| $$      | $$_____/| $$_____/      | $$     | $$  | $$| $$| $$  | $$  | $$ /$$| $$_____/| $$      /$$/
//    | $$| $$$$$$$/  \  $$   | $$    /$$/         \  $$$   | $$| $$      |  $$$$$$$|  $$$$$$$      | $$     |  $$$$$$/| $$| $$  | $$  |  $$$$/|  $$$$$$$| $$    /$$$/ 
//    |__/| $$____/    \__/   |__/   |__/           \___/   |__/|__/       \_______/ \_______/      |__/      \______/ |__/|__/  |__/   \___/   \_______/|__/   |___/  
//        | $$                                                                                                                                                         
//        | $$                                                                                                                                                         
//        |__/                                                                                                                                                         
//
//===================================================================================================================================================================================//

//?
//? Created by LunaticWyrm467 and others.
//? 
//? All code is licensed under the MIT license.
//? Feel free to reproduce, modify, and do whatever.
//?

//!
//! Provides the `Tp<T>` smart pointer which allows access to Nodes in the `NodeTree`.
//! Also provides the `TpDyn` alternative to allow easy access to dynamic values.
//! 

use std::ops::{ Deref, DerefMut };
use std::any::Any;
use std::marker::PhantomData;

use thiserror::Error;
use portable_intertrait::cast::*;

use crate::traits::{ node::Node, node_tree::NodeTree };
use super::rid::RID;
use super::logger::Log;
use super::tree_result::TreeResult;


/*
 * Tree Pointer
 *      Error Type
 */


/// Used to articulate any errors that may occur through the usage of the Tree Pointer type.
#[derive(Error, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum TPError {

    #[error("The node exists but ultimately is of the wrong type")]
    WrongType,

    #[error("A non-existent node was referenced")]
    IsNull,

    #[error("Cannot cast a null Tp<T> to a dynamic TpDyn")]
    AttemptedCastToDynOnNull,

    #[error("Cannot coerce a null TpDyn to a dynamic trait object")]
    AttemptedDynCastOnNull,

    #[error("The held node by this TpDyn does not extend the specified trait")]
    DynCastFailed,
}



/*
 * Tree
 *      Pointer
 */


/// A Tree Pointer (`Tp<T>`) is a reference to a specific RID and a pointer to the `NodeTree`,
/// meaning that it has access to grab a reference or mutable reference to a Node at will.
///
/// # Lifetimes
/// This shares a LifeTime with its owning Node, as its owning Node is what manages its internal
/// pointer to the `NodeTree`.
///
/// # `Deref` and `DerefMut`
/// The Tree Pointer implements `Deref` and `DerefMut`, which automatically call the panicking
/// versions of `get()` and `get_mut()`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Tp<'a, T: Node> {
    tree:   *mut dyn NodeTree,
    owner:  RID,
    node:   RID,
    p_life: PhantomData<&'a ()>,
    p_type: PhantomData<T>
}

impl <'a, T: Node> Tp<'a, T> {
    
    /// Creates a new `Tp<T>` via a raw pointer to the `NodeTree` and the referenced Node's `RID`.
    ///
    /// # Safety
    /// The responsibility of passing a valid pointer of the `NodeTree` to this structure is on the
    /// programmer.
    /// However, it is advised to use a `Node`'s `get_node()` or `get_node_from_tree()`
    /// function to have it be constructed in a safe manner for you!
    ///
    /// # Failure
    /// Will not return a valid `Tp<T>` pointer if the types do not match, or if the referenced
    /// `Node` is invalid!
    pub unsafe fn new(tree: *mut dyn NodeTree, owner: RID, node: RID) -> TreeResult<'a, Self, TPError> {
        
        // First check if the types match using dynamic dispatch!
        match unsafe { &*tree }.get_node(node) {
            Some(node) => {
                let any: &dyn Any = node.as_any_ref();
                match any.downcast_ref::<T>() {
                    Some(_) => (),
                    None    => return unsafe { TreeResult::new(tree, owner, Err(TPError::WrongType)) }
                }
            },
            None => return unsafe { TreeResult::new(tree, owner, Err(TPError::IsNull)) }
        }

        unsafe {
            TreeResult::new(tree, owner, Ok(Tp {
                tree,
                owner,
                node,
                p_life: PhantomData,
                p_type: PhantomData
            }))
        }
    }
    
    /// Converts this to a generic `TpDyn`.
    ///
    /// # Panics
    /// Panics if the node is invalid!
    #[inline]
    pub fn to_dyn(self) -> TpDyn<'a> {
        unsafe {
            match TpDyn::new(self.tree, self.owner, self.node).ok().to_option() {
                Some(success) => success,
                None          => self.fail(TPError::AttemptedCastToDynOnNull)
            }
        }
    }

    /// Converts this to a generic `TpDyn`.
    ///
    /// # Failure
    /// Will not return a valid `TpDyn` pointer if the internally referenced `Node` has been invalidated!
    #[inline]
    pub fn try_to_dyn(self) -> TreeResult<'a, TpDyn<'a>, TPError> {
        unsafe {
            TpDyn::new(self.tree, self.owner, self.node)
        }
    }

    /// Determines if the `Node` this pointer is pointing to is valid.
    #[inline]
    pub fn is_valid(&self) -> bool {
        match unsafe { &*self.tree }.get_node(self.node) {
            Some(node) => {
                let any: &dyn Any = node.as_any_ref();
                    any.downcast_ref::<T>().is_some()
            },
            None => false
        }
    }
    
    /// Determines if the `Node` this pointer is pointing to is invalid.
    #[inline]
    pub fn is_null(&self) -> bool {
        match unsafe { &*self.tree }.get_node(self.node) {
            Some(node) => {
                let any: &dyn Any = node.as_any_ref();
                    any.downcast_ref::<T>().is_none()
            },
            None => true
        }
    }
    
    /// Attempts to get a reference to the underlying `Node`.
    ///
    /// # Panics
    /// Panics if the node is invalid!
    pub fn get(&self) -> &T {
        let node: Option<&dyn Node> = unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n });
        match node {
            Some(node) => {
                let any: &dyn Any = node.as_any_ref();
                match any.downcast_ref::<T>() {
                    Some(node) => node,
                    None       => self.fail(TPError::WrongType)
                }
            },
            None => self.fail(TPError::IsNull)
        }
    }
    
    /// Attempts to get a reference to the underlying `Node`. Returns `Err` if the `Node` is invalid.
    pub fn try_get(&self) -> TreeResult<&T, TPError> {
        let node: Option<&dyn Node> = unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n });
        match node {
            Some(node) => {
                let any: &dyn Any = node.as_any_ref();
                match any.downcast_ref::<T>() {
                    Some(node) => unsafe { TreeResult::new(self.tree, self.owner, Ok(node)) },
                    None       => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::WrongType)) }
                }
            },
            None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::IsNull)) }
        }
    }
    
    /// Attempts to get a mutable reference to the underlying `Node`.
    ///
    /// # Panics
    /// Panics if the node is invalid!
    pub fn get_mut(&mut self) -> &mut T {
        let node: Option<&mut dyn Node> = unsafe { &mut *self.tree }.get_node_mut_raw(self.node).map(|n| unsafe { &mut *n });
        match node {
            Some(node) => {
                let any: &mut dyn Any = node.as_any_mut();
                match any.downcast_mut::<T>() {
                    Some(node) => node,
                    None       => self.fail(TPError::WrongType)
                }
            },
            None => self.fail(TPError::IsNull)
        }
    }
    
    /// Attempts to get a mutable reference to the underlying `Node`. Returns `Err` if the `Node` is invalid.
    pub fn try_get_mut(&mut self) -> TreeResult<&mut T, TPError> {
        let node: Option<&mut dyn Node> = unsafe { &mut *self.tree }.get_node_mut_raw(self.node).map(|n| unsafe { &mut *n });
        match node {
            Some(node) => {
                let any: &mut dyn Any = node.as_any_mut();
                match any.downcast_mut::<T>() {
                    Some(node) => unsafe { TreeResult::new(self.tree, self.owner, Ok(node)) },
                    None       => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::WrongType)) }
                }
            },
            None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::IsNull)) }
        }
    }

    /// Marks a failed operation with a panic on the log, and panics the main thread.
    #[inline]
    fn fail(&self, err: TPError) -> ! {
        unsafe { (*self.tree).get_node(self.owner).unwrap_unchecked() }.post(Log::Panic(&format!("{err:?}")));
        println!("\n[RUST TRACE]");
        panic!();
    }
}

impl <'a, T: Node> Deref for Tp<'a, T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &Self::Target {
        self.get()
    }
}

impl <'a, T: Node> DerefMut for Tp<'a, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.get_mut()
    }
}


/*
 * Tree Pointer
 *      Dynamic
 */


/// A Dynamic Tree Pointer (`TpDyn`) is a reference to a specific RID and a pointer to the `NodeTree`, meaning that it has access to grab
/// a reference or mutable reference to a Node at will. The difference between this and the standard `Tp<T>` is that it will allow
/// generic access to a dynamic Node object without forced coercion to a specific known node type. However, if a type is later determined,
/// it can easily be converted to a `Tp<T>` (`to<T>()`). In fact, this has a built in  method (`is<T>()`) to determine if this is of a
/// specified type.
///
/// # Lifetimes
/// This shares a LifeTime with its owning Node, as its owning Node is what manages its internal pointer to the `NodeTree`.
///
/// # `Deref` and `DerefMut`
/// The Tree Pointer implements `Deref` and `DerefMut`, which automatically call the panicking versions of `get()` and `get_mut()`.
/// 
/// # Casting
/// This allows casting to specific trait objects via the `cast()` and `cast_mut()` methods that the node this `TpDyn` is pointing to
/// extends from.
/// This is useful when you wish to coerce a node into a defined group of behaviours in a generic setting.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TpDyn<'a> {
    owner:  RID,
    node:   RID,
    tree:   *mut dyn NodeTree,
    p_life: PhantomData<&'a ()>
}

impl <'a> TpDyn<'a> {
    
    /// Creates a new `TpDyn` via a raw pointer to the `NodeTree` and the referenced Node's `RID`.
    ///
    /// # Safety
    /// The responsibility of passing a valid pointer of the `NodeTree` to this structure is on the
    /// programmer.
    /// However, it is advised to use a `Node`'s `get_node()` or `get_node_from_tree()`
    /// function to have it be constructed in a safe manner for you!
    ///
    /// # Failure
    /// Will not return a valid `TpDyn` pointer if the referenced `Node` is invalid!
    pub unsafe fn new(tree: *mut dyn NodeTree, owner: RID, node: RID) -> TreeResult<'a, Self, TPError> {
        
        // First check if the node exists!
        match unsafe { &*tree }.get_node(node) {
            Some(_) => (),
            None    => return unsafe { TreeResult::new(tree, owner, Err(TPError::IsNull)) }
        }

        unsafe {
            TreeResult::new(tree, owner, Ok(TpDyn {
                owner,
                node,
                tree,
                p_life: PhantomData
            }))
        }
    }

    /// This attempts to cast to a specific trait object.
    /// Useful when you wish to coerce a node into a defined group of behaviours, but do not know the type of the node.
    /// 
    /// # Failure
    /// This will fail if the node within is null, or if the node does not extend the specified trait.
    pub fn cast<T: ?Sized + 'static>(&self) -> TreeResult<&'a T, TPError> {
        use std::mem;

        match self.try_get().to_option() {
            Some(inner) => {
                match <dyn Node as CastRef>::cast::<T>(inner) {
                    Some(casted) => unsafe { TreeResult::new(self.tree, self.owner, Ok(mem::transmute(casted))) }, // Expand lifetime artificially
                    None         => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::DynCastFailed)) }
                }
            },
            None => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::AttemptedDynCastOnNull)) }
        }
    }

    /// This attempts to cast to a specific trait object.
    /// Useful when you wish to coerce a node into a defined group of behaviours, but do not know the type of the node.
    /// 
    /// # Failure
    /// This will fail if the node within is null, or if the node does not extend the specified trait.
    #[inline]
    pub fn cast_mut<T: ?Sized + 'static>(&mut self) -> TreeResult<&'a mut T, TPError> {
        use std::mem;

        // Grab these here so that we can avoid needed references during a mutable borrow.
        let tree: *mut dyn NodeTree = self.tree;
        let owner: RID              = self.owner;

        match self.try_get_mut().to_option() {
            Some(inner) => {
                match <dyn Node as CastMut>::cast::<T>(inner) {
                    Some(casted) => unsafe { TreeResult::new(tree, owner, Ok(mem::transmute(casted))) }, // Expand lifetime artificially
                    None         => unsafe { TreeResult::new(tree, owner, Err(TPError::DynCastFailed)) }
                }
            },
            None => unsafe { TreeResult::new(tree, owner, Err(TPError::AttemptedDynCastOnNull)) }
        }
    }

    /// Converts this to a type-coerced pointer.
    #[inline]
    pub fn to<T: Node>(self) -> TreeResult<'a, Tp<'a, T>, TPError> {
        unsafe {
            Tp::new(self.tree, self.owner, self.node)
        }
    }

    /// Checks if the node this points to can be cast to a specific trait.
    #[inline]
    pub fn is_of<T: ?Sized + 'static>(&self) -> bool {
        use std::mem;

        let node: TpDyn = unsafe { mem::transmute(*self) };
        <TpDyn as CastRef>::impls::<T>(&node)
    }

    /// Determines if this pointer references a specific type.
    pub fn is<T: Node>(&self) -> bool {
        let node: Option<&dyn Node> = unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n });
        match node {
            Some(node) => {
                let any: &dyn Any = node.as_any_ref();
                    any.downcast_ref::<T>().is_some()
            },
            None => false
        }
    }

    /// Determines if the `Node` this pointer is pointing to is valid.
    #[inline]
    pub fn is_valid(&self) -> bool {
        unsafe { &*self.tree }.get_node(self.node).is_some()
    }
    
    /// Determines if the `Node` this pointer is pointing to is invalid.
    #[inline]
    pub fn is_null(&self) -> bool {
        unsafe { &*self.tree }.get_node(self.node).is_none()
    }
    
    /// Attempts to get a reference to the underlying `Node`.
    ///
    /// # Panics
    /// Panics if the node is invalid!
    #[inline]
    pub fn get(&self) -> &dyn Node {
        let node: Option<&dyn Node> = unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n });
        match node {
            Some(node) => node,
            None       => self.fail(TPError::IsNull)
        }
    }
    
    /// Attempts to get a reference to the underlying `Node`. Returns `Err` if the `Node` is invalid.
    #[inline]
    pub fn try_get(&self) -> TreeResult<'a, &dyn Node, TPError> {
        match unsafe { &*self.tree }.get_node_raw(self.node).map(|n| unsafe { &*n }) {
            Some(node) => unsafe { TreeResult::new(self.tree, self.owner, Ok(node)) },
            None       => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::IsNull)) }
        }
    }
    
    /// Attempts to get a mutable reference to the underlying `Node`.
    ///
    /// # Panics
    /// Panics if the node is invalid!
    #[inline]
    pub fn get_mut(&mut self) -> &mut dyn Node {
        let node: Option<&mut dyn Node> = unsafe { &mut *self.tree }.get_node_mut_raw(self.node).map(|n| unsafe { &mut *n });
        match node {
            Some(node) => node,
            None       => self.fail(TPError::IsNull)
        }
    }
    
    /// Attempts to get a mutable reference to the underlying `Node`. Returns `Err` if the `Node` is invalid.
    #[inline]
    pub fn try_get_mut(&mut self) -> TreeResult<'a, &mut dyn Node, TPError> {
        match unsafe { &mut *self.tree }.get_node_mut_raw(self.node).map(|n| unsafe { &mut *n }) {
            Some(node) => unsafe { TreeResult::new(self.tree, self.owner, Ok(node)) },
            None       => unsafe { TreeResult::new(self.tree, self.owner, Err(TPError::IsNull)) }
        }
    }

    /// Marks a failed operation with a panic on the log, and panics the main thread.
    #[inline]
    fn fail(&self, err: TPError) -> ! {
        unsafe { (*self.tree).get_node(self.owner).unwrap_unchecked() }.post(Log::Panic(&format!("{err}")));
        println!("\n[RUST TRACE]");
        panic!();
    }
}

impl <'a> Deref for TpDyn<'a> {
    type Target = dyn Node;
    fn deref(&self) -> &Self::Target {
        self.get()
    }
}

impl <'a> DerefMut for TpDyn<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.get_mut()
    }
}