xmrs 0.14.6

Read, edit and serialize SoundTracker music with pleasure — MOD/XM/S3M/IT/DW import plus SID & OPL chip synthesis, no_std.
Documentation
//! Optional OpenMPT extension blocks: `XCNS` (channel names),
//! `XINS` (extended instrument names), `XSNS` (extended sample
//! names). Strict IT 2.14 files don't carry these; OpenMPT-saved
//! IT files do, and parsing them out preserves the channel labels
//! a user authored in the editor.

use alloc::string::{String, ToString};
use alloc::vec;
use alloc::vec::Vec;

use crate::tracker::import::bin_reader::ImportError;

#[derive(Debug, Default)]
pub struct ItXNames;

impl ItXNames {
    pub fn load(source: &[u8], chunk_size: usize) -> Result<(Vec<String>, usize), ImportError> {
        let data = source;

        if data.len() < 4 {
            return Err(ImportError::UnexpectedEof);
        }

        let length = u32::from_le_bytes(data[0..4].try_into().unwrap()) as usize;
        if length == 0 {
            return Ok((vec![], 4));
        }
        if data.len() < 4 + length {
            return Err(ImportError::OutOfRange("ItXNames length overshoots input"));
        }
        let body = &data[4..4 + length];

        let dest: Vec<String> = body
            .chunks(chunk_size)
            .map(|chunk| {
                String::from_utf8_lossy(chunk)
                    .trim_matches(char::from(0))
                    .trim()
                    .to_string()
            })
            .collect();

        Ok((dest, 4 + length))
    }

    pub fn is_pnam(data: &[u8]) -> bool {
        data.starts_with(b"PNAM")
    }

    pub fn is_cnam(data: &[u8]) -> bool {
        data.starts_with(b"CNAM")
    }
}