139
src/utils/inter_join.rs
Normal file
139
src/utils/inter_join.rs
Normal file
@ -0,0 +1,139 @@
|
||||
use std::iter::Peekable;
|
||||
|
||||
use rand::{seq::SliceRandom, Rng};
|
||||
|
||||
/// Trait for creating random intersperse.
|
||||
///
|
||||
/// It's implemented for all iterables.
|
||||
///
|
||||
/// The usage is the following:
|
||||
/// ```
|
||||
/// let words = &[4, 5, 6];
|
||||
/// let result = [1, 2, 3]
|
||||
/// .into_iter()
|
||||
/// .random_itersperse(words, &mut rand::thread_rng())
|
||||
/// .collect::<Vec<_>>();
|
||||
/// ```
|
||||
///
|
||||
/// Now if you print the result, you'll see that
|
||||
/// after every word from the source slice,
|
||||
/// placed one word from the `words` slice.
|
||||
/// Like this: `[1, 6, 2, 4, 3]`.
|
||||
pub trait RandomIntersperse<'a, L, R>
|
||||
where
|
||||
L: IntoIterator,
|
||||
R: Rng,
|
||||
{
|
||||
fn random_itersperse(
|
||||
self,
|
||||
choises: &'a [L::Item],
|
||||
random: &'a mut R,
|
||||
) -> RandomIntersperseStruct<'a, L, R>;
|
||||
}
|
||||
|
||||
/// Struct used to create `random_intresperse`.
|
||||
/// It has a peekable iterator, a reference to a
|
||||
/// random generator, a slice for items to choose from
|
||||
/// and boolean to check current state.
|
||||
///
|
||||
/// The iterator is peekable, because we need to check
|
||||
/// if next item exists, to avoid inserting
|
||||
/// a generated value at the end of iterator.
|
||||
#[derive(Debug)]
|
||||
pub struct RandomIntersperseStruct<'a, L, R>
|
||||
where
|
||||
L: IntoIterator,
|
||||
R: Rng,
|
||||
{
|
||||
iterator: Peekable<L::IntoIter>,
|
||||
choices: &'a [L::Item],
|
||||
random: &'a mut R,
|
||||
use_iter: bool,
|
||||
}
|
||||
|
||||
/// Implement a `RandomIntersperse` trait for all
|
||||
/// items that can be turned in iterators.
|
||||
impl<'a, L, R> RandomIntersperse<'a, L, R> for L
|
||||
where
|
||||
L: IntoIterator,
|
||||
R: Rng,
|
||||
{
|
||||
fn random_itersperse(
|
||||
self,
|
||||
choices: &'a [L::Item],
|
||||
random: &'a mut R,
|
||||
) -> RandomIntersperseStruct<'a, L, R> {
|
||||
RandomIntersperseStruct {
|
||||
random,
|
||||
choices,
|
||||
use_iter: true,
|
||||
iterator: self.into_iter().peekable(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of an interator for a randomitersperse structure,
|
||||
/// so it can be used in chain.
|
||||
impl<'a, L, R> Iterator for RandomIntersperseStruct<'a, L, R>
|
||||
where
|
||||
L: IntoIterator,
|
||||
R: Rng,
|
||||
L::Item: Clone,
|
||||
{
|
||||
// The type of item is the same as for
|
||||
// original iterator.
|
||||
type Item = L::Item;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Peek a value from the iterator to check if we have values.
|
||||
self.iterator.peek()?;
|
||||
|
||||
let choise = self.choices.choose(self.random);
|
||||
if choise.is_none() {
|
||||
self.use_iter = true;
|
||||
}
|
||||
|
||||
if self.use_iter {
|
||||
// We change use_iter, so a random
|
||||
// value is chosen on the next step.
|
||||
self.use_iter = false;
|
||||
self.iterator.next()
|
||||
} else {
|
||||
self.use_iter = true;
|
||||
self.choices.choose(self.random).cloned()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::utils::inter_join::RandomIntersperse;
|
||||
|
||||
#[test]
|
||||
pub fn success() {
|
||||
let randoms = &[4, 5, 6];
|
||||
let result = [1, 2, 3]
|
||||
.into_iter()
|
||||
.random_itersperse(randoms, &mut rand::thread_rng())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for value in [1, 2, 3] {
|
||||
assert!(result.contains(&value));
|
||||
}
|
||||
assert_eq!(result.len(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn empty_array() {
|
||||
let randoms = &[];
|
||||
let result = [1, 2, 3]
|
||||
.into_iter()
|
||||
.random_itersperse(randoms, &mut rand::thread_rng())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for value in [1, 2, 3] {
|
||||
assert!(result.contains(&value));
|
||||
}
|
||||
assert_eq!(result.len(), 3);
|
||||
}
|
||||
}
|
9
src/utils/messages.rs
Normal file
9
src/utils/messages.rs
Normal file
@ -0,0 +1,9 @@
|
||||
use grammers_client::{types::Message, Update};
|
||||
|
||||
#[must_use]
|
||||
pub fn get_message(update: &Update) -> Option<&Message> {
|
||||
match update {
|
||||
Update::NewMessage(msg) | Update::MessageEdited(msg) => Some(msg),
|
||||
_ => None,
|
||||
}
|
||||
}
|
2
src/utils/mod.rs
Normal file
2
src/utils/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
pub mod inter_join;
|
||||
pub mod messages;
|
Reference in New Issue
Block a user