1use std::{
4 borrow::{Borrow, BorrowMut},
5 marker::PhantomData,
6 os::fd::AsFd as _,
7};
8
9use crate::{
10 Pod,
11 maps::{MapData, MapError, check_kv_size},
12 sys::{SyscallError, bpf_map_lookup_and_delete_elem, bpf_map_update_elem},
13};
14
15#[doc(alias = "BPF_MAP_TYPE_STACK")]
33pub struct Stack<T, V: Pod> {
34 pub(crate) inner: T,
35 _v: PhantomData<V>,
36}
37
38impl<T: Borrow<MapData>, V: Pod> Stack<T, V> {
39 pub(crate) fn new(map: T) -> Result<Self, MapError> {
40 let data = map.borrow();
41 check_kv_size::<(), V>(data)?;
42
43 Ok(Self {
44 inner: map,
45 _v: PhantomData,
46 })
47 }
48
49 pub fn capacity(&self) -> u32 {
53 self.inner.borrow().obj.max_entries()
54 }
55}
56
57impl<T: BorrowMut<MapData>, V: Pod> Stack<T, V> {
58 pub fn pop(&mut self, flags: u64) -> Result<V, MapError> {
65 let fd = self.inner.borrow().fd().as_fd();
66
67 let value =
68 bpf_map_lookup_and_delete_elem::<u32, _>(fd, None, flags).map_err(|io_error| {
69 SyscallError {
70 call: "bpf_map_lookup_and_delete_elem",
71 io_error,
72 }
73 })?;
74 value.ok_or(MapError::ElementNotFound)
75 }
76
77 pub fn push(&mut self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
83 let fd = self.inner.borrow().fd().as_fd();
84 bpf_map_update_elem(fd, None::<&u32>, value.borrow(), flags)
85 .map_err(|io_error| SyscallError {
86 call: "bpf_map_update_elem",
87 io_error,
88 })
89 .map_err(Into::into)
90 }
91}