Select Git revision
Joueur.java
main.rs 5.92 KiB
/*!
This is an example of Rust crate comments (or inner comments).
They will be rendered in the front page of your (crate) library.
In this program we wrote an algorithm that computes the minimum of
a sequence of integers.
To create the documentation run the command
```bash
cargo doc
```
The obtain documentation can be found in the `target/doc/part04/index.html` directory
To view the documentation type
```bash
cargo doc --open
```
which will open the browser and show you the documentation.
The documentation supports the CommonMarkdown syntax.
Below we will use the `///` comments that will comment the code directly below.
We can also sue `//` but they will not be rendered.
Each line written here could be prefixed by `//!` instead of enclosed in `/*! */`.
For more informations about writing documentation [follow that link](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html).
Also Rust comes with great tooling.
- Clippy: A linter.
- Rustfmt: A formatter.
*/
// Rust basics:
// - Tests
// - Copy/Clone via derive
// - PartialEq
// - Documentation
// - clippy, rustfmt
/// An generic enumerated type that has two variants that are [Clone]
/// and [Copy] using derive.
///
/// - Nothing
/// - Something
#[derive(Clone, Copy)]
enum SomethingOrNothing<T> {
/// A [SomethingOrNothing::Nothing]
Nothing,
/// A [SomethingOrNothing::Something] encapsulating a T
Something(T),
}
impl<T: std::fmt::Display> SomethingOrNothing<T> {
/// A static function that prints the content of a SomethingOrNothing.
fn print(&self) {
match self {
SomethingOrNothing::Nothing => println!("Nothing."),
SomethingOrNothing::Something(val) => println!("Something is: {}", val),
}
}
}
impl<T> Default for SomethingOrNothing<T> {
/// By Default a [SomethingOrNothing] is a nothing.
fn default() -> Self {
SomethingOrNothing::Nothing
}
}
impl<T: PartialEq> PartialEq for SomethingOrNothing<T> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(SomethingOrNothing::Nothing, SomethingOrNothing::Nothing) => true,
(SomethingOrNothing::Something(lhs), SomethingOrNothing::Something(rhs)) => {
*lhs == *rhs
}
_ => false,
}
}
}
// If we remove Copy, we have a problem with the t in tab
// in the computation of the minimum.
trait Minimum: Copy {
fn min(self, rhs: Self) -> Self;
}
impl<T: Minimum> Minimum for SomethingOrNothing<T> {
fn min(self, rhs: Self) -> Self {
match (self, rhs) {
(SomethingOrNothing::Nothing, SomethingOrNothing::Nothing) => {
SomethingOrNothing::Nothing
}
(SomethingOrNothing::Something(lhs), SomethingOrNothing::Something(rhs)) => {
SomethingOrNothing::Something(lhs.min(rhs))
}
(SomethingOrNothing::Nothing, SomethingOrNothing::Something(rhs)) => {
SomethingOrNothing::Something(rhs)
}
(SomethingOrNothing::Something(lhs), SomethingOrNothing::Nothing) => {
SomethingOrNothing::Something(lhs)
}
}
}
}
// i32 is Copyable as a very basic type as f32, f64, etc.
// Arrays for example are not copyable.
impl Minimum for i32 {
fn min(self, rhs: Self) -> Self {
if self < rhs {
self
} else {
rhs
}
}
}
const SIZE: usize = 9;
/// Poorly emulates the parsing of a command line.
fn read_command_line() -> [i32; SIZE] {
[10, 32, 12, 43, 52, 53, 83, 2, 9]
}
/// Prints all the elements of the `tab` and returns `tab`.
fn print_tab(tab: &[i32; SIZE]) {
for t in tab {
print!("{} ", t);
}
println!();
}
/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
/// Returns the array and a [SomethingOrNothing::Something] containing the the minimum value
/// or [SomethingOrNothing::Nothing] if no minimum value was found.
///
/// # Example
///
/// ```
/// # fn main() {
/// let tab = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min(&tab);
/// assert!(min == SomethingOrNothing::Something(2));
/// # }
/// ```
fn find_min<T: Minimum>(tab: &[T; SIZE]) -> SomethingOrNothing<T> {
let mut min = SomethingOrNothing::Nothing;
// Here is T is not Copyable tab is consumed and cannot be returned
for t in tab {
min = min.min(SomethingOrNothing::Something(*t));
}
min
}
fn main() {
let tab = read_command_line();
println!("Among the Somethings in the list:");
print_tab(&tab);
// There are alternatives to access fields of tuples
let min = find_min(&tab);
// The first field is not used therefore we can replace it with "_"
min.print();
}
#[test]
fn test_creation() {
let n1: SomethingOrNothing<i32> = SomethingOrNothing::default();
assert!(n1 == SomethingOrNothing::Nothing);
let n2: SomethingOrNothing<i32> = SomethingOrNothing::Something(1);
assert!(n2 == SomethingOrNothing::Something(1));
}
#[test]
#[should_panic]
fn test_failure_creation() {
let n2: SomethingOrNothing<i32> = SomethingOrNothing::Something(1);
assert!(n2 == SomethingOrNothing::Nothing);
assert!(n2 == SomethingOrNothing::Something(2));
}
#[test]
fn test_min() {
let a = [1, 5, -1, 2, 0, 10, 11, 0, 3];
let min = find_min(&a);
assert!(min == SomethingOrNothing::Something(-1));
}
#[cfg(test)]
mod tests {
#[test]
fn test_min() {
let x = 5;
let y = 10;
assert_eq!(x.min(y), x);
assert_eq!(y.min(x), x);
}
#[test]
fn test_min_something_or_nothing() {
use crate::Minimum;
let x = crate::SomethingOrNothing::Something(5i32);
let y = crate::SomethingOrNothing::Something(10i32);
let z = crate::SomethingOrNothing::Nothing;
assert!(x.min(y) == x);
assert!(y.min(x) == x);
assert!(z.min(y) == y);
assert!(y.min(z) == y);
assert!(z.min(z) == z);
}
}