buffer_core/shm/
reader.rs1use std::fs::{self, OpenOptions};
2
3use core_types::{ErrorCode, ErrorDomain, RtError};
4
5use super::config::validate_cfg;
6use super::header::{HEADER_SIZE, read_header};
7use super::segment_io::{init_segment_files, io_to_err, map_ro, segment_path, slot_for};
8use super::{SharedMemoryBufferRef, SharedMemoryLease, SharedMemoryReader, ShmTransportConfig};
9
10impl SharedMemoryReader {
11 pub fn new(cfg: ShmTransportConfig) -> Result<Self, RtError> {
12 validate_cfg(&cfg)?;
13 fs::create_dir_all(&cfg.directory)
14 .map_err(|err| io_to_err("create shm directory failed", err))?;
15 init_segment_files(&cfg)?;
16 Ok(Self { cfg })
17 }
18
19 pub fn loan(&self, reference: SharedMemoryBufferRef) -> Result<SharedMemoryLease, RtError> {
20 if reference.len > self.cfg.segment_payload_bytes {
21 return Err(RtError::new(
22 ErrorCode::InvalidState,
23 ErrorDomain::Core,
24 false,
25 "invalid shared memory reference length",
26 ));
27 }
28
29 let slot = slot_for(reference.buffer_id, self.cfg.segment_count);
30 let segment_path = segment_path(&self.cfg, slot);
31 let file = OpenOptions::new()
32 .read(true)
33 .open(&segment_path)
34 .map_err(|err| io_to_err("open shm segment for read failed", err))?;
35 let mmap = map_ro(&file)?;
36
37 let (buf_id, len) = read_header(&mmap)?;
38 if buf_id != reference.buffer_id {
39 return Err(RtError::new(
40 ErrorCode::InvalidState,
41 ErrorDomain::Core,
42 false,
43 format!(
44 "stale shm slot content: expected buffer_id={} actual={}",
45 reference.buffer_id, buf_id
46 ),
47 ));
48 }
49
50 if len != reference.len {
51 return Err(RtError::new(
52 ErrorCode::InvalidState,
53 ErrorDomain::Core,
54 false,
55 format!(
56 "shm payload length mismatch: expected={} actual={}",
57 reference.len, len
58 ),
59 ));
60 }
61
62 let start = HEADER_SIZE + reference.offset;
63 let end = start + reference.len;
64 if end > HEADER_SIZE + self.cfg.segment_payload_bytes {
65 return Err(RtError::new(
66 ErrorCode::InvalidState,
67 ErrorDomain::Core,
68 false,
69 "shm reference range out of bounds",
70 ));
71 }
72
73 Ok(SharedMemoryLease {
74 mmap,
75 offset: start,
76 len: reference.len,
77 })
78 }
79}