chilen_backend/music_lib/sorting/
mod.rs1use std::sync::{Arc, RwLock};
4
5use icu::collator::CollatorBorrowed;
6
7use crate::music_lib::{AsAlbum, AsArtist, AsGenre, AsPlaylist, AsTrack};
8
9pub(crate) static COLLATOR: RwLock<Option<Arc<CollatorBorrowed<'_>>>> = RwLock::new(None);
10
11pub fn sort_tracks<T: AsTrack>(tracks: &mut [T]) {
13 let guard = COLLATOR.read().unwrap();
14 let collator = guard.as_ref();
15
16 tracks.sort_by(|t1, t2| {
17 let t1 = t1.as_track().title.as_deref().unwrap_or_default();
18 let t2 = t2.as_track().title.as_deref().unwrap_or_default();
19 match collator {
20 Some(collator) => collator.compare(t1, t2),
21 None => t1.cmp(t2),
22 }
23 });
24}
25
26pub fn sort_tracks_chronologically<T: AsTrack>(tracks: &mut [T]) {
28 let guard = COLLATOR.read().unwrap();
29 let collator = guard.as_ref();
30
31 tracks.sort_by(|a, b| match (a.as_track().date, b.as_track().date) {
32 (Some(ad), Some(bd)) => bd.cmp(&ad),
33 (Some(_), None) => std::cmp::Ordering::Less,
34 (None, Some(_)) => std::cmp::Ordering::Greater,
35 (None, None) => {
36 let t1 = a.as_track().title.as_deref().unwrap_or_default();
37 let t2 = b.as_track().title.as_deref().unwrap_or_default();
38
39 match collator {
40 Some(collator) => collator.compare(t1, t2),
41 None => t1.cmp(t2),
42 }
43 }
44 });
45}
46
47pub fn sort_tracks_in_album<T: AsTrack>(tracks: &mut [T]) {
49 let guard = COLLATOR.read().unwrap();
50 let collator = guard.as_ref();
51
52 tracks.sort_by(|a, b| {
53 let a = a.as_track();
54 let b = b.as_track();
55
56 let disc_cmp = match (a.disc, b.disc) {
57 (Some(ad), Some(bd)) => ad.cmp(&bd),
58 (Some(_), None) => std::cmp::Ordering::Less,
59 (None, Some(_)) => std::cmp::Ordering::Greater,
60 (None, None) => std::cmp::Ordering::Equal,
61 };
62
63 let track_cmp = match (a.track, b.track) {
64 (Some(at), Some(bt)) => at.cmp(&bt),
65 (Some(_), None) => std::cmp::Ordering::Less,
66 (None, Some(_)) => std::cmp::Ordering::Greater,
67 (None, None) => std::cmp::Ordering::Equal,
68 };
69
70 disc_cmp.then(track_cmp).then_with(|| {
71 let s1 = a.title.as_deref().unwrap_or_default();
72 let s2 = b.title.as_deref().unwrap_or_default();
73 match collator {
74 Some(collator) => collator.compare(s1, s2),
75 None => s1.cmp(s2),
76 }
77 })
78 });
79}
80
81pub fn sort_tracks_by_artist<T: AsTrack>(tracks: &mut [T]) {
83 let guard = COLLATOR.read().unwrap();
84 let collator = guard.as_ref();
85
86 tracks.sort_by(|t1, t2| {
87 match (
88 t1.as_track().artists.as_ref(),
89 t2.as_track().artists.as_ref(),
90 ) {
91 (Some(l1), Some(l2)) => {
92 for (s1, s2) in l1.iter().zip(l2.iter()) {
93 let res = match collator {
94 Some(collator) => collator.compare(s1, s2),
95 None => s1.cmp(s2),
96 };
97 if res != std::cmp::Ordering::Equal {
98 return res;
99 }
100 }
101 l1.len().cmp(&l2.len())
102 }
103 (Some(_), None) => std::cmp::Ordering::Less,
104 (None, Some(_)) => std::cmp::Ordering::Greater,
105 (None, None) => std::cmp::Ordering::Equal,
106 }
107 });
108}
109
110pub fn sort_tracks_by_album<T: AsTrack>(tracks: &mut [T]) {
112 let guard = COLLATOR.read().unwrap();
113 let collator = guard.as_ref();
114
115 tracks.sort_by(|t1, t2| {
116 let s1 = t1.as_track().album.as_deref().unwrap_or_default();
117 let s2 = t2.as_track().album.as_deref().unwrap_or_default();
118
119 match collator {
120 Some(collator) => collator.compare(s1, s2),
121 None => s1.cmp(s2),
122 }
123 });
124}
125
126pub fn sort_albums<T: AsAlbum>(albums: &mut [T]) {
128 let guard = COLLATOR.read().unwrap();
129 let collator = guard.as_ref();
130
131 match collator {
132 Some(collator) => {
133 albums.sort_by(|a1, a2| collator.compare(&a1.as_album().title, &a2.as_album().title));
134 }
135 None => {
136 albums.sort_by(|a1, a2| a1.as_album().title.cmp(&a2.as_album().title));
137 }
138 }
139}
140
141pub fn sort_albums_chronologically<T: AsAlbum>(albums: &mut [T]) {
143 let guard = COLLATOR.read().unwrap();
144 let collator = guard.as_ref();
145
146 albums.sort_by(|a, b| match (a.as_album().date, b.as_album().date) {
147 (Some(ad), Some(bd)) => bd.cmp(&ad),
148 (Some(_), None) => std::cmp::Ordering::Less,
149 (None, Some(_)) => std::cmp::Ordering::Greater,
150 (None, None) => match collator {
151 Some(collator) => collator.compare(&a.as_album().title, &b.as_album().title),
152 None => a.as_album().title.cmp(&b.as_album().title),
153 },
154 });
155}
156
157pub fn sort_albums_by_artist<T: AsAlbum>(albums: &mut [T]) {
159 let guard = COLLATOR.read().unwrap();
160 let collator = guard.as_ref();
161
162 albums.sort_by(|a1, a2| {
163 let a1 = a1.as_album();
164 let a2 = a2.as_album();
165 for (s1, s2) in a1.artists.iter().zip(a2.artists.iter()) {
166 let res = match collator {
167 Some(collator) => collator.compare(s1, s2),
168 None => s1.cmp(s2),
169 };
170 if res != std::cmp::Ordering::Equal {
171 return res;
172 }
173 }
174 a1.artists.len().cmp(&a2.artists.len())
175 });
176}
177
178pub fn sort_artists<T: AsArtist>(artists: &mut [T]) {
180 let guard = COLLATOR.read().unwrap();
181 let collator = guard.as_ref();
182
183 match collator {
184 Some(collator) => {
185 artists.sort_by(|a1, a2| collator.compare(&a1.as_artist().name, &a2.as_artist().name));
186 }
187 None => {
188 artists.sort_by(|a1, a2| a1.as_artist().name.cmp(&a2.as_artist().name));
189 }
190 }
191}
192
193pub fn sort_playlists<T: AsPlaylist>(playlists: &mut [T]) {
195 let guard = COLLATOR.read().unwrap();
196 let collator = guard.as_ref();
197
198 match collator {
199 Some(collator) => {
200 playlists
201 .sort_by(|p1, p2| collator.compare(&p1.as_playlist().name, &p2.as_playlist().name));
202 }
203 None => {
204 playlists.sort_by(|p1, p2| p1.as_playlist().name.cmp(&p2.as_playlist().name));
205 }
206 }
207}
208
209pub fn sort_genres<T: AsGenre>(genres: &mut [T]) {
211 let guard = COLLATOR.read().unwrap();
212 let collator = guard.as_ref();
213
214 match collator {
215 Some(collator) => {
216 genres.sort_by(|g1, g2| collator.compare(&g1.as_genre().name, &g2.as_genre().name));
217 }
218 None => {
219 genres.sort_by(|g1, g2| g1.as_genre().name.cmp(&g2.as_genre().name));
220 }
221 }
222}