ireal-parser 0.1.0

iReal Pro song parser and manipulation library
Documentation
//! # iReal Parser
//!
//! `ireal_parser` is a library that provides functionality to parse iReal Pro
//! URLs and chord progressions according to the [iReal Pro
//! specification](https://www.irealpro.com/ireal-pro-file-format).
//!
//! ## Features
//!
//! - Parse iReal Pro URLs into a [`Song`] struct with fields like title,
//!   composer, style, and key signature.
//! - Parse iReal Pro progressions into a [`Progression`] struct containing
//!   [`ProgressionElement`]s.
//! - Convert [`Song`], [`Progression`], and [`ProgressionElement`] structs back
//!   to iReal Pro URL and progression string formats.
//!
//! ## Usage
//!
//! Add `ireal_parser` as a dependency in your `Cargo.toml`, then use the
//! parsing functions provided by the crate:
//!
//! ```rust
//! use ireal_parser::parse_irealbook_url;
//!
//! // Parse an iReal Pro URL into a `Song` struct
//! let song = parse_irealbook_url("irealbook://Song Title=LastName FirstName=Style=Ab=n=T44*A{C^7 |A-7 |D-9 |G7#5 }").unwrap();
//! ```
//!
//! For more information, refer to the [iReal Pro
//! specification](https://www.irealpro.com/ireal-pro-file-format).

mod error;
pub use error::*;

mod time_signature;
pub use time_signature::*;

mod chord;
pub use chord::*;

mod staff_text;
pub use staff_text::*;

mod progression;
pub use progression::*;

mod song;
pub use song::*;

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_irealbook_progression() {
        let input = "{C |A- |D- |G7 }[C |A- |D- |G7 Z";
        let p = parse_irealbook_progression(input).unwrap();
        assert_eq!(input, p.to_string());

        let input = "T44[C |A- T98|D- |G7 Z";
        let p = parse_irealbook_progression(input).unwrap();
        assert_eq!(input, p.to_string());

        let input = "[T44C | x | x | x |D-7 |G7 | r| Z";
        let _p = parse_irealbook_progression(input).unwrap();

        let input = "*A[C |A- |SD- |G7 QZ";
        let p = parse_irealbook_progression(input).unwrap();
        assert_eq!(input, p.to_string());

        let input = "T44{C |A- |N1D- |G7 } |N2D- G7 |C6 Z";
        let _p = parse_irealbook_progression(input).unwrap();

        let input = "[T44<*74Solo Section:>C |A- |D- |G7 Z";
        let p = parse_irealbook_progression(input).unwrap();
        assert_eq!(input, p.to_string());

        let input = "[*AT44C |A- |D- |G7 |E- |A- |D- |G7 ZY[*BC |A- |D- |G7 Z";
        let p = parse_irealbook_progression(input).unwrap();
        assert_eq!(input, p.to_string());
    }

    #[test]
    fn test_parse_a_walking_thing() {
        let input = "irealbook://A Walkin Thing=Carter Benny=Medium Swing=D-=n=\
                     {*AT44D- D-/C |Bh7, Bb7(A7b9) |D-/A G-7 |D-/F sEh,A7,|Y\
                     |lD- D-/C |Bh7, Bb7(A7b9) |D-/A G-7 |N1D-/F sEh,A7} Y|N2sD-,G-,lD- ]\
                     [*BC-7 F7 |Bb^7 |C-7 F7 |Bb^7 n |\
                     |C-7 F7 |Bb^7 |B-7 E7 |A7,p,p,p,]\
                     [*AD- D-/C |Bh7, Bb7(A7b9) |D-/A G-7 |D-/F sEh,A7,|\
                     |lD- D-/C |Bh7, Bb7(A7b9) |D-/A G-7 |D-/F sEh,A7Z";
        let _p = parse_irealbook_url(input).unwrap();
    }

    #[test]
    fn test_parse_invalid_irealbook_url() {
        let input = "irealbook://Song Title=LastName FirstName=Ab=n=T44";
        let parsed = parse_irealbook_url(input);
        assert!(matches!(parsed, Err(Error::InvalidUrl)));
    }

    #[test]
    fn test_parse_irealbook_url() {
        let input = "irealbook://Song Title=LastName FirstName=Style=Ab=n=T44";
        let _parsed = parse_irealbook_url(input).unwrap();
    }
}