Skip to content

Commit a1b3e10

Browse files
committed
Simplified Peano-based Nop generator by just using const expressions.
This change was able to be done after the release of Rust Nightly 2022-08-12 that fixed rust-lang/rust#84669.
1 parent cc4ab29 commit a1b3e10

File tree

4 files changed

+24
-64
lines changed

4 files changed

+24
-64
lines changed

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ Rust.
55

66
This project was done for fun as a part of a Rust learning process. It
77
uses extremely unstable features from the nigthly compiler, such as
8-
`const_generic_exprs`, or `specialization` because it is more
9-
entertaining and useful for me to using them than not doing so. This
10-
library may be used as long as you keep that in mind.
8+
`const_generic_exprs` because it is more entertaining and useful for
9+
me to using them than not doing so. This library may be used as long
10+
as you keep that in mind.
1111

12-
Tested on Rust nightly 2022-07-03.
12+
Tested on Rust nightly 2022-08-12 (Minimum version required).
1313

1414
## Usage
1515

rust-toolchain.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
[toolchain]
2-
channel = "nightly-2022-07-10"
2+
channel = "nightly-2022-08-12"
33
components = ["rust-src"]
44
profile = "minimal"

ws2812-avr/src/lib.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ along with ws2812-avr. If not, see <https://www.gnu.org/licenses/>.
2222
#![feature(generic_const_exprs)]
2323
#![feature(never_type)]
2424
#![feature(const_mut_refs)]
25-
#![feature(specialization)]
2625
#![feature(adt_const_params)]
2726
#![feature(const_trait_impl)]
2827
#![feature(const_slice_index)]
@@ -38,7 +37,7 @@ use core::marker::PhantomData;
3837
use core::mem::size_of;
3938
use ports::{StaticPin, StaticPort};
4039
use util::time::TimeVal;
41-
use util::{time, IntoNopPeano, NopGen, Num};
40+
use util::{time, NopBlock, NopGen};
4241

4342
mod consts {
4443
use arduino_hal::{clock::Clock, DefaultClock};
@@ -220,13 +219,13 @@ impl<Ts: Timings> CalculatedTimings for Ts {
220219

221220
impl<Ts: Timings> TypedTimings for Ts
222221
where
223-
Num<{ Ts::S1_NOPS }>: IntoNopPeano,
224-
Num<{ Ts::S2_NOPS }>: IntoNopPeano,
225-
Num<{ Ts::S3_NOPS }>: IntoNopPeano,
222+
NopBlock<{ Ts::S1_NOPS }>: NopGen,
223+
NopBlock<{ Ts::S2_NOPS }>: NopGen,
224+
NopBlock<{ Ts::S3_NOPS }>: NopGen,
226225
{
227-
type S1Nops = <Num<{ Ts::S1_NOPS }> as IntoNopPeano>::Peano;
228-
type S2Nops = <Num<{ Ts::S2_NOPS }> as IntoNopPeano>::Peano;
229-
type S3Nops = <Num<{ Ts::S3_NOPS }> as IntoNopPeano>::Peano;
226+
type S1Nops = NopBlock<{ Ts::S1_NOPS }>;
227+
type S2Nops = NopBlock<{ Ts::S2_NOPS }>;
228+
type S3Nops = NopBlock<{ Ts::S3_NOPS }>;
230229
}
231230

232231
/**

ws2812-avr/src/util/nop_block.rs

+12-51
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,10 @@ General Public License for more details.
1414
You should have received a copy of the GNU General Public License
1515
along with ws2812-avr. If not, see <https://www.gnu.org/licenses/>.
1616
*/
17-
use core::{arch::asm, marker::PhantomData};
18-
19-
// This file allows to generate block of NOP instructions based on the
20-
// value of a const generic type. It is done by using a simple
21-
// implementation of Peano numbers, for being able to count how many
22-
// NOPs should be generated using type recursion. Then, the
23-
// "IntoNopPeano" trait is provided along with the "Num" struct that
24-
// allows to convert between common numbers and Peano ones.
25-
26-
// This could have been done using const expressions and const
27-
// generics directly, but due to an opened in the Rust compiler it was
28-
// giving me a lot of headaches to actually make this to be able to
29-
// link successfully, so this is just a workaround for that issue:
30-
// https://github.com/rust-lang/rust/issues/84669.
17+
use core::arch::asm;
3118

19+
// This code requires Rust Nightly 2022-08-12 to compile because of
20+
// https://github.com/rust-lang/rust/issues/84669
3221
pub trait IsTrue {}
3322
pub struct BExpr<const B: bool> {}
3423
impl IsTrue for BExpr<true> {}
@@ -37,54 +26,26 @@ pub trait NopGen {
3726
fn gen();
3827
}
3928

40-
pub struct Num<const V: u8> {}
41-
pub struct Zero {}
42-
pub struct Succ<N> {
43-
_n: PhantomData<N>,
44-
}
45-
46-
// This trait is specialized on returning Peano numbers that are
47-
// verified that return instances that can generate NOP blocks,
48-
// instead of using a generic definition, because some issues I've
49-
// encountered while trying to apply this type restriction in other
50-
// places in the code.
51-
pub trait IntoNopPeano {
52-
type Peano: NopGen;
53-
}
54-
55-
impl IntoNopPeano for Num<0> {
56-
type Peano = Zero;
57-
}
58-
59-
impl<const X: u8> IntoNopPeano for Num<X>
60-
where
61-
BExpr<{ X > 0 }>: IsTrue,
62-
Num<{ X - 1 }>: IntoNopPeano,
63-
{
64-
type Peano = Succ<<Num<{ X - 1 }> as IntoNopPeano>::Peano>;
65-
}
29+
pub struct NopBlock<const SIZE: u8> {}
6630

67-
impl NopGen for Zero {
31+
impl NopGen for NopBlock<0> {
32+
#[inline(always)]
6833
fn gen() {}
6934
}
7035

71-
impl<X> NopGen for Succ<X>
72-
where
73-
X: NopGen,
74-
{
36+
impl NopGen for NopBlock<1> {
7537
#[inline(always)]
76-
default fn gen() {
38+
fn gen() {
7739
unsafe {
7840
asm!("nop");
7941
}
80-
81-
<X as NopGen>::gen();
8242
}
8343
}
8444

85-
impl<X> NopGen for Succ<Succ<X>>
45+
impl<const N: u8> NopGen for NopBlock<N>
8646
where
87-
X: NopGen,
47+
BExpr<{ N > 1 }>: IsTrue,
48+
NopBlock<{ N - 1 }>: NopGen,
8849
{
8950
#[inline(always)]
9051
fn gen() {
@@ -97,6 +58,6 @@ where
9758
asm!("rjmp +0");
9859
}
9960

100-
<X as NopGen>::gen();
61+
<NopBlock<{ N - 1 }> as NopGen>::gen();
10162
}
10263
}

0 commit comments

Comments
 (0)