From 443693b948def8784b3bf5f81057488ac3f8c31e Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 27 Dec 2025 18:31:30 +0100 Subject: [PATCH 1/4] Initial commit with task details Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: https://github.com/linksplatform/core-rs/issues/8 --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..bf21242 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: https://github.com/linksplatform/core-rs/issues/8 +Your prepared branch: issue-8-53c25630aa7b +Your prepared working directory: /tmp/gh-issue-solver-1766856689023 + +Proceed. \ No newline at end of file From dfac9b3b4c184b546ec2c3e632cd17860971f1ac Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 27 Dec 2025 18:38:48 +0100 Subject: [PATCH 2/4] feat: migrate to stable Rust, remove unstable features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove all nightly feature flags from lib.rs: - 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 - Simplify Flow type by removing Try trait implementation - Replace with helper methods (is_continue, is_break) - Add bidirectional conversion with ControlFlow - Simplify LinkType and FuntyPart traits - Remove const trait implementations - Remove Step trait requirement - Remove Destruct marker usage - Fix Point IntoIterator to use concrete iterator type - Use std::iter::RepeatN instead of impl Trait - Update CI/CD pipeline to use stable Rust toolchain - Update rustfmt.toml to use stable-compatible options - Fix unused imports in converters.rs and hybrid.rs - Apply clippy suggestions (is_some_and, repeat_n) Fixes #8 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/release.yml | 10 ++-- .../20251227_183811_migrate_to_stable_rust.md | 11 ++++ rustfmt.toml | 8 ++- src/constants.rs | 2 +- src/converters.rs | 2 - src/flow.rs | 40 ++++++++------- src/hybrid.rs | 2 - src/lib.rs | 12 +---- src/link_type.rs | 50 ++++++++++--------- src/point.rs | 4 +- tests/flow.rs | 28 +++++++++-- 11 files changed, 96 insertions(+), 73 deletions(-) create mode 100644 changelog.d/20251227_183811_migrate_to_stable_rust.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5172c09..6a586ac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,7 +40,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Rust - uses: dtolnay/rust-toolchain@nightly + uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy @@ -76,7 +76,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Rust - uses: dtolnay/rust-toolchain@nightly + uses: dtolnay/rust-toolchain@stable - name: Cache cargo registry uses: actions/cache@v4 @@ -104,7 +104,7 @@ jobs: - uses: actions/checkout@v4 - name: Setup Rust - uses: dtolnay/rust-toolchain@nightly + uses: dtolnay/rust-toolchain@stable - name: Cache cargo registry uses: actions/cache@v4 @@ -172,7 +172,7 @@ jobs: fetch-depth: 0 - name: Setup Rust - uses: dtolnay/rust-toolchain@nightly + uses: dtolnay/rust-toolchain@stable - name: Check if version changed id: version_check @@ -218,7 +218,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Rust - uses: dtolnay/rust-toolchain@nightly + uses: dtolnay/rust-toolchain@stable - name: Configure git run: | diff --git a/changelog.d/20251227_183811_migrate_to_stable_rust.md b/changelog.d/20251227_183811_migrate_to_stable_rust.md new file mode 100644 index 0000000..c010e6f --- /dev/null +++ b/changelog.d/20251227_183811_migrate_to_stable_rust.md @@ -0,0 +1,11 @@ +### Changed +- Migrated from nightly Rust to stable Rust toolchain +- Removed all unstable feature flags (`try_trait_v2`, `type_alias_impl_trait`, `const_trait_impl`, `step_trait`, etc.) +- Simplified `Flow` type by removing `Try` trait implementation +- Simplified `LinkType` and `FuntyPart` traits by removing const trait features +- Updated CI/CD pipeline to use stable Rust toolchain +- Updated `rustfmt.toml` to use stable-compatible options only + +### Fixed +- Removed unused imports in `converters.rs` and `hybrid.rs` +- Applied clippy suggestions for `is_some_and` and `repeat_n` diff --git a/rustfmt.toml b/rustfmt.toml index 4dd7be3..02a3e70 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,5 +1,3 @@ -error_on_line_overflow = true -error_on_unformatted = true -version = "Two" - -imports_granularity = "Crate" \ No newline at end of file +# Stable rustfmt configuration +# For available options, see: https://rust-lang.github.io/rustfmt/ +edition = "2018" diff --git a/src/constants.rs b/src/constants.rs index 3cb2b4b..597a87b 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -96,7 +96,7 @@ impl LinksConstants { 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 { diff --git a/src/converters.rs b/src/converters.rs index 3cc2800..5e3b966 100644 --- a/src/converters.rs +++ b/src/converters.rs @@ -1,6 +1,4 @@ use crate::{Hybrid, LinkType}; -use funty::Integral; -use std::ops::Sub; #[derive(Default)] pub struct AddrToRaw; diff --git a/src/flow.rs b/src/flow.rs index 70bb581..ed0d29a 100644 --- a/src/flow.rs +++ b/src/flow.rs @@ -1,30 +1,25 @@ -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(_: ::Residual) -> Self { - Flow::Break - } -} - -impl Try for Flow { - type Output = (); - type Residual = Flow; - - fn from_output(_: Self::Output) -> Self { - Flow::Continue +impl Flow { + /// Returns `true` if this is `Flow::Continue`. + pub fn is_continue(&self) -> bool { + matches!(self, Flow::Continue) } - fn branch(self) -> ControlFlow { - match self { - Flow::Continue => ControlFlow::Continue(()), - Flow::Break => ControlFlow::Break(Flow::Break), - } + /// Returns `true` if this is `Flow::Break`. + pub fn is_break(&self) -> bool { + matches!(self, Flow::Break) } } @@ -36,3 +31,12 @@ impl From> for Flow { } } } + +impl From for ControlFlow<()> { + fn from(flow: Flow) -> Self { + match flow { + Flow::Continue => ControlFlow::Continue(()), + Flow::Break => ControlFlow::Break(()), + } + } +} diff --git a/src/hybrid.rs b/src/hybrid.rs index f2368b0..bbcaf2a 100644 --- a/src/hybrid.rs +++ b/src/hybrid.rs @@ -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 { diff --git a/src/lib.rs b/src/lib.rs index 8b40d2d..aae65f3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; @@ -22,6 +12,6 @@ pub use converters::{AddrToRaw, RawToAddr}; pub use flow::Flow; pub use hybrid::Hybrid; pub use link_type::LinkType; -pub use links::{Links, ReadHandler, WriteHandler, Error}; +pub use links::{Error, Links, ReadHandler, WriteHandler}; pub use point::Point; pub use query::{Query, ToQuery}; diff --git a/src/link_type.rs b/src/link_type.rs index 4c65df8..dc44366 100644 --- a/src/link_type.rs +++ b/src/link_type.rs @@ -2,40 +2,40 @@ use funty::Unsigned; use std::{ convert::{TryFrom, TryInto}, fmt::Debug, - hint, - iter::Step, - marker::Destruct, }; -#[const_trait] +/// Helper trait for converting from small unsigned integers. +/// +/// This trait provides a convenient way to convert `u8` values +/// to any type that implements `TryFrom`. pub trait FuntyPart: Sized + TryFrom { + /// Convert a `u8` value to `Self`. + /// + /// # Panics + /// + /// This should never panic for unsigned integer types as they all + /// implement `TryFrom` with `Error = Infallible`. fn funty(n: u8) -> Self; } -// TryFrom has `Error = Infallible` for all types -impl> const FuntyPart for All { - fn funty(n: u8) -> Self - where - All: ~const Destruct, - >::Error: ~const Destruct, - { - // std `Result::unwrap_unchecked` is not const - match All::try_from(n) { - Ok(all) => all, - Err(_) => { - // >::Error is Infallible - unsafe { hint::unreachable_unchecked() } - } - } +// TryFrom has `Error = Infallible` for all unsigned integer types +impl FuntyPart for T +where + T: TryFrom, + >::Error: Debug, +{ + fn funty(n: u8) -> Self { + T::try_from(n).expect("conversion from u8 should never fail for unsigned types") } } -// fixme: track https://github.com/rust-lang/rust/issues/67792 -#[const_trait] +/// Trait for types that can be used as link identifiers. +/// +/// This trait bounds the type to be an unsigned integer with +/// various conversion capabilities. pub trait LinkType: Unsigned + FuntyPart - + Step + TryFrom + TryFrom + TryFrom @@ -63,8 +63,10 @@ pub trait LinkType: { } -impl const LinkType for All where - All: TryFrom +impl LinkType for T where + T: Unsigned + + FuntyPart + + TryFrom + TryFrom + TryFrom + TryFrom diff --git a/src/point.rs b/src/point.rs index 5d79dfa..3842428 100644 --- a/src/point.rs +++ b/src/point.rs @@ -49,9 +49,9 @@ impl Point { impl IntoIterator for Point { type Item = T; - type IntoIter = impl Iterator; + type IntoIter = std::iter::RepeatN; fn into_iter(self) -> Self::IntoIter { - (0..self.len()).map(move |_| self.index) + std::iter::repeat_n(self.index, self.size) } } diff --git a/tests/flow.rs b/tests/flow.rs index b6b4a84..637f203 100644 --- a/tests/flow.rs +++ b/tests/flow.rs @@ -1,13 +1,35 @@ use platform_data::Flow; +use std::ops::ControlFlow; #[test] fn basic() { let mut vec = vec![]; - (0..20).try_for_each(|i| { + for i in 0..20 { vec.push(i); - if i == 10 { Flow::Break } else { Flow::Continue } - }); + let flow = if i == 10 { Flow::Break } else { Flow::Continue }; + if flow.is_break() { + break; + } + } assert_eq!(vec, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); } + +#[test] +fn from_control_flow() { + let continue_flow: Flow = ControlFlow::<(), ()>::Continue(()).into(); + assert!(continue_flow.is_continue()); + + let break_flow: Flow = ControlFlow::<(), ()>::Break(()).into(); + assert!(break_flow.is_break()); +} + +#[test] +fn into_control_flow() { + let cf: ControlFlow<()> = Flow::Continue.into(); + assert!(matches!(cf, ControlFlow::Continue(()))); + + let cf: ControlFlow<()> = Flow::Break.into(); + assert!(matches!(cf, ControlFlow::Break(()))); +} From 34de66b10b09c79e149ec27295d132d19fef3938 Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 27 Dec 2025 18:41:49 +0100 Subject: [PATCH 3/4] Revert "Initial commit with task details" This reverts commit 443693b948def8784b3bf5f81057488ac3f8c31e. --- CLAUDE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index bf21242..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: https://github.com/linksplatform/core-rs/issues/8 -Your prepared branch: issue-8-53c25630aa7b -Your prepared working directory: /tmp/gh-issue-solver-1766856689023 - -Proceed. \ No newline at end of file From 59016a29bab9d3c2315214a82a3affc627e98271 Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 27 Dec 2025 22:00:29 +0100 Subject: [PATCH 4/4] feat: migrate to stable Rust toolchain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR migrates the crate from nightly Rust to stable Rust (1.79+), removing all unstable feature flags while maintaining full functionality. Changes: - Remove all nightly feature flags from lib.rs - Simplify LinkType and FuntyPart traits (remove const, Step bound) - Replace Try trait on Flow with into_control_flow() method - Add explicit PointIter type for Point's IntoIterator - Update CI/CD to use dtolnay/rust-toolchain@stable - Update README to reflect stable Rust requirement - Fix clippy warnings (is_some_and, unit struct default) All 80 tests pass on stable Rust. Fixes #8 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/release.yml | 27 ++-- README.md | 26 ++-- .../20251227_183811_migrate_to_stable_rust.md | 28 ++-- rust-toolchain.toml | 2 +- src/constants.rs | 2 +- src/flow.rs | 36 ++--- src/lib.rs | 12 +- src/link_type.rs | 41 +++--- src/point.rs | 36 ++++- tests/flow.rs | 125 ++++++++++-------- tests/hybrid.rs | 4 +- 11 files changed, 187 insertions(+), 152 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2928ac5..1a8b967 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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: | diff --git a/README.md b/README.md index bac34c9..54e01be 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 diff --git a/changelog.d/20251227_183811_migrate_to_stable_rust.md b/changelog.d/20251227_183811_migrate_to_stable_rust.md index c010e6f..1011b9e 100644 --- a/changelog.d/20251227_183811_migrate_to_stable_rust.md +++ b/changelog.d/20251227_183811_migrate_to_stable_rust.md @@ -1,11 +1,23 @@ ### Changed -- Migrated from nightly Rust to stable Rust toolchain -- Removed all unstable feature flags (`try_trait_v2`, `type_alias_impl_trait`, `const_trait_impl`, `step_trait`, etc.) -- Simplified `Flow` type by removing `Try` trait implementation -- Simplified `LinkType` and `FuntyPart` traits by removing const trait features -- Updated CI/CD pipeline to use stable Rust toolchain -- Updated `rustfmt.toml` to use stable-compatible options only +- 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 -- Removed unused imports in `converters.rs` and `hybrid.rs` -- Applied clippy suggestions for `is_some_and` and `repeat_n` +- Crate now compiles on stable Rust without any feature flags diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d7c5705..292fe49 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,2 @@ [toolchain] -channel = "nightly-2022-08-22" +channel = "stable" diff --git a/src/constants.rs b/src/constants.rs index 3cb2b4b..597a87b 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -96,7 +96,7 @@ impl LinksConstants { 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 { diff --git a/src/flow.rs b/src/flow.rs index f4e8a0a..4c88463 100644 --- a/src/flow.rs +++ b/src/flow.rs @@ -1,4 +1,4 @@ -use std::ops::{ControlFlow, FromResidual, Try}; +use std::ops::ControlFlow; /// Represents the control flow of an operation, similar to `ControlFlow`. /// @@ -21,26 +21,26 @@ impl Flow { pub fn is_break(&self) -> bool { matches!(self, Flow::Break) } -} - -impl FromResidual for Flow { - fn from_residual(_: ::Residual) -> Self { - Flow::Break - } -} -impl Try for Flow { - type Output = (); - type Residual = Flow; - - fn from_output(_: Self::Output) -> Self { - Flow::Continue - } - - fn branch(self) -> ControlFlow { + /// 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(()), } } } diff --git a/src/lib.rs b/src/lib.rs index ee19c31..fe865e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; @@ -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}; diff --git a/src/link_type.rs b/src/link_type.rs index 4c65df8..84e1d26 100644 --- a/src/link_type.rs +++ b/src/link_type.rs @@ -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 { + /// Create a value from a u8. Panics if the conversion fails. fn funty(n: u8) -> Self; } -// TryFrom has `Error = Infallible` for all types -impl> const FuntyPart for All { - fn funty(n: u8) -> Self - where - All: ~const Destruct, - >::Error: ~const Destruct, - { - // std `Result::unwrap_unchecked` is not const - match All::try_from(n) { - Ok(all) => all, - Err(_) => { - // >::Error is Infallible - unsafe { hint::unreachable_unchecked() } - } - } +impl> FuntyPart for All +where + >::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 + TryFrom + TryFrom @@ -63,7 +58,7 @@ pub trait LinkType: { } -impl const LinkType for All where +impl LinkType for All where All: TryFrom + TryFrom + TryFrom diff --git a/src/point.rs b/src/point.rs index 5d79dfa..a981398 100644 --- a/src/point.rs +++ b/src/point.rs @@ -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 { index: T, size: usize, @@ -47,11 +51,39 @@ impl Point { } } +/// Iterator for Point that yields copies of the stored value. +pub struct PointIter { + value: T, + remaining: usize, +} + +impl Iterator for PointIter { + type Item = T; + + fn next(&mut self) -> Option { + if self.remaining > 0 { + self.remaining -= 1; + Some(self.value) + } else { + None + } + } + + fn size_hint(&self) -> (usize, Option) { + (self.remaining, Some(self.remaining)) + } +} + +impl ExactSizeIterator for PointIter {} + impl IntoIterator for Point { type Item = T; - type IntoIter = impl Iterator; + type IntoIter = PointIter; fn into_iter(self) -> Self::IntoIter { - (0..self.len()).map(move |_| self.index) + PointIter { + value: self.index, + remaining: self.size, + } } } diff --git a/tests/flow.rs b/tests/flow.rs index 41d4937..8888710 100644 --- a/tests/flow.rs +++ b/tests/flow.rs @@ -1,7 +1,5 @@ -#![feature(try_trait_v2)] - use platform_data::Flow; -use std::ops::{ControlFlow, FromResidual, Try}; +use std::ops::ControlFlow; #[test] fn basic() { @@ -19,21 +17,21 @@ fn basic() { } #[test] -fn test_flow_continue() { +fn test_flow_continue_with_control_flow() { let mut count = 0; - (0..5).try_for_each(|_| { + let _ = (0..5).try_for_each(|_| { count += 1; - Flow::Continue + Flow::Continue.into_control_flow() }); assert_eq!(count, 5); } #[test] -fn test_flow_break_early() { +fn test_flow_break_early_with_control_flow() { let mut count = 0; - (0..100).try_for_each(|_| { + let _ = (0..100).try_for_each(|_| { count += 1; - Flow::Break + Flow::Break.into_control_flow() }); assert_eq!(count, 1); // Should stop after first iteration } @@ -43,16 +41,7 @@ fn test_from_control_flow_continue() { // Test conversion from ControlFlow::Continue let cf: ControlFlow = ControlFlow::Continue(()); let flow: Flow = cf.into(); - // We can't directly compare Flow values, but we can verify the conversion happened - // by checking behavior - the flow should be Continue - let result = std::iter::once(0).try_for_each(|_| { - let cf2: ControlFlow = ControlFlow::Continue(()); - let _: Flow = cf2.into(); - Flow::Continue - }); - // Verify the result is ok (iterator completed) - let _ = result; - let _ = flow; // Use the flow variable + assert!(flow.is_continue()); } #[test] @@ -60,50 +49,17 @@ fn test_from_control_flow_break() { // Test conversion from ControlFlow::Break let cf: ControlFlow<(), i32> = ControlFlow::Break(()); let flow: Flow = cf.into(); - let _ = flow; // Use the flow variable + assert!(flow.is_break()); // Verify Break behavior let mut count = 0; - (0..10).try_for_each(|_| { + let _ = (0..10).try_for_each(|_| { count += 1; - let cf2: ControlFlow<(), i32> = ControlFlow::Break(()); - let f: Flow = cf2.into(); - f + Flow::Break.into_control_flow() }); assert_eq!(count, 1); } -#[test] -fn test_try_trait_from_output() { - // Test that Flow::from_output returns Continue - let flow = Flow::from_output(()); - let _ = flow; // Use the flow variable - - // Verify from_output behavior by testing in iteration - let mut count = 0; - std::iter::once(()).try_for_each(|_| { - count += 1; - Flow::from_output(()) - }); - assert_eq!(count, 1); -} - -#[test] -fn test_from_residual() { - // Test FromResidual implementation - let flow: Flow = Flow::from_residual(Flow::Break); - let _ = flow; // Use the flow variable - - // Verify from_residual behavior - let mut count = 0; - (0..10).try_for_each(|_| { - count += 1; - Flow::from_residual(Flow::Break) - }); - // from_residual(Break) returns Break, so should stop after first - assert_eq!(count, 1); -} - #[test] fn from_control_flow() { let continue_flow: Flow = ControlFlow::<(), ()>::Continue(()).into(); @@ -121,3 +77,62 @@ fn into_control_flow() { let cf: ControlFlow<()> = Flow::Break.into(); assert!(matches!(cf, ControlFlow::Break(()))); } + +#[test] +fn test_into_control_flow_method() { + // Test the into_control_flow() method + let continue_cf = Flow::Continue.into_control_flow(); + assert!(matches!(continue_cf, ControlFlow::Continue(()))); + + let break_cf = Flow::Break.into_control_flow(); + assert!(matches!(break_cf, ControlFlow::Break(()))); +} + +#[test] +fn test_flow_with_iterator() { + // Test using Flow with iterators via into_control_flow + let mut collected = vec![]; + let _ = (0..20).try_for_each(|i| { + collected.push(i); + 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]); +} + +#[test] +fn test_is_continue() { + assert!(Flow::Continue.is_continue()); + assert!(!Flow::Break.is_continue()); +} + +#[test] +fn test_is_break() { + assert!(Flow::Break.is_break()); + assert!(!Flow::Continue.is_break()); +} + +#[test] +fn test_flow_copy() { + let flow = Flow::Continue; + let copied1 = flow; + let copied2 = flow; + assert_eq!(flow, copied1); + assert_eq!(flow, copied2); +} + +#[test] +fn test_flow_eq() { + assert_eq!(Flow::Continue, Flow::Continue); + assert_eq!(Flow::Break, Flow::Break); + assert_ne!(Flow::Continue, Flow::Break); +} + +#[test] +fn test_flow_debug() { + assert_eq!(format!("{:?}", Flow::Continue), "Continue"); + assert_eq!(format!("{:?}", Flow::Break), "Break"); +} diff --git a/tests/hybrid.rs b/tests/hybrid.rs index ef4ff61..8710b97 100644 --- a/tests/hybrid.rs +++ b/tests/hybrid.rs @@ -76,7 +76,7 @@ fn test_hybrid_as_inner() { #[test] fn test_addr_to_raw_default() { - let converter = AddrToRaw::default(); + let converter = AddrToRaw; let result = converter.convert(100usize); // convert creates an external hybrid and returns its inner value assert!(result > 0); @@ -84,7 +84,7 @@ fn test_addr_to_raw_default() { #[test] fn test_raw_to_addr_default() { - let converter = RawToAddr::default(); + let converter = RawToAddr; let result = converter.convert(100usize); // convert creates an external hybrid and returns its abs value assert!(result > 0);