tracepoint/descriptors.rs
1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT license.
3
4#[allow(unused_imports)]
5use crate::native::TracepointState; // For docs
6
7use core::marker::PhantomData;
8use core::mem;
9
10/// Low-level API: Describes a block of data to be sent to user_events via
11/// [`TracepointState::write`].
12///
13/// Note: This must have the same underlying representation as `struct iovec`.
14#[repr(C)]
15#[derive(Debug, Default)]
16pub struct EventDataDescriptor<'a> {
17 ptr: usize,
18 size: usize,
19 lifetime: PhantomData<&'a [u8]>,
20}
21
22impl<'a> EventDataDescriptor<'a> {
23 /// Returns an EventDataDescriptor initialized with { null, 0 }.
24 pub const fn zero() -> Self {
25 return Self {
26 ptr: 0,
27 size: 0,
28 lifetime: PhantomData,
29 };
30 }
31
32 /// Returns true if this descriptor's size is 0.
33 pub const fn is_empty(&self) -> bool {
34 return self.size == 0;
35 }
36
37 /// Returns an EventDataDescriptor initialized with the specified ptr and size.
38 ///
39 /// # Safety
40 ///
41 /// This bypasses lifetime tracking. Caller must ensure that this
42 /// EventDataDescriptor is not used after the referenced data's lifetime.
43 /// Typically, this is done by overwriting the descriptor with
44 /// [`EventDataDescriptor::zero`] after it has been used.
45 pub const unsafe fn from_raw_ptr(ptr: usize, size: usize) -> Self {
46 return Self {
47 ptr,
48 size,
49 lifetime: PhantomData,
50 };
51 }
52
53 /// Returns an EventDataDescriptor initialized with the specified slice's bytes.
54 pub fn from_bytes(value: &'a [u8]) -> Self {
55 return Self {
56 ptr: value.as_ptr() as usize,
57 size: value.len(),
58 lifetime: PhantomData,
59 };
60 }
61
62 /// Returns an EventDataDescriptor initialized with the specified value's bytes.
63 pub fn from_value<T: Copy>(value: &'a T) -> Self {
64 return Self {
65 ptr: value as *const T as usize,
66 size: mem::size_of::<T>(),
67 lifetime: PhantomData,
68 };
69 }
70
71 /// Returns an EventDataDescriptor for a nul-terminated string.
72 /// Returned descriptor does NOT include the nul-termination.
73 ///
74 /// Resulting descriptor's size is the minimum of:
75 /// - `size_of::<T>() * 65535`
76 /// - `size_of::<T>() * value.len()`
77 /// - `size_of::<T>() * (index of first element equal to T::default())`
78 pub fn from_cstr<T: Copy + Default + Eq>(mut value: &'a [T]) -> Self {
79 let mut value_len = value.len();
80
81 const MAX_LEN: usize = 65535;
82 if value_len > MAX_LEN {
83 value = &value[..MAX_LEN];
84 value_len = value.len();
85 }
86
87 let zero = T::default();
88 let mut len = 0;
89 while len < value_len {
90 if value[len] == zero {
91 value = &value[..len];
92 break;
93 }
94
95 len += 1;
96 }
97
98 return Self {
99 ptr: value.as_ptr() as usize,
100 size: mem::size_of_val(value),
101 lifetime: PhantomData,
102 };
103 }
104
105 /// Returns an EventDataDescriptor for a variable-length array field.
106 ///
107 /// Resulting descriptor's size is the minimum of:
108 /// - `size_of::<T>() * 65535`
109 /// - `size_of::<T>() * value.len()`
110 pub fn from_slice<T: Copy>(mut value: &'a [T]) -> Self {
111 let value_len = value.len();
112
113 const MAX_LEN: usize = 65535;
114 if MAX_LEN < value_len {
115 value = &value[..MAX_LEN];
116 }
117
118 return Self {
119 ptr: value.as_ptr() as usize,
120 size: mem::size_of_val(value),
121 lifetime: PhantomData,
122 };
123 }
124}