capitol 0.5.1

Parse United States Congress legislative document citations
Documentation
use std::fmt::Display;

use crate::constants::{
    BILL_SEQUENCES, COMMITTEE_PRINT_SEQUENCES, COMMITTEE_REPORT_SEQUENCES,
    CONCURRENT_RESOLUTION_SEQUENCES, CURRENT_CONGRESS, JOINT_RESOLUTION_SEQUENCES, PUBL_SEQUENCES,
    SIMPLE_RESOLUTION_SEQUENCES,
};
use crate::error::Error;
use crate::utils::Result;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Congress(pub usize);

impl Congress {
    pub(crate) fn parse(
        input: usize,
        chamber: Option<&Chamber>,
        document_type: &str,
    ) -> Result<Self> {
        if (chamber.is_some() || PUBL_SEQUENCES.contains(&document_type))
            && input <= *CURRENT_CONGRESS
        {
            Ok(Congress(input))
        } else {
            Err(Error::InvalidCongress)
        }
    }
}

impl Display for Congress {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Chamber {
    House,
    Senate,
}

impl Display for Chamber {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Self::House => 'h',
                Self::Senate => 's',
            }
        )
    }
}

impl Chamber {
    pub(crate) fn parse(input: &str) -> Option<Self> {
        if input.starts_with('h') {
            Some(Self::House)
        } else if input.starts_with('s') && input != "stat" {
            Some(Self::Senate)
        } else {
            None
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum MeasureType {
    Bill,
    Resolution,
    ConcurrentResolution,
    JointResolution,
}

impl MeasureType {
    pub(crate) fn parse(document_type: &str) -> Option<Self> {
        if BILL_SEQUENCES.contains(&document_type) {
            Some(Self::Bill)
        } else if SIMPLE_RESOLUTION_SEQUENCES.contains(&document_type) {
            Some(Self::Resolution)
        } else if CONCURRENT_RESOLUTION_SEQUENCES.contains(&document_type) {
            Some(Self::ConcurrentResolution)
        } else if JOINT_RESOLUTION_SEQUENCES.contains(&document_type) {
            Some(Self::JointResolution)
        } else {
            None
        }
    }
}

impl Display for MeasureType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Self::Bill => "",
                Self::Resolution => "res",
                Self::ConcurrentResolution => "conres",
                Self::JointResolution => "jres",
            }
        )
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum CommitteeDocumentType {
    Print,
    Report,
}

impl CommitteeDocumentType {
    pub(crate) fn parse(document_type: &str) -> Option<CommitteeDocumentType> {
        if COMMITTEE_REPORT_SEQUENCES.contains(&document_type) {
            Some(CommitteeDocumentType::Report)
        } else if COMMITTEE_PRINT_SEQUENCES.contains(&document_type) {
            Some(CommitteeDocumentType::Print)
        } else {
            None
        }
    }
}

impl Display for CommitteeDocumentType {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Self::Print => "prt",
                Self::Report => "rpt",
            }
        )
    }
}