linera-sdk 0.15.17

Library to support developing Linera applications in Rust.
Documentation
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! Conversions from types generated by [`wit-bindgen`] to types declared in [`linera-sdk`].

use linera_base::{
    crypto::CryptoHash,
    data_types::{
        Amount, ApplicationDescription, ApplicationPermissions, BlockHeight, TimeDelta, Timestamp,
    },
    http,
    identifiers::{AccountOwner, ApplicationId, ChainId, DataBlobHash, ModuleId},
    ownership::{ChainOwnership, TimeoutConfig},
    vm::VmRuntime,
};

use crate::{
    contract::wit::base_runtime_api as base_contract_api,
    service::wit::base_runtime_api as base_service_api,
};

macro_rules! impl_from_wit {
    ($wit_base_api:ident) => {
        impl From<$wit_base_api::CryptoHash> for CryptoHash {
            fn from(hash_value: $wit_base_api::CryptoHash) -> Self {
                CryptoHash::from([
                    hash_value.part1,
                    hash_value.part2,
                    hash_value.part3,
                    hash_value.part4,
                ])
            }
        }

        impl From<$wit_base_api::DataBlobHash> for DataBlobHash {
            fn from(hash_value: $wit_base_api::DataBlobHash) -> Self {
                DataBlobHash(hash_value.inner0.into())
            }
        }

        impl From<$wit_base_api::Array20> for [u8; 20] {
            fn from(ethereum_address: $wit_base_api::Array20) -> Self {
                let mut bytes = [0u8; 20];
                bytes[0..8].copy_from_slice(&ethereum_address.part1.to_be_bytes());
                bytes[8..16].copy_from_slice(&ethereum_address.part2.to_be_bytes());
                bytes[16..20].copy_from_slice(&ethereum_address.part3.to_be_bytes()[0..4]);
                bytes
            }
        }

        impl From<$wit_base_api::AccountOwner> for AccountOwner {
            fn from(account_owner: $wit_base_api::AccountOwner) -> Self {
                match account_owner {
                    $wit_base_api::AccountOwner::Reserved(value) => AccountOwner::Reserved(value),
                    $wit_base_api::AccountOwner::Address32(value) => {
                        AccountOwner::Address32(value.into())
                    }
                    $wit_base_api::AccountOwner::Address20(value) => {
                        AccountOwner::Address20(value.into())
                    }
                }
            }
        }

        impl From<$wit_base_api::Amount> for Amount {
            fn from(balance: $wit_base_api::Amount) -> Self {
                let (lower_half, upper_half) = balance.inner0;
                let value = ((upper_half as u128) << 64) | (lower_half as u128);
                Amount::from_attos(value)
            }
        }

        impl From<$wit_base_api::BlockHeight> for BlockHeight {
            fn from(block_height: $wit_base_api::BlockHeight) -> Self {
                BlockHeight(block_height.inner0)
            }
        }

        impl From<$wit_base_api::ChainId> for ChainId {
            fn from(chain_id: $wit_base_api::ChainId) -> Self {
                ChainId(chain_id.inner0.into())
            }
        }

        impl From<$wit_base_api::ApplicationId> for ApplicationId {
            fn from(application_id: $wit_base_api::ApplicationId) -> Self {
                ApplicationId::new(application_id.application_description_hash.into())
            }
        }

        impl From<$wit_base_api::Timestamp> for Timestamp {
            fn from(timestamp: $wit_base_api::Timestamp) -> Self {
                Timestamp::from(timestamp.inner0)
            }
        }

        impl From<$wit_base_api::TimeDelta> for TimeDelta {
            fn from(guest: $wit_base_api::TimeDelta) -> Self {
                TimeDelta::from_micros(guest.inner0)
            }
        }

        impl From<$wit_base_api::TimeoutConfig> for TimeoutConfig {
            fn from(guest: $wit_base_api::TimeoutConfig) -> TimeoutConfig {
                let $wit_base_api::TimeoutConfig {
                    fast_round_duration,
                    base_timeout,
                    timeout_increment,
                    fallback_duration,
                } = guest;
                TimeoutConfig {
                    fast_round_duration: fast_round_duration.map(TimeDelta::from),
                    base_timeout: base_timeout.into(),
                    timeout_increment: timeout_increment.into(),
                    fallback_duration: fallback_duration.into(),
                }
            }
        }

        impl From<$wit_base_api::ChainOwnership> for ChainOwnership {
            fn from(guest: $wit_base_api::ChainOwnership) -> ChainOwnership {
                let $wit_base_api::ChainOwnership {
                    super_owners,
                    owners,
                    multi_leader_rounds,
                    open_multi_leader_rounds,
                    timeout_config,
                } = guest;
                ChainOwnership {
                    super_owners: super_owners.into_iter().map(Into::into).collect(),
                    owners: owners
                        .into_iter()
                        .map(|(owner, weight)| (owner.into(), weight))
                        .collect(),
                    multi_leader_rounds,
                    open_multi_leader_rounds,
                    timeout_config: timeout_config.into(),
                }
            }
        }

        impl From<$wit_base_api::ApplicationPermissions> for ApplicationPermissions {
            fn from(guest: $wit_base_api::ApplicationPermissions) -> ApplicationPermissions {
                let $wit_base_api::ApplicationPermissions {
                    execute_operations,
                    mandatory_applications,
                    close_chain,
                    change_application_permissions,
                    call_service_as_oracle,
                    make_http_requests,
                } = guest;
                ApplicationPermissions {
                    execute_operations: execute_operations
                        .map(|apps| apps.into_iter().map(Into::into).collect()),
                    mandatory_applications: mandatory_applications
                        .into_iter()
                        .map(Into::into)
                        .collect(),
                    close_chain: close_chain.into_iter().map(Into::into).collect(),
                    change_application_permissions: change_application_permissions
                        .into_iter()
                        .map(Into::into)
                        .collect(),
                    call_service_as_oracle: call_service_as_oracle
                        .map(|apps| apps.into_iter().map(Into::into).collect()),
                    make_http_requests: make_http_requests
                        .map(|apps| apps.into_iter().map(Into::into).collect()),
                }
            }
        }

        impl From<$wit_base_api::HttpResponse> for http::Response {
            fn from(response: $wit_base_api::HttpResponse) -> http::Response {
                http::Response {
                    status: response.status,
                    headers: response
                        .headers
                        .into_iter()
                        .map(http::Header::from)
                        .collect(),
                    body: response.body,
                }
            }
        }

        impl From<$wit_base_api::HttpHeader> for http::Header {
            fn from(header: $wit_base_api::HttpHeader) -> http::Header {
                http::Header::new(header.name, header.value)
            }
        }

        impl From<$wit_base_api::VmRuntime> for VmRuntime {
            fn from(vm_runtime: $wit_base_api::VmRuntime) -> Self {
                match vm_runtime {
                    $wit_base_api::VmRuntime::Wasm => VmRuntime::Wasm,
                    $wit_base_api::VmRuntime::Evm => VmRuntime::Evm,
                }
            }
        }

        impl From<$wit_base_api::ModuleId> for ModuleId {
            fn from(module_id: $wit_base_api::ModuleId) -> Self {
                ModuleId::new(
                    module_id.contract_blob_hash.into(),
                    module_id.service_blob_hash.into(),
                    module_id.vm_runtime.into(),
                )
            }
        }

        impl From<$wit_base_api::ApplicationDescription> for ApplicationDescription {
            fn from(description: $wit_base_api::ApplicationDescription) -> Self {
                ApplicationDescription {
                    module_id: description.module_id.into(),
                    creator_chain_id: description.creator_chain_id.into(),
                    block_height: description.block_height.into(),
                    application_index: description.application_index,
                    parameters: description.parameters,
                    required_application_ids: description
                        .required_application_ids
                        .into_iter()
                        .map(Into::into)
                        .collect(),
                }
            }
        }
    };
}

impl_from_wit!(base_service_api);
impl_from_wit!(base_contract_api);