Change pass to NonNull + docs on it
This commit is contained in:
parent
7785a8310f
commit
407ce3bae4
48
src/pass.rs
48
src/pass.rs
@ -1,33 +1,51 @@
|
||||
//! Interfaces for passing stuff between the kernel and the userspace
|
||||
// TODO
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use core::ptr::NonNull;
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
// TODO use NonNull instead
|
||||
pub trait Placer {
|
||||
fn place_ref<T: Place>(&mut self, r: &T) -> Result<*const T::Output, Error>;
|
||||
fn place_slice<T: Place>(&mut self, r: &[T]) -> Result<*const [T::Output], Error>;
|
||||
/// Interface for a "writer", producing objects "owned" by the userspace.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The trait is marked unsafe as it is the implementor's concern that the produced pointers can
|
||||
/// actually hold the requested values and are properly aligned for that.
|
||||
pub unsafe trait Placer {
|
||||
/// Converts a kernel-space reference into a pointer that can be safely dereferenced in
|
||||
/// userspace
|
||||
fn place_ref<T: Place>(&mut self, r: &T) -> Result<NonNull<T::Output>, Error>;
|
||||
/// Converts a kernel-space slice reference into a slice pointer, elements of which are placed
|
||||
/// in safely-accessible memory by userspace
|
||||
fn place_slice<T: Place>(&mut self, r: &[T]) -> Result<NonNull<[T::Output]>, Error>;
|
||||
}
|
||||
|
||||
pub trait Place {
|
||||
/// Interface for "transferring ownership" of an object to userspace.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The trait is marked unsafe because it may produce arbitrary pointer, so it's the implementor's
|
||||
/// concern that they are actually correct.
|
||||
pub unsafe trait Place {
|
||||
/// Conversion result type, must be safely accessible from userspace
|
||||
type Output: 'static;
|
||||
|
||||
/// Creates a userspace-reachable variant of the internal value
|
||||
fn place<P: Placer>(&self, placer: &mut P) -> Result<Self::Output, Error>;
|
||||
|
||||
/// Converts the internal value using [Place::place] and returns a safe userspace reference
|
||||
fn place_ref<P: Placer>(&self, placer: &mut P) -> Result<&'static Self::Output, Error>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let ptr = placer.place_ref(self)?;
|
||||
unsafe { Ok(&*ptr) }
|
||||
unsafe { Ok(ptr.as_ref()) }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_primitive {
|
||||
($($ty:ty),+) => {
|
||||
$(
|
||||
impl $crate::pass::Place for $ty {
|
||||
unsafe impl $crate::pass::Place for $ty {
|
||||
type Output = $ty;
|
||||
|
||||
fn place<P: $crate::pass::Placer>(&self, _placer: &mut P) -> Result<$ty, Error> {
|
||||
@ -40,25 +58,27 @@ macro_rules! impl_primitive {
|
||||
|
||||
impl_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, bool, char);
|
||||
|
||||
impl<'s> Place for &'s str {
|
||||
unsafe impl<'s> Place for &'s str {
|
||||
type Output = &'static str;
|
||||
|
||||
fn place<P: Placer>(&self, placer: &mut P) -> Result<Self::Output, Error> {
|
||||
let data = placer.place_slice(self.as_bytes())?;
|
||||
// Safety: safe, object passed in was already a proper &str
|
||||
Ok(unsafe { core::str::from_utf8_unchecked(data.as_ref().unwrap()) })
|
||||
Ok(unsafe { core::str::from_utf8_unchecked(data.as_ref()) })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Place> Place for [T] {
|
||||
unsafe impl<T: Place> Place for [T] {
|
||||
type Output = &'static [T::Output];
|
||||
|
||||
fn place<P: Placer>(&self, placer: &mut P) -> Result<Self::Output, Error> {
|
||||
let data = placer.place_slice(self)?;
|
||||
Ok(unsafe { data.as_ref().unwrap() })
|
||||
Ok(unsafe { data.as_ref() })
|
||||
}
|
||||
}
|
||||
|
||||
/// Automatically implements the [Place] interface for a struct, properly handling any nested
|
||||
/// references
|
||||
#[macro_export]
|
||||
macro_rules! impl_place_lifetime {
|
||||
(
|
||||
@ -78,7 +98,7 @@ macro_rules! impl_place_lifetime {
|
||||
),*
|
||||
}
|
||||
|
||||
impl<$struct_lifetime> $crate::pass::Place for $struct_name<$struct_lifetime> {
|
||||
unsafe impl<$struct_lifetime> $crate::pass::Place for $struct_name<$struct_lifetime> {
|
||||
type Output = $struct_name<'static>;
|
||||
|
||||
fn place<P: $crate::pass::Placer>(&self, placer: &mut P)
|
||||
|
Loading…
x
Reference in New Issue
Block a user