use shogi_core::{Color, Hand, Piece};
use crate::{Error, FromUsi, Result};
impl FromUsi for [Hand; 2] {
fn parse_usi_slice(s: &[u8]) -> Result<(&[u8], Self)> {
if let Some((&first, s)) = s.split_first() {
if first == b'-' {
return Ok((s, [Hand::default(); 2]));
}
} else {
return Err(Error::InvalidInput {
from: 0,
to: 0,
description: "A `[Hand; 2]` expected, but nothing found",
});
}
let mut index = 0;
let mut hand = [Hand::default(); 2];
while let Some(current) = s.get(index).copied() {
let mut count = 1;
let mut count_len = 0;
if matches!(current, b'0'..=b'9') {
let mut this = current - b'0';
if index + 1 < s.len() && matches!(s[index + 1], b'0'..=b'9') {
this = 10 * this + (s[index + 1] - b'0');
count_len = 2;
} else {
count_len = 1;
}
count = this;
}
if index + count_len >= s.len() {
return Err(Error::InvalidInput {
from: index,
to: index + count_len,
description: "A `Piece` was expected, but not found",
});
}
let result = Piece::parse_usi_slice(unsafe {
s.get_unchecked(index + count_len..index + count_len + 1)
});
let piece = if let Ok((_, piece)) = result {
piece
} else {
break;
};
let piece_kind = piece.piece_kind();
match piece.color() {
Color::Black => {
for _ in 0..count {
hand[0] = if let Some(newhand) = hand[0].added(piece_kind) {
newhand
} else {
break;
}
}
}
Color::White => {
for _ in 0..count {
hand[1] = if let Some(newhand) = hand[1].added(piece_kind) {
newhand
} else {
break;
}
}
}
}
index += count_len + 1;
}
if index == 0 {
return Err(Error::InvalidInput {
from: 0,
to: 1,
description: "A `[Hand; 2]` expected, but no pieces were found",
});
}
Ok((unsafe { s.get_unchecked(index..) }, hand))
}
}
#[no_mangle]
pub unsafe extern "C" fn Hand_parse_usi_slice(hand: &mut [Hand; 2], s: *const u8) -> isize {
crate::common::make_parse_usi_slice_c(hand, s)
}