From 73ca64e4e95ab483ec9b212725d8c143410a82ee Mon Sep 17 00:00:00 2001 From: Chris Mounce Date: Tue, 17 Jun 2025 01:22:18 -0700 Subject: [PATCH] Add helper for generating anonymous labels --- src/labels/sanitize.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/labels/sanitize.rs b/src/labels/sanitize.rs index 9b223e4..ba8bbcb 100644 --- a/src/labels/sanitize.rs +++ b/src/labels/sanitize.rs @@ -27,6 +27,7 @@ impl LabelId { pub struct Registry { label_transforms: HashMap, existing: HashSet, + anonymous_counter: CompactString, } enum Transform { @@ -61,6 +62,7 @@ impl Registry { Self { label_transforms, existing, + anonymous_counter: "_".into(), } } @@ -103,6 +105,15 @@ impl Registry { candidate } + pub fn gen_anonymous(&mut self) -> CompactString { + while self.existing.contains(&self.anonymous_counter) { + increment(&mut self.anonymous_counter); + } + let result = self.anonymous_counter.clone(); + increment(&mut self.anonymous_counter); + result + } + fn preferred_name(label: &LabelName) -> CompactString { let src = if let Some(local) = &label.local { local @@ -183,7 +194,7 @@ fn increment(s: &mut CompactString) { mod test { use std::collections::HashSet; - use compact_str::CompactString; + use compact_str::{CompactString, CompactStringExt}; use insta::assert_snapshot; use crate::labels::{parse::LabelName, sanitize::Registry}; @@ -299,4 +310,23 @@ mod test { LabelName { namespace: None, name: "foo2bar", local: None } => foo_bar "#); } + + #[test] + fn test_gen_anonymous() { + let mut registry = Registry::new(); + for letter in ["a", "e", "i"] { + registry.sanitize(&LabelName { + namespace: None, + name: letter.into(), + local: None, + }); + } + let result: Vec<_> = (0..10).map(|_| registry.gen_anonymous()).collect(); + let result = result.join(", "); + + // It's safer if anonymous labels don't start with a digit. + // If one ever did, it could change `#take gems 123@f` to something + // like `#take gems 1230`, altering how the ZZT-OOP parses. + assert_snapshot!(result, @"_, b, c, d, f, g, h, j, k, l"); + } }