pub(crate) struct RefMatrix<'a> {
inner: &'a [u8],
len: usize,
}
impl<'a> RefMatrix<'a> {
fn new(from: &'a [u8]) -> Self {
let len = from
.iter()
.position(|ch| *ch == b'\n')
.expect("Input had no \\n");
Self { inner: from, len }
}
fn get(&self, x: usize, y: usize) -> u8 {
self.inner[y * (self.len + 1) + x]
}
}
pub(crate) struct RefMatrixMut<'a> {
inner: &'a mut [u8],
len: usize,
}
impl<'a> RefMatrixMut<'a> {
fn new(from: &'a mut [u8]) -> Self {
let len = from
.iter()
.position(|ch| *ch == b'\n')
.expect("Input had no \\n");
Self { inner: from, len }
}
fn get(&self, x: usize, y: usize) -> u8 {
self.inner[y * (self.len + 1) + x]
}
pub(crate) fn get_mut(&mut self, x: usize, y: usize) -> &mut u8 {
&mut self.inner[y * (self.len) + x]
}
pub(crate) fn set(&mut self, x: usize, y: usize, value: u8) {
self.inner[y * (self.len) + x] = value;
}
}
pub(crate) struct OwnedMatrix {
inner: Vec<u8>,
len: usize,
}
impl OwnedMatrix {
pub(crate) fn new(from: &[u8]) -> Self {
let len = from
.into_iter()
.position(|ch| *ch == b'\n')
.expect("Input had no \\n");
let number_of_newlines = from.len() / (len + 1);
let mut inner = Vec::with_capacity(from.len() - number_of_newlines);
for i in 0..number_of_newlines + 1 {
inner.extend_from_slice(&from[i * (len + 1)..(i + 1) * (len + 1) - 1]);
}
Self { inner, len }
}
pub(crate) fn get(&self, x: usize, y: usize) -> u8 {
self.inner[y * (self.len) + x]
}
pub(crate) fn get_mut(&mut self, x: usize, y: usize) -> &mut u8 {
&mut self.inner[y * (self.len) + x]
}
pub(crate) fn set(&mut self, x: usize, y: usize, value: u8) {
self.inner[y * (self.len) + x] = value;
}
}
#How to reduce code duplication?
23 messages · Page 1 of 1 (latest)
I don't like the whole
pub(crate) fn get(&self, x: usize, y: usize) -> u8 {
self.inner[y * (self.len) + x]
}
pub(crate) fn get_mut(&mut self, x: usize, y: usize) -> &mut u8 {
&mut self.inner[y * (self.len) + x]
}
pub(crate) fn set(&mut self, x: usize, y: usize, value: u8) {
self.inner[y * (self.len) + x] = value;
}
}
thing repeated 3 times.
I also don't like having 3 structs here
I'd much rather have 2
You could make a generic Matrix<T> where T: Deref<[u8]>
(I think it's Deref, but I could be wrong)
What do I do with it?
I can't put it in the OwnedMatrix for example
I'm not sure what you mean
Well, perhaps not a generic struct, because the new impls may have to be different, but you could probably make a trait
Just have fn as_slice[_mut](&[mut ]self) -> &[mut ][u8]; so you can use default impls for the methods
What do I do with the trait? I can't have a blanket implementation because I can't access self. inner and self.len :/
I've never seen that syntax :o
You can have a method to return a slice that each struct implements, and the same for self.len
Oh that's smart
It's not a thing lol, just demonstrating you could have both mutable and immutable versions of the methods
Note that, since RefMatrix doesn't have the same mutability, it won't be able to implement the trait; to work around this, you could instead use a macro like impl_matrix!(RefMatrix<'a>, immut); impl_matrix!(OwnedMatrix, mut);
how can I make a trait depend on another trait? Make MatrixMut require Matrix to be implemented
trait MatrixMut: Matrix
thanks
Here's your example implemented with traits. It still has some code duplication, but now it's much more readable and extensible
A browser interface to the Rust compiler to experiment with the language
Thank you!