use std::convert::Infallible;
use crate::Ordinal;
impl<A: Ordinal> Ordinal for Option<A> {
const ORDINAL_SIZE: usize = A::ORDINAL_SIZE + 1;
fn ordinal(&self) -> usize {
match self {
None => 0,
Some(a) => a.ordinal() + 1,
}
}
fn from_ordinal(ordinal: usize) -> Option<Self> {
if ordinal == 0 {
Some(None)
} else {
A::from_ordinal(ordinal - 1).map(Some)
}
}
}
impl<A: Ordinal, B: Ordinal> Ordinal for Result<A, B> {
const ORDINAL_SIZE: usize = A::ORDINAL_SIZE + B::ORDINAL_SIZE;
fn ordinal(&self) -> usize {
match self {
Ok(a) => a.ordinal(),
Err(b) => A::ORDINAL_SIZE + b.ordinal(),
}
}
fn from_ordinal(ordinal: usize) -> Option<Self> {
if ordinal < A::ORDINAL_SIZE {
Some(Ok(A::from_ordinal(ordinal).unwrap()))
} else {
B::from_ordinal(ordinal - A::ORDINAL_SIZE).map(Err)
}
}
}
impl Ordinal for Infallible {
const ORDINAL_SIZE: usize = 0;
fn ordinal(&self) -> usize {
match *self {}
}
fn from_ordinal(_: usize) -> Option<Self> {
None
}
}
#[cfg(test)]
mod tests {
use std::convert::Infallible;
use crate::tests::util::test_ordinal;
#[test]
fn test_option() {
test_ordinal([None, Some(false), Some(true)]);
}
#[test]
fn test_result() {
test_ordinal([
Ok(false),
Ok(true),
Err(None),
Err(Some(false)),
Err(Some(true)),
]);
}
#[test]
fn test_infallible() {
test_ordinal::<Infallible>([]);
}
}