use std::{
borrow::{Borrow, BorrowMut},
marker::PhantomData,
os::fd::{AsRawFd, RawFd},
};
use crate::{
Pod,
maps::{
IterableMap, MapData, MapError, MapIter, MapKeys, check_kv_size, hash_map, sock::SockMapFd,
},
};
#[doc(alias = "BPF_MAP_TYPE_SOCKHASH")]
pub struct SockHash<T, K> {
pub(crate) inner: T,
_k: PhantomData<K>,
}
impl<T: Borrow<MapData>, K: Pod> SockHash<T, K> {
pub(crate) fn new(map: T) -> Result<Self, MapError> {
let data = map.borrow();
check_kv_size::<K, u32>(data)?;
Ok(Self {
inner: map,
_k: PhantomData,
})
}
pub fn get(&self, key: &K, flags: u64) -> Result<RawFd, MapError> {
hash_map::get(self.inner.borrow(), key, flags)
}
pub fn iter(&self) -> MapIter<'_, K, RawFd, Self> {
MapIter::new(self)
}
pub fn keys(&self) -> MapKeys<'_, K> {
MapKeys::new(self.inner.borrow())
}
pub fn fd(&self) -> &SockMapFd {
let fd = self.inner.borrow().fd();
unsafe { std::mem::transmute(fd) }
}
}
impl<'a, T: Borrow<MapData>, K: Pod> IntoIterator for &'a SockHash<T, K> {
type Item = Result<(K, RawFd), MapError>;
type IntoIter = MapIter<'a, K, RawFd, SockHash<T, K>>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<T: BorrowMut<MapData>, K: Pod> SockHash<T, K> {
pub fn insert<I: AsRawFd>(
&mut self,
key: impl Borrow<K>,
value: I,
flags: u64,
) -> Result<(), MapError> {
hash_map::insert(
self.inner.borrow_mut(),
key.borrow(),
&value.as_raw_fd(),
flags,
)
}
pub fn remove(&mut self, key: &K) -> Result<(), MapError> {
hash_map::remove(self.inner.borrow_mut(), key)
}
}
impl<T: Borrow<MapData>, K: Pod> IterableMap<K, RawFd> for SockHash<T, K> {
fn map(&self) -> &MapData {
self.inner.borrow()
}
fn get(&self, key: &K) -> Result<RawFd, MapError> {
Self::get(self, key, 0)
}
}