1use core::{marker::PhantomData, mem};
2
3use crate::{
4 bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_STACK},
5 helpers::{bpf_map_pop_elem, bpf_map_push_elem},
6 maps::PinningType,
7};
8
9#[repr(transparent)]
10pub struct Stack<T> {
11 def: bpf_map_def,
12 _t: PhantomData<T>,
13}
14
15impl<T> Stack<T> {
16 pub const fn with_max_entries(max_entries: u32, flags: u32) -> Stack<T> {
17 Stack {
18 def: bpf_map_def {
19 type_: BPF_MAP_TYPE_STACK,
20 key_size: 0,
21 value_size: mem::size_of::<T>() as u32,
22 max_entries,
23 map_flags: flags,
24 id: 0,
25 pinning: PinningType::None as u32,
26 },
27 _t: PhantomData,
28 }
29 }
30
31 pub const fn pinned(max_entries: u32, flags: u32) -> Stack<T> {
32 Stack {
33 def: bpf_map_def {
34 type_: BPF_MAP_TYPE_STACK,
35 key_size: 0,
36 value_size: mem::size_of::<T>() as u32,
37 max_entries,
38 map_flags: flags,
39 id: 0,
40 pinning: PinningType::ByName as u32,
41 },
42 _t: PhantomData,
43 }
44 }
45
46 pub fn push(&mut self, value: &T, flags: u64) -> Result<(), i64> {
47 let ret = unsafe {
48 bpf_map_push_elem(
49 &mut self.def as *mut _ as *mut _,
50 value as *const _ as *const _,
51 flags,
52 )
53 };
54 (ret == 0).then_some(()).ok_or(ret)
55 }
56
57 pub fn pop(&mut self) -> Option<T> {
58 unsafe {
59 let mut value = mem::MaybeUninit::uninit();
60 let ret = bpf_map_pop_elem(
61 &mut self.def as *mut _ as *mut _,
62 value.as_mut_ptr() as *mut _,
63 );
64 (ret == 0).then_some(value.assume_init())
65 }
66 }
67}