-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.rs
More file actions
45 lines (38 loc) · 1.49 KB
/
mod.rs
File metadata and controls
45 lines (38 loc) · 1.49 KB
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
use err::LoadErr;
use impulse_format::{header, pattern};
use crate::project::song::Song;
pub mod err;
pub mod impulse_format;
#[derive(Debug, Clone, Copy)]
pub struct InFilePtr(pub(crate) std::num::NonZeroU32);
impl InFilePtr {
/// Move the Read Cursor to the value of the file ptr
pub fn move_to_self<S: std::io::Seek>(self, seeker: &mut S) -> Result<(), std::io::Error> {
seeker
.seek(std::io::SeekFrom::Start(self.0.get().into()))
.map(|_| ())
}
}
/// Default parsing of a song. Should be fine for most usecases. If you want more customization use the different parsing functions directly.
///
/// R should be buffered in some way and not do a syscall on every read.
/// If you ever find yourself using multiple different reader and/or handlers please open an issue on Github, i will change this to take &dyn.
pub fn parse_song<R: std::io::Read + std::io::Seek>(reader: &mut R) -> Result<Song, LoadErr> {
let header = header::ImpulseHeader::parse(reader)?;
let mut song = Song::default();
song.copy_values_from_header(&header);
// parse patterns
for (idx, ptr) in header
.pattern_offsets
.iter()
// number the pointer slots
.enumerate()
// filter out empty pointers. Keep the old slot numbering
.flat_map(|(idx, ptr)| ptr.map(|ptr| (idx, ptr)))
{
ptr.move_to_self(reader)?;
let pattern = pattern::parse_pattern(reader)?;
song.patterns[idx] = pattern;
}
Ok(song)
}