rep_str/lib.rs
1//! This is a crate for caching a repeat pattern of a str
2//! with only one allocation by generate a new `RepStr` struct
3//! this crate provides.
4//! # Example 1: Crate RepStr directly.
5//! ```rust
6//! use rep_str::RepStr;
7//! let repstr = rep_str::RepStr::new("#", 50); // generate a RepStr object with max repeat time 50
8//! assert!("##########" == repstr.repeat_unwrap(10));
9//! assert!("####################" == repstr.repeat_unwrap(20));
10//! // no extra allocation would occurs:
11//! assert!(repstr.repeat_unwrap(20).as_ptr() == repstr.repeat(12).unwrap().as_ptr())
12//! // repstr.repeat_unwrap(51) // panic!
13//! ```
14//! # Example 2: Crate RepStr by IntoRepStr trait
15//! ```rust
16//! use rep_str::IntoRepStr;
17//! let repstr = "🦀".repeat_cache(20);
18//! assert!(Some("🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀🦀") == repstr.repeat(20));
19//! assert!(None == repstr.repeat(21));
20//! ```
21#[cfg(test)]
22mod tests {
23 use crate::*;
24 #[test]
25 fn rep_str_new_and_repeat_unwrap() {
26 let repstr = RepStr::new("#", 50);
27 assert!(format!("{empty:#>width$}", empty = "", width = 20) == repstr.repeat_unwrap(20));
28 assert!(repstr.repeat_unwrap(20).as_ptr()==repstr.repeat(12).unwrap().as_ptr())
29 }
30 #[test]
31 fn rep_str_into_rep_str_check(){
32 let repstr = "#".repeat_cache(20);
33 assert!(format!("{empty:#>width$}", empty = "", width = 20) == repstr.repeat(20).unwrap());
34 assert!(None == repstr.repeat(21));
35 }
36}
37/// The cache result for a repeatable string.
38pub struct RepStr {
39 cache: String,
40 orig_len: usize,
41}
42impl RepStr {
43 pub fn new(s: &str, max_repeat_time: usize) -> Self {
44 Self {
45 cache: s.repeat(max_repeat_time),
46 orig_len: s.len(),
47 }
48 }
49 #[inline(always)]
50 /// This is the function to extract reference of a str with the given repeat time
51 /// would panic if the given repeat time is larger than max_repeat_time.
52 pub fn repeat_unwrap(&self, repeat: usize) -> &str {
53 self.cache.split_at(repeat * self.orig_len).0
54 }
55 /// This is a basic function to extract reference of a str with the given repeat time
56 /// will return Some<&str> if the given repeat time is smaller than max_repeat_time
57 /// otherwise return None.
58 pub fn repeat(&self, repeat: usize) -> Option<&str> {
59 if repeat * self.orig_len <= self.cache.len() {
60 Some(self.repeat_unwrap(repeat))
61 } else {
62 None
63 }
64 }
65}
66pub trait IntoRepStr{
67 fn repeat_cache(self,repeat:usize)->RepStr;
68}
69impl IntoRepStr for &str{
70 fn repeat_cache(self,repeat:usize)->RepStr{
71 RepStr::new(self,repeat)
72 }
73}
74