There are two places you can write the body of a trait method:
- inside the trait itself, as a provided method
- inside an
impl
block.
If a method is not provided, it is required, which means all implementors have to write their own body in the appropriate impl
block.
Provided methods can only use properties that are common to all the implementors of the trait, which means you can only use other trait methods or methods of supertraits (like : Debug
). But methods in an impl
block may use properties that are specific to the type implementing the trait. You want to use something specific to [u8]
-- indexing via [..]
-- so xor
should be a required method:
pub trait Xor {
fn xor(&self, key_bytes: &[u8]) -> &[u8];
}
impl Xor for [u8] {
fn xor(&self, key_bytes: &[u8]) -> &[u8] {
for n in &self[..] {
dbg!(n);
}
unimplemented!()
}
}
Provided methods are usually for conveniences that only use other methods of the same trait, like most of the methods on Iterator
(see Why don't we implement all the functions from Iterator to implement an iterator?).
is it possible to implement the trait for several kind of types [without writing multiple impl
blocks]?
Yes, if there is a trait that exposes the functionality you would use to write Xor
, you may use that trait to write a generic impl
. For example, String
and [u8]
both implement AsRef<[u8]>
, so you can use that to write an impl
that applies to both:
impl<T: ?Sized + AsRef<[u8]>> Xor for T {
fn xor(&self, key_bytes: &[u8]) -> &[u8] {
for n in &self.as_ref()[..] {
dbg!(n);
}
unimplemented!()
}
}
Playground link.
See also