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 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}