use crate::{convert, mem, prims::*, traits::*, types::*};
use concordium_contracts_common::*;
use mem::MaybeUninit;
impl convert::From<()> for Reject {
#[inline(always)]
fn from(_: ()) -> Self { Reject {} }
}
impl convert::From<ParseError> for Reject {
#[inline(always)]
fn from(_: ParseError) -> Self { Reject {} }
}
impl Seek for ContractState {
type Err = ();
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Err> {
use core::convert::TryFrom;
use SeekFrom::*;
match pos {
Start(offset) => match u32::try_from(offset) {
Ok(offset_u32) => {
self.current_position = offset_u32;
Ok(offset)
}
_ => Err(()),
},
End(delta) => {
let end = self.size();
if delta >= 0 {
match u32::try_from(delta)
.ok()
.and_then(|x| self.current_position.checked_add(x))
{
Some(offset_u32) => {
self.current_position = offset_u32;
Ok(u64::from(offset_u32))
}
_ => Err(()),
}
} else {
match delta.checked_abs().and_then(|x| u32::try_from(x).ok()) {
Some(before) if before <= end => {
let new_pos = end - before;
self.current_position = new_pos;
Ok(u64::from(new_pos))
}
_ => Err(()),
}
}
}
Current(delta) => {
let new_offset = if delta >= 0 {
u32::try_from(delta).ok().and_then(|x| self.current_position.checked_add(x))
} else {
delta
.checked_abs()
.and_then(|x| u32::try_from(x).ok())
.and_then(|x| self.current_position.checked_sub(x))
};
match new_offset {
Some(offset) => {
self.current_position = offset;
Ok(u64::from(offset))
}
_ => Err(()),
}
}
}
}
}
impl Read for ContractState {
fn read(&mut self, buf: &mut [u8]) -> ParseResult<usize> {
use core::convert::TryInto;
let len: u32 = {
match buf.len().try_into() {
Ok(v) => v,
_ => return Err(ParseError::default()),
}
};
let num_read = unsafe { load_state(buf.as_mut_ptr(), len, self.current_position) };
self.current_position += num_read;
Ok(num_read as usize)
}
fn read_u64(&mut self) -> ParseResult<u64> {
let mut bytes: MaybeUninit<[u8; 8]> = MaybeUninit::uninit();
let num_read =
unsafe { load_state(bytes.as_mut_ptr() as *mut u8, 8, self.current_position) };
self.current_position += num_read;
if num_read == 8 {
unsafe { Ok(u64::from_le_bytes(bytes.assume_init())) }
} else {
Err(ParseError::default())
}
}
fn read_u32(&mut self) -> ParseResult<u32> {
let mut bytes: MaybeUninit<[u8; 4]> = MaybeUninit::uninit();
let num_read =
unsafe { load_state(bytes.as_mut_ptr() as *mut u8, 4, self.current_position) };
self.current_position += num_read;
if num_read == 4 {
unsafe { Ok(u32::from_le_bytes(bytes.assume_init())) }
} else {
Err(ParseError::default())
}
}
fn read_u8(&mut self) -> ParseResult<u8> {
let mut bytes: MaybeUninit<[u8; 1]> = MaybeUninit::uninit();
let num_read =
unsafe { load_state(bytes.as_mut_ptr() as *mut u8, 1, self.current_position) };
self.current_position += num_read;
if num_read == 1 {
unsafe { Ok(bytes.assume_init()[0]) }
} else {
Err(ParseError::default())
}
}
}
impl Write for ContractState {
type Err = ();
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err> {
use core::convert::TryInto;
let len: u32 = {
match buf.len().try_into() {
Ok(v) => v,
_ => return Err(()),
}
};
if self.current_position.checked_add(len).is_none() {
return Err(());
}
let num_bytes = unsafe { write_state(buf.as_ptr(), len, self.current_position) };
self.current_position += num_bytes;
Ok(num_bytes as usize)
}
}
impl HasContractState<()> for ContractState {
type ContractStateData = ();
#[inline(always)]
fn open(_: Self::ContractStateData) -> Self {
ContractState {
current_position: 0,
}
}
fn reserve(&mut self, len: u32) -> bool {
let cur_size = unsafe { state_size() };
if cur_size < len {
let res = unsafe { resize_state(len) };
res == 1
} else {
true
}
}
#[inline(always)]
fn size(&self) -> u32 { unsafe { state_size() } }
fn truncate(&mut self, new_size: u32) {
let cur_size = self.size();
if cur_size > new_size {
unsafe { resize_state(new_size) };
}
if new_size < self.current_position {
self.current_position = new_size
}
}
}
impl Read for Parameter {
fn read(&mut self, buf: &mut [u8]) -> ParseResult<usize> {
use core::convert::TryInto;
let len: u32 = {
match buf.len().try_into() {
Ok(v) => v,
_ => return Err(ParseError::default()),
}
};
let num_read =
unsafe { get_parameter_section(buf.as_mut_ptr(), len, self.current_position) };
self.current_position += num_read;
Ok(num_read as usize)
}
}
impl HasParameter for Parameter {
#[inline(always)]
fn size(&self) -> u32 { unsafe { get_parameter_size() } }
}
impl HasChainMetadata for ChainMetaExtern {
#[inline(always)]
fn slot_time(&self) -> SlotTime { Timestamp::from_timestamp_millis(unsafe { get_slot_time() }) }
}
impl HasPolicy for Policy<AttributesCursor> {
fn identity_provider(&self) -> IdentityProvider { self.identity_provider }
fn created_at(&self) -> Timestamp { self.created_at }
fn valid_to(&self) -> Timestamp { self.valid_to }
fn next_item(&mut self, buf: &mut [u8; 31]) -> Option<(AttributeTag, u8)> {
if self.items.remaining_items == 0 {
return None;
}
let (tag_value_len, num_read) = unsafe {
let mut tag_value_len = MaybeUninit::<[u8; 2]>::uninit();
let num_read = get_policy_section(
tag_value_len.as_mut_ptr() as *mut u8,
2,
self.items.current_position,
);
(tag_value_len.assume_init(), num_read)
};
self.items.current_position += num_read;
if tag_value_len[1] > 31 {
return None;
}
let num_read = unsafe {
get_policy_section(
buf.as_mut_ptr(),
u32::from(tag_value_len[1]),
self.items.current_position,
)
};
self.items.current_position += num_read;
self.items.remaining_items -= 1;
Some((AttributeTag(tag_value_len[0]), tag_value_len[1]))
}
}
pub struct PoliciesIterator {
pos: u32,
remaining_items: u16,
}
impl Iterator for PoliciesIterator {
type Item = Policy<AttributesCursor>;
fn next(&mut self) -> Option<Self::Item> {
if self.remaining_items == 0 {
return None;
}
let mut buf: MaybeUninit<[u8; 2 + 4 + 8 + 8 + 2]> = MaybeUninit::uninit();
let buf = unsafe {
get_policy_section(buf.as_mut_ptr() as *mut u8, 2 + 4 + 8 + 8 + 2, self.pos);
buf.assume_init()
};
use convert::TryInto;
let skip_part: [u8; 2] = buf[0..2].try_into().unwrap_abort();
let ip_part: [u8; 4] = buf[2..2 + 4].try_into().unwrap_abort();
let created_at_part: [u8; 8] = buf[2 + 4..2 + 4 + 8].try_into().unwrap_abort();
let valid_to_part: [u8; 8] = buf[2 + 4 + 8..2 + 4 + 8 + 8].try_into().unwrap_abort();
let len_part: [u8; 2] = buf[2 + 4 + 8 + 8..2 + 4 + 8 + 8 + 2].try_into().unwrap_abort();
let identity_provider = IdentityProvider::from_le_bytes(ip_part);
let created_at = Timestamp::from_timestamp_millis(u64::from_le_bytes(created_at_part));
let valid_to = Timestamp::from_timestamp_millis(u64::from_le_bytes(valid_to_part));
let remaining_items = u16::from_le_bytes(len_part);
let attributes_start = self.pos + 2 + 4 + 8 + 8 + 2;
self.pos += u32::from(u16::from_le_bytes(skip_part)) + 2;
self.remaining_items -= 1;
Some(Policy {
identity_provider,
created_at,
valid_to,
items: AttributesCursor {
current_position: attributes_start,
remaining_items,
},
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
let rem = self.remaining_items as usize;
(rem, Some(rem))
}
}
impl ExactSizeIterator for PoliciesIterator {
#[inline(always)]
fn len(&self) -> usize { self.remaining_items as usize }
}
impl<T: sealed::ContextType> HasCommonData for ExternContext<T> {
type MetadataType = ChainMetaExtern;
type ParamType = Parameter;
type PolicyIteratorType = PoliciesIterator;
type PolicyType = Policy<AttributesCursor>;
#[inline(always)]
fn metadata(&self) -> &Self::MetadataType { &ChainMetaExtern {} }
fn policies(&self) -> PoliciesIterator {
let mut buf: MaybeUninit<[u8; 2]> = MaybeUninit::uninit();
let buf = unsafe {
get_policy_section(buf.as_mut_ptr() as *mut u8, 2, 0);
buf.assume_init()
};
PoliciesIterator {
pos: 2,
remaining_items: u16::from_le_bytes(buf),
}
}
#[inline(always)]
fn parameter_cursor(&self) -> Self::ParamType {
Parameter {
current_position: 0,
}
}
}
impl HasInitContext for ExternContext<crate::types::InitContextExtern> {
type InitData = ();
fn open(_: Self::InitData) -> Self { ExternContext::default() }
#[inline(always)]
fn init_origin(&self) -> AccountAddress {
let mut bytes: MaybeUninit<[u8; ACCOUNT_ADDRESS_SIZE]> = MaybeUninit::uninit();
let ptr = bytes.as_mut_ptr();
let address = unsafe {
get_init_origin(ptr as *mut u8);
bytes.assume_init()
};
AccountAddress(address)
}
}
impl HasReceiveContext for ExternContext<crate::types::ReceiveContextExtern> {
type ReceiveData = ();
fn open(_: Self::ReceiveData) -> Self { ExternContext::default() }
#[inline(always)]
fn invoker(&self) -> AccountAddress {
let mut bytes: MaybeUninit<[u8; ACCOUNT_ADDRESS_SIZE]> = MaybeUninit::uninit();
let ptr = bytes.as_mut_ptr();
let address = unsafe {
get_receive_invoker(ptr as *mut u8);
bytes.assume_init()
};
AccountAddress(address)
}
#[inline(always)]
fn self_address(&self) -> ContractAddress {
let mut bytes: MaybeUninit<[u8; 16]> = MaybeUninit::uninit();
let ptr = bytes.as_mut_ptr();
let address = unsafe {
get_receive_self_address(ptr as *mut u8);
bytes.assume_init()
};
match from_bytes(&address) {
Ok(v) => v,
Err(_) => crate::trap(),
}
}
#[inline(always)]
fn self_balance(&self) -> Amount {
Amount::from_micro_gtu(unsafe { get_receive_self_balance() })
}
#[inline(always)]
fn sender(&self) -> Address {
let mut bytes: MaybeUninit<[u8; 33]> = MaybeUninit::uninit();
let ptr = bytes.as_mut_ptr() as *mut u8;
unsafe {
get_receive_sender(ptr);
let tag = *ptr;
match tag {
0u8 => {
match from_bytes(core::slice::from_raw_parts(ptr.add(1), ACCOUNT_ADDRESS_SIZE))
{
Ok(v) => Address::Account(v),
Err(_) => crate::trap(),
}
}
1u8 => match from_bytes(core::slice::from_raw_parts(ptr.add(1), 16)) {
Ok(v) => Address::Contract(v),
Err(_) => crate::trap(),
},
_ => crate::trap(),
}
}
}
#[inline(always)]
fn owner(&self) -> AccountAddress {
let mut bytes: MaybeUninit<[u8; ACCOUNT_ADDRESS_SIZE]> = MaybeUninit::uninit();
let ptr = bytes.as_mut_ptr();
let address = unsafe {
get_receive_owner(ptr as *mut u8);
bytes.assume_init()
};
AccountAddress(address)
}
}
impl HasLogger for Logger {
#[inline(always)]
fn init() -> Self {
Self {
_private: (),
}
}
#[inline(always)]
fn log_bytes(&mut self, event: &[u8]) {
unsafe {
log_event(event.as_ptr(), event.len() as u32);
}
}
}
impl HasActions for Action {
#[inline(always)]
fn accept() -> Self {
Action {
_private: unsafe { accept() },
}
}
#[inline(always)]
fn simple_transfer(acc: &AccountAddress, amount: Amount) -> Self {
let res = unsafe { simple_transfer(acc.0.as_ptr(), amount.micro_gtu) };
Action {
_private: res,
}
}
#[inline(always)]
fn send(ca: &ContractAddress, receive_name: &str, amount: Amount, parameter: &[u8]) -> Self {
let receive_bytes = receive_name.as_bytes();
let res = unsafe {
send(
ca.index,
ca.subindex,
receive_bytes.as_ptr(),
receive_bytes.len() as u32,
amount.micro_gtu,
parameter.as_ptr(),
parameter.len() as u32,
)
};
Action {
_private: res,
}
}
#[inline(always)]
fn and_then(self, then: Self) -> Self {
let res = unsafe { combine_and(self._private, then._private) };
Action {
_private: res,
}
}
#[inline(always)]
fn or_else(self, el: Self) -> Self {
let res = unsafe { combine_or(self._private, el._private) };
Action {
_private: res,
}
}
}
#[doc(hidden)]
pub fn put_in_memory(input: &[u8]) -> *mut u8 {
let bytes_length = input.len() as u32;
let mut bytes = to_bytes(&bytes_length);
bytes.extend_from_slice(input);
let ptr = bytes.as_mut_ptr();
#[cfg(feature = "std")]
::std::mem::forget(bytes);
#[cfg(not(feature = "std"))]
core::mem::forget(bytes);
ptr
}
impl<A, E> UnwrapAbort for Result<A, E> {
type Unwrap = A;
#[inline]
fn unwrap_abort(self) -> Self::Unwrap {
match self {
Ok(x) => x,
Err(_) => crate::trap(),
}
}
}
#[cfg(not(feature = "std"))]
use core::fmt;
#[cfg(feature = "std")]
use std::fmt;
impl<A, E: fmt::Debug> ExpectReport for Result<A, E> {
type Unwrap = A;
fn expect_report(self, msg: &str) -> Self::Unwrap {
match self {
Ok(x) => x,
Err(e) => crate::fail!("{}: {:?}", msg, e),
}
}
}
impl<A: fmt::Debug, E> ExpectErrReport for Result<A, E> {
type Unwrap = E;
fn expect_err_report(self, msg: &str) -> Self::Unwrap {
match self {
Ok(a) => crate::fail!("{}: {:?}", msg, a),
Err(e) => e,
}
}
}
impl<A> UnwrapAbort for Option<A> {
type Unwrap = A;
#[inline(always)]
fn unwrap_abort(self) -> Self::Unwrap { self.unwrap_or_else(|| crate::trap()) }
}
impl<A> ExpectReport for Option<A> {
type Unwrap = A;
fn expect_report(self, msg: &str) -> Self::Unwrap {
match self {
Some(v) => v,
None => crate::fail!("{}", msg),
}
}
}
impl<A: fmt::Debug> ExpectNoneReport for Option<A> {
fn expect_none_report(self, msg: &str) {
if let Some(x) = self {
crate::fail!("{}: {:?}", msg, x)
}
}
}