linera_base/
abi.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4//! This module defines the notion of Application Binary Interface (ABI) for Linera
5//! applications across Wasm and native architectures.
6
7use std::fmt::Debug;
8
9use serde::{de::DeserializeOwned, Serialize};
10
11// ANCHOR: abi
12/// A trait that includes all the types exported by a Linera application (both contract
13/// and service).
14pub trait Abi: ContractAbi + ServiceAbi {}
15// ANCHOR_END: abi
16
17// T::Parameters is duplicated for simplicity but it must match.
18impl<T> Abi for T where T: ContractAbi + ServiceAbi {}
19
20// ANCHOR: contract_abi
21/// A trait that includes all the types exported by a Linera application contract.
22pub trait ContractAbi {
23    /// The type of operation executed by the application.
24    type Operation: Serialize + DeserializeOwned + Send + Sync + Debug + 'static;
25
26    /// The response type of an application call.
27    type Response: Serialize + DeserializeOwned + Send + Sync + Debug + 'static;
28
29    /// How the `Operation` is deserialized
30    fn deserialize_operation(operation: Vec<u8>) -> Result<Self::Operation, String> {
31        bcs::from_bytes(&operation)
32            .map_err(|e| format!("BCS deserialization error {e:?} for operation {operation:?}"))
33    }
34
35    /// How the `Operation` is serialized
36    fn serialize_operation(operation: &Self::Operation) -> Result<Vec<u8>, String> {
37        bcs::to_bytes(operation)
38            .map_err(|e| format!("BCS serialization error {e:?} for operation {operation:?}"))
39    }
40    /// How the `Response` is deserialized
41    fn deserialize_response(response: Vec<u8>) -> Result<Self::Response, String> {
42        bcs::from_bytes(&response)
43            .map_err(|e| format!("BCS deserialization error {e:?} for response {response:?}"))
44    }
45
46    /// How the `Response` is serialized
47    fn serialize_response(response: Self::Response) -> Result<Vec<u8>, String> {
48        bcs::to_bytes(&response)
49            .map_err(|e| format!("BCS serialization error {e:?} for response {response:?}"))
50    }
51}
52// ANCHOR_END: contract_abi
53
54// ANCHOR: service_abi
55/// A trait that includes all the types exported by a Linera application service.
56pub trait ServiceAbi: ContractAbi {
57    /// The type of a query receivable by the application's service.
58    type Query: Serialize + DeserializeOwned + Send + Sync + Debug + 'static;
59
60    /// The response type of the application's service.
61    type QueryResponse: Serialize + DeserializeOwned + Send + Sync + Debug + 'static;
62}
63// ANCHOR_END: service_abi
64
65/// Marker trait to help importing contract types.
66pub trait WithContractAbi {
67    /// The contract types to import.
68    type Abi: ContractAbi;
69}
70
71impl<A> WithContractAbi for A
72where
73    A: WithServiceAbi,
74{
75    type Abi = <A as WithServiceAbi>::Abi;
76}
77
78impl<A> ContractAbi for A
79where
80    A: WithContractAbi,
81{
82    type Operation = <<A as WithContractAbi>::Abi as ContractAbi>::Operation;
83    type Response = <<A as WithContractAbi>::Abi as ContractAbi>::Response;
84
85    fn deserialize_operation(operation: Vec<u8>) -> Result<Self::Operation, String> {
86        <<A as WithContractAbi>::Abi as ContractAbi>::deserialize_operation(operation)
87    }
88
89    fn serialize_operation(operation: &Self::Operation) -> Result<Vec<u8>, String> {
90        <<A as WithContractAbi>::Abi as ContractAbi>::serialize_operation(operation)
91    }
92
93    fn deserialize_response(response: Vec<u8>) -> Result<Self::Response, String> {
94        <<A as WithContractAbi>::Abi as ContractAbi>::deserialize_response(response)
95    }
96
97    fn serialize_response(response: Self::Response) -> Result<Vec<u8>, String> {
98        <<A as WithContractAbi>::Abi as ContractAbi>::serialize_response(response)
99    }
100}
101
102/// Marker trait to help importing service types.
103pub trait WithServiceAbi {
104    /// The service types to import.
105    type Abi: ServiceAbi;
106}
107
108impl<A> ServiceAbi for A
109where
110    A: WithServiceAbi,
111{
112    type Query = <<A as WithServiceAbi>::Abi as ServiceAbi>::Query;
113    type QueryResponse = <<A as WithServiceAbi>::Abi as ServiceAbi>::QueryResponse;
114}