strings.rs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // /// String that gets cropped if it exceeds a certain size.
  2. // #[derive(PartialEq, Eq, Hash, Debug)]
  3. // struct SizeCappedString<const N: usize> {
  4. // inner: String,
  5. // length: usize,
  6. // is_cropped: bool,
  7. // }
  8. // impl<const N: usize> SizeCappedString<N> {
  9. // const MAX_SIZE: usize = N;
  10. // pub fn new(data: String) -> Self {
  11. // let length = data.len();
  12. // if length > Self::MAX_SIZE {
  13. // Self {
  14. // inner: data[..Self::MAX_SIZE].to_string(),
  15. // length,
  16. // is_cropped: true,
  17. // }
  18. // } else {
  19. // Self {
  20. // inner: data,
  21. // length,
  22. // is_cropped: false,
  23. // }
  24. // }
  25. // }
  26. // pub fn to_string_lossy(&self) -> String {
  27. // self.inner.clone()
  28. // }
  29. // pub fn to_string_marked(&self, mark: &str) -> String {
  30. // if self.is_cropped {
  31. // format!("{}{}", self.inner, mark)
  32. // } else {
  33. // self.inner.clone()
  34. // }
  35. // }
  36. // pub fn to_string(&self) -> Option<String> {
  37. // if self.is_cropped {
  38. // None
  39. // } else {
  40. // Some(self.inner.clone())
  41. // }
  42. // }
  43. // }
  44. /// String with a consistent size.
  45. #[derive(Debug, Clone, PartialEq, Eq)]
  46. pub struct StaticString<const N: usize>([char; N]);
  47. impl<const N: usize> From<&StaticString<N>> for String {
  48. fn from(value: &StaticString<N>) -> Self {
  49. let mut result = String::new();
  50. for &c in value.0.iter() {
  51. if c == 0 as char {
  52. break;
  53. }
  54. result.push(c);
  55. }
  56. result
  57. }
  58. }
  59. impl<const N: usize> From<String> for StaticString<N> {
  60. fn from(value: String) -> Self {
  61. let mut s = Self::new();
  62. for (i, c) in value.chars().take(N).enumerate() {
  63. s.0[i] = c;
  64. }
  65. s
  66. }
  67. }
  68. impl<const N: usize> Default for StaticString<N> {
  69. fn default() -> Self {
  70. Self::new()
  71. }
  72. }
  73. impl<const N: usize> StaticString<N> {
  74. pub fn new() -> Self {
  75. StaticString([0 as char; N])
  76. }
  77. pub fn is_empty(&self) -> bool {
  78. let first = self.0.first();
  79. first.is_none() || first == Some(&(0 as char))
  80. }
  81. }
  82. pub fn insensitive_string(s: &str) -> String {
  83. let out = s.to_lowercase();
  84. assert_eq!(out.len(), s.len());
  85. out
  86. }
  87. pub fn remove_bad_words(s: &str, wordlist: &[String], censor_char: char) -> String {
  88. let mut s = s.to_string();
  89. let mut s_ins = insensitive_string(&s);
  90. for word in wordlist {
  91. let word_len = word.len();
  92. let replacement = censor_char.to_string().repeat(word_len);
  93. while let Some(start) = s_ins.find(word) {
  94. let end = start + word_len;
  95. s.replace_range(start..end, &replacement);
  96. s_ins = insensitive_string(&s);
  97. }
  98. }
  99. s
  100. }