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}