ice ice baby (god no)

This commit is contained in:
nora 2021-11-07 21:44:29 +01:00
parent c2ce5dcae0
commit b707d044d2
5 changed files with 99 additions and 23 deletions

1
rust-toolchain Normal file
View file

@ -0,0 +1 @@
nightly

View file

@ -1,25 +1,4 @@
use std::marker::PhantomData;
trait Nat {
fn int() -> i32;
}
struct Z;
impl Nat for Z {
fn int() -> i32 {
0
}
}
struct S<N: Nat>(PhantomData<N>);
impl<N: Nat> Nat for S<N> {
fn int() -> i32 {
N::int() + 1
}
}
use crate::helper::{Nat, S, Z};
trait Count: Nat {
fn count() -> String;
@ -39,4 +18,4 @@ impl<N: Count> Count for S<N> {
pub fn count() {
println!("{}", <S<S<S<Z>>> as Count>::count());
}
}

60
src/helper.rs Normal file
View file

@ -0,0 +1,60 @@
use std::marker::PhantomData;
/////////// type level arithmetic
pub trait Nat {
fn int() -> i32;
}
pub struct Z;
impl Nat for Z {
fn int() -> i32 {
0
}
}
pub struct S<N: Nat>(PhantomData<N>);
impl<N: Nat> Nat for S<N> {
fn int() -> i32 {
N::int() + 1
}
}
/////////// bound numbers
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Bound<const UPPER: usize>(usize);
impl<const UPPER: usize> Bound<UPPER> {
pub fn new(num: usize) -> Option<Bound<UPPER>> {
if num < UPPER {
Some(Self(num))
} else {
None
}
}
}
impl<const UPPER: usize> Bound<UPPER> {
pub fn inner(&self) -> usize {
self.0
}
}
//////////// boolean expression testing
pub trait True {}
pub trait False {}
pub struct Test<const COND: bool>();
impl True for Test<true> {}
impl False for Test<false> {}
pub struct Not<B>(PhantomData<B>);
impl<B> True for Not<B> where B: False {}
impl<B> False for Not<B> where B: True {}

21
src/index.rs Normal file
View file

@ -0,0 +1,21 @@
use crate::helper::{Bound, Test, True};
pub trait SafeIdx<const SIZE: usize> {
type Output;
fn safe_idx(&self, num: Bound<SIZE>) -> &Self::Output;
}
impl<const BOUND: usize, const SIZE: usize, T> SafeIdx<BOUND> for [T; SIZE]
where
Test<{ BOUND <= SIZE }>: True,
{
type Output = T;
fn safe_idx(&self, num: Bound<BOUND>) -> &Self::Output {
// SAFETY: We can be sure that we are not out of bounds because
// `num` will always be less than `BOUND`, and `BOUND` will always
// be less than or equal to our SIZE
unsafe { self.get_unchecked(num.inner()) }
}
}

View file

@ -1,5 +1,20 @@
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
use crate::helper::Bound;
use crate::index::SafeIdx;
mod count;
mod helper;
mod index;
fn main() {
count::count();
let array = [1, 2, 3];
let bound_1 = Bound::<3>::new(2).unwrap();
let bound_2 = Bound::<1>::new(0).unwrap();
println!("{}", array.safe_idx(bound_1));
println!("{}", array.safe_idx(bound_2));
}