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}