1use crate::{HandleRef, Status, ok, sys};
8use std::mem::MaybeUninit;
9use std::ops::Deref;
10use zerocopy::{FromBytes, Immutable};
11
12pub(crate) const INFO_VEC_SIZE_INITIAL: usize = 16;
14
15#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
16#[repr(transparent)]
17pub struct Topic(sys::zx_object_info_topic_t);
18
19impl Deref for Topic {
20 type Target = sys::zx_object_info_topic_t;
21
22 fn deref(&self) -> &Self::Target {
23 &self.0
24 }
25}
26
27pub(crate) unsafe trait ObjectQuery {
33 const TOPIC: Topic;
35 type InfoTy: FromBytes + Immutable;
37}
38
39assoc_values!(Topic, [
40 NONE = sys::ZX_INFO_NONE;
41 HANDLE_VALID = sys::ZX_INFO_HANDLE_VALID;
42 HANDLE_BASIC = sys::ZX_INFO_HANDLE_BASIC;
43 PROCESS = sys::ZX_INFO_PROCESS;
44 PROCESS_THREADS = sys::ZX_INFO_PROCESS_THREADS;
45 VMAR = sys::ZX_INFO_VMAR;
46 VMAR_MAPS = sys::ZX_INFO_VMAR_MAPS;
47 JOB_CHILDREN = sys::ZX_INFO_JOB_CHILDREN;
48 JOB_PROCESSES = sys::ZX_INFO_JOB_PROCESSES;
49 THREAD = sys::ZX_INFO_THREAD;
50 THREAD_EXCEPTION_REPORT = sys::ZX_INFO_THREAD_EXCEPTION_REPORT;
51 TASK_STATS = sys::ZX_INFO_TASK_STATS;
52 TASK_RUNTIME = sys::ZX_INFO_TASK_RUNTIME;
53 PROCESS_MAPS = sys::ZX_INFO_PROCESS_MAPS;
54 PROCESS_VMOS = sys::ZX_INFO_PROCESS_VMOS;
55 THREAD_STATS = sys::ZX_INFO_THREAD_STATS;
56 CPU_STATS = sys::ZX_INFO_CPU_STATS;
57 KMEM_STATS = sys::ZX_INFO_KMEM_STATS;
58 KMEM_STATS_EXTENDED = sys::ZX_INFO_KMEM_STATS_EXTENDED;
59 KMEM_STATS_COMPRESSION = sys::ZX_INFO_KMEM_STATS_COMPRESSION;
60 RESOURCE = sys::ZX_INFO_RESOURCE;
61 HANDLE_COUNT = sys::ZX_INFO_HANDLE_COUNT;
62 BTI = sys::ZX_INFO_BTI;
63 PROCESS_HANDLE_STATS = sys::ZX_INFO_PROCESS_HANDLE_STATS;
64 SOCKET = sys::ZX_INFO_SOCKET;
65 TIMER = sys::ZX_INFO_TIMER;
66 VMO = sys::ZX_INFO_VMO;
67 JOB = sys::ZX_INFO_JOB;
68 IOB = sys::ZX_INFO_IOB;
69 IOB_REGIONS = sys::ZX_INFO_IOB_REGIONS;
70 MEMORY_STALL = sys::ZX_INFO_MEMORY_STALL;
71 CLOCK_MAPPED_SIZE = sys::ZX_INFO_CLOCK_MAPPED_SIZE;
72]);
73
74pub(crate) fn object_get_info<'a, Q: ObjectQuery>(
77 handle: HandleRef<'_>,
78 out: &'a mut [MaybeUninit<Q::InfoTy>],
79) -> Result<(&'a mut [Q::InfoTy], &'a mut [MaybeUninit<Q::InfoTy>], usize), Status>
80where
81 Q::InfoTy: FromBytes + Immutable,
82{
83 let mut actual = 0;
84 let mut avail = 0;
85
86 let status = unsafe {
89 sys::zx_object_get_info(
90 handle.raw_handle(),
91 *Q::TOPIC,
92 out.as_mut_ptr().cast::<u8>(),
93 std::mem::size_of_val(out),
94 &mut actual,
95 &mut avail,
96 )
97 };
98 ok(status)?;
99
100 let (initialized, uninit) = out.split_at_mut(actual);
101
102 let initialized: &mut [Q::InfoTy] = unsafe {
106 std::slice::from_raw_parts_mut(
107 initialized.as_mut_ptr().cast::<Q::InfoTy>(),
108 initialized.len(),
109 )
110 };
111
112 Ok((initialized, uninit, avail))
113}
114
115pub(crate) fn object_get_info_single<Q: ObjectQuery>(
117 handle: HandleRef<'_>,
118) -> Result<Q::InfoTy, Status>
119where
120 Q::InfoTy: Copy + FromBytes + Immutable,
121{
122 let mut info = MaybeUninit::<Q::InfoTy>::uninit();
123 let (info, _, _) = object_get_info::<Q>(handle, std::slice::from_mut(&mut info))?;
124 Ok(info[0])
125}
126
127pub(crate) fn object_get_info_vec<Q: ObjectQuery>(
131 handle: HandleRef<'_>,
132) -> Result<Vec<Q::InfoTy>, Status> {
133 let mut out = Vec::<Q::InfoTy>::with_capacity(INFO_VEC_SIZE_INITIAL);
135 loop {
136 let (init, _uninit, avail) =
137 object_get_info::<Q>(handle.clone(), out.spare_capacity_mut())?;
138 let num_initialized = init.len();
139 if num_initialized == avail {
140 unsafe { out.set_len(num_initialized) };
142 return Ok(out);
143 } else {
144 if avail > out.capacity() {
145 out.reserve_exact(avail - out.len());
146 }
147 }
148 }
149}