light_id/lib.rs
1//! # light_id
2//!
3//! `light_id` is a Rust crate for generating and manipulating light-weight IDs. It provides a flexible and customizable way to generate and switch between different bases for IDs.
4//!
5//! ## Features
6//!
7//! - Lightweight and customizable ID generation.
8//! - Switching IDs between different bases.
9//! - Skipping and iterating through IDs.
10//!
11//! ## Example
12//!
13//! ```rust
14//! use light_id::{LightId, IdSwitcher};
15//!
16//! let mut generator = LightId::new();
17//! println!("Current ID: {}", generator.next());
18//!
19//! let switcher = IdSwitcher::new("0123456789", "abcdef");
20//! let switched_id = switcher.switch("2");
21//! println!("Switched ID: {}", switched_id);
22//! ```
23//!
24//! ## Installation
25//!
26//! Add the following lines to your `Cargo.toml` file:
27//!
28//! ```toml
29//! [dependencies]
30//! light-id = "0.1.0"
31//! ```
32//!
33//! ## Usage
34//!
35//! ### LightId
36//!
37//! The `LightId` struct allows you to generate and manipulate IDs with various options.
38//!
39//! ```rust
40//! use light_id::LightId;
41//!
42//! let mut generator = LightId::new();
43//! generator.increment();
44//! println!("Current ID: {}", generator.current());
45//! ```
46//!
47//! ### IdSwitcher
48//!
49//! The `IdSwitcher` struct facilitates switching IDs between different bases.
50//!
51//! ```rust
52//! use light_id::IdSwitcher;
53//!
54//! let switcher = IdSwitcher::new("0123456789", "abcdef");
55//! let switched_id = switcher.switch("2");
56//! println!("Switched ID: {}", switched_id);
57//! ```
58//!
59//! ## API Documentation
60//!
61//! See the detailed documentation for each struct, including methods and usage examples.
62//!
63//! - [`LightId`](struct.LightId.html)
64//! - [`IdSwitcher`](struct.IdSwitcher.html)
65//!
66//! ## License
67//!
68//! This crate is licensed under the [MIT License](https://opensource.org/licenses/MIT).
69//!
70//! ## Changelog
71//!
72//! - **0.1.0** (2023-12-14): Initial release
73
74mod utils;
75
76pub const DEFAULT_CHARACTERS: &str =
77 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
78
79pub struct LightId {
80 pub characters: Vec<char>,
81 pub min_length: usize,
82 status: usize,
83}
84
85impl PartialEq for LightId {
86 fn eq(&self, other: &Self) -> bool {
87 self.count() == other.count() && self.characters == other.characters
88 }
89}
90
91impl PartialOrd for LightId {
92 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
93 Some(self.count().cmp(&other.count()))
94 }
95}
96
97impl LightId {
98 /// Creates a new [`LightId`] with the default configuration.
99 /// ```
100 /// use light_id::LightId;
101 ///
102 /// let mut generator = LightId::new();
103 /// ```
104 pub fn new() -> Self {
105 LightId {
106 status: 0,
107 characters: DEFAULT_CHARACTERS.chars().collect(),
108 min_length: 0,
109 }
110 }
111
112 /// Creates a new [`LightId`] with a custom alphabet
113 /// ```
114 /// use light_id::LightId;
115 ///
116 /// let generator = LightId::from("abcdef");
117 /// ```
118 /// If the provided `characters` is equal to [`DEFAULT_CHARACTERS`], the expression can be replaced with
119 /// ```
120 /// use light_id::LightId;
121 ///
122 /// let generator = LightId::new();
123 /// ```
124 pub fn from<S: AsRef<str>>(characters: S) -> Self {
125 LightId {
126 status: 0,
127 characters: characters.as_ref().chars().collect(),
128 min_length: 0,
129 }
130 }
131
132 /// Skip the first `n` ids
133 /// ```
134 /// use light_id::LightId;
135 ///
136 /// let mut generator = LightId::new();
137 ///
138 /// generator.skip(2);
139 ///
140 /// assert_eq!("2", generator.current());
141 /// ```
142 pub fn skip(&mut self, n: usize) -> &mut Self {
143 self.status = n;
144
145 self
146 }
147
148 /// Skips the first ids until the provided id.
149 /// ```
150 /// use light_id::LightId;
151 ///
152 /// let mut generator = LightId::new();
153 ///
154 /// generator.last("c");
155 ///
156 /// assert_eq!("c", generator.current());
157 /// ```
158 pub fn last<S: AsRef<str>>(&mut self, id: S) -> &mut Self {
159 self.status = utils::parse_id(id.as_ref(), &self.characters);
160 self
161 }
162
163 /// Sets the min length of the ids
164 /// ```
165 /// use light_id::LightId;
166 ///
167 /// let mut generator = LightId::new();
168 ///
169 /// generator.min(6);
170 ///
171 /// assert_eq!("000000", generator.current());
172 /// ```
173 pub fn min(&mut self, n: usize) -> &mut Self {
174 self.min_length = n;
175
176 self
177 }
178
179 /// Sets the possible characters, in their order of importance (custom base)
180 /// ```
181 /// use light_id::LightId;
182 ///
183 /// let mut generator = LightId::new();
184 ///
185 /// generator.chars("abc");
186 ///
187 /// assert_eq!("a", generator.current());
188 /// ```
189 pub fn chars<S: AsRef<str>>(&mut self, characters: S) -> &mut Self {
190 self.characters = characters.as_ref().chars().collect();
191 self
192 }
193
194 /// Clone the current [`LighId`].
195 /// ```
196 /// use light_id::LightId;
197 ///
198 /// let mut generator = LightId::new();
199 ///
200 /// let mut generator2 = generator.clone();
201 /// ```
202 pub fn clone(&self) -> Self {
203 LightId {
204 status: self.status.clone(),
205 characters: self.characters.clone(),
206 min_length: self.min_length.clone(),
207 }
208 }
209
210 /// Returns the current number of ids
211 /// ```
212 /// use light_id::LightId;
213 ///
214 /// let mut generator = LightId::new();
215 ///
216 /// generator.increment();
217 ///
218 /// assert_eq!(1, generator.count());
219 /// ```
220 pub fn count(&self) -> usize {
221 return self.status;
222 }
223
224 /// Decrements the current id.
225 /// Internally uses an alias to [`LightId::decrement_by`]
226 /// ```
227 /// use light_id::LightId;
228 ///
229 /// let mut generator = LightId::new();
230 ///
231 /// generator.increment();
232 /// generator.decrement();
233 ///
234 /// assert_eq!("0", generator.current());
235 /// ```
236 pub fn decrement(&mut self) -> &mut Self {
237 self.decrement_by(1)
238 }
239
240 /// Decrements the current id with a given factor
241 /// ```
242 /// use light_id::LightId;
243 ///
244 /// let mut generator = LightId::new();
245 ///
246 /// generator.increment_by(10);
247 /// generator.decrement_by(10);
248 ///
249 /// assert_eq!("0", generator.current());
250 /// ```
251 pub fn decrement_by(&mut self, count: usize) -> &mut Self {
252 if count > self.status {
253 self.status = 0;
254 } else {
255 self.status -= count;
256 }
257 self
258 }
259
260 /// Increments the current id by one.
261 /// Internally uses an alias to [`LightId::increment_by`]
262 /// ```
263 /// use light_id::LightId;
264 ///
265 /// let mut generator = LightId::new();
266 ///
267 /// generator.increment();
268 ///
269 /// assert_eq!("1", generator.current());
270 /// ```
271 pub fn increment(&mut self) -> &mut Self {
272 self.increment_by(1)
273 }
274
275 /// Increments the current id with a given factor
276 /// ```
277 /// use light_id::LightId;
278 ///
279 /// let mut generator = LightId::new();
280 ///
281 /// generator.increment_by(10);
282 ///
283 /// assert_eq!("a", generator.current());
284 /// ```
285 pub fn increment_by(&mut self, count: usize) -> &mut Self {
286 self.status += count;
287
288 self
289 }
290
291 /// Increments the id by one and returns it.
292 /// ```
293 /// use light_id::LightId;
294 ///
295 /// let mut generator = LightId::new();
296 ///
297 /// assert_eq!("0", generator.next());
298 /// assert_eq!("1", generator.next());
299 /// assert_eq!("2", generator.next());
300 /// ```
301 /// Internally uses an alias to [`LightId::current`] and [`LightId::increment`]
302 /// ```
303 /// use light_id::LightId;
304 ///
305 /// let mut generator = LightId::new();
306 ///
307 /// let value = generator.current();
308 /// generator.increment();
309 ///
310 /// assert_eq!("0", value);
311 /// ```
312 pub fn next(&mut self) -> String {
313 self.status += 1;
314 utils::format_id(&(&self.status - 1), &self.min_length, &self.characters)
315 }
316
317 /// Returns the current id.
318 /// ```
319 /// use light_id::LightId;
320 ///
321 /// let mut generator = LightId::new();
322 ///
323 /// assert_eq!("0", generator.current());
324 /// ```
325 pub fn current(&self) -> String {
326 utils::format_id(&self.status, &self.min_length, &self.characters)
327 }
328
329 /// Returns the length of the current id.
330 /// ```
331 /// use light_id::LightId;
332 ///
333 /// let mut generator = LightId::new();
334 ///
335 /// assert_eq!(1, generator.len());
336 ///
337 /// generator.increment_by(100);
338 ///
339 /// assert_eq!(2, generator.len());
340 /// ```
341 pub fn len(&self) -> usize {
342 if self.status == 0 {
343 return std::cmp::max(self.min_length, 1);
344 }
345 return std::cmp::max(
346 self.min_length,
347 self.status.ilog(self.characters.len()) as usize + 1,
348 );
349 }
350
351 /// Returns the nth id.
352 /// ```
353 /// use light_id::LightId;
354 ///
355 /// let generator = LightId::new();
356 ///
357 /// assert_eq!("2", generator.nth(2));
358 /// ```
359 pub fn nth(&self, n: usize) -> String {
360 utils::format_id(&n, &self.min_length, &self.characters)
361 }
362
363 /// Returns the index of the provided id
364 /// ```
365 /// use light_id::LightId;
366 ///
367 /// let generator = LightId::new();
368 ///
369 /// assert_eq!(2, generator.index("2"));
370 /// ```
371 pub fn index<S: AsRef<str>>(&self, id: S) -> usize {
372 utils::parse_id(id.as_ref(), &self.characters)
373 }
374}
375
376pub struct IdSwitcher {
377 source: Vec<char>,
378 source_min: usize,
379 target: Vec<char>,
380 target_min: usize,
381}
382
383impl IdSwitcher {
384
385 /// Create a new [`IdSwitcher`].
386 /// It can be used to switch the ids from a source base to a target base.
387 /// ```
388 /// use light_id::IdSwitcher;
389 ///
390 /// let switcher = IdSwitcher::new("0123456789", "abcdefghij");
391 /// ```
392 pub fn new<S: AsRef<str>>(source: S, target: S) -> Self {
393 IdSwitcher {
394 source: source.as_ref().chars().collect(),
395 source_min: 0,
396 target: target.as_ref().chars().collect(),
397 target_min: 0
398 }
399 }
400
401 /// Returns a copy of the [`IdSwitcher`].
402 /// ```
403 /// use light_id::IdSwitcher;
404 ///
405 /// let switcher = IdSwitcher::new("0123456789", "abcdefghij");
406 /// let switcher_2 = switcher.clone();
407 /// ```
408 pub fn clone (&self) -> Self {
409 IdSwitcher {
410 source: self.source.clone(),
411 source_min: self.source_min.clone(),
412 target: self.target.clone(),
413 target_min: self.target_min.clone(),
414 }
415 }
416
417 /// Sets the min length of the converted ids.
418 /// ```
419 /// use light_id::IdSwitcher;
420 ///
421 /// let mut switcher = IdSwitcher::new("0123456789", "abcdefghij");
422 ///
423 /// switcher.min_target(10);
424 ///
425 /// assert_eq!("aaaaaaaaaa", switcher.switch("0"));
426 /// ```
427 pub fn min_target(&mut self, n: usize) -> &mut Self {
428 self.target_min = n;
429
430 self
431 }
432
433 /// Sets the min length of the source ids.
434 /// ```
435 /// use light_id::IdSwitcher;
436 ///
437 /// let mut switcher = IdSwitcher::new("0123456789", "abcdefghij");
438 ///
439 /// switcher.min_source(10);
440 ///
441 /// assert_eq!("0000000000", switcher.switch_reverse("a"));
442 /// ```
443 pub fn min_source(&mut self, n: usize) -> &mut Self {
444 self.source_min = n;
445
446 self
447 }
448
449 /// Switches an id count from the source base to the target base.
450 /// ```
451 /// use light_id::IdSwitcher;
452 ///
453 /// let switcher = IdSwitcher::new("0123456789", "abcdefghij");
454 ///
455 /// assert_eq!("a", switcher.switch_count(0));
456 /// ```
457 pub fn switch_count(&self, id: usize) -> String {
458 utils::format_id(&id, &self.target_min, &self.target)
459 }
460
461 /// Switches an id from the source base to the target base.
462 /// ```
463 /// use light_id::IdSwitcher;
464 ///
465 /// let switcher = IdSwitcher::new("0123456789", "abcdefghij");
466 ///
467 /// assert_eq!("a", switcher.switch("0"));
468 /// ```
469 pub fn switch<S: AsRef<str>>(&self, id: S) -> String {
470 self.switch_count(utils::parse_id(id.as_ref(), &self.source))
471 }
472
473 /// Switches an id count from the target base to the source base.
474 /// ```
475 /// use light_id::IdSwitcher;
476 ///
477 /// let switcher = IdSwitcher::new("0123456789", "abcdefghij");
478 ///
479 /// assert_eq!("0", switcher.switch_count_reverse(0));
480 /// ```
481 pub fn switch_count_reverse(&self, id: usize) -> String {
482 utils::format_id(&id, &self.source_min, &self.source)
483 }
484
485 /// Switches an id from the target base to the source base.
486 /// ```
487 /// use light_id::IdSwitcher;
488 ///
489 /// let switcher = IdSwitcher::new("0123456789", "abcdefghij");
490 ///
491 /// assert_eq!("0", switcher.switch_reverse("a"));
492 /// ```
493 pub fn switch_reverse<S: AsRef<str>>(&self, id: S) -> String {
494 self.switch_count_reverse(utils::parse_id(id.as_ref(), &self.target))
495 }
496}