dear-imgui-winit 0.18.0

Winit platform backend for dear-imgui-rs
Documentation
use winit::dpi::{LogicalPosition, LogicalSize};

pub(crate) fn finite_f32(value: f32) -> Option<f32> {
    value.is_finite().then_some(value)
}

pub(crate) fn finite_f64_to_f32(value: f64) -> Option<f32> {
    if !value.is_finite() {
        return None;
    }

    finite_f32(value as f32)
}

pub(crate) fn finite_vec2_f64_to_f32(value: [f64; 2]) -> Option<[f32; 2]> {
    Some([finite_f64_to_f32(value[0])?, finite_f64_to_f32(value[1])?])
}

pub(crate) fn finite_vec2_f32(value: [f32; 2]) -> Option<[f32; 2]> {
    Some([finite_f32(value[0])?, finite_f32(value[1])?])
}

pub(crate) fn finite_position(value: LogicalPosition<f64>) -> Option<[f32; 2]> {
    finite_vec2_f64_to_f32([value.x, value.y])
}

pub(crate) fn finite_non_negative_size(value: LogicalSize<f64>) -> [f32; 2] {
    [
        finite_non_negative_f64_to_f32(value.width).unwrap_or(0.0),
        finite_non_negative_f64_to_f32(value.height).unwrap_or(0.0),
    ]
}

pub(crate) fn finite_non_negative_f64_to_f32(value: f64) -> Option<f32> {
    let value = finite_f64_to_f32(value)?;
    (value >= 0.0).then_some(value)
}

pub(crate) fn finite_or_zero(value: f32) -> f32 {
    finite_f32(value).unwrap_or(0.0)
}

pub(crate) fn positive_finite_or(value: f64, fallback: f64) -> f64 {
    if value.is_finite() && value > 0.0 {
        value
    } else {
        fallback
    }
}

pub(crate) fn positive_finite_f32_or(value: f32, fallback: f32) -> f32 {
    if value.is_finite() && value > 0.0 {
        value
    } else {
        fallback
    }
}

pub(crate) fn framebuffer_scale(value: f64, fallback: f64) -> [f32; 2] {
    let scale = positive_finite_f32_or(positive_finite_or(value, fallback) as f32, 1.0);
    [scale, scale]
}

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

    #[test]
    fn rejects_non_finite_positions() {
        assert_eq!(finite_vec2_f64_to_f32([1.0, 2.0]), Some([1.0, 2.0]));
        assert_eq!(finite_vec2_f64_to_f32([f64::NAN, 2.0]), None);
        assert_eq!(finite_vec2_f64_to_f32([1.0, f64::INFINITY]), None);
        assert_eq!(finite_vec2_f64_to_f32([f64::MAX, 2.0]), None);
    }

    #[test]
    fn clamps_invalid_sizes_to_zero() {
        assert_eq!(
            finite_non_negative_size(LogicalSize::new(640.0, 480.0)),
            [640.0, 480.0]
        );
        assert_eq!(
            finite_non_negative_size(LogicalSize::new(-1.0, f64::NAN)),
            [0.0, 0.0]
        );
    }

    #[test]
    fn positive_scale_uses_fallback_for_invalid_values() {
        assert_eq!(positive_finite_or(2.0, 1.0), 2.0);
        assert_eq!(positive_finite_or(0.0, 1.0), 1.0);
        assert_eq!(positive_finite_or(f64::NAN, 1.0), 1.0);
        assert_eq!(positive_finite_or(f64::INFINITY, 1.0), 1.0);
    }
}