const_str/__ctfe/
sorted.rs1const fn str_clone<'a, const N: usize>(ss: &[&'a str]) -> [&'a str; N] {
2 assert!(ss.len() == N);
3 let mut buf = [""; N];
4 let mut i = 0;
5 while i < ss.len() {
6 buf[i] = ss[i];
7 i += 1;
8 }
9 buf
10}
11
12const fn str_sorted<'a, const N: usize>(ss: &[&'a str]) -> [&'a str; N] {
13 let mut buf = str_clone(ss);
14
15 let mut l = N;
16 while l > 1 {
17 let mut swapped = false;
18
19 let mut i = 0;
20 while i < l - 1 {
21 let (lhs, rhs) = (buf[i], buf[i + 1]);
22 if crate::compare!(>, lhs, rhs) {
23 (buf[i], buf[i + 1]) = (rhs, lhs);
24 swapped = true;
25 }
26 i += 1;
27 }
28
29 if !swapped {
30 break;
31 }
32
33 l -= 1;
34 }
35
36 buf
37}
38
39pub struct Sorted<T>(pub T);
40
41impl<'a> Sorted<&[&'a str]> {
42 pub const fn output_len(&self) -> usize {
43 self.0.len()
44 }
45
46 pub const fn const_eval<const N: usize>(&self) -> [&'a str; N] {
47 str_sorted(self.0)
48 }
49}
50
51impl<'a, const L: usize> Sorted<[&'a str; L]> {
52 pub const fn output_len(&self) -> usize {
53 L
54 }
55
56 pub const fn const_eval(&self) -> [&'a str; L] {
57 str_sorted(&self.0)
58 }
59}
60
61impl<'a, const L: usize> Sorted<&[&'a str; L]> {
62 pub const fn output_len(&self) -> usize {
63 L
64 }
65
66 pub const fn const_eval(&self) -> [&'a str; L] {
67 str_sorted(self.0)
68 }
69}
70
71#[macro_export]
91macro_rules! sorted {
92 ($s:expr) => {{
93 const N: usize = $crate::__ctfe::Sorted($s).output_len();
94 const SS: [&str; N] = $crate::__ctfe::Sorted($s).const_eval();
95 SS
96 }};
97}
98
99#[cfg(test)]
100mod tests {
101 fn std_sorted<'a>(iter: impl IntoIterator<Item = &'a str>) -> Vec<&'a str> {
102 let mut v: Vec<_> = iter.into_iter().collect();
103 v.sort_unstable();
104 v
105 }
106
107 #[test]
108 fn test_sorted() {
109 macro_rules! testcase {
110 ($s:expr) => {
111 let const_sorted = sorted!($s);
112 let std_sorted = std_sorted($s);
113 assert_eq!(const_sorted, &*std_sorted);
114 };
115 }
116
117 testcase!([]);
118 testcase!(["a"]);
119 testcase!(["a", "a"]);
120 testcase!(["b", "a"]);
121 testcase!(["a", "b", "c"]);
122 testcase!(["b", "a", "c"]);
123 testcase!(["c", "b", "a"]);
124 testcase!(["1", "2", "10", "20", "3"]);
125 }
126
127 #[test]
128 fn test_sorted_runtime() {
129 use super::*;
130
131 let sorted1 = Sorted(&["c", "a", "b"]);
133 assert_eq!(sorted1.output_len(), 3);
134 let result1: [&str; 3] = sorted1.const_eval();
135 assert_eq!(result1, ["a", "b", "c"]);
136
137 let sorted2 = Sorted(&["z", "a", "m", "b"]);
138 assert_eq!(sorted2.output_len(), 4);
139 let result2: [&str; 4] = sorted2.const_eval();
140 assert_eq!(result2, ["a", "b", "m", "z"]);
141
142 let empty: &[&str] = &[];
143 let sorted_empty = Sorted(empty);
144 assert_eq!(sorted_empty.output_len(), 0);
145
146 let sorted_single = Sorted(&["only"]);
147 let result_single: [&str; 1] = sorted_single.const_eval();
148 assert_eq!(result_single, ["only"]);
149
150 let sorted_duplicates = Sorted(&["x", "x", "y"]);
151 let result_dup: [&str; 3] = sorted_duplicates.const_eval();
152 assert_eq!(result_dup, ["x", "x", "y"]);
153 }
154
155 #[test]
156 fn test_sorted_different_types() {
157 use super::*;
158
159 let array: [&str; 3] = ["c", "a", "b"];
161 let sorted_array = Sorted(array);
162 assert_eq!(sorted_array.output_len(), 3);
163 let result_array: [&str; 3] = sorted_array.const_eval();
164 assert_eq!(result_array, ["a", "b", "c"]);
165 }
166}