use std::ffi::CStr;
use std::ffi::CString;
use libc::EINVAL;
use serde::Deserialize;
use serde::Serialize;
use crate::descriptor::AsRawDescriptor;
use crate::descriptor::SafeDescriptor;
use crate::Error;
use crate::RawDescriptor;
use crate::Result;
#[derive(Debug, Deserialize, Serialize)]
pub struct SharedMemory {
#[serde(with = "crate::with_as_descriptor")]
pub descriptor: SafeDescriptor,
pub size: u64,
}
pub(crate) trait PlatformSharedMemory {
fn new(debug_name: &CStr, size: u64) -> Result<SharedMemory>;
fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>;
}
impl SharedMemory {
pub fn new<T: Into<Vec<u8>>>(debug_name: T, size: u64) -> Result<SharedMemory> {
let debug_name = CString::new(debug_name).map_err(|_| super::Error::new(EINVAL))?;
<SharedMemory as PlatformSharedMemory>::new(&debug_name, size)
}
pub fn size(&self) -> u64 {
self.size
}
pub fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory> {
<SharedMemory as PlatformSharedMemory>::from_safe_descriptor(descriptor, size)
}
pub fn try_clone(&self) -> Result<SharedMemory> {
Ok(SharedMemory {
descriptor: self.descriptor.try_clone()?,
size: self.size,
})
}
}
impl AsRawDescriptor for SharedMemory {
fn as_raw_descriptor(&self) -> RawDescriptor {
self.descriptor.as_raw_descriptor()
}
}
impl From<SharedMemory> for SafeDescriptor {
fn from(sm: SharedMemory) -> SafeDescriptor {
sm.descriptor
}
}
impl audio_streams::shm_streams::SharedMemory for SharedMemory {
type Error = Error;
fn anon(size: u64) -> Result<Self> {
SharedMemory::new("shm_streams", size)
}
fn size(&self) -> u64 {
self.size()
}
#[cfg(any(target_os = "android", target_os = "linux"))]
fn as_raw_fd(&self) -> RawDescriptor {
self.as_raw_descriptor()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_1024() {
let shm = SharedMemory::new("test", 1024).expect("failed to create shared memory");
assert_eq!(shm.size(), 1024);
}
#[test]
fn new_1028() {
let shm = SharedMemory::new("name", 1028).expect("failed to create shared memory");
assert_eq!(shm.size(), 1028);
}
#[test]
fn new_too_huge() {
SharedMemory::new("test", 0x8000_0000_0000_0000)
.expect_err("8 exabyte shared memory creation should fail");
}
}