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:
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};