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