use crate::base32::config::Base32DecodeConfig;
use crate::base32::error::Base32Error;
#[inline(always)]
#[allow(unsafe_op_in_unsafe_fn)]
pub(crate) unsafe fn decode_full_group_into(
config: &Base32DecodeConfig,
chunk: &[u8],
chunk_start: usize,
dst: &mut [u8],
dst_offset: usize,
) -> Result<usize, Base32Error> {
debug_assert_eq!(chunk.len(), 8);
let c0 = chunk[0];
let c1 = chunk[1];
let c2 = chunk[2];
let c3 = chunk[3];
let c4 = chunk[4];
let c5 = chunk[5];
let c6 = chunk[6];
let c7 = chunk[7];
if let Some(padding) = config.padding {
if c0 == padding
|| c1 == padding
|| c2 == padding
|| c3 == padding
|| c4 == padding
|| c5 == padding
|| c6 == padding
|| c7 == padding
{
return Err(Base32Error::InvalidPadding);
}
}
if (c0 | c1 | c2 | c3 | c4 | c5 | c6 | c7) & 0x80 != 0 {
let pos = if c0 & 0x80 != 0 {
0
} else if c1 & 0x80 != 0 {
1
} else if c2 & 0x80 != 0 {
2
} else if c3 & 0x80 != 0 {
3
} else if c4 & 0x80 != 0 {
4
} else if c5 & 0x80 != 0 {
5
} else if c6 & 0x80 != 0 {
6
} else {
7
};
return Err(Base32Error::InvalidCharacter(chunk[pos], chunk_start + pos));
}
let decode_table = config.decode_table;
let i0 = decode_table[c0 as usize];
let i1 = decode_table[c1 as usize];
let i2 = decode_table[c2 as usize];
let i3 = decode_table[c3 as usize];
let i4 = decode_table[c4 as usize];
let i5 = decode_table[c5 as usize];
let i6 = decode_table[c6 as usize];
let i7 = decode_table[c7 as usize];
if i0 < 0 || i1 < 0 || i2 < 0 || i3 < 0 || i4 < 0 || i5 < 0 || i6 < 0 || i7 < 0 {
let pos = if i0 < 0 {
0
} else if i1 < 0 {
1
} else if i2 < 0 {
2
} else if i3 < 0 {
3
} else if i4 < 0 {
4
} else if i5 < 0 {
5
} else if i6 < 0 {
6
} else {
7
};
return Err(Base32Error::InvalidCharacter(chunk[pos], chunk_start + pos));
}
let b0 = ((i0 as u32) << 3) | ((i1 as u32) >> 2);
let b1 = ((i1 as u32) << 6) | ((i2 as u32) << 1) | ((i3 as u32) >> 4);
let b2 = ((i3 as u32) << 4) | ((i4 as u32) >> 1);
let b3 = ((i4 as u32) << 7) | ((i5 as u32) << 2) | ((i6 as u32) >> 3);
let b4 = ((i6 as u32) << 5) | (i7 as u32);
let ptr = dst.as_mut_ptr().add(dst_offset);
ptr.write(b0 as u8);
ptr.add(1).write(b1 as u8);
ptr.add(2).write(b2 as u8);
ptr.add(3).write(b3 as u8);
ptr.add(4).write(b4 as u8);
Ok(5)
}