use crate::structs::{HitObject, HitObjectType};
#[inline(always)]
pub fn parse_int_fast(bytes: &[u8]) -> i32 {
let mut i = 0;
let mut result = 0;
let mut negative = false;
while i < bytes.len() && bytes[i] == b' ' {
i += 1;
}
if i < bytes.len() && bytes[i] == b'-' {
negative = true;
i += 1;
}
let len = bytes.len();
while i + 3 < len {
let b0 = bytes[i];
let b1 = bytes[i + 1];
let b2 = bytes[i + 2];
let b3 = bytes[i + 3];
if b0 >= b'0' && b0 <= b'9' && b1 >= b'0' && b1 <= b'9' &&
b2 >= b'0' && b2 <= b'9' && b3 >= b'0' && b3 <= b'9' {
result = result * 10000 +
(b0 - b'0') as i32 * 1000 +
(b1 - b'0') as i32 * 100 +
(b2 - b'0') as i32 * 10 +
(b3 - b'0') as i32;
i += 4;
} else {
break;
}
}
while i < len {
let byte = bytes[i];
if byte >= b'0' && byte <= b'9' {
result = result * 10 + (byte - b'0') as i32;
} else {
break;
}
i += 1;
}
if negative { -result } else { result }
}
pub fn parse_hit_object_line(line: &[u8], mode: u8) -> HitObject {
let mut start = 0usize;
let mut end = 0usize;
while end < line.len() && line[end] != b',' { end += 1; }
let x = parse_int_fast(&line[start..end]);
start = end + 1; end = start;
while end < line.len() && line[end] != b',' { end += 1; }
let y = parse_int_fast(&line[start..end]);
start = end + 1; end = start;
while end < line.len() && line[end] != b',' { end += 1; }
let time = parse_int_fast(&line[start..end]);
start = end + 1; end = start;
while end < line.len() && line[end] != b',' { end += 1; }
let type_flags = parse_int_fast(&line[start..end]) as u8;
let object_type = if mode == 3 && (type_flags & 128) != 0 { HitObjectType::Hold } else { HitObjectType::Circle };
let end_time = if matches!(object_type, HitObjectType::Hold) {
start = end + 1; end = start;
while end < line.len() && line[end] != b',' { end += 1; }
start = end + 1; end = start;
while end < line.len() && line[end] != b':' && line[end] != b',' { end += 1; }
Some(parse_int_fast(&line[start..end]))
} else {
None
};
HitObject { x, y, time, object_type, end_time }
}