use super::{Ioctl, IoctlOutput, Opcode};
use crate::backend::c;
use crate::io::Result;
use core::ptr::addr_of_mut;
use core::{fmt, mem};
pub struct NoArg<const OPCODE: Opcode> {}
impl<const OPCODE: Opcode> fmt::Debug for NoArg<OPCODE> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("NoArg").field(&OPCODE).finish()
}
}
impl<const OPCODE: Opcode> NoArg<OPCODE> {
#[inline]
pub const unsafe fn new() -> Self {
Self {}
}
}
unsafe impl<const OPCODE: Opcode> Ioctl for NoArg<OPCODE> {
type Output = ();
const IS_MUTATING: bool = false;
fn opcode(&self) -> self::Opcode {
OPCODE
}
fn as_ptr(&mut self) -> *mut c::c_void {
core::ptr::null_mut()
}
unsafe fn output_from_ptr(_: IoctlOutput, _: *mut c::c_void) -> Result<Self::Output> {
Ok(())
}
}
pub struct Getter<const OPCODE: Opcode, Output> {
output: mem::MaybeUninit<Output>,
}
impl<const OPCODE: Opcode, Output> fmt::Debug for Getter<OPCODE, Output> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Getter").field(&OPCODE).finish()
}
}
impl<const OPCODE: Opcode, Output> Getter<OPCODE, Output> {
#[inline]
pub const unsafe fn new() -> Self {
Self {
output: mem::MaybeUninit::uninit(),
}
}
}
unsafe impl<const OPCODE: Opcode, Output> Ioctl for Getter<OPCODE, Output> {
type Output = Output;
const IS_MUTATING: bool = true;
fn opcode(&self) -> self::Opcode {
OPCODE
}
fn as_ptr(&mut self) -> *mut c::c_void {
self.output.as_mut_ptr().cast()
}
unsafe fn output_from_ptr(_: IoctlOutput, ptr: *mut c::c_void) -> Result<Self::Output> {
Ok(ptr.cast::<Output>().read())
}
}
pub struct Setter<const OPCODE: Opcode, Input> {
input: Input,
}
impl<const OPCODE: Opcode, Input: fmt::Debug> fmt::Debug for Setter<OPCODE, Input> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("Setter")
.field(&OPCODE)
.field(&self.input)
.finish()
}
}
impl<const OPCODE: Opcode, Input> Setter<OPCODE, Input> {
#[inline]
pub const unsafe fn new(input: Input) -> Self {
Self { input }
}
}
unsafe impl<const OPCODE: Opcode, Input> Ioctl for Setter<OPCODE, Input> {
type Output = ();
const IS_MUTATING: bool = false;
fn opcode(&self) -> self::Opcode {
OPCODE
}
fn as_ptr(&mut self) -> *mut c::c_void {
addr_of_mut!(self.input).cast::<c::c_void>()
}
unsafe fn output_from_ptr(_: IoctlOutput, _: *mut c::c_void) -> Result<Self::Output> {
Ok(())
}
}
pub struct Updater<'a, const OPCODE: Opcode, Value> {
value: &'a mut Value,
}
impl<'a, const OPCODE: Opcode, Value> Updater<'a, OPCODE, Value> {
#[inline]
pub unsafe fn new(value: &'a mut Value) -> Self {
Self { value }
}
}
unsafe impl<'a, const OPCODE: Opcode, T> Ioctl for Updater<'a, OPCODE, T> {
type Output = ();
const IS_MUTATING: bool = true;
fn opcode(&self) -> self::Opcode {
OPCODE
}
fn as_ptr(&mut self) -> *mut c::c_void {
(self.value as *mut T).cast()
}
unsafe fn output_from_ptr(_output: IoctlOutput, _ptr: *mut c::c_void) -> Result<()> {
Ok(())
}
}
pub struct IntegerSetter<const OPCODE: Opcode> {
value: *mut c::c_void,
}
impl<const OPCODE: Opcode> IntegerSetter<OPCODE> {
#[inline]
pub const unsafe fn new_usize(value: usize) -> Self {
Self { value: value as _ }
}
#[inline]
pub const unsafe fn new_pointer(value: *mut c::c_void) -> Self {
Self { value }
}
}
unsafe impl<const OPCODE: Opcode> Ioctl for IntegerSetter<OPCODE> {
type Output = ();
const IS_MUTATING: bool = false;
fn opcode(&self) -> self::Opcode {
OPCODE
}
fn as_ptr(&mut self) -> *mut c::c_void {
self.value
}
unsafe fn output_from_ptr(
_out: IoctlOutput,
_extract_output: *mut c::c_void,
) -> Result<Self::Output> {
Ok(())
}
}