Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 8 additions & 19 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,8 @@ jobs:
- uses: actions/checkout@v4

- name: Setup Rust
uses: dtolnay/rust-toolchain@master
uses: dtolnay/rust-toolchain@stable
with:
toolchain: nightly-2022-08-22
components: rustfmt, clippy

- name: Cache cargo registry
Expand All @@ -60,7 +59,7 @@ jobs:
run: cargo fmt --all -- --check

- name: Run Clippy
run: cargo clippy --all-targets --all-features
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Check file size limit
run: python3 scripts/check_file_size.py
Expand All @@ -77,9 +76,7 @@ jobs:
- uses: actions/checkout@v4

- name: Setup Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly-2022-08-22
uses: dtolnay/rust-toolchain@stable

- name: Cache cargo registry
uses: actions/cache@v4
Expand All @@ -105,10 +102,8 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Setup Rust nightly
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly-2022-08-22
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable

# Install tarpaulin using pre-built binary (avoids compilation issues)
- name: Install cargo-tarpaulin
Expand Down Expand Up @@ -154,9 +149,7 @@ jobs:
- uses: actions/checkout@v4

- name: Setup Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly-2022-08-22
uses: dtolnay/rust-toolchain@stable

- name: Cache cargo registry
uses: actions/cache@v4
Expand Down Expand Up @@ -224,9 +217,7 @@ jobs:
fetch-depth: 0

- name: Setup Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly-2022-08-22
uses: dtolnay/rust-toolchain@stable

- name: Check if version changed
id: version_check
Expand Down Expand Up @@ -272,9 +263,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Setup Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly-2022-08-22
uses: dtolnay/rust-toolchain@stable

- name: Configure git
run: |
Expand Down
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,24 @@ use platform_data::Flow;

let mut collected = vec![];

// Use Flow with try_for_each by converting to ControlFlow
(0..20).try_for_each(|i| {
collected.push(i);
if i == 10 { Flow::Break } else { Flow::Continue }
if i == 10 { Flow::Break.into_control_flow() } else { Flow::Continue.into_control_flow() }
});

