use core::slice;
use std::ptr;
use libc::size_t;
use super::util::make_bytes;
use crate::ffi::error::Error;
use crate::protobuf::ToProtobuf;
use crate::PublicKey;
#[repr(C)]
pub struct AccountId {
shard: u64,
realm: u64,
num: u64,
alias: *mut PublicKey,
evm_address: *mut u8,
}
impl AccountId {
pub(super) fn borrow_ref<'a>(&'a self) -> RefAccountId<'a> {
let alias = unsafe { self.alias.as_ref() };
let evm_address = unsafe { self.alias.cast::<[u8; 20]>().as_ref() };
RefAccountId { shard: self.shard, realm: self.realm, num: self.num, alias, evm_address }
}
}
impl From<crate::AccountId> for AccountId {
fn from(id: crate::AccountId) -> Self {
Self {
shard: id.shard,
realm: id.realm,
num: id.num,
alias: id.alias.map(Box::new).map_or_else(ptr::null_mut, Box::into_raw),
evm_address: id
.evm_address
.map(|it| it.to_bytes().to_vec().into_boxed_slice())
.map_or_else(ptr::null_mut, |it| Box::leak(it).as_mut_ptr()),
}
}
}
impl From<AccountId> for crate::AccountId {
fn from(value: AccountId) -> Self {
let value = value.borrow_ref();
crate::AccountId {
shard: value.shard,
realm: value.realm,
num: value.num,
alias: value.alias.cloned(),
evm_address: value.evm_address.cloned().map(crate::EvmAddress),
checksum: None,
}
}
}
pub(super) struct RefAccountId<'a> {
shard: u64,
realm: u64,
num: u64,
alias: Option<&'a PublicKey>,
evm_address: Option<&'a [u8; 20]>,
}
impl<'a> RefAccountId<'a> {
fn into_bytes(self) -> Vec<u8> {
use prost::Message;
self.to_protobuf().encode_to_vec()
}
}
impl<'a> ToProtobuf for RefAccountId<'a> {
type Protobuf = hedera_proto::services::AccountId;
fn to_protobuf(&self) -> Self::Protobuf {
use hedera_proto::services;
services::AccountId {
realm_num: self.realm as i64,
shard_num: self.shard as i64,
account: Some(match self.alias {
None => match self.evm_address {
Some(evm_address) => services::account_id::Account::Alias(evm_address.to_vec()),
None => services::account_id::Account::AccountNum(self.num as i64),
},
Some(alias) => services::account_id::Account::Alias(alias.to_bytes_raw()),
}),
}
}
}
#[no_mangle]
pub unsafe extern "C" fn hedera_account_id_from_bytes(
bytes: *const u8,
bytes_size: size_t,
id: *mut AccountId,
) -> Error {
assert!(!bytes.is_null());
assert!(!id.is_null());
let bytes = unsafe { std::slice::from_raw_parts(bytes, bytes_size) };
let parsed = ffi_try!(crate::AccountId::from_bytes(&bytes)).into();
unsafe {
ptr::write(id, parsed);
}
Error::Ok
}
#[no_mangle]
pub unsafe extern "C" fn hedera_account_id_to_bytes(id: AccountId, buf: *mut *mut u8) -> size_t {
let bytes = id.borrow_ref().into_bytes();
unsafe { make_bytes(bytes, buf) }
}
#[no_mangle]
pub unsafe extern "C" fn hedera_account_id_array_free(ids: *mut AccountId, size: size_t) {
assert!(!ids.is_null());
let buf = unsafe {
let ids = slice::from_raw_parts_mut(ids, size);
Box::from_raw(ids)
};
drop(buf);
}