I have the following thing that I'm searching a nice abstraction for: in leveldb (GitHub - skade/leveldb), keys handled as ptr+length (slice). But they may represent complex data, e.g. encoding a key and it's type.
Previously, I used a hand-rolled trait for that:
/// this is very old-school
pub trait Key {
fn from_u8(key: &[u8]) -> Self;
fn as_slice<T, F: Fn(&[u8]) -> T>(&self, f: F) -> T;
}
I now try to express it through convert:
pub trait Key<'a> : From<&'a [u8]> + AsRef<[u8]>
Now, I have the problem of a very unwieldy lifetime. Is there any way to avoid this?
Preferably, easy implementations for all integer types would be great, which isn't possible with From, as integer types are defined in a another crate.
I think you want for<'a>. But take my solution with a grain of salt, this is the first time I have used for<'a>, I've seen it quite a few times though.
Level 2: From and AsRef are implemented in libcore and some of the types I'd like to allow as keys as well. So implementing From<&'a [u8]> is not possible for i32.
Problem is: I am unable to find a clean way around this. I tried implementing my own From and AsRef traits that would be automatically implemented if there is an existing implementation, but this doesn't seem to work:
src/lib.rs:12:1: 17:2 error: conflicting implementations for trait `From` [E0119]
src/lib.rs:12 impl<T, X> From<T> for X where X: convert::From<T> {
src/lib.rs:13 #[inline]
src/lib.rs:14 fn from(input: T) -> Self {
src/lib.rs:15 convert::From::from(input)
src/lib.rs:16 }
src/lib.rs:17 }
src/lib.rs:19:1: 24:2 note: note conflicting implementation here
src/lib.rs:19 impl<'a> From<&'a [u8]> for &'a [u8] {
src/lib.rs:20 #[inline]
src/lib.rs:21 fn from(input: &'a [u8]) -> &'a [u8] {
src/lib.rs:22 input
src/lib.rs:23 }
src/lib.rs:24 }
src/lib.rs:35:1: 35:30 error: the trait `for<'a> core::convert::From<&'a [u8]>` is not implemented for the type `&'a [u8]` [E0277]
This is interesting, as &[u8] does not implement From<&a [u8]>, if I remove my own implementation:
src/lib.rs:35:1: 35:30 error: the trait `for<'a> core::convert::From<&'a [u8]>` is not implemented for the type `&'a [u8]` [E0277]
src/lib.rs:35 impl<'a> Key for &'a [u8] { }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Which it should, as:
// From (and thus Into) is reflexive
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> From<T> for T {
fn from(t: T) -> T { t }
}
Logically Key should have a lifetime for whatever it references, in addition, implementing the From for all lifetimes of a slice seems tricky, maybe its possible, but it doesn't seem to be a default impl in std::convert. Here is one way that it works for slice. Though it may not be exactly what you want, its a way that works given my above qualifying statements