1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
#![forbid(unsafe_code)]
use core::cmp::Ordering;
use crate::toodee::*;
use crate::view::*;
use crate::ops::*;
/// Provides basic copying operations for `TooDee` structures.
pub trait CopyOps<T> : TooDeeOpsMut<T> {
/// Copies data from another slice into this area. The source slice's length
/// must match the size of this object's area. Data is copied row by row.
///
/// # Examples
///
/// ```
/// use toodee::{TooDee,TooDeeOps,TooDeeOpsMut,CopyOps};
/// let ascending = vec![0, 1, 2, 3, 4];
/// let mut toodee : TooDee<u32> = TooDee::new(10, 5);
/// toodee.view_mut((5, 1), (10, 2)).copy_from_slice(&ascending);
/// ```
fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
let cols = self.num_cols();
assert_eq!(cols * self.num_rows(), src.len());
for (d, s) in self.rows_mut().zip(src.chunks_exact(cols)) {
d.copy_from_slice(s)
}
}
/// Clones data from another slice into this area. The source slice's length
/// must match the size of this object's area. Data is cloned row by row.
///
/// # Examples
///
/// ```
/// use toodee::{TooDee,TooDeeOps,TooDeeOpsMut,CopyOps};
/// let ascending = vec![0, 1, 2, 3, 4];
/// let mut toodee : TooDee<u32> = TooDee::new(10, 5);
/// toodee.view_mut((5, 1), (10, 2)).clone_from_slice(&ascending);
/// ```
fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
let cols = self.num_cols();
assert_eq!(cols * self.num_rows(), src.len());
for (d, s) in self.rows_mut().zip(src.chunks_exact(cols)) {
d.clone_from_slice(s)
}
}
/// Copies data from another `TooDeeOps` object into this one. The source and
/// destination dimensions must match.
///
/// # Examples
///
/// ```
/// use toodee::{TooDee,TooDeeOps,TooDeeOpsMut,CopyOps};
/// let ascending = TooDee::from_vec(5, 1, vec![0, 1, 2, 3, 4]);
/// let mut toodee : TooDee<u32> = TooDee::new(10, 5);
/// toodee.view_mut((5, 1), (10, 2)).copy_from_toodee(&ascending);
/// ```
fn copy_from_toodee(&mut self, src: &impl TooDeeOps<T>) where T : Copy {
assert_eq!(self.size(), src.size());
// Data is copied row by row.
for (d, s) in self.rows_mut().zip(src.rows()) {
d.copy_from_slice(s);
}
}
/// Copies data from another `TooDeeOps` object into this one. The source and
/// destination dimensions must match.
///
/// # Examples
///
/// ```
/// use toodee::{TooDee,TooDeeOps,TooDeeOpsMut,CopyOps};
/// let ascending = TooDee::from_vec(5, 1, vec![0, 1, 2, 3, 4]);
/// let mut toodee : TooDee<u32> = TooDee::new(10, 5);
/// toodee.view_mut((5, 1), (10, 2)).clone_from_toodee(&ascending);
/// ```
fn clone_from_toodee(&mut self, src: &impl TooDeeOps<T>) where T : Clone {
assert_eq!(self.size(), src.size());
// Data is copied row by row.
for (d, s) in self.rows_mut().zip(src.rows()) {
d.clone_from_slice(s);
}
}
/// Copies the `src` area (top-left to bottom-right) to a destination area. `dest` specifies
/// the top-left position of destination area. The `src` area will be partially overwritten
/// if the regions overlap.
///
/// # Panics
///
/// Panics if:
/// - `src` dimensions are outside the array's bounds
/// - there's insufficient room to copy all of `src` to `dest`
///
/// # Examples
///
/// ```
/// use toodee::{TooDee,TooDeeOps,TooDeeOpsMut,CopyOps};
/// let mut toodee : TooDee<u32> = TooDee::new(10, 5);
/// toodee.view_mut((0, 0), (5, 1)).fill(42);
/// assert_eq!(toodee[(3,1)], 0);
/// toodee.copy_within(((0, 0), (5, 1)), (0, 1));
/// assert_eq!(toodee[(3,1)], 42);
/// ```
fn copy_within(&mut self, src: (Coordinate, Coordinate), dest: Coordinate)
where T : Copy {
let (top_left, bottom_right) = src;
assert!(top_left.0 <= bottom_right.0);
assert!(top_left.1 <= bottom_right.1);
let num_cols = self.num_cols();
let num_rows = self.num_rows();
assert!(bottom_right.0 <= num_cols);
assert!(bottom_right.1 <= num_rows);
let cols = bottom_right.0 - top_left.0;
let rows = bottom_right.1 - top_left.1;
assert!(dest.0 + cols <= num_cols);
assert!(dest.1 + rows <= num_rows);
// Ensure that we don't copy over src before copying it to dest.
match top_left.1.cmp(&dest.1) {
Ordering::Less => {
let row_offset = dest.1 - top_left.1;
for r in (top_left.1..bottom_right.1).rev() {
let (s, d) = self.row_pair_mut(r, r + row_offset);
d[dest.0..dest.0 + cols].copy_from_slice(&s[top_left.0..bottom_right.0]);
}
},
Ordering::Greater => {
let row_offset = top_left.1 - dest.1;
for r in top_left.1..bottom_right.1 {
let (s, d) = self.row_pair_mut(r, r - row_offset);
d[dest.0..dest.0 + cols].copy_from_slice(&s[top_left.0..bottom_right.0]);
}
},
Ordering::Equal => {
for r in top_left.1..bottom_right.1 {
let row_data = &mut self[r];
row_data.copy_within(top_left.0..bottom_right.0, dest.0);
}
},
}
}
}
impl<T> CopyOps<T> for TooDeeViewMut<'_, T> {}
impl<T> CopyOps<T> for TooDee<T> {
fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
self.data_mut().copy_from_slice(src);
}
fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
self.data_mut().clone_from_slice(src);
}
fn copy_from_toodee(&mut self, src: &impl TooDeeOps<T>) where T : Copy {
assert_eq!(self.size(), src.size());
let num_cols = self.num_cols();
let mut v = self.data_mut();
for r in src.rows() {
let (fst, snd) = v.split_at_mut(num_cols);
fst.copy_from_slice(r);
v = snd;
}
}
fn clone_from_toodee(&mut self, src: &impl TooDeeOps<T>) where T : Clone {
assert_eq!(self.size(), src.size());
let num_cols = self.num_cols();
let mut v = self.data_mut();
for r in src.rows() {
let (fst, snd) = v.split_at_mut(num_cols);
fst.clone_from_slice(r);
v = snd;
}
}
}