music_tag/
lib.rs

1pub mod lyrics;
2pub mod audio;
3pub mod error;
4pub use error::*;
5
6pub use imagesize;
7use std::io::{ErrorKind, SeekFrom};
8use symphonia::core::io::MediaSource;
9#[derive(Debug, PartialEq, Eq, Clone, Copy)]
10pub enum MusicFmt {
11    M4a,
12    Mp3,
13    Flac,
14    Ogg,
15}
16
17pub struct AudioReader {
18    pos: usize,
19    buf: Vec<u8>,
20}
21impl MediaSource for AudioReader {
22    fn is_seekable(&self) -> bool {
23        true
24    }
25
26    fn byte_len(&self) -> Option<u64> {
27        Some(self.buf.len() as u64)
28    }
29}
30unsafe impl Send for AudioReader {}
31unsafe impl Sync for AudioReader {}
32impl AudioReader {
33    pub fn new(buf: Vec<u8>) -> AudioReader {
34        Self { pos: 0, buf }
35    }
36}
37impl std::io::Seek for AudioReader {
38    fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
39        match pos {
40            SeekFrom::Current(i) => {
41                let pos = i as usize + self.pos;
42                if self.buf.len() > pos {
43                    self.pos = pos;
44                    Ok(self.pos as u64)
45                } else {
46                    Err(std::io::Error::new(
47                        ErrorKind::InvalidInput,
48                        "Invalid position",
49                    ))
50                }
51            }
52            SeekFrom::End(e) => {
53                if self.buf.len() >= e as usize {
54                    self.pos = self.buf.len() - e as usize;
55                    Ok(self.pos as u64)
56                } else {
57                    Err(std::io::Error::new(
58                        ErrorKind::InvalidInput,
59                        "Invalid position",
60                    ))
61                }
62            }
63            SeekFrom::Start(s) => {
64                if self.buf.len() >= s as usize {
65                    self.pos = s as usize;
66                    Ok(self.pos as u64)
67                } else {
68                    Err(std::io::Error::new(
69                        ErrorKind::InvalidInput,
70                        "Invalid position",
71                    ))
72                }
73            }
74        }
75    }
76}
77impl std::io::Read for AudioReader {
78    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
79        let pos = self.pos;
80        for i in self.pos..self.buf.len() {
81            if i - pos >= buf.len() {
82                break;
83            }
84            buf[i - pos] = self.buf[i];
85            self.pos = i + 1;
86        }
87        Ok(self.pos - pos)
88    }
89}