Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add specific lease read and write errors #55

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 44 additions & 19 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ pub enum ClientError {
WentAway = 0xFFFF_FE03,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Count)]
pub enum LeaseReadErr {
Rc(NonZeroU32),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, we could probably make this more specific, but right now I'm not finding a convenient enumeraiton to point to.

BadLen(u32),
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Count)]
pub enum LeaseWriteErr {
Rc(NonZeroU32),
BadLen(u32),
Eof,
}

/// Marker trait indicating a simple error type is able to represent server
/// death.
///
Expand Down Expand Up @@ -592,7 +605,7 @@ impl<A: AttributeRead, T: Sized + Copy + FromBytes + AsBytes> Leased<A, [T]> {
&self,
range: Range<usize>,
dest: &mut [T],
) -> Result<(), ()> {
) -> Result<(), LeaseReadErr> {
let offset = core::mem::size_of::<T>()
.checked_mul(range.start)
.ok_or(())?;
Expand All @@ -607,8 +620,10 @@ impl<A: AttributeRead, T: Sized + Copy + FromBytes + AsBytes> Leased<A, [T]> {
dest.as_bytes_mut(),
);

if rc != 0 || len != expected_len {
Err(())
if let Some(v) = NonZeroU32::new(rc) {
Err(LeaseReadErr::Rc(v))
} else if len != expected_len {
Err(LeaseReadErr::BadLen(len))
} else {
Ok(())
}
Expand All @@ -625,11 +640,13 @@ impl<A: AttributeWrite, T: Sized + Copy + AsBytes> Leased<A, T> {
/// attributes and the time you call `write`, this will return `Err(())`.
/// Otherwise, it returns `Ok(())`. It's therefore safe to treat an `Err`
/// return as aborting the request.
pub fn write(&self, value: T) -> Result<(), ()> {
pub fn write(&self, value: T) -> Result<(), LeaseWriteErr> {
let (rc, len) =
sys_borrow_write(self.lender, self.index, 0, value.as_bytes());
if rc != 0 || len != core::mem::size_of::<T>() {
Err(())
if let Some(v) = NonZeroU32::new(rc) {
Err(LeaseWriteErr::Rc(v))
} else if len != core::mem::size_of::<T>() {
Err(LeaseWriteErr::BadLen(len))
} else {
Ok(())
}
Expand All @@ -649,12 +666,18 @@ impl<A: AttributeWrite, T: Sized + Copy + AsBytes> Leased<A, [T]> {
/// attributes and the time you call `write_at`, this will return `Err(())`.
/// Otherwise, it returns `Ok(())`. It's therefore safe to treat an `Err`
/// return as aborting the request.
pub fn write_at(&self, index: usize, value: T) -> Result<(), ()> {
pub fn write_at(
&self,
index: usize,
value: T,
) -> Result<(), LeaseWriteErr> {
let offset = core::mem::size_of::<T>().checked_mul(index).ok_or(())?;
let (rc, len) =
sys_borrow_write(self.lender, self.index, offset, value.as_bytes());
if rc != 0 || len != core::mem::size_of::<T>() {
Err(())
if let Some(v) = NonZeroU32::new(rc) {
Err(LeaseWriteErr::Rc(v))
} else if len != core::mem::size_of::<T>() {
Err(LeaseWriteErr::BadLen(len))
} else {
Ok(())
}
Expand All @@ -674,7 +697,7 @@ impl<A: AttributeWrite, T: Sized + Copy + AsBytes> Leased<A, [T]> {
&self,
range: Range<usize>,
src: &[T],
) -> Result<(), ()> {
) -> Result<(), LeaseReadErr> {
let offset = core::mem::size_of::<T>()
.checked_mul(range.start)
.ok_or(())?;
Expand All @@ -685,8 +708,10 @@ impl<A: AttributeWrite, T: Sized + Copy + AsBytes> Leased<A, [T]> {
let (rc, len) =
sys_borrow_write(self.lender, self.index, offset, src.as_bytes());

if rc != 0 || len != expected_len {
Err(())
if let Some(v) = NonZeroU32::new(rc) {
Err(LeaseReadErr::Rc(v))
} else if len != expected_len {
Err(LeaseReadErr::BadLen(len))
} else {
Ok(())
}
Expand Down Expand Up @@ -798,7 +823,7 @@ impl<A: AttributeRead, const N: usize> LeaseBufReader<A, N> {
self.pos == self.lease.len() && self.buf_left == 0
}

pub fn refill(&mut self) -> Result<(), ()> {
pub fn refill(&mut self) -> Result<(), LeaseReadErr> {
if self.buf_left == 0 {
if self.pos == self.lease.len() {
// We've hit the end.
Expand Down Expand Up @@ -861,9 +886,9 @@ impl<A: AttributeWrite, const N: usize> LeaseBufWriter<A, N> {
self.pos + self.buf_valid == self.lease.len()
}

pub fn write(&mut self, byte: u8) -> Result<(), ()> {
pub fn write(&mut self, byte: u8) -> Result<(), LeaseWriteErr> {
if self.is_eof() {
return Err(());
return Err(LeaseWriteErr::Eof);
}
self.buf[self.buf_valid] = byte;
self.buf_valid += 1;
Expand All @@ -875,7 +900,7 @@ impl<A: AttributeWrite, const N: usize> LeaseBufWriter<A, N> {
Ok(())
}

fn flush(&mut self) -> Result<(), ()> {
fn flush(&mut self) -> Result<(), LeaseWriteErr> {
// Try to flush. If this fails, the client has gone away, so we fail
// too. However, we zero `buf_valid` either way to maintain our
// invariant on that field. Since client errors never recover, losing
Expand Down Expand Up @@ -942,11 +967,11 @@ pub trait BufWriter<'a> {

/// Writes a single byte to the buffer, incrementing the internal position
/// and returning `Err(())` if we've reached the end.
fn write(&mut self, v: u8) -> Result<(), ()>;
fn write(&mut self, v: u8) -> Result<(), LeaseWriteErr>;
}

impl<'a, const BUFSIZ: usize> BufWriter<'a> for LeaseBufWriter<W, BUFSIZ> {
fn write(&mut self, v: u8) -> Result<(), ()> {
fn write(&mut self, v: u8) -> Result<(), LeaseWriteErr> {
LeaseBufWriter::write(self, v)
}
fn remaining_size(&self) -> usize {
Expand All @@ -955,7 +980,7 @@ impl<'a, const BUFSIZ: usize> BufWriter<'a> for LeaseBufWriter<W, BUFSIZ> {
}

impl<'a> BufWriter<'a> for &'a mut [u8] {
fn write(&mut self, v: u8) -> Result<(), ()> {
fn write(&mut self, v: u8) -> Result<(), LeaseWriteErr> {
// We have to get a little sneaky to work around variance checks,
// because self is a &'b &'a mut [u8]
let real = core::mem::replace(self, &mut []);
Expand Down