[go: up one dir, main page]

reis/
object.rs

1use std::{fmt, hash, sync::Arc};
2
3use crate::{
4    wire::{Arg, Backend, BackendWeak},
5    Interface,
6};
7
8#[derive(Clone)]
9pub struct Object(Arc<ObjectInner>);
10
11struct ObjectInner {
12    backend: BackendWeak,
13    client_side: bool,
14    id: u64,
15    interface: String,
16    version: u32,
17}
18
19impl PartialEq for Object {
20    fn eq(&self, rhs: &Self) -> bool {
21        Arc::ptr_eq(&self.0, &rhs.0)
22    }
23}
24
25impl Eq for Object {}
26
27impl hash::Hash for Object {
28    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
29        self.0.id.hash(hasher)
30    }
31}
32
33impl fmt::Debug for Object {
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        write!(f, "Object(_, {})", self.id())
36    }
37}
38
39impl Object {
40    // Should only be called by `Backend`
41    // Other references are then cloned from the version stored there
42    pub(crate) fn for_new_id(
43        backend: BackendWeak,
44        id: u64,
45        client_side: bool,
46        interface: String,
47        version: u32,
48    ) -> Self {
49        Self(Arc::new(ObjectInner {
50            backend,
51            id,
52            client_side,
53            interface,
54            version,
55        }))
56    }
57
58    pub fn backend(&self) -> Option<Backend> {
59        self.0.backend.upgrade()
60    }
61
62    pub(crate) fn backend_weak(&self) -> &BackendWeak {
63        &self.0.backend
64    }
65
66    pub fn is_alive(&self) -> bool {
67        if let Some(backend) = self.backend() {
68            backend.has_object_for_id(self.id())
69        } else {
70            false
71        }
72    }
73
74    pub fn id(&self) -> u64 {
75        self.0.id
76    }
77
78    pub fn interface(&self) -> &str {
79        &self.0.interface
80    }
81
82    pub fn version(&self) -> u32 {
83        self.0.version
84    }
85
86    pub fn request(&self, opcode: u32, args: &[Arg]) {
87        if let Some(backend) = self.backend() {
88            backend.request(self.0.id, opcode, args);
89        }
90    }
91
92    pub(crate) fn downcast_unchecked<T: Interface>(self) -> T {
93        T::new_unchecked(self)
94    }
95
96    pub(crate) fn as_arg(&self) -> Arg<'_> {
97        Arg::Id(self.0.id)
98    }
99
100    pub fn downcast<T: Interface>(self) -> Option<T> {
101        if (self.0.client_side, self.interface()) == (T::CLIENT_SIDE, T::NAME) {
102            Some(self.downcast_unchecked())
103        } else {
104            None
105        }
106    }
107}