imxrt-log 0.1.2

Logging extensions for i.MX RT processors.
Documentation
use std::{env, fs::File, io::Write, path::PathBuf};

type Error = Box<dyn std::error::Error>;

const CHECKED_ENV_VARS: &[&str] = &[
    "IMXRT_LOG_USB_BULK_MPS",
    "IMXRT_LOG_USB_SPEED",
    "IMXRT_LOG_BUFFER_SIZE",
];

fn handle_usb_speed(file: &mut dyn Write) -> Result<bool, Error> {
    let speed = env::var("IMXRT_LOG_USB_SPEED").unwrap_or_else(|_| "HIGH".into());
    let is_high_speed = if speed.to_uppercase() == "HIGH" {
        true
    } else if speed == "FULL" {
        false
    } else {
        return Err(
            format!("Unsupported USB speed '{speed}'. Select either 'HIGH' or 'LOW'.").into(),
        );
    };

    let speed = if is_high_speed { "High" } else { "LowFull" };
    writeln!(file, "\t#[cfg(feature = \"usbd\")]")?;
    writeln!(
        file,
        "\tpub const USB_SPEED: ::imxrt_usbd::Speed = ::imxrt_usbd::Speed::{speed};"
    )?;
    Ok(is_high_speed)
}
fn handle_usb_bulk_speed_mps(file: &mut dyn Write, is_high_speed: bool) -> Result<(), Error> {
    const ALLOWED_MPS: &[usize] = &[8, 16, 32, 64, 512];
    let mps = env::var("IMXRT_LOG_USB_BULK_MPS").unwrap_or_else(|_| "512".into());
    let mps: usize = mps.parse().map_err(|err| -> Error {
        format!("{err:?} when trying to parse IMXRT_LOG_USB_BULK_MPS={mps}").into()
    })?;
    if !ALLOWED_MPS.contains(&mps) {
        return Err(format!("Unsupported bulk MPS '{mps}'. Select on of {ALLOWED_MPS:?}").into());
    }
    if !is_high_speed && mps == 512 {
        return Err("Bulk MPS of 512 does not work with full-speed USB devices. Either pick a different MPS, or configure a high-speed USB device".into());
    } else if is_high_speed && mps != 512 {
        return Err("High-speed USB devices must use a 512 byte MPS.".into());
    }
    writeln!(file, "\t#[cfg(feature = \"usbd\")]")?;
    writeln!(file, "\tpub const USB_BULK_MPS: usize = {mps};")?;
    Ok(())
}
fn handle_buffer_size(file: &mut dyn Write) -> Result<(), Error> {
    let buffer_size = env::var("IMXRT_LOG_BUFFER_SIZE").unwrap_or_else(|_| "1024".into());
    let buffer_size: usize = buffer_size.parse().map_err(|err| -> Error {
        format!("{err:?} when trying to parse IMXRT_LOG_BUFFER_SIZE={buffer_size}").into()
    })?;
    if !buffer_size.is_power_of_two() {
        return Err(format!("Buffer size '{buffer_size}' must be a power of two.").into());
    }
    writeln!(file, "\tpub const BUFFER_SIZE: usize = {buffer_size};")?;
    Ok(())
}

fn main() -> Result<(), Error> {
    for env_var in CHECKED_ENV_VARS {
        println!("cargo:rerun-if-env-changed={env_var}");
    }

    let out = PathBuf::from(env::var("OUT_DIR")?);
    let mut cfg = File::create(out.join("config.rs"))?;

    writeln!(&mut cfg, "/// Auto-generated by build.rs.\nmod config {{")?;
    handle_buffer_size(&mut cfg)?;
    let is_high_speed = handle_usb_speed(&mut cfg)?;
    handle_usb_bulk_speed_mps(&mut cfg, is_high_speed)?;
    writeln!(&mut cfg, "}}")?;

    Ok(())
}