Skip to content

Commit c97abc5

Browse files
committed
add and refactor abstractions
1 parent 2f83885 commit c97abc5

1 file changed

Lines changed: 77 additions & 55 deletions

File tree

‎src/lib.rs‎

Lines changed: 77 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,29 @@ impl Pattern {
6464
}
6565
}
6666

67+
/// Returns a pattern based on a boolean slice
68+
///
69+
/// # Arguments
70+
///
71+
/// * `slice` - A boolean slice holding the initial pattern
72+
///
73+
/// # Examples
74+
///
75+
/// ```
76+
/// use rhythms::Pattern;
77+
/// let pattern = Pattern::from_slice(&[false, false, false, true]);
78+
/// assert_eq!([false, false, false, true], pattern.as_slice());
79+
/// ```
80+
pub fn from_slice(slice: &[bool]) -> Self {
81+
Self {
82+
steps: SmallVec::from_slice(slice),
83+
length: slice.len(),
84+
cursor: 0,
85+
pulses: 0,
86+
rotation: 0,
87+
}
88+
}
89+
6790
/// Clears all pulses from a pattern
6891
///
6992
/// # Examples
@@ -82,7 +105,7 @@ impl Pattern {
82105
}
83106
}
84107

85-
/// Resize the current pattern
108+
/// Resize the current pattern. If length is
86109
///
87110
/// # Arguments
88111
///
@@ -92,46 +115,24 @@ impl Pattern {
92115
///
93116
/// ```
94117
/// use rhythms::Pattern;
95-
/// let mut pattern = Pattern::with_length(8);
118+
/// let mut pattern = Pattern::with_length(1);
119+
/// assert_eq!([false], pattern.as_slice());
96120
/// pattern.resize(4);
97121
/// assert_eq!(4, pattern.len());
122+
/// assert_eq!([false, false, false, false], pattern.as_slice());
98123
/// ```
99-
pub fn resize(&mut self, length: usize) -> &mut Self {
100-
self.steps = SmallVec::with_capacity(length);
124+
pub fn resize(&mut self, length: usize) {
125+
self.steps.resize(length, false);
101126
self.length = length;
102-
self.pulses(self.pulses);
103-
self
104127
}
105128

106-
/// Returns a pattern based on a boolean slice
129+
/// Updates the current pattern with a evenly distributed number of pulses, using an
130+
/// abstraction based on Bjorklund's Euclidean algorithm.
107131
///
108132
/// # Arguments
109133
///
110-
/// * `slice` - A boolean slice holding the initial pattern
111-
///
112-
/// # Examples
113-
///
114-
/// ```
115-
/// use rhythms::Pattern;
116-
/// let pattern = Pattern::from_slice(&[false, false, false, true]);
117-
/// assert_eq!([false, false, false, true], pattern.as_slice());
118-
/// ```
119-
pub fn from_slice(slice: &[bool]) -> Self {
120-
Self {
121-
steps: SmallVec::from_slice(slice),
122-
length: slice.len(),
123-
cursor: 0,
124-
pulses: 0,
125-
rotation: 0,
126-
}
127-
}
128-
129-
/// Updates the current pattern with a number of pulses, using an abstraction based on
130-
/// Bjorklund's Euclidean algorithm.
131-
///
132-
/// # Arguments
133-
///
134-
/// * `pulses` - Total number of pulses
134+
/// * `pulses` - Total number of pulses, from `0` to the pattern length. If `pulses` exceeds
135+
/// the pattern length, the max value will be used
135136
///
136137
/// # Examples
137138
///
@@ -146,34 +147,29 @@ impl Pattern {
146147
/// pattern.pulses(2);
147148
/// assert_eq!([true, false, true, false], pattern.as_slice());
148149
/// ```
149-
pub fn pulses(&mut self, pulses: usize) -> &mut Self {
150-
if pulses == 0 {
151-
self.clear();
152-
return self
153-
}
154-
let length = self.length;
155-
let pulses = if pulses > length {
156-
length
150+
pub fn pulses(&mut self, pulses: usize) {
151+
self.pulses = if pulses > self.length {
152+
self.length
157153
} else {
158154
pulses
159155
};
156+
160157
self.steps.clear();
161-
self.pulses = pulses;
162158
let mut bucket: usize = 0;
163-
for _ in 0..length {
164-
bucket += pulses;
165-
if bucket >= length {
166-
bucket -= length;
159+
for _ in 0..self.length {
160+
bucket += self.pulses;
161+
if bucket >= self.length {
162+
bucket -= self.length;
167163
self.steps.push(true);
168164
} else {
169165
self.steps.push(false);
170166
}
171167
}
172-
if length > 0 {
173-
let offset = length / pulses - 1;
168+
169+
if self.length > 0 && self.pulses > 0 {
170+
let offset = self.length / self.pulses - 1;
174171
self.steps.rotate_right(offset);
175172
}
176-
self
177173
}
178174

179175
/// Rotates the current pattern
@@ -195,14 +191,13 @@ impl Pattern {
195191
/// let pattern = Pattern::new(3, 1, -1);
196192
/// assert_eq!([true, false, false], pattern.as_slice());
197193
/// ```
198-
pub fn rotate(&mut self, rotation: isize) -> &mut Self {
194+
pub fn rotate(&mut self, rotation: isize) {
199195
self.rotation = rotation;
200196
if rotation.is_positive() {
201197
self.steps.rotate_right(rotation as usize);
202198
} else if rotation.is_negative() {
203199
self.steps.rotate_left(rotation.abs() as usize);
204200
}
205-
self
206201
}
207202

208203
/// Returns a boolean slice reprensenting the pattern
@@ -270,7 +265,7 @@ impl Pattern {
270265
/// ```
271266
pub fn next_looped(&mut self) -> bool {
272267
let step = self.steps[self.cursor];
273-
if self.cursor == self.len() - 1 {
268+
if self.cursor == self.last_index() {
274269
self.reset();
275270
} else {
276271
self.move_cursor(self.cursor + 1);
@@ -312,12 +307,20 @@ impl Pattern {
312307
/// assert_eq!(Some(false), pattern.next());
313308
/// ```
314309
pub fn move_cursor(&mut self, step: usize) {
315-
self.cursor = if step >= self.len() {
316-
self.len() - 1
317-
} else {
310+
self.cursor = if self.is_in_range(step) {
318311
step
312+
} else {
313+
self.last_index()
319314
};
320315
}
316+
317+
fn is_in_range(&self, step: usize) -> bool {
318+
step < self.len()
319+
}
320+
321+
fn last_index(&self) -> usize {
322+
self.len() - 1
323+
}
321324
}
322325

323326
/// Iterate over a pattern
@@ -332,7 +335,7 @@ impl Pattern {
332335
impl Iterator for Pattern {
333336
type Item = bool;
334337
fn next(&mut self) -> Option<bool> {
335-
if self.cursor < self.steps.len() {
338+
if self.is_in_range(self.cursor) {
336339
let current = self.cursor;
337340
self.cursor += 1;
338341
Some(self.steps[current])
@@ -427,4 +430,23 @@ mod tests {
427430
pattern.as_slice()
428431
);
429432
}
433+
434+
#[test]
435+
fn zero_length() {
436+
let pattern = Pattern::with_length(0);
437+
assert_eq!(
438+
0,
439+
pattern.len()
440+
);
441+
}
442+
443+
#[test]
444+
fn zero_pulses() {
445+
let mut pattern = Pattern::with_length(2);
446+
pattern.pulses(0);
447+
assert_eq!(
448+
[false, false],
449+
pattern.as_slice()
450+
);
451+
}
430452
}

0 commit comments

Comments
 (0)