Code
Playground (Stable Rust 1.45.0, 2018 edition) No external crates needed for example.
type Error = Box<dyn std::error::Error>;
type Result<R=()> = std::result::Result<R, Error>;
struct Arena;
pub trait AsSized<'a> {
type AsSized: Sized + 'a;
}
impl<'a, T: Sized + 'a> AsSized<'a> for T {
type AsSized = Self;
}
impl<'a, T: AsSized<'a>> AsSized<'a> for [T] {
type AsSized = &'a [T::AsSized];
}
pub trait Format<T>: Send + Sync
where T: ?Sized
{
fn get_bytes<'a>(&self, value: &'a T, arena: &'a Arena) -> Result<&'a [u8]>;
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<T::AsSized>
where T: AsSized<'a>;
}
struct RawBytes;
impl Format<[u8]> for RawBytes
where [u8]: for<'a> AsSized<'a, AsSized=&'a [u8]>
{
fn get_bytes<'a>(&self, value: &'a [u8], _arena: &'a Arena) -> Result<&'a [u8]> {
Ok(value)
}
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<<[u8] as AsSized<'a>>::AsSized> {
Ok(bytes)
}
}
Issue
I'm getting a compiler error on the impl of get_value
for RawBytes
:
error[E0195]: lifetime parameters or bounds on method `get_value` do not match the trait declaration
I don't understand what the problem is. It seems like the lifetime specification is the same between both definitions. How do I write the impl of get_value
for RawBytes
so that it works?
I would think that since u8: Sized
then <u8 as AsSized<'a>>::AsSized = u8
and then <[u8] as AsSized<'a>>::AsSized = &'a [u8]
but it seems like that isn't the case?
Background
Format
takes an arena based allocator and converts a slice of bytes to and from a complex type. I plan to write an adapter for various Serde formats. RawBytes
is a trivial implementaiton of Format
for a slice of bytes that just returns the original slice.
Both methods of Format
are allowed to return a value that borrows from the input value. The format itself may be shared between threads, so the lifetime of self is unrelated to the returned value.
The purpose of AsSized
is to allow dynamically sized types like str
and [u8]
to be used directly, but since dynamically sized types can't be returned directly, AsSized
provides a sized equivalent for any type; dynamically sized types return a reference to the DST instead (borrowed from the arena). Sized types like u8
that can be returned directly have an AsSized
type of self
Also tried
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<'a [u8]>
I tried simplifying the impl's get_value
to just name the slice directly; rust then says that the impl for get_value
is missing entirely.
fn get_value<'a>(&self, bytes: &'a [u8], arena: &'a Arena) -> Result<&'a [<u8 as AsSized<'a>>::AsSized]>
This give the same "lifetime parameters... do not match" error.