Split lib.rs into modules
This commit is contained in:
parent
8652b455be
commit
1a029d44a4
|
@ -0,0 +1,84 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NrgCuex {
|
||||||
|
pub size: u32,
|
||||||
|
pub tracks: Vec<NrgCuexTrack>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NrgCuex {
|
||||||
|
pub fn new() -> NrgCuex {
|
||||||
|
NrgCuex {
|
||||||
|
size: 0,
|
||||||
|
tracks: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NrgCuex {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
try!(write!(f, "Chunk ID: CUEX\n\
|
||||||
|
Chunk description: Cue Sheet\n\
|
||||||
|
Chunk size: {} Bytes", self.size));
|
||||||
|
if self.tracks.is_empty() {
|
||||||
|
try!(write!(f, "\nNo CUEX tracks!"));
|
||||||
|
} else {
|
||||||
|
for track in &self.tracks {
|
||||||
|
try!(write!(f, "\n\
|
||||||
|
Track:\n\
|
||||||
|
{}", track));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NrgCuexTrack {
|
||||||
|
pub mode: u8,
|
||||||
|
pub track_number: u8,
|
||||||
|
pub index_number: u8,
|
||||||
|
pub padding: u8,
|
||||||
|
pub position_sectors: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NrgCuexTrack {
|
||||||
|
pub fn new() -> NrgCuexTrack {
|
||||||
|
NrgCuexTrack {
|
||||||
|
mode: 0,
|
||||||
|
track_number: 0,
|
||||||
|
index_number: 0,
|
||||||
|
padding: 0,
|
||||||
|
position_sectors: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NrgCuexTrack {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
try!(writeln!(f, "\tMode: 0x{:02X}", self.mode));
|
||||||
|
|
||||||
|
try!(write!(f, "\tTrack number: "));
|
||||||
|
if self.track_number == 0 {
|
||||||
|
try!(writeln!(f, "0 (lead-in area)"));
|
||||||
|
} else if self.track_number == 0xAA {
|
||||||
|
try!(writeln!(f, "0xAA (lead-out area)"));
|
||||||
|
} else {
|
||||||
|
try!(writeln!(f, "{}", self.track_number));
|
||||||
|
}
|
||||||
|
|
||||||
|
try!(writeln!(f, "\tIndex number: {}", self.index_number));
|
||||||
|
|
||||||
|
if self.padding != 0 {
|
||||||
|
try!(writeln!(f, "\tPadding: {} (Warning: should be 0!)",
|
||||||
|
self.padding));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Audio CDs are played at a 75 sectors per second rate:
|
||||||
|
let position_seconds: f64 = (self.position_sectors as f64) / 75.0;
|
||||||
|
write!(f, "\tPosition: {} sectors ({:.2} seconds)",
|
||||||
|
self.position_sectors, position_seconds)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NrgDaox {
|
||||||
|
pub size: u32,
|
||||||
|
pub size2: u32,
|
||||||
|
pub upc: String,
|
||||||
|
pub padding: u8,
|
||||||
|
pub toc_type: u16,
|
||||||
|
pub first_track: u8,
|
||||||
|
pub last_track: u8,
|
||||||
|
pub tracks: Vec<NrgDaoxTrack>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NrgDaox {
|
||||||
|
pub fn new() -> NrgDaox {
|
||||||
|
NrgDaox {
|
||||||
|
size: 0,
|
||||||
|
size2: 0,
|
||||||
|
upc: String::new(),
|
||||||
|
padding: 0,
|
||||||
|
toc_type: 0,
|
||||||
|
first_track: 0,
|
||||||
|
last_track: 0,
|
||||||
|
tracks: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NrgDaox {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
try!(writeln!(f, "Chunk ID: DAOX\n\
|
||||||
|
Chunk description: DAO (Disc At Once) Information\n\
|
||||||
|
Chunk size: {} Bytes\n\
|
||||||
|
Chunk size 2: {}\n\
|
||||||
|
UPC: \"{}\"",
|
||||||
|
self.size,
|
||||||
|
self.size2,
|
||||||
|
self.upc));
|
||||||
|
|
||||||
|
if self.padding != 0 {
|
||||||
|
try!(writeln!(f, "Padding: {} (Warning: should be 0!)",
|
||||||
|
self.padding));
|
||||||
|
}
|
||||||
|
|
||||||
|
try!(write!(f, "TOC type: 0x{:04X}\n\
|
||||||
|
First track in the session: {}\n\
|
||||||
|
Last track in the session: {}",
|
||||||
|
self.toc_type,
|
||||||
|
self.first_track,
|
||||||
|
self.last_track));
|
||||||
|
|
||||||
|
if self.tracks.is_empty() {
|
||||||
|
try!(write!(f, "\nNo DAOX tracks!"));
|
||||||
|
} else {
|
||||||
|
let mut i = 1;
|
||||||
|
for track in &self.tracks {
|
||||||
|
try!(write!(f, "\n\
|
||||||
|
Track {:02}:\n\
|
||||||
|
{}", i, track));
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NrgDaoxTrack {
|
||||||
|
pub isrc: String,
|
||||||
|
pub sector_size: u16,
|
||||||
|
pub data_mode: u16,
|
||||||
|
pub unknown: u16,
|
||||||
|
pub index0: u64,
|
||||||
|
pub index1: u64,
|
||||||
|
pub track_end: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NrgDaoxTrack {
|
||||||
|
pub fn new() -> NrgDaoxTrack {
|
||||||
|
NrgDaoxTrack {
|
||||||
|
isrc: String::new(),
|
||||||
|
sector_size: 0,
|
||||||
|
data_mode: 0,
|
||||||
|
unknown: 0,
|
||||||
|
index0: 0,
|
||||||
|
index1: 0,
|
||||||
|
track_end: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NrgDaoxTrack {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
try!(writeln!(f, "\tISRC: \"{}\"\n\
|
||||||
|
\tSector size in the image file: {} Bytes\n\
|
||||||
|
\tMode of the data in the image file: 0x{:04X}",
|
||||||
|
self.isrc,
|
||||||
|
self.sector_size,
|
||||||
|
self.data_mode));
|
||||||
|
|
||||||
|
if self.unknown != 0x0001 {
|
||||||
|
try!(writeln!(f, "\tUnknown field: 0x{:04X} \
|
||||||
|
(Warning: should be 0x0001!)",
|
||||||
|
self.unknown));
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "\tIndex0 (Pre-gap): {} Bytes\n\
|
||||||
|
\tIndex1 (Start of track): {} Bytes\n\
|
||||||
|
\tEnd of track + 1: {} Bytes",
|
||||||
|
self.index0,
|
||||||
|
self.index1,
|
||||||
|
self.track_end)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum NrgError {
|
||||||
|
Io(io::Error),
|
||||||
|
NrgFormat,
|
||||||
|
NrgFormatV1,
|
||||||
|
NrgChunkId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NrgError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
NrgError::Io(ref err) => err.fmt(f),
|
||||||
|
NrgError::NrgFormat => write!(f, "NRG format unknown."),
|
||||||
|
NrgError::NrgFormatV1 => write!(f, "NRG v1 format is not handled."),
|
||||||
|
NrgError::NrgChunkId => write!(f, "NRG chunk ID unknown."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for NrgError {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
NrgError::Io(ref err) => err.description(),
|
||||||
|
NrgError::NrgFormat => "NRG format",
|
||||||
|
NrgError::NrgFormatV1 => "NRG format v1",
|
||||||
|
NrgError::NrgChunkId => "NRG chunk ID",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&Error> {
|
||||||
|
match *self {
|
||||||
|
NrgError::Io(ref err) => Some(err),
|
||||||
|
NrgError::NrgFormat => None,
|
||||||
|
NrgError::NrgFormatV1 => None,
|
||||||
|
NrgError::NrgChunkId => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for NrgError {
|
||||||
|
fn from(err: io::Error) -> NrgError {
|
||||||
|
NrgError::Io(err)
|
||||||
|
}
|
||||||
|
}
|
424
src/lib.rs
424
src/lib.rs
|
@ -1,367 +1,26 @@
|
||||||
use std::error::Error;
|
|
||||||
use std::fmt;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{self, Read, Seek, SeekFrom};
|
use std::io::{Seek, SeekFrom};
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
|
mod error;
|
||||||
|
use error::NrgError;
|
||||||
|
|
||||||
#[derive(Debug)]
|
mod metadata;
|
||||||
pub enum NrgError {
|
use metadata::NrgMetadata;
|
||||||
Io(io::Error),
|
|
||||||
NrgFormat,
|
|
||||||
NrgFormatV1,
|
|
||||||
NrgChunkId,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NrgError {
|
mod cuex;
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
use cuex::{NrgCuex, NrgCuexTrack};
|
||||||
match *self {
|
|
||||||
NrgError::Io(ref err) => err.fmt(f),
|
|
||||||
NrgError::NrgFormat => write!(f, "NRG format unknown."),
|
|
||||||
NrgError::NrgFormatV1 => write!(f, "NRG v1 format is not handled."),
|
|
||||||
NrgError::NrgChunkId => write!(f, "NRG chunk ID unknown."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Error for NrgError {
|
mod daox;
|
||||||
fn description(&self) -> &str {
|
use daox::{NrgDaox, NrgDaoxTrack};
|
||||||
match *self {
|
|
||||||
NrgError::Io(ref err) => err.description(),
|
|
||||||
NrgError::NrgFormat => "NRG format",
|
|
||||||
NrgError::NrgFormatV1 => "NRG format v1",
|
|
||||||
NrgError::NrgChunkId => "NRG chunk ID",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cause(&self) -> Option<&Error> {
|
mod sinf;
|
||||||
match *self {
|
use sinf::{NrgSinf};
|
||||||
NrgError::Io(ref err) => Some(err),
|
|
||||||
NrgError::NrgFormat => None,
|
|
||||||
NrgError::NrgFormatV1 => None,
|
|
||||||
NrgError::NrgChunkId => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<io::Error> for NrgError {
|
mod mtyp;
|
||||||
fn from(err: io::Error) -> NrgError {
|
use mtyp::{NrgMtyp};
|
||||||
NrgError::Io(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
mod readers;
|
||||||
#[derive(Debug)]
|
use readers::*;
|
||||||
pub struct NrgMetadata {
|
|
||||||
pub file_size: u64,
|
|
||||||
pub nrg_version: u8,
|
|
||||||
pub chunk_offset: u64,
|
|
||||||
pub cuex_chunk: Option<NrgCuex>,
|
|
||||||
pub daox_chunk: Option<NrgDaox>,
|
|
||||||
pub sinf_chunk: Option<NrgSinf>,
|
|
||||||
pub mtyp_chunk: Option<NrgMtyp>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NrgMetadata {
|
|
||||||
fn new() -> NrgMetadata {
|
|
||||||
NrgMetadata {
|
|
||||||
file_size: 0,
|
|
||||||
nrg_version: 0,
|
|
||||||
chunk_offset: 0,
|
|
||||||
cuex_chunk: None,
|
|
||||||
daox_chunk: None,
|
|
||||||
sinf_chunk: None,
|
|
||||||
mtyp_chunk: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NrgMetadata {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
try!(write!(f, "Image size: {} Bytes\n\
|
|
||||||
NRG format version: {}\n\
|
|
||||||
First chunk offset: {}",
|
|
||||||
self.file_size,
|
|
||||||
self.nrg_version,
|
|
||||||
self.chunk_offset,
|
|
||||||
));
|
|
||||||
match self.cuex_chunk {
|
|
||||||
None => {},
|
|
||||||
Some(ref chunk) => try!(write!(f, "\n\n\
|
|
||||||
{}", chunk)),
|
|
||||||
}
|
|
||||||
match self.daox_chunk {
|
|
||||||
None => {},
|
|
||||||
Some(ref chunk) => try!(write!(f, "\n\n\
|
|
||||||
{}", chunk)),
|
|
||||||
}
|
|
||||||
match self.sinf_chunk {
|
|
||||||
None => {},
|
|
||||||
Some(ref chunk) => try!(write!(f, "\n\n\
|
|
||||||
{}", chunk)),
|
|
||||||
}
|
|
||||||
match self.mtyp_chunk {
|
|
||||||
None => {},
|
|
||||||
Some(ref chunk) => try!(write!(f, "\n\n\
|
|
||||||
{}", chunk)),
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NrgCuex {
|
|
||||||
pub size: u32,
|
|
||||||
pub tracks: Vec<NrgCuexTrack>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NrgCuex {
|
|
||||||
fn new() -> NrgCuex {
|
|
||||||
NrgCuex {
|
|
||||||
size: 0,
|
|
||||||
tracks: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NrgCuex {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
try!(write!(f, "Chunk ID: CUEX\n\
|
|
||||||
Chunk description: Cue Sheet\n\
|
|
||||||
Chunk size: {} Bytes", self.size));
|
|
||||||
if self.tracks.is_empty() {
|
|
||||||
try!(write!(f, "\nNo CUEX tracks!"));
|
|
||||||
} else {
|
|
||||||
for track in &self.tracks {
|
|
||||||
try!(write!(f, "\n\
|
|
||||||
Track:\n\
|
|
||||||
{}", track));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NrgCuexTrack {
|
|
||||||
mode: u8,
|
|
||||||
track_number: u8,
|
|
||||||
index_number: u8,
|
|
||||||
padding: u8,
|
|
||||||
position_sectors: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NrgCuexTrack {
|
|
||||||
fn new() -> NrgCuexTrack {
|
|
||||||
NrgCuexTrack {
|
|
||||||
mode: 0,
|
|
||||||
track_number: 0,
|
|
||||||
index_number: 0,
|
|
||||||
padding: 0,
|
|
||||||
position_sectors: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NrgCuexTrack {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
try!(writeln!(f, "\tMode: 0x{:02X}", self.mode));
|
|
||||||
|
|
||||||
try!(write!(f, "\tTrack number: "));
|
|
||||||
if self.track_number == 0 {
|
|
||||||
try!(writeln!(f, "0 (lead-in area)"));
|
|
||||||
} else if self.track_number == 0xAA {
|
|
||||||
try!(writeln!(f, "0xAA (lead-out area)"));
|
|
||||||
} else {
|
|
||||||
try!(writeln!(f, "{}", self.track_number));
|
|
||||||
}
|
|
||||||
|
|
||||||
try!(writeln!(f, "\tIndex number: {}", self.index_number));
|
|
||||||
|
|
||||||
if self.padding != 0 {
|
|
||||||
try!(writeln!(f, "\tPadding: {} (Warning: should be 0!)",
|
|
||||||
self.padding));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Audio CDs are played at a 75 sectors per second rate:
|
|
||||||
let position_seconds: f64 = (self.position_sectors as f64) / 75.0;
|
|
||||||
write!(f, "\tPosition: {} sectors ({:.2} seconds)",
|
|
||||||
self.position_sectors, position_seconds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NrgDaox {
|
|
||||||
pub size: u32,
|
|
||||||
pub size2: u32,
|
|
||||||
pub upc: String,
|
|
||||||
pub padding: u8,
|
|
||||||
pub toc_type: u16,
|
|
||||||
pub first_track: u8,
|
|
||||||
pub last_track: u8,
|
|
||||||
pub tracks: Vec<NrgDaoxTrack>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NrgDaox {
|
|
||||||
fn new() -> NrgDaox {
|
|
||||||
NrgDaox {
|
|
||||||
size: 0,
|
|
||||||
size2: 0,
|
|
||||||
upc: String::new(),
|
|
||||||
padding: 0,
|
|
||||||
toc_type: 0,
|
|
||||||
first_track: 0,
|
|
||||||
last_track: 0,
|
|
||||||
tracks: Vec::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NrgDaox {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
try!(writeln!(f, "Chunk ID: DAOX\n\
|
|
||||||
Chunk description: DAO (Disc At Once) Information\n\
|
|
||||||
Chunk size: {} Bytes\n\
|
|
||||||
Chunk size 2: {}\n\
|
|
||||||
UPC: \"{}\"",
|
|
||||||
self.size,
|
|
||||||
self.size2,
|
|
||||||
self.upc));
|
|
||||||
|
|
||||||
if self.padding != 0 {
|
|
||||||
try!(writeln!(f, "Padding: {} (Warning: should be 0!)",
|
|
||||||
self.padding));
|
|
||||||
}
|
|
||||||
|
|
||||||
try!(write!(f, "TOC type: 0x{:04X}\n\
|
|
||||||
First track in the session: {}\n\
|
|
||||||
Last track in the session: {}",
|
|
||||||
self.toc_type,
|
|
||||||
self.first_track,
|
|
||||||
self.last_track));
|
|
||||||
|
|
||||||
if self.tracks.is_empty() {
|
|
||||||
try!(write!(f, "\nNo DAOX tracks!"));
|
|
||||||
} else {
|
|
||||||
let mut i = 1;
|
|
||||||
for track in &self.tracks {
|
|
||||||
try!(write!(f, "\n\
|
|
||||||
Track {:02}:\n\
|
|
||||||
{}", i, track));
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NrgDaoxTrack {
|
|
||||||
isrc: String,
|
|
||||||
sector_size: u16,
|
|
||||||
data_mode: u16,
|
|
||||||
unknown: u16,
|
|
||||||
index0: u64,
|
|
||||||
index1: u64,
|
|
||||||
track_end: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NrgDaoxTrack {
|
|
||||||
fn new() -> NrgDaoxTrack {
|
|
||||||
NrgDaoxTrack {
|
|
||||||
isrc: String::new(),
|
|
||||||
sector_size: 0,
|
|
||||||
data_mode: 0,
|
|
||||||
unknown: 0,
|
|
||||||
index0: 0,
|
|
||||||
index1: 0,
|
|
||||||
track_end: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NrgDaoxTrack {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
try!(writeln!(f, "\tISRC: \"{}\"\n\
|
|
||||||
\tSector size in the image file: {} Bytes\n\
|
|
||||||
\tMode of the data in the image file: 0x{:04X}",
|
|
||||||
self.isrc,
|
|
||||||
self.sector_size,
|
|
||||||
self.data_mode));
|
|
||||||
|
|
||||||
if self.unknown != 0x0001 {
|
|
||||||
try!(writeln!(f, "\tUnknown field: 0x{:04X} \
|
|
||||||
(Warning: should be 0x0001!)",
|
|
||||||
self.unknown));
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(f, "\tIndex0 (Pre-gap): {} Bytes\n\
|
|
||||||
\tIndex1 (Start of track): {} Bytes\n\
|
|
||||||
\tEnd of track + 1: {} Bytes",
|
|
||||||
self.index0,
|
|
||||||
self.index1,
|
|
||||||
self.track_end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NrgSinf {
|
|
||||||
pub size: u32,
|
|
||||||
pub nb_tracks: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NrgSinf {
|
|
||||||
fn new() -> NrgSinf {
|
|
||||||
NrgSinf {
|
|
||||||
size: 0,
|
|
||||||
nb_tracks: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NrgSinf {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "Chunk ID: SINF\n\
|
|
||||||
Chunk description: Session Information\n\
|
|
||||||
Chunk size: {} Bytes\n\
|
|
||||||
Number of tracks in the session: {}",
|
|
||||||
self.size,
|
|
||||||
self.nb_tracks)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct NrgMtyp {
|
|
||||||
pub size: u32,
|
|
||||||
pub unknown: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NrgMtyp {
|
|
||||||
fn new() -> NrgMtyp {
|
|
||||||
NrgMtyp {
|
|
||||||
size: 0,
|
|
||||||
unknown: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for NrgMtyp {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "Chunk ID: MTYP\n\
|
|
||||||
Chunk description: Media Type (?)\n\
|
|
||||||
Chunk size: {} Bytes\n\
|
|
||||||
Unknown field: 0x{:04X}",
|
|
||||||
self.size,
|
|
||||||
self.unknown)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_nrg_metadata(img_name: String) -> Result<NrgMetadata, NrgError> {
|
pub fn parse_nrg_metadata(img_name: String) -> Result<NrgMetadata, NrgError> {
|
||||||
|
@ -454,59 +113,6 @@ fn read_nrg_chunk_id(fd: &File) -> Result<String, NrgError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Reads a String of size `size` from `fd`.
|
|
||||||
fn read_sized_string(fd: &File, size: u64) -> Result<String, NrgError> {
|
|
||||||
let mut handle = fd.take(size);
|
|
||||||
let mut string = String::new();
|
|
||||||
try!(handle.read_to_string(&mut string));
|
|
||||||
Ok(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Reads a 64-bit unsigned integer from `fd`.
|
|
||||||
fn read_u64(fd: &mut File) -> Result<u64, NrgError> {
|
|
||||||
let mut buf = [0u8; 8];
|
|
||||||
try!(fd.read_exact(&mut buf));
|
|
||||||
let i: u64;
|
|
||||||
unsafe {
|
|
||||||
i = mem::transmute(buf);
|
|
||||||
}
|
|
||||||
Ok(u64::from_be(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Reads a 32-bit unsigned integer from `fd`.
|
|
||||||
fn read_u32(fd: &mut File) -> Result<u32, NrgError> {
|
|
||||||
let mut buf = [0u8; 4];
|
|
||||||
try!(fd.read_exact(&mut buf));
|
|
||||||
let i: u32;
|
|
||||||
unsafe {
|
|
||||||
i = mem::transmute(buf);
|
|
||||||
}
|
|
||||||
Ok(u32::from_be(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Reads a 16-bit unsigned integer from `fd`.
|
|
||||||
fn read_u16(fd: &mut File) -> Result<u16, NrgError> {
|
|
||||||
let mut buf = [0u8; 2];
|
|
||||||
try!(fd.read_exact(&mut buf));
|
|
||||||
let i: u16;
|
|
||||||
unsafe {
|
|
||||||
i = mem::transmute(buf);
|
|
||||||
}
|
|
||||||
Ok(u16::from_be(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Reads an unsigned byte from `fd`.
|
|
||||||
fn read_u8(fd: &mut File) -> Result<u8, NrgError> {
|
|
||||||
let mut buf = [0u8; 1];
|
|
||||||
try!(fd.read_exact(&mut buf));
|
|
||||||
Ok(buf[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn skip_unhandled_chunk(fd: &mut File, chunk_id: &str) -> Result<(), NrgError> {
|
fn skip_unhandled_chunk(fd: &mut File, chunk_id: &str) -> Result<(), NrgError> {
|
||||||
let chunk_size = try!(read_u32(fd));
|
let chunk_size = try!(read_u32(fd));
|
||||||
try!(fd.seek(SeekFrom::Current(chunk_size as i64)));
|
try!(fd.seek(SeekFrom::Current(chunk_size as i64)));
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use cuex::NrgCuex;
|
||||||
|
use daox::NrgDaox;
|
||||||
|
use sinf::NrgSinf;
|
||||||
|
use mtyp::NrgMtyp;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NrgMetadata {
|
||||||
|
pub file_size: u64,
|
||||||
|
pub nrg_version: u8,
|
||||||
|
pub chunk_offset: u64,
|
||||||
|
pub cuex_chunk: Option<NrgCuex>,
|
||||||
|
pub daox_chunk: Option<NrgDaox>,
|
||||||
|
pub sinf_chunk: Option<NrgSinf>,
|
||||||
|
pub mtyp_chunk: Option<NrgMtyp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NrgMetadata {
|
||||||
|
pub fn new() -> NrgMetadata {
|
||||||
|
NrgMetadata {
|
||||||
|
file_size: 0,
|
||||||
|
nrg_version: 0,
|
||||||
|
chunk_offset: 0,
|
||||||
|
cuex_chunk: None,
|
||||||
|
daox_chunk: None,
|
||||||
|
sinf_chunk: None,
|
||||||
|
mtyp_chunk: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NrgMetadata {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
try!(write!(f, "Image size: {} Bytes\n\
|
||||||
|
NRG format version: {}\n\
|
||||||
|
First chunk offset: {}",
|
||||||
|
self.file_size,
|
||||||
|
self.nrg_version,
|
||||||
|
self.chunk_offset,
|
||||||
|
));
|
||||||
|
match self.cuex_chunk {
|
||||||
|
None => {},
|
||||||
|
Some(ref chunk) => try!(write!(f, "\n\n\
|
||||||
|
{}", chunk)),
|
||||||
|
}
|
||||||
|
match self.daox_chunk {
|
||||||
|
None => {},
|
||||||
|
Some(ref chunk) => try!(write!(f, "\n\n\
|
||||||
|
{}", chunk)),
|
||||||
|
}
|
||||||
|
match self.sinf_chunk {
|
||||||
|
None => {},
|
||||||
|
Some(ref chunk) => try!(write!(f, "\n\n\
|
||||||
|
{}", chunk)),
|
||||||
|
}
|
||||||
|
match self.mtyp_chunk {
|
||||||
|
None => {},
|
||||||
|
Some(ref chunk) => try!(write!(f, "\n\n\
|
||||||
|
{}", chunk)),
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NrgMtyp {
|
||||||
|
pub size: u32,
|
||||||
|
pub unknown: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NrgMtyp {
|
||||||
|
pub fn new() -> NrgMtyp {
|
||||||
|
NrgMtyp {
|
||||||
|
size: 0,
|
||||||
|
unknown: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NrgMtyp {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Chunk ID: MTYP\n\
|
||||||
|
Chunk description: Media Type (?)\n\
|
||||||
|
Chunk size: {} Bytes\n\
|
||||||
|
Unknown field: 0x{:04X}",
|
||||||
|
self.size,
|
||||||
|
self.unknown)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
use error::NrgError;
|
||||||
|
|
||||||
|
|
||||||
|
/// Reads a String of size `size` from `fd`.
|
||||||
|
pub fn read_sized_string(fd: &File, size: u64) -> Result<String, NrgError> {
|
||||||
|
let mut handle = fd.take(size);
|
||||||
|
let mut string = String::new();
|
||||||
|
try!(handle.read_to_string(&mut string));
|
||||||
|
Ok(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Reads a 64-bit unsigned integer from `fd`.
|
||||||
|
pub fn read_u64(fd: &mut File) -> Result<u64, NrgError> {
|
||||||
|
let mut buf = [0u8; 8];
|
||||||
|
try!(fd.read_exact(&mut buf));
|
||||||
|
let i: u64;
|
||||||
|
unsafe {
|
||||||
|
i = mem::transmute(buf);
|
||||||
|
}
|
||||||
|
Ok(u64::from_be(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Reads a 32-bit unsigned integer from `fd`.
|
||||||
|
pub fn read_u32(fd: &mut File) -> Result<u32, NrgError> {
|
||||||
|
let mut buf = [0u8; 4];
|
||||||
|
try!(fd.read_exact(&mut buf));
|
||||||
|
let i: u32;
|
||||||
|
unsafe {
|
||||||
|
i = mem::transmute(buf);
|
||||||
|
}
|
||||||
|
Ok(u32::from_be(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Reads a 16-bit unsigned integer from `fd`.
|
||||||
|
pub fn read_u16(fd: &mut File) -> Result<u16, NrgError> {
|
||||||
|
let mut buf = [0u8; 2];
|
||||||
|
try!(fd.read_exact(&mut buf));
|
||||||
|
let i: u16;
|
||||||
|
unsafe {
|
||||||
|
i = mem::transmute(buf);
|
||||||
|
}
|
||||||
|
Ok(u16::from_be(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Reads an unsigned byte from `fd`.
|
||||||
|
pub fn read_u8(fd: &mut File) -> Result<u8, NrgError> {
|
||||||
|
let mut buf = [0u8; 1];
|
||||||
|
try!(fd.read_exact(&mut buf));
|
||||||
|
Ok(buf[0])
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct NrgSinf {
|
||||||
|
pub size: u32,
|
||||||
|
pub nb_tracks: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NrgSinf {
|
||||||
|
pub fn new() -> NrgSinf {
|
||||||
|
NrgSinf {
|
||||||
|
size: 0,
|
||||||
|
nb_tracks: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for NrgSinf {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "Chunk ID: SINF\n\
|
||||||
|
Chunk description: Session Information\n\
|
||||||
|
Chunk size: {} Bytes\n\
|
||||||
|
Number of tracks in the session: {}",
|
||||||
|
self.size,
|
||||||
|
self.nb_tracks)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue