mirror of
https://github.com/Noratrieb/typed.git
synced 2026-01-14 08:35:05 +01:00
ice ice baby (god no)
This commit is contained in:
parent
c2ce5dcae0
commit
b707d044d2
5 changed files with 99 additions and 23 deletions
1
rust-toolchain
Normal file
1
rust-toolchain
Normal file
|
|
@ -0,0 +1 @@
|
|||
nightly
|
||||
25
src/count.rs
25
src/count.rs
|
|
@ -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
60
src/helper.rs
Normal 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
21
src/index.rs
Normal 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()) }
|
||||
}
|
||||
}
|
||||
15
src/main.rs
15
src/main.rs
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue