gonk_database/
playlist.rs1use walkdir::WalkDir;
2
3use crate::{database_path, Index, RawSong, SONG_LEN};
4use std::{
5 fs::{self, File},
6 io::{BufWriter, Write},
7 path::{Path, PathBuf},
8 str::from_utf8_unchecked,
9};
10
11pub fn playlists() -> Vec<RawPlaylist> {
12 let mut path = database_path();
13 path.pop();
14
15 WalkDir::new(path)
16 .into_iter()
17 .flatten()
18 .filter(|path| match path.path().extension() {
19 Some(ex) => {
20 matches!(ex.to_str(), Some("playlist"))
21 }
22 None => false,
23 })
24 .flat_map(|entry| fs::read(entry.path()))
25 .map(|bytes| RawPlaylist::from(bytes.as_slice()))
26 .collect()
27}
28
29pub fn remove_playlist(path: &Path) {
30 fs::remove_file(path).unwrap();
31}
32
33#[derive(Debug)]
34pub struct RawPlaylist {
35 pub name: String,
36 pub path: PathBuf,
37 pub songs: Index<RawSong>,
38}
39
40impl RawPlaylist {
41 pub fn new(name: &str, data: Vec<RawSong>) -> Self {
42 let mut path = database_path();
43 path.pop();
44 path.push(format!("{}.playlist", name));
45
46 Self {
47 path,
48 name: name.to_string(),
49 songs: Index::from(data),
50 }
51 }
52 pub fn save(&self) {
53 let file = File::create(&self.path).unwrap();
55 let mut writer = BufWriter::new(file);
56
57 let mut bytes = Vec::new();
59 bytes.extend((self.name.len() as u16).to_le_bytes());
60 bytes.extend(self.name.as_bytes());
61 for song in &self.songs.data {
62 bytes.extend(song.into_bytes());
63 }
64
65 writer.write_all(&bytes).unwrap();
66 writer.flush().unwrap();
67 }
68}
69
70impl From<&[u8]> for RawPlaylist {
71 fn from(bytes: &[u8]) -> Self {
72 unsafe {
73 let name_len = u16::from_le_bytes(bytes[0..2].try_into().unwrap_unchecked()) as usize;
74 let name = from_utf8_unchecked(&bytes[2..name_len + 2]);
75
76 let mut i = name_len + 2;
77 let mut songs = Vec::new();
78
79 while let Some(bytes) = bytes.get(i..i + SONG_LEN) {
80 songs.push(RawSong::from(bytes));
81 i += SONG_LEN;
82 }
83
84 let mut path = database_path();
85 path.pop();
86 path.push(format!("{}.playlist", name));
87
88 Self {
89 name: name.to_string(),
90 path,
91 songs: Index::from(songs),
92 }
93 }
94 }
95}