use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::{
io::{self, Read, Write},
path::PathBuf,
};
use zcash_primitives::{memo::MemoBytes, transaction::TxId};
pub fn read_string<R: Read>(mut reader: R) -> io::Result<String> {
let str_len = reader.read_u64::<LittleEndian>()?;
let mut str_bytes = vec![0; str_len as usize];
reader.read_exact(&mut str_bytes)?;
let str = String::from_utf8(str_bytes)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e.to_string()))?;
Ok(str)
}
pub fn write_string<W: Write>(mut writer: W, s: &String) -> io::Result<()> {
writer.write_u64::<LittleEndian>(s.len() as u64)?;
writer.write_all(s.as_bytes())
}
pub fn interpret_memo_string(memo_str: String) -> Result<MemoBytes, String> {
let s_bytes = if memo_str.to_lowercase().starts_with("0x") {
match hex::decode(&memo_str[2..memo_str.len()]) {
Ok(data) => data,
Err(_) => Vec::from(memo_str.as_bytes()),
}
} else {
Vec::from(memo_str.as_bytes())
};
MemoBytes::from_bytes(&s_bytes)
.map_err(|_| format!("Error creating output. Memo '{:?}' is too long", memo_str))
}
pub fn txid_from_slice(txid: &[u8]) -> TxId {
let mut txid_bytes = [0u8; 32];
txid_bytes.copy_from_slice(txid);
TxId::from_bytes(txid_bytes)
}
pub(crate) fn read_sapling_params() -> Result<(PathBuf, PathBuf), String> {
let zcash_params_path = zcash_proofs::download_sapling_parameters(Some(5)).unwrap();
let sapling_output_path = zcash_params_path.output;
let sapling_spend_path = zcash_params_path.spend;
Ok((sapling_output_path, sapling_spend_path))
}