freenet_stdlib/
client_api.rs

1//! A node client API. Intended to be used from applications (web or otherwise) using the
2//! node capabilities to execute contract, delegate, etc. instructions and communicating
3//! over the network.
4//!
5//! Communication, independent of the transport, revolves around the [`ClientRequest`]
6//! and [`HostResponse`] types.
7//!
8//! Currently the clients available are:
9//! - `websocket`:
10//!   - `regular` (native): Using TCP transport directly, for native applications programmed in Rust.
11//!   - `browser` (wasm): Via wasm-bindgen (and by extension web-sys).
12//!     (In order to use this client from JS/Typescript refer to the Typescript std lib).
13mod client_events;
14
15#[cfg(all(any(unix, windows), feature = "net"))]
16mod regular;
17#[cfg(all(any(unix, windows), feature = "net"))]
18pub use regular::*;
19
20#[cfg(all(target_family = "wasm", feature = "net"))]
21mod browser;
22#[cfg(all(target_family = "wasm", feature = "net"))]
23pub use browser::*;
24
25pub use client_events::*;
26
27#[cfg(feature = "net")]
28type HostResult = Result<HostResponse, ClientError>;
29
30#[derive(thiserror::Error, Debug)]
31#[non_exhaustive]
32pub enum Error {
33    #[error(transparent)]
34    Deserialization(#[from] bincode::Error),
35    #[error("channel closed")]
36    ChannelClosed,
37    #[cfg(all(any(unix, windows), feature = "net"))]
38    #[error(transparent)]
39    ConnectionError(#[from] tokio_tungstenite::tungstenite::Error),
40    #[cfg(all(target_family = "wasm", feature = "net"))]
41    #[error("request error: {0}")]
42    ConnectionError(serde_json::Value),
43    #[error("connection closed")]
44    ConnectionClosed,
45    #[error("unhandled error: {0}")]
46    OtherError(Box<dyn std::error::Error + Send + Sync>),
47}
48
49pub trait TryFromFbs<T>: Sized {
50    fn try_decode_fbs(value: T) -> Result<Self, WsApiError>;
51}
52
53#[derive(thiserror::Error, Debug)]
54#[non_exhaustive]
55pub enum WsApiError {
56    #[error("Unsupported contract version")]
57    UnsupportedContractVersion,
58    #[error("Failed unpacking contract container")]
59    UnpackingContractContainerError(Box<dyn std::error::Error + Send + Sync + 'static>),
60    #[error("Failed decoding message from client request: {cause}")]
61    DeserError { cause: String },
62}
63
64impl WsApiError {
65    pub fn deserialization(cause: String) -> Self {
66        Self::DeserError { cause }
67    }
68
69    pub fn into_fbs_bytes(self) -> Vec<u8> {
70        use crate::generated::host_response::{
71            finish_host_response_buffer, Error, ErrorArgs, HostResponse, HostResponseArgs,
72            HostResponseType,
73        };
74        let mut builder = flatbuffers::FlatBufferBuilder::new();
75        let as_msg = format!("{self}");
76        let msg_offset = builder.create_string(&as_msg);
77        let err_offset = Error::create(
78            &mut builder,
79            &ErrorArgs {
80                msg: Some(msg_offset),
81            },
82        );
83        let res = HostResponse::create(
84            &mut builder,
85            &HostResponseArgs {
86                response_type: HostResponseType::Error,
87                response: Some(err_offset.as_union_value()),
88            },
89        );
90        finish_host_response_buffer(&mut builder, res);
91        builder.finished_data().to_vec()
92    }
93}