1use std::ffi::CStr;
6use std::ffi::CString;
7
8use libc::EINVAL;
9use serde::Deserialize;
10use serde::Serialize;
11
12use crate::descriptor::AsRawDescriptor;
13use crate::descriptor::SafeDescriptor;
14use crate::Error;
15use crate::RawDescriptor;
16use crate::Result;
17
18#[derive(Debug, Deserialize, Serialize)]
20pub struct SharedMemory {
21 #[serde(with = "crate::with_as_descriptor")]
22 pub descriptor: SafeDescriptor,
23 pub size: u64,
24}
25
26pub(crate) trait PlatformSharedMemory {
27 fn new(debug_name: &CStr, size: u64) -> Result<SharedMemory>;
28 fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory>;
29}
30
31impl SharedMemory {
32 pub fn new<T: Into<Vec<u8>>>(debug_name: T, size: u64) -> Result<SharedMemory> {
37 let debug_name = CString::new(debug_name).map_err(|_| super::Error::new(EINVAL))?;
38 <SharedMemory as PlatformSharedMemory>::new(&debug_name, size)
39 }
40
41 pub fn size(&self) -> u64 {
46 self.size
47 }
48
49 pub fn from_safe_descriptor(descriptor: SafeDescriptor, size: u64) -> Result<SharedMemory> {
53 <SharedMemory as PlatformSharedMemory>::from_safe_descriptor(descriptor, size)
54 }
55
56 pub fn try_clone(&self) -> Result<SharedMemory> {
59 Ok(SharedMemory {
60 descriptor: self.descriptor.try_clone()?,
61 size: self.size,
62 })
63 }
64}
65
66impl AsRawDescriptor for SharedMemory {
70 fn as_raw_descriptor(&self) -> RawDescriptor {
71 self.descriptor.as_raw_descriptor()
72 }
73}
74
75impl From<SharedMemory> for SafeDescriptor {
76 fn from(sm: SharedMemory) -> SafeDescriptor {
77 sm.descriptor
78 }
79}
80
81impl audio_streams::shm_streams::SharedMemory for SharedMemory {
82 type Error = Error;
83
84 fn anon(size: u64) -> Result<Self> {
85 SharedMemory::new("shm_streams", size)
86 }
87
88 fn size(&self) -> u64 {
89 self.size()
90 }
91
92 #[cfg(any(target_os = "android", target_os = "linux"))]
93 fn as_raw_fd(&self) -> RawDescriptor {
94 self.as_raw_descriptor()
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn new_1024() {
104 let shm = SharedMemory::new("test", 1024).expect("failed to create shared memory");
105 assert_eq!(shm.size(), 1024);
106 }
107
108 #[test]
109 fn new_1028() {
110 let shm = SharedMemory::new("name", 1028).expect("failed to create shared memory");
111 assert_eq!(shm.size(), 1028);
112 }
113
114 #[test]
115 fn new_too_huge() {
116 SharedMemory::new("test", 0x8000_0000_0000_0000)
117 .expect_err("8 exabyte shared memory creation should fail");
118 }
119}