app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 99c644eb61fc8cb0c987318c5bafa61200e425ef
parent 439e22843499a36f628de40d726dfec00f65599d
Author: triesap <triesap@radroots.dev>
Date:   Wed, 21 Jan 2026 19:52:39 +0000

ui: add core id helper

- add no-std ui-core id sequence and prefixed ids

- expose RadrootsAppUiId and RadrootsAppUiIdSequence

- implement atomic global counter for ids

- add unit tests for id sequencing and prefixing

Diffstat:
Acrates/ui-core/src/id.rs | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/ui-core/src/lib.rs | 7+++++++
2 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/crates/ui-core/src/id.rs b/crates/ui-core/src/id.rs @@ -0,0 +1,82 @@ +use alloc::string::{String, ToString}; +use core::sync::atomic::{AtomicUsize, Ordering}; + +static RADROOTS_APP_UI_ID_SEQ: AtomicUsize = AtomicUsize::new(0); + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct RadrootsAppUiId { + value: usize, +} + +impl RadrootsAppUiId { + pub fn next() -> Self { + let value = RADROOTS_APP_UI_ID_SEQ.fetch_add(1, Ordering::Relaxed); + Self { value } + } + + pub const fn value(self) -> usize { + self.value + } + + pub fn prefixed(self, prefix: &str) -> String { + let mut out = String::with_capacity(prefix.len() + 1 + 20); + out.push_str(prefix); + out.push('-'); + out.push_str(self.value.to_string().as_str()); + out + } +} + +#[derive(Debug, Default, Clone)] +pub struct RadrootsAppUiIdSequence { + next: usize, +} + +impl RadrootsAppUiIdSequence { + pub const fn new() -> Self { + Self { next: 0 } + } + + pub fn next(&mut self) -> RadrootsAppUiId { + let value = self.next; + self.next = self.next.saturating_add(1); + RadrootsAppUiId { value } + } + + pub const fn peek(&self) -> usize { + self.next + } +} + +#[cfg(test)] +mod tests { + use super::{RadrootsAppUiId, RadrootsAppUiIdSequence}; + + #[test] + fn id_sequence_increments() { + let first = RadrootsAppUiId::next().value(); + let second = RadrootsAppUiId::next().value(); + assert!(second > first); + } + + #[test] + fn id_prefix_builds_value() { + let id = RadrootsAppUiId { value: 7 }; + assert_eq!(id.prefixed("radroots"), "radroots-7"); + } + + #[test] + fn id_sequence_local_increments() { + let mut seq = RadrootsAppUiIdSequence::new(); + let first = seq.next(); + let second = seq.next(); + assert_eq!(first.value(), 0); + assert_eq!(second.value(), 1); + } + + #[test] + fn id_sequence_peek_is_next_value() { + let seq = RadrootsAppUiIdSequence::new(); + assert_eq!(seq.peek(), 0); + } +} diff --git a/crates/ui-core/src/lib.rs b/crates/ui-core/src/lib.rs @@ -1 +1,8 @@ #![forbid(unsafe_code)] +#![no_std] + +extern crate alloc; + +mod id; + +pub use id::{RadrootsAppUiId, RadrootsAppUiIdSequence};