### Get File Type Example Source: https://docs.rs/ncmdump/0.8.0/ncmdump/utils/fn.get_file_type.html Demonstrates how to open a file and determine its type using the `get_file_type` function. Ensure the file exists at the specified path. ```rust let mut file = File::open("res/test.ncm").unwrap(); let file_type = get_file_type(&mut file).unwrap(); ``` -------------------------------- ### Install ncmdump using cargo add Source: https://docs.rs/ncmdump/0.8.0/ncmdump If you have cargo-edit installed, you can use this command to add the ncmdump crate to your project. ```bash cargo add ncmdump ``` -------------------------------- ### Get Music Data from QmcDump Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.QmcDump.html Extracts music data from a QmcDump instance and writes it to a specified output file. Requires necessary imports and error handling. ```rust use std::fs::File; use std::io::Write; use std::path::Path; use anyhow::Result; use ncmdump::QmcDump; fn main() -> Result<()> { let file = File::open("res/test.qmcflac")?; let mut qmc = QmcDump::from_reader(file)?; let music = qmc.get_data()?; let mut target = File::options() .create(true) .write(true) .open("res/test.flac")?; target.write_all(&music)?; Ok(()) } ``` -------------------------------- ### Get Music Data from Ncmdump Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Extracts the music data from an Ncmdump instance and writes it to a specified output file. ```rust use std::fs::File; use std::io::Write; use std::path::Path; use anyhow::Result; use ncmdump::Ncmdump; fn main() -> Result<()> { let file = File::open("res/test.ncm")?; let mut ncm = Ncmdump::from_reader(file)?; let music = ncm.get_data()?; let mut target = File::options() .create(true) .write(true) .open("res/test.flac")?; target.write_all(&music)?; Ok(()) } ``` -------------------------------- ### Ncmdump::check_format Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Checks if the provided buffer starts with the expected NCM file header. ```APIDOC ## Ncmdump::check_format ### Description Verifies if the given byte slice matches the magic number for NCM files. ### Method `fn check_format(buffer: &[u8]) -> bool` ### Parameters - `buffer`: A byte slice representing the beginning of a file. ### Returns `true` if the buffer starts with `b"CTENFDAM"`, `false` otherwise. ### Example ```rust // Assuming Ncmdump is in scope let header = b"CTENFDAM\x02\x00\x00\x00"; let is_ncm = Ncmdump::check_format(header); assert!(is_ncm); ``` ``` -------------------------------- ### Same Trait Implementation Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.NcmInfo.html Provides a way to get the same type back. ```rust impl Same for T Source§ #### type Output = T Should always be `Self` § ``` -------------------------------- ### Get Bytes from Reader Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Reads a specified number of bytes from a given start position within the reader. ```rust /// Utils for get bytes. fn get_bytes(&mut self, start: u64, length: u64) -> Result> { let reader = self.reader.by_ref(); let mut buf = Vec::new(); reader.seek(SeekFrom::Start(start))?; reader.take(length).read_to_end(&mut buf)?; Ok(buf) } ``` -------------------------------- ### Create QmcDump from Reader Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.QmcDump.html Instantiate QmcDump by providing a reader. Ensure the file exists and is accessible. ```rust let file = File::open("res/test.qmcflac").expect("Can't open file"); let _ = QmcDump::from_reader(file).unwrap(); ``` -------------------------------- ### Initialize Ncmdump from File Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Creates a new Ncmdump instance by reading from a standard file. ```rust /// # Example /// /// From a file. /// /// ```rust /// # use std::fs::File; /// # /// # use ncmdump::Ncmdump; /// # /// let file = File::open("res/test.ncm").expect("Can't open file"); /// let _ = Ncmdump::from_reader(file).unwrap(); /// ``` ``` -------------------------------- ### type_id Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Gets the `TypeId` of `self`. ```APIDOC ## fn type_id(&self) -> TypeId ### Description Gets the `TypeId` of `self`. ### Method `type_id` ### Parameters None ### Response - `TypeId`: The type identifier of the object. ``` -------------------------------- ### Creating a QmcDump Instance Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Use the `from_reader` function to create a new instance of `QmcDump` from any type that implements the `Read` trait. This initializes the dumper with the provided data source. ```APIDOC /// Create QmcDump from reader. /// /// # Example /// /// ```rust /// # use std::fs::File; /// # /// # use ncmdump::QmcDump; /// # /// let file = File::open("res/test.qmcflac").expect("Can't open file"); /// let _ = QmcDump::from_reader(file).unwrap(); /// ``` pub fn from_reader(reader: S) -> Result ``` -------------------------------- ### try_from Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Performs the conversion. ```APIDOC ## fn try_from(value: U) -> Result>::Error> ### Description Performs the conversion. ### Method `try_from` ### Parameters - `value` (U) - Required - The value to convert. ### Response - `Result>::Error>`: The converted value or an error. ``` -------------------------------- ### stream_position Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Returns the current seek position from the start of the stream. ```APIDOC ## fn stream_position(&mut self) -> Result ### Description Returns the current seek position from the start of the stream. ### Method `stream_position` ### Parameters None ### Response - `Result`: The current stream position or an error. ``` -------------------------------- ### into Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Calls `U::from(self)`. ```APIDOC ## fn into(self) -> U ### Description Calls `U::from(self)`. That is, this conversion is whatever the implementation of `From for U` chooses to do. ### Method `into` ### Parameters None ### Response - `U`: The converted value. ``` -------------------------------- ### QmcDump::from_reader Function Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Creates a new QmcDump instance from a given reader. This is the entry point for processing QMC files. ```rust /// Create QmcDump from reader. /// /// # Example /// /// ```rust /// # use std::fs::File; /// # /// # use ncmdump::QmcDump; /// # /// let file = File::open("res/test.qmcflac").expect("Can't open file"); /// let _ = QmcDump::from_reader(file).unwrap(); /// ``` pub fn from_reader(reader: S) -> Result { Ok(Self { reader, cursor: 0 }) } ``` -------------------------------- ### Get NcmInfo from Ncmdump Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Decodes and returns the information buffer from an Ncmdump instance. Requires a mutable reference to the Ncmdump. ```rust use std::fs::File; use std::path::Path; use anyhow::Result; use ncmdump::Ncmdump; fn main() -> Result<()> { let file = File::open("res/test.ncm")?; let mut ncm = Ncmdump::from_reader(file)?; let info = ncm.get_info(); println!("{:?}", info); Ok(()) } ``` -------------------------------- ### try_into Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Performs the conversion. ```APIDOC ## fn try_into(self) -> Result>::Error> ### Description Performs the conversion. ### Method `try_into` ### Parameters None ### Response - `Result>::Error>`: The converted value or an error. ``` -------------------------------- ### get_file_type (deprecated) Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/utils.rs.html Deprecated function to get the file type of a reader. It is recommended to use `FileType::parse` instead. ```APIDOC ## get_file_type ### Description Deprecated function to get the file type of a reader. It is recommended to use `FileType::parse` instead. ### Signature ```rust #[deprecated] pub fn get_file_type(reader: &mut R) -> Result where R: Read, ``` ### Parameters * `reader`: A mutable reference to a type implementing `std::io::Read`. ### Returns A `Result` containing the `FileType` enum variant (Ncm, Qmc, or Other) or an error. ### Example ```rust # use std::fs::File; # use ncmdump::utils::get_file_type; # let mut file = File::open("res/test.ncm").unwrap(); let file_type = get_file_type(&mut file).unwrap(); ``` ``` -------------------------------- ### QmcDump::from_reader Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.QmcDump.html Creates a QmcDump instance from a given reader. This is the primary way to initialize a QmcDump object. ```APIDOC ## pub fn from_reader(reader: S) -> Result ### Description Create QmcDump from reader. ### Parameters #### Path Parameters - **reader** (S) - Required - The source reader implementing the `Read` trait. ### Response #### Success Response (Result) - **Self** - A new `QmcDump` instance. - **Errors** - An error type if the creation fails. ### Example ```rust use std::fs::File; use ncmdump::QmcDump; let file = File::open("res/test.qmcflac").expect("Can't open file"); let _ = QmcDump::from_reader(file).unwrap(); ``` ``` -------------------------------- ### Get Image Bytes from Ncmdump Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Retrieves the image bytes from an Ncmdump instance, if available. Writes the image data to a specified file. ```rust use std::fs::File; use std::path::Path; use anyhow::Result; use ncmdump::Ncmdump; fn main() -> Result<()> { use std::io::Write; let file = File::open("res/test.ncm")?; let mut ncm = Ncmdump::from_reader(file)?; let image = ncm.get_image()?; let mut target = File::options() .create(true) .write(true) .open("res/test.jpeg")?; target.write_all(&image)?; Ok(()) } ``` -------------------------------- ### Get File Type (Deprecated) Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/utils.rs.html A deprecated function that retrieves the file type of a reader by calling `FileType::parse`. It is recommended to use `FileType::parse` directly. ```rust #[deprecated] pub fn get_file_type(reader: &mut R) -> Result where R: Read, { FileType::parse(reader) } ``` -------------------------------- ### StructuralPartialEq Implementation for NcmInfo Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.NcmInfo.html Enables structural equality comparison for NcmInfo. ```rust impl StructuralPartialEq for NcmInfo ## Auto Trait Implementations§ § ### impl Freeze for NcmInfo § ### impl RefUnwindSafe for NcmInfo § ### impl Send for NcmInfo § ### impl Sync for NcmInfo § ### impl Unpin for NcmInfo § ### impl UnwindSafe for NcmInfo ``` -------------------------------- ### Test QMC Dump File Conversion Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Tests the complete process of reading a QMC file and writing its decrypted content to a new file. Requires 'res/test.qmcflac' and creates 'res/test.flac'. ```rust #[test] fn test_qmcdump_ok() -> Result<()> { let input = File::open("res/test.qmcflac")?; let mut output = File::options() .create(true) .write(true) .open("res/test.flac")?; let mut qmc = QmcDump::from_reader(input)?; let data = qmc.get_data()?; output.write_all(&data)?; Ok(()) } ``` -------------------------------- ### Initialize Ncmdump from Cursor Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Creates a new Ncmdump instance from an in-memory byte buffer using a Cursor. ```rust /// Or from a Cursor. /// ```rust /// # use std::fs::File; /// # use std::io::{Cursor, Read}; /// # /// # use ncmdump::Ncmdump; /// # /// # let mut file = File::open("res/test.ncm").expect("Can't open file."); /// # let mut data = Vec::new(); /// # file.read_to_end(&mut data).expect("Can't read file"); /// let cursor = Cursor::new(data); /// let _ = Ncmdump::from_reader(cursor).unwrap(); /// ``` ``` -------------------------------- ### Extract Music Data from NCM File Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Opens an NCM file, extracts its music data, and saves it as a FLAC file. Requires `ncmdump` and `anyhow` crates. ```rust use std::fs::File; use std::io::Write; use std::path::Path; use anyhow::Result; use ncmdump::Ncmdump; fn main() -> Result<()> { let file = File::open("res/test.ncm")?; let mut ncm = Ncmdump::from_reader(file)?; let music = ncm.get_data()?; let mut target = File::options() .create(true) .write(true) .open("res/test.flac")?; target.write_all(&music)?; Ok(()) } ``` -------------------------------- ### Test Ncmdump Creation Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Tests the successful creation of an `Ncmdump` instance from a file. ```rust #[test] fn test_create_dump_ok() -> Result<()> { let reader = File::open("res/test.ncm")?; let _ = Ncmdump::from_reader(reader)?; Ok(()) } ``` -------------------------------- ### Ncmdump Initialization from Reader Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Constructs an Ncmdump instance from a generic seekable reader, performing header checks and key/info extraction. ```rust pub fn from_reader(mut reader: S) -> Result { // check format let mut format = [0; 10]; reader .read_exact(&mut format) .map_err(|_| Errors::InvalidFileType)?; if !Self::check_format(&format) { return Err(Errors::InvalidFileType); } let mut key_length = [0; 4]; reader .read_exact(&mut key_length) .map_err(|_| Errors::InvalidKeyLength)?; let key_length = u32::from_le_bytes(key_length) as usize; let mut key = vec![0u8; key_length]; reader .read_exact(&mut key) .map_err(|_| Errors::InvalidKeyLength)?; let key = Self::get_key(&key)?; let key_box = Self::build_key_box(&key); // reader.seek(SeekFrom::Current(key_length as i64))?; let mut info_length = [0; 4]; reader .read_exact(&mut info_length) .map_err(|_| Errors::InvalidInfoLength)?; let info_start = reader.stream_position()?; let info_length = u32::from_le_bytes(info_length) as u64; reader.seek(SeekFrom::Current(info_length as i64))?; reader.seek(SeekFrom::Current(5))?; let mut cover_frame_len = [0; 4]; reader.read_exact(&mut cover_frame_len)?; let cover_frame_len = u32::from_le_bytes(cover_frame_len) as u64; let mut image_length = [0; 4]; reader .read_exact(&mut image_length) .map_err(|_| Errors::InvalidImageLength)?; let image_start = reader.stream_position()?; let image_length = u32::from_le_bytes(image_length) as u64; reader.seek(SeekFrom::Start(image_start + cover_frame_len))?; Ok(Self { reader, key_box, cursor: 0, info: (info_start, info_length), image: (image_start, image_length), }) } ``` -------------------------------- ### Build Ncmdump KeyBox Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Initializes the Ncmdump's internal key box (256 bytes) based on a provided key. This key box is used for the custom encryption/decryption algorithm. ```rust fn build_key_box(key: &[u8]) -> [u8; 256] { let mut j = 0; let mut key_box = [0u8; 256]; key_box ``` -------------------------------- ### Check NCM File Format Header Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Verifies if the provided byte slice matches the expected NCM file header signature. ```rust /// Check the file format by header. fn check_format(buffer: &[u8]) -> bool { buffer.starts_with(b"CTENFDAM") } ``` -------------------------------- ### Extract Audio Data from NCM File Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Opens an NCM file, creates an `Ncmdump` instance, and extracts the audio data. Asserts the data length and verifies the header and footer byte sequences. ```rust let reader = File::open("res/test.ncm")?; let mut ncm = Ncmdump::from_reader(reader)?; let data = ncm.get_data()?; let length = data.len(); assert_eq!(length, 61440); assert_eq!( data[..16], [ 0x66, 0x4c, 0x61, 0x43, 0x00, 0x00, 0x00, 0x22, 0x12, 0x00, 0x12, 0x00, 0x00, 0x01, 0x01, 0x00, ], ); assert_eq!( data[61424..], [ 0x8b, 0x25, 0x88, 0x08, 0x4b, 0x49, 0x89, 0xc2, 0xba, 0xe3, 0xda, 0x88, 0x48, 0xc1, 0x09, 0x7b, ], ); ``` -------------------------------- ### PartialEq Implementation for NcmInfo Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.NcmInfo.html Enables comparison of NcmInfo structs for equality. ```rust impl PartialEq for NcmInfo Source§ #### fn eq(&self, other: &NcmInfo) -> bool Tests for `self` and `other` values to be equal, and is used by `==`. 1.0.0§ #### fn ne(&self, other: &Rhs) -> bool Tests for `!=`. The default implementation is almost always sufficient, and should not be overridden without very good reason. Source ``` -------------------------------- ### Test QMC Dump Head Encryption Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Tests the encryption of specific file headers like fLaC and ID3 using QmcDump. Verifies correct transformation for known header patterns. ```rust #[test] fn test_encrypt_head_ok() -> Result<()> { // fLaC let mut input = [0xA5, 0x06, 0xB7, 0x89]; QmcDump::::encrypt(0, &mut input); assert_eq!(input, [0x66, 0x4C, 0x61, 0x43]); // ID3 let mut input = [0x8A, 0x0E, 0xE5]; QmcDump::::encrypt(0, &mut input); assert_eq!(input, [0x49, 0x44, 0x33]); Ok(()) } ``` -------------------------------- ### Test QMC Dump Encryption Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Tests the encryption functionality of QmcDump with different keys. Ensures data is correctly transformed. ```rust #[test] fn test_encrypt() -> Result<()> { // fLaC let mut data = [0xC3, 0x4B, 0xD4, 0xC9]; QmcDump::::encrypt(0, &mut data); assert_eq!(data, [0xC3, 0x4B, 0xD4, 0xC9]); let mut data = [0x00, 0x01, 0x02, 0x03]; QmcDump::::encrypt(0x7fff, &mut data); assert_eq!(data, [0x4A, 0x4B, 0xD4, 0xC9]); Ok(()) } ``` -------------------------------- ### Test NcmInfo Conversion Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Tests the conversion of `RawNcmInfo` to `NcmInfo`, ensuring default values are handled correctly. ```rust #[test] fn test_ncm_info_convert_ok() { let info = NcmInfo::from(RawNcmInfo { name: "".to_string(), id: NcmId::String(String::from("")), album: "".to_string(), artist: vec![], bitrate: NcmId::String(String::from("")), duration: NcmId::String(String::from("")), format: "".to_string(), mv_id: None, alias: None, }); assert_eq!(info.id, 0); assert_eq!(info.artist, Vec::new()); assert_eq!(info.bitrate, 0); assert_eq!(info.duration, 0); } ``` -------------------------------- ### Any Trait Implementation Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.NcmInfo.html Provides runtime type information for any type T. ```rust impl Any for T where T: 'static + ?Sized, § #### fn type_id(&self) -> TypeId Gets the `TypeId` of `self`. Read more § ``` -------------------------------- ### from Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.Ncmdump.html Returns the argument unchanged. ```APIDOC ## fn from(t: T) -> T ### Description Returns the argument unchanged. ### Method `from` ### Parameters - `t` (T) - Required - The value to return. ### Response - `T`: The input value `t`. ``` -------------------------------- ### Add ncmdump to Cargo.toml Source: https://docs.rs/ncmdump/0.8.0/index.html Add the ncmdump crate to your project's Cargo.toml file to include it as a dependency. Alternatively, use the `cargo add` command. ```toml ncmdump = "0.7.3" ``` -------------------------------- ### Same for T Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.QmcDump.html A generic implementation for type `T` where `Output` is always `T` itself. ```APIDOC ## impl Same for T ### Description Provides a generic implementation where the `Output` type is always `Self`. ### Type Alias `type Output = T` ### Details Should always be `Self`. ``` -------------------------------- ### Extract Album Image from NCM File Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Opens an NCM file, creates an `Ncmdump` instance, and extracts the album image data. Asserts the image length and verifies the header and footer byte sequences. ```rust let reader = File::open("res/test.ncm")?; let mut ncm = Ncmdump::from_reader(reader)?; let image = ncm.get_image()?; let length = image.len(); assert_eq!(length, 39009); assert_eq!( image[..16], [ 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x48, ], ); assert_eq!( image[38993..], [ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xff, 0xd9, ], ); Ok(()) } ``` -------------------------------- ### Build Key Box for NCM Decryption Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Constructs the key box required for NCM file decryption using a provided key. This is a crucial step in the decryption process. ```rust let key = [ 0x31, 0x31, 0x38, 0x31, 0x39, 0x38, 0x30, 0x33, 0x33, 0x32, 0x38, 0x35, 0x45, 0x37, 0x66, 0x54, 0x34, 0x39, 0x78, 0x37, 0x64, 0x6F, 0x66, 0x39, 0x4F, 0x4B, 0x43, 0x67, 0x67, 0x39, 0x63, 0x64, 0x76, 0x68, 0x45, 0x75, 0x65, 0x7A, 0x79, 0x33, 0x69, 0x5A, 0x43, 0x4C, 0x31, 0x6E, 0x46, 0x76, 0x42, 0x46, 0x64, 0x31, 0x54, 0x34, 0x75, 0x53, 0x6B, 0x74, 0x41, 0x4A, 0x4B, 0x6D, 0x77, 0x5A, 0x58, 0x73, 0x69, 0x6A, 0x50, 0x62, 0x69, 0x6A, 0x6C, 0x69, 0x69, 0x6F, 0x6E, 0x56, 0x55, 0x58, 0x58, 0x67, 0x39, 0x70, 0x6C, 0x54, 0x62, 0x58, 0x45, 0x63, 0x6C, 0x41, 0x45, 0x39, 0x4C, 0x62, ]; let key_box = [ 0x43, 0x63, 0x9D, 0xE2, 0x5B, 0x4B, 0x55, 0xBB, 0x4C, 0xCF, 0x2A, 0x62, 0x0E, 0x48, 0x8A, 0x15, 0x59, 0x52, 0xBA, 0x6C, 0xEF, 0x6D, 0x72, 0x39, 0xA0, 0x9A, 0xA9, 0x27, 0x66, 0xBC, 0xF9, 0xC0, 0x47, 0xDF, 0x7D, 0xDE, 0x3B, 0x81, 0x04, 0xFF, 0x90, 0x77, 0x80, 0x50, 0x54, 0xBD, 0x0D, 0x58, 0x34, 0x0A, 0x44, 0xA8, 0x5F, 0x99, 0xC6, 0xBE, 0x4E, 0x4D, 0x13, 0x17, 0x83, 0x01, 0x35, 0x5C, 0xF4, 0x7B, 0x53, 0x31, 0x86, 0xD4, 0xB8, 0xAB, 0xD1, 0xB5, 0x68, 0xDC, 0x96, 0xF1, 0x9C, 0xE8, 0x7A, 0x1B, 0xB0, 0x56, 0x22, 0x1A, 0x51, 0x92, 0xBF, 0xFA, 0xB1, 0x19, 0x88, 0x26, 0x49, 0x08, 0xEB, 0xAC, 0x14, 0x28, 0xAD, 0x3A, 0x8C, 0x85, 0x84, 0x2C, 0x82, 0xB3, 0xA6, 0xA2, 0xA3, 0x12, 0x78, 0xA1, 0x57, 0xAE, 0x00, 0x2F, 0xB6, 0x61, 0xA5, 0x6F, 0x5A, 0x89, 0x29, 0x46, 0x2E, 0x4F, 0x36, 0x40, 0x07, 0x87, 0xA7, 0x65, 0x73, 0xC4, 0x7C, 0x33, 0x1E, 0xE5, 0x10, 0xB4, 0xFD, 0xC9, 0xE0, 0xB7, 0x97, 0x32, 0x5D, 0x64, 0x41, 0xF0, 0x20, 0xC3, 0x95, 0xFE, 0xD2, 0x21, 0xFB, 0x75, 0x3D, 0x0B, 0x3E, 0xF2, 0xD5, 0xCB, 0xD6, 0xF7, 0x1F, 0x24, 0x45, 0x69, 0xB9, 0xDA, 0x6A, 0x76, 0x03, 0xF8, 0x70, 0x8E, 0xC1, 0xC8, 0xD7, 0x4A, 0xD0, 0x9E, 0xCD, 0xA4, 0xCE, 0xAA, 0x1D, 0xED, 0xF6, 0x02, 0x60, 0xE3, 0xDB, 0x8D, 0x09, 0xF3, 0x37, 0xE1, 0xC5, 0xCA, 0x8F, 0x2D, 0x7F, 0x74, 0x42, 0x6E, 0x8B, 0x3F, 0x23, 0xC2, 0xD3, 0xCC, 0xD9, 0xEE, 0x98, 0xE6, 0x11, 0x05, 0xEA, 0xD8, 0xB2, 0xE4, 0xF5, 0xE7, 0x71, 0x2B, 0x93, 0x9B, 0x3C, 0x30, 0xE9, 0xC7, 0x38, 0xEC, 0x18, 0x6B, 0x79, 0xFC, 0xAF, 0x5E, 0x9F, 0x7E, 0x91, 0xDD, 0x16, 0x94, 0x0F, 0x06, 0x67, 0x25, 0x0C, 0x1C, ]; assert_eq!(Ncmdump::::build_key_box(&key), key_box); ``` -------------------------------- ### Read Implementation Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html The `Read` trait implementation for `QmcDump` intercepts read operations, applies decryption using the internal key and offset, and then forwards the data to the underlying reader. ```APIDOC impl Read for QmcDump where R: Read, { fn read(&mut self, buf: &mut [u8]) -> std::io::Result } ``` -------------------------------- ### QmcDump::get_data Function Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Retrieves the decrypted music data from the QMC file. It reads the file in chunks, decrypts them, and returns the complete data as a Vec. ```rust /// Get the music data from qmcdump. /// /// # Example: /// /// ```rust /// use std::fs::File; /// use std::io::Write; /// use std::path::Path; /// /// use anyhow::Result; /// use ncmdump::QmcDump; /// /// fn main() -> Result<()> { /// let file = File::open("res/test.qmcflac")?; /// let mut qmc = QmcDump::from_reader(file)?; /// let music = qmc.get_data()?; /// /// let mut target = File::options() /// .create(true) /// .write(true) /// .open("res/test.flac")?; /// target.write_all(&music)?; /// Ok(()) /// } /// ``` pub fn get_data(&mut self) -> std::io::Result> { let mut buffer = [0; BUFFER_SIZE]; let mut output = Vec::new(); while let Ok(size) = self.read(&mut buffer) { if size == 0 { break; } output.write_all(&buffer[..size])?; } Ok(output) } ``` -------------------------------- ### NcmInfo Struct Definition Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.NcmInfo.html Defines the structure for storing music metadata. Includes fields for name, ID, album, artist details, bitrate, duration, format, and optional MV ID and aliases. ```rust pub struct NcmInfo { pub name: String, pub id: u64, pub album: String, pub artist: Vec<(String, u64)>, pub bitrate: u64, pub duration: u64, pub format: String, pub mv_id: Option, pub alias: Option>, } ``` -------------------------------- ### QmcDump::get_data Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.QmcDump.html Retrieves the music data from the qmcdump. This method processes the qmc file and returns the raw music bytes. ```APIDOC ## pub fn get_data(&mut self) -> Result> ### Description Get the music data from qmcdump. ### Parameters - `self`: A mutable reference to the `QmcDump` instance. ### Response #### Success Response (Result>) - **Vec** - A vector of bytes representing the music data. ### Example ```rust use std::fs::File; use std::io::Write; use anyhow::Result; use ncmdump::QmcDump; fn main() -> Result<()> { let file = File::open("res/test.qmcflac")?; let mut qmc = QmcDump::from_reader(file)?; let music = qmc.get_data()?; let mut target = File::options() .create(true) .write(true) .open("res/test.flac")?; target.write_all(&music)?; Ok(()) } ``` ``` -------------------------------- ### Convert RawNcmInfo to NcmInfo Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Implements the `From` trait to convert a `RawNcmInfo` struct into a `NcmInfo` struct. It handles the conversion of `NcmId` types to `u64`. ```rust impl From for NcmInfo { fn from(raw_info: RawNcmInfo) -> Self { Self { name: raw_info.name, id: raw_info.id.get_id().unwrap_or(0), album: raw_info.album, artist: raw_info .artist .into_iter() .map(|(name, id)| (name, id.get_id().unwrap_or(0))) .collect::>(), bitrate: raw_info.bitrate.get_id().unwrap_or(0), duration: raw_info.duration.get_id().unwrap_or(0), format: raw_info.format, mv_id: match raw_info.mv_id { Some(id) => match id.get_id() { Ok(inner) => Some(inner), Err(_) => None, }, None => None, }, alias: raw_info.alias, } } } ``` -------------------------------- ### Check if a file is QMC format Source: https://docs.rs/ncmdump/0.8.0/ncmdump/utils/fn.is_qmc_file.html Use this function to determine if a file is in QMC format before processing. Ensure the file path is correct and the file exists. ```rust let mut file = File::open("res/test.ncm").unwrap(); let result = is_qmc_file(&mut file).unwrap(); ``` -------------------------------- ### Test File Type Parsing Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/utils.rs.html Tests the `FileType::parse` function by opening a test NCM file and asserting that it is correctly parsed as `FileType::Ncm`. ```rust #[cfg(feature = "ncmdump")] #[test] fn test_get_file_type_ok() -> Result<(), Error> { let mut file = File::open("res/test.ncm")?; let file_type = FileType::parse(&mut file); assert!(file_type.is_ok()); assert_eq!(file_type.unwrap(), FileType::Ncm); Ok(()) } ``` -------------------------------- ### Extracting Music Data Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html The `get_data` method reads the entire content from the underlying reader, decrypts it on the fly, and returns the decrypted music data as a `Vec`. This is useful for saving the decrypted audio to a new file. ```APIDOC /// Get the music data from qmcdump. /// /// # Example: /// /// ```rust /// use std::fs::File; /// use std::io::Write; /// use std::path::Path; /// /// use anyhow::Result; /// use ncmdump::QmcDump; /// /// fn main() -> Result<()> { /// let file = File::open("res/test.qmcflac")?; /// let mut qmc = QmcDump::from_reader(file)?; /// let music = qmc.get_data()?; /// /// let mut target = File::options() /// .create(true) /// .write(true) /// .open("res/test.flac")?; /// target.write_all(&music)?; /// Ok(()) /// } /// ``` pub fn get_data(&mut self) -> std::io::Result> ``` -------------------------------- ### Debug Implementation for NcmInfo Source: https://docs.rs/ncmdump/0.8.0/ncmdump/struct.NcmInfo.html Provides a way to format the NcmInfo struct for debugging purposes. ```rust impl Debug for NcmInfo Source§ #### fn fmt(&self, f: &mut Formatter<'_>) -> Result Formats the value using the given formatter. Read more Source ``` -------------------------------- ### Test QMC Dump Multi-Read Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Tests reading data in chunks from a QMC dump. Ensures that subsequent reads correctly retrieve the remaining decrypted data. ```rust #[test] fn test_qmcdump_multi_read_ok() -> Result<()> { let input = Cursor::new([0x00, 0x01, 0x02, 0x03]); let mut qmc = QmcDump::from_reader(input)?; let mut buf = [0; 2]; let size = qmc.read(&mut buf)?; assert_eq!(size, 2); assert_eq!(buf, [0xC3, 0x4B]); let size = qmc.read(&mut buf)?; assert_eq!(size, 2); assert_eq!(buf, [0xD4, 0xC9]); Ok(()) } ``` -------------------------------- ### Extract Image from NCM File Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Opens an NCM file, extracts its embedded image, and saves it as a JPEG. Requires `ncmdump` and `anyhow` crates. ```rust use std::fs::File; use std::path::Path; use anyhow::Result; use ncmdump::Ncmdump; fn main() -> Result<()> { use std::io::Write; let file = File::open("res/test.ncm")?; let mut ncm = Ncmdump::from_reader(file)?; let image = ncm.get_image()?; let mut target = File::options() .create(true) .write(true) .open("res/test.jpeg")?; target.write_all(&image)?; Ok(()) } ``` -------------------------------- ### QmcDump Encryption Logic Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Contains the core encryption/decryption logic using a predefined key and an offset-dependent mapping function. ```rust fn map_l(value: u64) -> u8 { let v = if value > 0x7FFF { value % 0x7FFF } else { value } as usize; let index = (v * v + 80923) % 256; KEY[index] } fn encrypt(offset: u64, buffer: &mut [u8]) { for (index, byte) in buffer.iter_mut().enumerate() { *byte ^= Self::map_l(offset + index as u64); } } ``` -------------------------------- ### Test QMC Dump Single Read Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/qmcdump.rs.html Tests reading data from a QMC dump using a Cursor as input. Verifies that the correct amount of data is read and matches the expected decrypted output. ```rust #[test] fn test_qmcdump_read_ok() -> Result<()> { let input = Cursor::new([0x00, 0x01, 0x02, 0x03]); let mut qmc = QmcDump::from_reader(input)?; let mut buf = [0; 4]; let size = qmc.read(&mut buf)?; assert_eq!(size, 4); assert_eq!(buf, [0xC3, 0x4B, 0xD4, 0xC9]); Ok(()) } ``` -------------------------------- ### Decrypt Data using AES-128 with PKCS7 Padding Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Decrypts data using AES-128 in CBC mode with PKCS7 padding. Requires the key and the encrypted data as input. Returns the decrypted data or an error. ```rust fn decrypt(data: &[u8], key: &[u8; 16]) -> Result> { let result = Aes128::new(key.into()) .decrypt_padded_vec_mut::(data) .map_err(|_| Errors::DecryptError)?; Ok(result) } ``` -------------------------------- ### Test NCM Info Extraction Source: https://docs.rs/ncmdump/0.8.0/src/ncmdump/ncmdump.rs.html Tests the extraction of metadata from an NCM file and verifies its correctness. ```rust #[test] fn test_get_info_ok() -> Result<()> { let reader = File::open("res/test.ncm")?; let mut ncm = Ncmdump::from_reader(reader)?; let info = ncm.get_info()?; assert_eq!( info, NcmInfo { name: "寒鸦少年".to_string(), id: 1305366556, album: "寒鸦少年".to_string(), artist: vec![("华晨宇".into(), 861777)], bitrate: 923378, duration: 315146, format: "flac".to_string(), mv_id: Some(0), alias: Some(vec!["电视剧《斗破苍穹》主题曲".into()]) }, ); Ok(()) } ``` -------------------------------- ### is_qmc_file Source: https://docs.rs/ncmdump/0.8.0/ncmdump/utils/index.html Checks if the provided reader is in QMC format. ```APIDOC ## is_qmc_file ### Description Check if the reader is qmc format. ```