assert_eq!(collected, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

// Or use Flow directly with manual iteration
let mut collected2 = vec![];
for i in 0..20 {
collected2.push(i);
let flow = if i == 10 { Flow::Break } else { Flow::Continue };
if flow.is_break() {
break;
}
}
assert_eq!(collected2, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
```

### Using Point for repeated elements
Expand Down Expand Up @@ -144,17 +156,7 @@ use platform_data::{Links, LinkType, LinksConstants, Flow, Error, ReadHandler, W

## Requirements

This crate requires the **nightly** Rust toolchain due to the use of unstable features:

- `try_trait_v2`
- `associated_type_bounds`
- `type_alias_impl_trait`
- `const_refs_to_cell`
- `const_result_drop`
- `const_trait_impl`
- `const_convert`
- `const_deref`
- `step_trait`
This crate requires **Rust 1.79 or later** (stable toolchain). The `associated_type_bounds` feature used for `Error:` bounds was stabilized in Rust 1.79.

## Dependencies

Expand Down
23 changes: 23 additions & 0 deletions changelog.d/20251227_183811_migrate_to_stable_rust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### Changed
- Migrated from nightly Rust to **stable Rust** toolchain (requires Rust 1.79+)
- Removed all unstable feature flags:
- `try_trait_v2` - Flow no longer implements `Try` trait
- `type_alias_impl_trait` - Point now uses explicit `PointIter` type
- `const_trait_impl`, `const_convert`, `const_deref`, `const_refs_to_cell`, `const_result_drop` - LinkType/FuntyPart traits are no longer const
- `step_trait` - LinkType no longer requires `Step` bound
- `associated_type_bounds` - still used but stabilized in Rust 1.79
- `Flow` type changes:
- Added `into_control_flow()` method for use with `try_for_each`
- Removed `Try` and `FromResidual` trait implementations (nightly-only)
- `Point` type changes:
- Added explicit `PointIter` iterator type (publicly exported)
- `LinkType` trait changes:
- Removed `Step` trait bound
- Removed `const` from trait and impl
- `FuntyPart` trait changes:
- Simplified implementation without const generics
- Now uses `expect()` instead of `unreachable_unchecked()`
- Updated CI/CD pipeline to use `dtolnay/rust-toolchain@stable`

### Fixed
- Crate now compiles on stable Rust without any feature flags
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[toolchain]
channel = "nightly-2022-08-22"
channel = "stable"
8 changes: 3 additions & 5 deletions rustfmt.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
error_on_line_overflow = true
error_on_unformatted = true
version = "Two"

imports_granularity = "Crate"
# Stable rustfmt configuration
# For available options, see: https://rust-lang.github.io/rustfmt/
edition = "2018"
2 changes: 1 addition & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl<T: LinkType> LinksConstants<T> {
pub fn is_external(&self, address: T) -> bool {
self.external_range
.clone()
.map_or(false, |range| range.contains(&address))
.is_some_and(|range| range.contains(&address))
}

pub fn is_reference(&self, address: T) -> bool {
Expand Down
2 changes: 0 additions & 2 deletions src/converters.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::{Hybrid, LinkType};
use funty::Integral;
use std::ops::Sub;

#[derive(Default)]
pub struct AddrToRaw;
Expand Down
52 changes: 39 additions & 13 deletions src/flow.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,46 @@
use std::ops::{ControlFlow, FromResidual, Try};
use std::ops::ControlFlow;

/// Represents the control flow of an operation, similar to `ControlFlow`.
///
/// This is a simplified enum that can be used with iterators and callbacks
/// to indicate whether to continue or break early.
#[repr(usize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Flow {
Continue,
Break,
}

impl FromResidual for Flow {
fn from_residual(_: <Self as Try>::Residual) -> Self {
Flow::Break
impl Flow {
/// Returns `true` if this is `Flow::Continue`.
pub fn is_continue(&self) -> bool {
matches!(self, Flow::Continue)
}
}

impl Try for Flow {
type Output = ();
type Residual = Flow;

fn from_output(_: Self::Output) -> Self {
Flow::Continue
/// Returns `true` if this is `Flow::Break`.
pub fn is_break(&self) -> bool {
matches!(self, Flow::Break)
}

fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
/// Converts this Flow into a ControlFlow that can be used with try_for_each.
///
/// This method enables using Flow with iterator methods like `try_for_each`:
///
/// ```
/// use platform_data::Flow;
/// use std::ops::ControlFlow;
///
/// let mut count = 0;
/// let result = (0..10).try_for_each(|i| {
/// count += 1;
/// if i == 5 { Flow::Break.into_control_flow() } else { Flow::Continue.into_control_flow() }
/// });
/// assert_eq!(count, 6);
/// ```
pub fn into_control_flow(self) -> ControlFlow<()> {
match self {
Flow::Continue => ControlFlow::Continue(()),
Flow::Break => ControlFlow::Break(Flow::Break),
Flow::Break => ControlFlow::Break(()),
}
}
}
Expand All @@ -36,3 +53,12 @@ impl<C, B> From<ControlFlow<C, B>> for Flow {
}
}
}

impl From<Flow> for ControlFlow<()> {
fn from(flow: Flow) -> Self {
match flow {
Flow::Continue => ControlFlow::Continue(()),
Flow::Break => ControlFlow::Break(()),
}
}
}
2 changes: 0 additions & 2 deletions src/hybrid.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::LinkType;
use funty::Integral;
use std::ops::{Div, Sub};

#[derive(Debug, Clone, Copy, Hash, PartialOrd, PartialEq, Ord, Eq)]
pub struct Hybrid<T> {
Expand Down
12 changes: 1 addition & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
#![feature(try_trait_v2)]
#![feature(associated_type_bounds)]
#![feature(type_alias_impl_trait)]
#![feature(const_refs_to_cell)]
#![feature(const_result_drop)]
#![feature(const_trait_impl)]
#![feature(const_convert)]
#![feature(const_deref)]
#![feature(step_trait)]

mod constants;
mod converters;
mod flow;
Expand All @@ -23,5 +13,5 @@ pub use flow::Flow;
pub use hybrid::Hybrid;
pub use link_type::LinkType;
pub use links::{Error, Links, ReadHandler, WriteHandler};
pub use point::Point;
pub use point::{Point, PointIter};
pub use query::{Query, ToQuery};
41 changes: 18 additions & 23 deletions src/link_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,35 @@ use funty::Unsigned;
use std::{
convert::{TryFrom, TryInto},
fmt::Debug,
hint,
iter::Step,
marker::Destruct,
};

#[const_trait]
/// Trait for creating small numeric values from u8.
///
/// This trait provides a convenient way to create numeric types from small u8 values,
/// which is commonly needed when working with link constants and indices.
pub trait FuntyPart: Sized + TryFrom<u8> {
/// Create a value from a u8. Panics if the conversion fails.
fn funty(n: u8) -> Self;
}

// TryFrom<u8> has `Error = Infallible` for all types
impl<All: ~const TryFrom<u8>> const FuntyPart for All {
fn funty(n: u8) -> Self
where
All: ~const Destruct,
<All as TryFrom<u8>>::Error: ~const Destruct,
{
// std `Result::unwrap_unchecked` is not const
match All::try_from(n) {
Ok(all) => all,
Err(_) => {
// <All as TryFrom<u8>>::Error is Infallible
unsafe { hint::unreachable_unchecked() }
}
}
impl<All: TryFrom<u8>> FuntyPart for All
where
<All as TryFrom<u8>>::Error: Debug,
{
fn funty(n: u8) -> Self {
All::try_from(n).expect("conversion from u8 should succeed for all unsigned types")
}
}

// fixme: track https://github.com/rust-lang/rust/issues/67792
#[const_trait]
/// Trait bound for numeric types that can be used as link identifiers.
///
/// This trait combines several requirements:
/// - Must be an unsigned integer type (via `Unsigned`)
/// - Must support creation from small values (via `FuntyPart`)
/// - Must support conversions to/from various integer types
pub trait LinkType:
Unsigned
+ FuntyPart
+ Step
+ TryFrom<i8, Error: Debug>
+ TryFrom<u8, Error: Debug>
+ TryFrom<i16, Error: Debug>
Expand Down Expand Up @@ -63,7 +58,7 @@ pub trait LinkType:
{
}

impl<All: Unsigned + FuntyPart + Step> const LinkType for All where
impl<All: Unsigned + FuntyPart> LinkType for All where
All: TryFrom<i8, Error: Debug>
+ TryFrom<u8, Error: Debug>
+ TryFrom<i16, Error: Debug>
Expand Down
36 changes: 34 additions & 2 deletions src/point.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/// A structure representing a single value repeated multiple times.
///
/// This is useful for creating queries or representing repeated elements
/// without allocating a vector.
pub struct Point<T> {
index: T,
size: usize,
Expand Down Expand Up @@ -47,11 +51,39 @@ impl<T: PartialEq> Point<T> {
}
}

/// Iterator for Point that yields copies of the stored value.
pub struct PointIter<T> {
value: T,
remaining: usize,
}

impl<T: Copy> Iterator for PointIter<T> {
type Item = T;

fn next(&mut self) -> Option<Self::Item> {
if self.remaining > 0 {
self.remaining -= 1;
Some(self.value)
} else {
None
}
}

fn size_hint(&self) -> (usize, Option<usize>) {
(self.remaining, Some(self.remaining))
}
}

impl<T: Copy> ExactSizeIterator for PointIter<T> {}

impl<T: PartialEq + Copy> IntoIterator for Point<T> {
type Item = T;
type IntoIter = impl Iterator<Item = T>;
type IntoIter = PointIter<T>;

fn into_iter(self) -> Self::IntoIter {
(0..self.len()).map(move |_| self.index)
PointIter {
value: self.index,
remaining: self.size,
}
}
}
Loading