use std::convert::TryFrom;
use bamboo_rs_core_ed25519_yasmf::entry::MAX_ENTRY_SIZE;
use bamboo_rs_core_ed25519_yasmf::{Signature as BambooSignature, YasmfHash};
use lipmaa_link::is_skip_link;
use rstest::fixture;
use varu64::encode as varu64_encode;
use crate::entry::{sign_and_encode, Entry, EntrySigned, LogId, SeqNum};
use crate::hash::{Blake3ArrayVec, Hash};
use crate::identity::KeyPair;
use crate::operation::{Operation, OperationEncoded};
use crate::test_utils::constants::default_fields;
use crate::test_utils::fixtures::{key_pair, operation, operation_fields, random_hash};
#[fixture]
pub fn entry(
#[default(1)] seq_num: u64,
#[default(1)] log_id: u64,
#[default(None)] backlink: Option<Hash>,
#[default(None)] skiplink: Option<Hash>,
#[default(Some(operation(Some(operation_fields(default_fields())), None, None)))]
operation: Option<Operation>,
) -> Entry {
Entry::new(
&LogId::new(log_id),
operation.as_ref(),
skiplink.as_ref(),
backlink.as_ref(),
&SeqNum::new(seq_num).unwrap(),
)
.unwrap()
}
#[fixture]
pub fn entry_auto_gen_links(#[default(1)] seq_num: u64, #[default(1)] log_id: u64) -> Entry {
let backlink = match seq_num {
1 => None,
_ => Some(random_hash()),
};
let skiplink = match is_skip_link(seq_num) {
false => None,
true => Some(random_hash()),
};
Entry::new(
&LogId::new(log_id),
Some(&operation(
Some(operation_fields(default_fields())),
backlink.clone().map(|hash| hash.into()),
None,
)),
skiplink.as_ref(),
backlink.as_ref(),
&SeqNum::new(seq_num).unwrap(),
)
.unwrap()
}
#[fixture]
pub fn entry_signed_encoded(entry: Entry, key_pair: KeyPair) -> EntrySigned {
sign_and_encode(&entry, &key_pair).unwrap()
}
#[fixture]
pub fn entry_signed_encoded_unvalidated(
#[default(1)] seq_num: u64,
#[default(1)] log_id: u64,
#[default(None)] backlink: Option<Hash>,
#[default(None)] skiplink: Option<Hash>,
#[default(Some(operation(Some(operation_fields(default_fields())), None, None)))]
operation: Option<Operation>,
key_pair: KeyPair,
) -> String {
let mut entry_bytes = [0u8; MAX_ENTRY_SIZE];
let mut next_byte_num = 0;
entry_bytes[0] = 0;
next_byte_num += 1;
let author_bytes = key_pair.public_key().as_bytes();
entry_bytes[next_byte_num..author_bytes.len() + next_byte_num]
.copy_from_slice(&author_bytes[..]);
next_byte_num += author_bytes.len();
next_byte_num += varu64_encode(log_id, &mut entry_bytes[next_byte_num..]);
next_byte_num += varu64_encode(seq_num, &mut entry_bytes[next_byte_num..]);
next_byte_num = match skiplink {
Some(lipmaa_link) => {
next_byte_num += Into::<YasmfHash<Blake3ArrayVec>>::into(lipmaa_link)
.encode(&mut entry_bytes[next_byte_num..])
.unwrap();
next_byte_num
}
_ => next_byte_num,
};
next_byte_num = match backlink {
Some(backlink) => {
next_byte_num += Into::<YasmfHash<Blake3ArrayVec>>::into(backlink)
.encode(&mut entry_bytes[next_byte_num..])
.unwrap();
next_byte_num
}
_ => next_byte_num,
};
match operation {
Some(operation) => {
let operation_encoded = OperationEncoded::try_from(&operation).unwrap();
let operation_size = operation_encoded.size();
next_byte_num += varu64_encode(operation_size, &mut entry_bytes[next_byte_num..]);
let operation_hash = operation_encoded.hash();
next_byte_num += Into::<YasmfHash<Blake3ArrayVec>>::into(operation_hash)
.encode(&mut entry_bytes[next_byte_num..])
.unwrap();
}
None => (),
};
let signature = key_pair.sign(&entry_bytes[..next_byte_num]);
let signature_bytes = signature.to_bytes();
let sig = Some(BambooSignature(&signature_bytes[..])).unwrap();
next_byte_num += sig.encode(&mut entry_bytes[next_byte_num..]).unwrap();
hex::encode(&entry_bytes[..next_byte_num])
}