reverie-syscalls/src/raw.rs (163 lines of code) (raw):

/* * Copyright (c) Facebook, Inc. and its affiliates. * * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. */ use nix::{ fcntl::{AtFlags, OFlag}, sched::CloneFlags, sys::{ epoll::EpollCreateFlags, eventfd::EfdFlags, inotify::InitFlags, mman::{MapFlags, ProtFlags}, signalfd::SfdFlags, socket::SockFlag, stat::Mode, timerfd::TimerFlags, wait::WaitPidFlag, }, unistd::Pid, }; use crate::{Addr, AddrMut, Errno}; /// Trait representing a raw value. Note that the assertion /// `assert_eq!(T::from_raw(x).into_raw(), x)` should hold true for every /// possible value of `T` and `x`. In other words, there should be no loss of /// information and conversions should never fail. This ensures that adding type /// information to a value will always be forward compatible. /// /// This trait is very similar to `From<u64>` and `Into<u64>`. Instead of reusing /// those existing traits, this separate trait is necessary such that it can be /// implemented for foreign types. pub trait FromToRaw: Sized { /// Converts a raw value into this type. fn from_raw(value: u64) -> Self; /// Converts this type into a raw value. fn into_raw(self) -> u64; } impl FromToRaw for u32 { fn from_raw(raw: u64) -> Self { raw as Self } fn into_raw(self) -> u64 { self as u64 } } impl FromToRaw for i32 { fn from_raw(raw: u64) -> Self { raw as Self } fn into_raw(self) -> u64 { self as u64 } } impl FromToRaw for u64 { fn from_raw(raw: u64) -> Self { raw } fn into_raw(self) -> u64 { self } } impl FromToRaw for usize { fn from_raw(raw: u64) -> Self { raw as Self } fn into_raw(self) -> u64 { self as u64 } } impl FromToRaw for i64 { fn from_raw(raw: u64) -> Self { raw as Self } fn into_raw(self) -> u64 { self as u64 } } impl<'a, T> FromToRaw for Option<Addr<'a, T>> { fn from_raw(raw: u64) -> Self { Addr::from_raw(raw as usize) } fn into_raw(self) -> u64 { self.map_or(0, |addr| addr.as_raw() as u64) } } impl<'a, T> FromToRaw for Option<AddrMut<'a, T>> { fn from_raw(raw: u64) -> Self { AddrMut::from_raw(raw as usize) } fn into_raw(self) -> u64 { self.map_or(0, |addr| addr.as_raw() as u64) } } macro_rules! impl_raw_bits { ($t:ty : $inner:ty) => { impl $crate::FromToRaw for $t { fn from_raw(raw: u64) -> Self { unsafe { Self::from_bits_unchecked(raw as $inner) } } fn into_raw(self) -> u64 { self.bits() as u64 } } }; ($t:ty) => { impl_raw_bits!($t: i32); }; } impl_raw_bits!(AtFlags); impl_raw_bits!(OFlag); impl_raw_bits!(CloneFlags); impl_raw_bits!(Mode: libc::mode_t); impl_raw_bits!(WaitPidFlag); impl_raw_bits!(MapFlags); impl_raw_bits!(ProtFlags); impl_raw_bits!(EpollCreateFlags); impl_raw_bits!(EfdFlags); impl_raw_bits!(InitFlags); impl_raw_bits!(SockFlag); impl_raw_bits!(SfdFlags); impl_raw_bits!(TimerFlags); impl FromToRaw for Option<Mode> { fn from_raw(raw: u64) -> Self { if raw == 0 { None } else { Some(Mode::from_raw(raw)) } } fn into_raw(self) -> u64 { match self { None => 0, Some(mode) => mode.into_raw(), } } } impl FromToRaw for Pid { fn from_raw(raw: u64) -> Self { Pid::from_raw(raw as i32) } fn into_raw(self) -> u64 { self.as_raw() as u64 } } impl<T> FromToRaw for Result<T, Errno> where T: FromToRaw, { fn from_raw(raw: u64) -> Self { Errno::from_ret(raw as i64).map(|x| T::from_raw(x as u64)) } fn into_raw(self) -> u64 { match self { Ok(x) => x.into_raw(), Err(err) => -err.into_raw() as u64, } } } #[cfg(test)] mod test { use super::*; use nix::unistd::Pid; #[test] fn test_results() { assert_eq!( Result::<Pid, Errno>::from_raw(-2i64 as u64), Err(Errno::ENOENT) ); assert_eq!(Result::<Pid, Errno>::from_raw(42), Ok(Pid::from_raw(42))); } }