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