The following is the test code:
pub fn reverse_complement_seq_u8<T>(seq: T, len: usize) -> Vec<u8>
where T: std::ops::Index<usize, Output = u8>
{
(0..len).rev().map(|i| match seq[i] {
65 | 97 => 84, // 'A' | 'a' => 'T'
84 | 116 => 65, // 'T' | 't' => 'A'
71 | 103 => 67, // 'G' | 'g' => 'C'
67 | 99 => 71, // 'C' | 'c' => 'G'
n => n,
}
).collect()
}
fn main() {
let seqs = "ACGATGCTACGA".as_bytes();//generated by another function
let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
println!("{:?}", revcom_seq);
}
Because call seqs.to_owend() is expensive, so I just want to pass its reference to reverse_complement_seq_u8, however this cause the following errors:
error[E0277]: the type `&[u8]` cannot be indexed by `usize`
--> src/main.rs:17:48
|
17 | let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
| ------------------------- ^^^^ `&[u8]` cannot be indexed by `usize`
| |
| required by a bound introduced by this call
|
= help: the trait `Index<usize>` is not implemented for `&[u8]`
= help: the following other types implement trait `Index<Idx>`:
[T; N]
[T]
note: required by a bound in `reverse_complement_seq_u8`
The problem is that while the slice itself [u8] can be indexed, a reference to the slice &[u8] can't. Most of the time indexing a slice reference works because Rust automatically dereferences as needed, but when using generics you need to be more strict in what you tell the compiler.
One possible fix is to use seq: &T in the arguments so that T will be [u8] which can be indexed. This requires an extra + ?Sized bound, otherwise the compiler adds an implicit Sized bound which slices don't implement:
pub fn reverse_complement_seq_u8<T>(seq: &T, len: usize) -> Vec<u8>
where
T: std::ops::Index<usize, Output = u8> + ?Sized,
{
(0..len)
.rev()
.map(|i| match seq[i] {
65 | 97 => 84, // 'A' | 'a' => 'T'
84 | 116 => 65, // 'T' | 't' => 'A'
71 | 103 => 67, // 'G' | 'g' => 'C'
67 | 99 => 71, // 'C' | 'c' => 'G'
n => n,
})
.collect()
}
fn main() {
let seqs = "ACGATGCTACGA".as_bytes(); //generated by another function
let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
println!("{:?}", revcom_seq);
}
Playground
Another option that will also work with boxed slices is to specify that T must deref to some indexable type:
use std::ops::Deref;
pub fn reverse_complement_seq_u8<T, U>(seq: T, len: usize) -> Vec<u8>
where
T: Deref<Target = U>,
U: std::ops::Index<usize, Output = u8> + ?Sized,
{
(0..len)
.rev()
.map(|i| match seq[i] {
65 | 97 => 84, // 'A' | 'a' => 'T'
84 | 116 => 65, // 'T' | 't' => 'A'
71 | 103 => 67, // 'G' | 'g' => 'C'
67 | 99 => 71, // 'C' | 'c' => 'G'
n => n,
})
.collect()
}
fn main() {
let seqs = "ACGATGCTACGA".as_bytes(); //generated by another function
let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
println!("{:?}", revcom_seq);
}
Playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With