diff --git a/src/device.rs b/src/device.rs index ec092b8..48d85fa 100644 --- a/src/device.rs +++ b/src/device.rs @@ -128,28 +128,26 @@ impl DeviceExport { pub fn get_playlists(&self) -> crate::Result> { match &self.pdb { Some(pdb) => pdb.get_playlists(), - None => Ok(Vec::new()), + None => Err(crate::Error::NotLoadedError), } } /// Get the entries for a single playlist. - #[must_use] pub fn get_playlist_entries( &self, id: PlaylistTreeNodeId, - ) -> Box> + '_> { + ) -> crate::Result> + '_> { match &self.pdb { - Some(pdb) => Box::new(pdb.get_playlist_entries(id)), - None => Box::new(std::iter::empty()), + Some(pdb) => Ok(pdb.get_playlist_entries(id)), + None => Err(crate::Error::NotLoadedError), } } /// Get the tracks. - #[must_use] - pub fn get_tracks(&self) -> Box> + '_> { + pub fn get_tracks(&self) -> crate::Result> + '_> { match &self.pdb { - Some(pdb) => Box::new(pdb.get_tracks()), - None => Box::new(std::iter::empty()), + Some(pdb) => Ok(pdb.get_tracks()), + None => Err(crate::Error::NotLoadedError), } } } @@ -393,12 +391,16 @@ impl Pdb { self.get_rows_by_page_type(PageType::PlaylistTree) .map(|row| { if let Row::PlaylistTreeNode(playlist_tree) = row { - playlist_tree + Ok(playlist_tree) } else { - unreachable!("encountered non-playlist tree row in playlist table"); + Err(crate::Error::IntegrityError( + "encountered non-playlist tree row in playlist table", + )) } }) - .for_each(|row| playlists.entry(row.parent_id).or_default().push(row)); + .try_for_each(|row| { + row.map(|node| playlists.entry(node.parent_id).or_default().push(node)) + })?; fn get_child_nodes<'a>( playlists: &'a HashMap>, @@ -446,7 +448,9 @@ impl Pdb { None } } else { - unreachable!("encountered non-playlist tree row in playlist table"); + Some(Err(crate::Error::IntegrityError( + "encountered non-playlist tree row in playlist table", + ))) } }) } @@ -457,7 +461,9 @@ impl Pdb { if let Row::Track(track) = row { Ok(track.clone()) } else { - unreachable!("encountered non-track row in track table"); + Err(crate::Error::IntegrityError( + "encountered non-track row in track table", + )) } }) } diff --git a/src/main.rs b/src/main.rs index 797d883..ae1a642 100644 --- a/src/main.rs +++ b/src/main.rs @@ -83,7 +83,10 @@ fn list_playlists(path: &Path) -> rekordcrate::Result<()> { .for_each(|child| walk_tree(export, child, level + 1)); } PlaylistNode::Playlist(playlist) => { - let num_tracks = export.get_playlist_entries(playlist.id).count(); + let num_tracks = export + .get_playlist_entries(playlist.id) + .expect("failed to get playlist entries") + .count(); println!("{}🗎 {} ({} tracks)", indent, playlist.name, num_tracks) } }; @@ -106,7 +109,7 @@ fn export_playlists(path: &Path, output_dir: &PathBuf) -> rekordcrate::Result<() export.load_pdb()?; let playlists = export.get_playlists()?; let mut tracks: HashMap = HashMap::new(); - export.get_tracks().try_for_each(|result| { + export.get_tracks()?.try_for_each(|result| { if let Ok(track) = result { tracks.insert(track.id, track); Ok(()) @@ -129,7 +132,7 @@ fn export_playlists(path: &Path, output_dir: &PathBuf) -> rekordcrate::Result<() } PlaylistNode::Playlist(playlist) => { let mut playlist_entries = export - .get_playlist_entries(playlist.id) + .get_playlist_entries(playlist.id)? .collect::>>()?; playlist_entries.sort_by_key(|entry| entry.0); diff --git a/src/util.rs b/src/util.rs index 6b8caad..880cdfd 100644 --- a/src/util.rs +++ b/src/util.rs @@ -24,9 +24,17 @@ pub enum RekordcrateError { #[error(transparent)] ParseError(#[from] binrw::Error), + /// Represents a failure to validate a constraint. + #[error("failed integrity constraint: {0}")] + IntegrityError(&'static str), + /// Represents an `std::io::Error`. #[error(transparent)] IOError(#[from] std::io::Error), + + /// Represents an `std::io::Error`. + #[error("component not loaded")] + NotLoadedError, } /// Type alias for results where the error is a `RekordcrateError`.