-
Notifications
You must be signed in to change notification settings - Fork 503
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Put everything that was in `misc.rs` into their own files, with some opportunistic refactoring, because why not.
- Loading branch information
Showing
15 changed files
with
313 additions
and
210 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
use crate::common::*; | ||
|
||
pub struct Count<T: Display>(pub T, pub usize); | ||
|
||
impl<T: Display> Display for Count<T> { | ||
fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
if self.1 == 1 { | ||
write!(f, "{}", self.0) | ||
} else { | ||
write!(f, "{}s", self.0) | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn count() { | ||
assert_eq!(Count("dog", 0).to_string(), "dogs"); | ||
assert_eq!(Count("dog", 1).to_string(), "dog"); | ||
assert_eq!(Count("dog", 2).to_string(), "dogs"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub(crate) fn default<T: Default>() -> T { | ||
Default::default() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
use crate::common::*; | ||
|
||
pub(crate) fn empty<T, C: iter::FromIterator<T>>() -> C { | ||
iter::empty().collect() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use crate::common::*; | ||
|
||
pub struct Enclosure<T: Display> { | ||
enclosure: &'static str, | ||
value: T, | ||
} | ||
|
||
impl<T: Display> Enclosure<T> { | ||
pub fn tick(value: T) -> Enclosure<T> { | ||
Enclosure { | ||
enclosure: "`", | ||
value, | ||
} | ||
} | ||
} | ||
|
||
impl<T: Display> Display for Enclosure<T> { | ||
fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
write!(f, "{}{}{}", self.enclosure, self.value, self.enclosure) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn tick() { | ||
assert_eq!(Enclosure::tick("foo").to_string(), "`foo`") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
use crate::common::*; | ||
|
||
pub struct List<T: Display, I: Iterator<Item = T> + Clone> { | ||
conjunction: &'static str, | ||
values: I, | ||
} | ||
|
||
impl<T: Display, I: Iterator<Item = T> + Clone> List<T, I> { | ||
pub fn or<II: IntoIterator<Item = T, IntoIter = I>>(values: II) -> List<T, I> { | ||
List { | ||
conjunction: "or", | ||
values: values.into_iter(), | ||
} | ||
} | ||
|
||
pub fn and<II: IntoIterator<Item = T, IntoIter = I>>(values: II) -> List<T, I> { | ||
List { | ||
conjunction: "and", | ||
values: values.into_iter(), | ||
} | ||
} | ||
|
||
pub fn or_ticked<II: IntoIterator<Item = T, IntoIter = I>>( | ||
values: II, | ||
) -> List<Enclosure<T>, impl Iterator<Item = Enclosure<T>> + Clone> { | ||
List::or(values.into_iter().map(Enclosure::tick)) | ||
} | ||
|
||
pub fn and_ticked<II: IntoIterator<Item = T, IntoIter = I>>( | ||
values: II, | ||
) -> List<Enclosure<T>, impl Iterator<Item = Enclosure<T>> + Clone> { | ||
List::and(values.into_iter().map(Enclosure::tick)) | ||
} | ||
} | ||
|
||
impl<T: Display, I: Iterator<Item = T> + Clone> Display for List<T, I> { | ||
fn fmt(&self, f: &mut Formatter) -> fmt::Result { | ||
let mut values = self.values.clone().fuse(); | ||
|
||
if let Some(first) = values.next() { | ||
write!(f, "{}", first)?; | ||
} else { | ||
return Ok(()); | ||
} | ||
|
||
let second = values.next(); | ||
|
||
if second.is_none() { | ||
return Ok(()); | ||
} | ||
|
||
let third = values.next(); | ||
|
||
if let (Some(second), None) = (second.as_ref(), third.as_ref()) { | ||
write!(f, " {} {}", self.conjunction, second)?; | ||
return Ok(()); | ||
} | ||
|
||
let mut current = second; | ||
let mut next = third; | ||
|
||
loop { | ||
match (current, next) { | ||
(Some(c), Some(n)) => { | ||
write!(f, ", {}", c)?; | ||
current = Some(n); | ||
next = values.next(); | ||
} | ||
(Some(c), None) => { | ||
write!(f, ", {} {}", self.conjunction, c)?; | ||
return Ok(()); | ||
} | ||
_ => panic!("Iterator was fused, but returned Some after None"), | ||
} | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn or() { | ||
assert_eq!("1", List::or(&[1]).to_string()); | ||
assert_eq!("1 or 2", List::or(&[1, 2]).to_string()); | ||
assert_eq!("1, 2, or 3", List::or(&[1, 2, 3]).to_string()); | ||
assert_eq!("1, 2, 3, or 4", List::or(&[1, 2, 3, 4]).to_string()); | ||
} | ||
|
||
#[test] | ||
fn and() { | ||
assert_eq!("1", List::and(&[1]).to_string()); | ||
assert_eq!("1 and 2", List::and(&[1, 2]).to_string()); | ||
assert_eq!("1, 2, and 3", List::and(&[1, 2, 3]).to_string()); | ||
assert_eq!("1, 2, 3, and 4", List::and(&[1, 2, 3, 4]).to_string()); | ||
} | ||
|
||
#[test] | ||
fn or_ticked() { | ||
assert_eq!("`1`", List::or_ticked(&[1]).to_string()); | ||
assert_eq!("`1` or `2`", List::or_ticked(&[1, 2]).to_string()); | ||
assert_eq!("`1`, `2`, or `3`", List::or_ticked(&[1, 2, 3]).to_string()); | ||
assert_eq!( | ||
"`1`, `2`, `3`, or `4`", | ||
List::or_ticked(&[1, 2, 3, 4]).to_string() | ||
); | ||
} | ||
|
||
#[test] | ||
fn and_ticked() { | ||
assert_eq!("`1`", List::and_ticked(&[1]).to_string()); | ||
assert_eq!("`1` and `2`", List::and_ticked(&[1, 2]).to_string()); | ||
assert_eq!( | ||
"`1`, `2`, and `3`", | ||
List::and_ticked(&[1, 2, 3]).to_string() | ||
); | ||
assert_eq!( | ||
"`1`, `2`, `3`, and `4`", | ||
List::and_ticked(&[1, 2, 3, 4]).to_string() | ||
); | ||
} | ||
} |
Oops, something went wrong.