hibana 0.9.7

Choreographic programming in Rust with no_std and no heap allocation
use super::{ColumnRange, ROLE_IMAGE_ROUTE_ARM_STRIDE, column_row_offset, read_u32};

#[derive(Clone, Copy)]
pub(super) struct RouteArmLaneMetadata {
    pub(super) event_start: usize,
    pub(super) event_len: usize,
    pub(super) lane_step_len: usize,
}

pub(super) const fn decode_route_arm_lane_metadata<const N: usize>(
    bytes: &[u8; N],
    route_arms: ColumnRange,
    row: usize,
) -> Option<RouteArmLaneMetadata> {
    let offset = match column_row_offset(route_arms, row, ROLE_IMAGE_ROUTE_ARM_STRIDE, 0) {
        Some(offset) => offset,
        None => return None,
    };
    let event_range = match read_u32(bytes, offset) {
        Some(raw) => raw,
        None => return None,
    };
    let metadata_offset = match offset.checked_add(4) {
        Some(offset) => offset,
        None => return None,
    };
    let metadata = match read_u32(bytes, metadata_offset) {
        Some(raw) => raw,
        None => return None,
    };
    let event_start = (event_range >> 16) as usize;
    let event_len = (event_range & u16::MAX as u32) as usize;
    let encoded_step_len = ((metadata >> 16) & u8::MAX as u32) as usize;
    if event_range == u32::MAX
        || (event_len == 0 && event_start != 0)
        || metadata & 0xff00_0000 != 0
    {
        return None;
    }
    let lane_step_len = if event_len == 0 {
        if encoded_step_len == 0 {
            0
        } else {
            return None;
        }
    } else {
        match encoded_step_len.checked_add(1) {
            Some(len) => len,
            None => return None,
        }
    };
    Some(RouteArmLaneMetadata {
        event_start,
        event_len,
        lane_step_len,
    })
}