php_parser_rs/
downcast.rs

1use crate::node::Node;
2use std::any::TypeId;
3
4pub fn downcast<T: Node + 'static>(node: &dyn Node) -> Option<&T> {
5    // Get `TypeId` of the type this function is instantiated with.
6    let t = TypeId::of::<T>();
7
8    // Get `TypeId` of the node we want to downcast.
9    let concrete = node.type_id();
10
11    // Compare both `TypeId`s on equality.
12    if t == concrete {
13        // Get the concrete type pointer from the trait object.
14        let concrete = node as *const dyn Node as *const T;
15
16        // Convert it to a reference and return it.
17        //
18        // SAFETY: This is safe because we know for sure that the pointer
19        // is valid and references are only handed out for the lifetime
20        // of the function.
21        let concrete = unsafe { &*concrete };
22
23        Some(concrete)
24    } else {
25        None
26    }
27}
28
29pub fn downcast_mut<T: Node>(node: &mut dyn Node) -> Option<&mut T> {
30    let t = TypeId::of::<T>();
31    let concrete = node.type_id();
32
33    if t == concrete {
34        let concrete = node as *mut dyn Node as *mut T;
35        let concrete = unsafe { &mut *concrete };
36
37        Some(concrete)
38    } else {
39        None
40    }
41}