-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlib.rs
60 lines (49 loc) · 2 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
extern crate peg;
use std::fs;
#[derive(Debug, PartialEq)]
pub struct Song {
pub file: String,
pub title: String,
pub length: Option<u32>,
}
peg::parser! {
pub grammar playlist_parser() for str {
pub rule playlist() -> Vec<Song>
= "[playlist]" eol() "Version=" number() eol() "NumberOfEntries=" number() eol()
entry()* { Vec::new() }
pub rule entry() -> Song
= "File" number() "=" filename:filename() eol()
"Title" number() "=" title:title() eol()
"Length" number() "=" length:number()? eol()
{ Song { file: filename.to_string(), title: title.to_string(), length } }
pub rule filename() -> String
= filename:$(['A'..='Z' | 'a'..='z' | '0'..='9' | '/' | '.' | ' ' | '-' | '(' | ')' | '&' | '!' | ',' | '+' | '\'' | '#']+) { filename.to_string() }
pub rule title() -> String
= title:$(['A'..='Z' | 'a'..='z' | '0'..='9' | ' ' | '-' | '/' | '.' | '(' | ')' | '&' | '!' | ',' | '+' | '\'' | '#' | ']' | '[' | ']' | '[' | ':' | ';' | '?' | '$' | '%' | '^' | '*' | '@' | '=' | '~' | '`']+) { title.to_string() }
pub rule number() -> u32
= n:$(['0'..='9']+) { n.parse().unwrap() }
pub rule eol()
= "\r"? "\n"
}
}
pub fn parse(path: &str) -> &str {
let contents = fs::read_to_string(path).expect("Failed to read file");
let parsed = match playlist_parser::playlist(&contents) {
Ok(entries) => entries,
Err(err) => {
eprintln!("Error parsing PLS file: {:?}", err);
std::process::exit(1);
}
};
for (index, song) in parsed.iter().enumerate() {
match &song.length {
Some(length) => {
println!("Entry {}: Title: {}, File: {}, Length: {} seconds", index + 1, song.title, song.file, length);
}
None => {
println!("Entry {}: Title: {}, File: {}", index + 1, song.title, song.file);
}
}
}
""
}