#![allow(clippy::needless_range_loop)]
use crate::{PenisBlock, PrivateBlock, State};
use alloc::vec::Vec;
pub struct Penis(pub Vec<PenisBlock>);
impl Penis {
pub fn encode_compact(&self) -> Vec<u8> {
let estimated_capacity = self
.0
.iter()
.map(|block| match block {
PenisBlock::Private(_) => 0x61,
PenisBlock::Public(_) => 0x41,
})
.sum();
let mut encoded_bytes = Vec::with_capacity(estimated_capacity);
for block in &self.0 {
match block {
PenisBlock::Private(private_block) => {
encoded_bytes.push(1);
for &value in &private_block.psa {
encoded_bytes.extend(&value.to_be_bytes());
}
encoded_bytes.extend(private_block.state.finalize().as_ref());
}
PenisBlock::Public(raw_block) => {
encoded_bytes.push(0);
encoded_bytes.extend(raw_block);
}
}
}
encoded_bytes
}
pub fn decode_compact(compact_bytes: &[u8]) -> Self {
let mut penis_blocks = Vec::new();
let mut i = 0;
while i < compact_bytes.len() {
let block_type = compact_bytes[i];
i += 1;
match block_type {
1 => {
let mut psa = [0u32; 16];
for j in 0..16 {
let base_ptr = i + j * 4;
psa[j] = u32::from_be_bytes([
compact_bytes[base_ptr],
compact_bytes[base_ptr + 1],
compact_bytes[base_ptr + 2],
compact_bytes[base_ptr + 3],
]);
}
i += 64;
let state = State::from_bytes(&compact_bytes[i..i + 32]);
penis_blocks.push(PenisBlock::Private(PrivateBlock { psa, state }));
i += 32;
}
0 => {
let mut raw_block = [0u8; 64];
raw_block.copy_from_slice(&compact_bytes[i..i + 64]);
penis_blocks.push(PenisBlock::Public(raw_block));
i += 64;
}
_ => panic!("Unknown block type"),
}
}
Self(penis_blocks)
}
pub fn encode_u32(&self) -> Vec<u32> {
let estimated_capacity = self
.0
.iter()
.map(|block| match block {
PenisBlock::Private(_) => 25,
PenisBlock::Public(_) => 17,
})
.sum();
let mut encoded_bytes = Vec::with_capacity(estimated_capacity);
for block in &self.0 {
match block {
PenisBlock::Private(private_block) => {
encoded_bytes.push(1);
encoded_bytes.extend(private_block.psa);
encoded_bytes.extend(private_block.state.finalize_u32().as_ref());
}
PenisBlock::Public(raw_block) => {
encoded_bytes.push(0);
encoded_bytes.extend(raw_block.iter().map(|&x| x as u32));
}
}
}
encoded_bytes
}
pub fn decode_u32(u32_data: &[u32]) -> Self {
let mut penis_blocks = Vec::new();
let mut i = 0;
while i < u32_data.len() {
let block_type = u32_data[i];
i += 1;
match block_type {
1 => {
let mut psa = [0u32; 16];
psa.copy_from_slice(&u32_data[i..i + 16]);
let state_data = &u32_data[i + 16..i + 24];
let state = State {
a: state_data[0],
b: state_data[1],
c: state_data[2],
d: state_data[3],
e: state_data[4],
f: state_data[5],
g: state_data[6],
h: state_data[7],
};
penis_blocks.push(PenisBlock::Private(PrivateBlock { psa, state }));
i += 24;
}
0 => {
let mut raw_block = [0u8; 64];
for j in 0..16 {
let bytes = u32_data[i + j].to_be_bytes();
raw_block[j * 4..j * 4 + 4].copy_from_slice(&bytes);
}
penis_blocks.push(PenisBlock::Public(raw_block));
i += 16;
}
_ => panic!("Unknown block type"),
}
}
Self(penis_blocks)
}
pub fn encode_test(&self) -> Vec<u8> {
let estimated_capacity = self
.0
.iter()
.map(|block| match block {
PenisBlock::Private(_) => 0x60,
PenisBlock::Public(_) => 0x40,
})
.sum();
let mut encoded_bytes = Vec::with_capacity(estimated_capacity);
for block in &self.0 {
match block {
PenisBlock::Private(private_block) => {
for &value in &private_block.psa {
encoded_bytes.extend(&value.to_be_bytes());
}
encoded_bytes.extend(private_block.state.finalize().as_ref());
}
PenisBlock::Public(raw_block) => {
encoded_bytes.extend(raw_block);
}
}
}
encoded_bytes
}
}