#[macro_use]
extern crate cfg_if;
cfg_if! {
if #[cfg(target_os="windows")] {
mod win;
use win as os_impl;
} else if #[cfg(target_os="linux")] {
mod linux;
use linux as os_impl;
} else if #[cfg(target_os="macos")] {
mod macos;
use macos as os_impl;
} else {
compile_error!("This library isnt implemented for this platform...");
}
}
mod locking;
pub use locking::*;
use std::path::PathBuf;
use std::fs::{File};
use std::io::{Write, Read};
use std::fs::remove_file;
use std::slice;
type Result<T> = std::result::Result<T, Box<std::error::Error>>;
pub struct SharedMem<'a> {
meta: Option<os_impl::MemMetadata<'a>>,
owner: bool,
link_path: Option<PathBuf>,
real_path: Option<String>,
size: usize,
}
impl<'a> SharedMem<'a> {
pub fn create(new_link_path: PathBuf, lock_type: LockType, size: usize) -> Result<SharedMem<'a>> {
let mut cur_link;
if new_link_path.is_file() {
return Err(From::from("Cannot create SharedMem because file already exists"));
} else {
cur_link = File::create(&new_link_path)?;
}
let my_shmem: SharedMem = SharedMem {
meta: None,
owner: true,
link_path: Some(new_link_path),
real_path: None,
size: size,
};
let created_file = os_impl::create(my_shmem, lock_type)?;
if let Some(ref real_path) = created_file.real_path {
match cur_link.write(real_path.as_bytes()) {
Ok(write_sz) => if write_sz != real_path.as_bytes().len() {
return Err(From::from("Failed to write full contents info on disk"));
},
Err(_) => return Err(From::from("Failed to write info on disk")),
};
} else {
panic!("os_impl::create() returned succesfully but didnt update SharedMem::real_path() !");
}
Ok(created_file)
}
pub fn open(existing_link_path: PathBuf) -> Result<SharedMem<'a>> {
if !existing_link_path.is_file() {
return Err(From::from("Cannot open SharedMem because file doesnt exists"));
}
let mut my_shmem: SharedMem = SharedMem {
meta: None,
owner: false,
link_path: Some(existing_link_path.clone()),
real_path: None,
size: 0, };
{
let mut disk_file = File::open(&existing_link_path)?;
let mut file_contents: Vec<u8> = Vec::with_capacity(existing_link_path.to_string_lossy().len() + 5);
disk_file.read_to_end(&mut file_contents)?;
my_shmem.real_path = Some(String::from_utf8(file_contents)?);
}
os_impl::open(my_shmem)
}
pub fn create_raw(shmem_path: String, size: usize) -> Result<SharedMem<'a>> {
let my_shmem: SharedMem = SharedMem {
meta: None,
owner: true,
link_path: None, real_path: Some(shmem_path),
size: size,
};
Ok(os_impl::create(my_shmem, LockType::None)?)
}
pub fn open_raw(shmem_path: String) -> Result<SharedMem<'a>> {
let my_shmem: SharedMem = SharedMem {
meta: None,
owner: false,
link_path: None, real_path: Some(shmem_path),
size: 0, };
os_impl::open(my_shmem)
}
pub fn get_size(&self) -> &usize {
&self.size
}
pub fn get_link_path(&self) -> Option<&PathBuf> {
self.link_path.as_ref()
}
pub fn get_real_path(&self) -> Option<&String> {
self.real_path.as_ref()
}
}
impl<'a> Drop for SharedMem<'a> {
fn drop(&mut self) {
if self.owner {
if let Some(ref file_path) = self.link_path {
if file_path.is_file() {
match remove_file(file_path) {_=>{},};
}
}
}
if let Some(meta) = self.meta.take() {
drop(meta);
}
}
}
pub unsafe trait SharedMemCast {}
unsafe impl SharedMemCast for bool {}
unsafe impl SharedMemCast for char {}
unsafe impl SharedMemCast for str {}
unsafe impl SharedMemCast for i8 {}
unsafe impl SharedMemCast for i16 {}
unsafe impl SharedMemCast for i32 {}
unsafe impl SharedMemCast for u8 {}
unsafe impl SharedMemCast for i64 {}
unsafe impl SharedMemCast for u16 {}
unsafe impl SharedMemCast for u64 {}
unsafe impl SharedMemCast for isize {}
unsafe impl SharedMemCast for u32 {}
unsafe impl SharedMemCast for usize {}
unsafe impl SharedMemCast for f32 {}
unsafe impl SharedMemCast for f64 {}