ic_cdk/
lib.rs

1#![doc = include_str!("../README.md")]
2#![warn(
3    elided_lifetimes_in_paths,
4    missing_debug_implementations,
5    missing_docs,
6    unsafe_op_in_unsafe_fn,
7    clippy::undocumented_unsafe_blocks,
8    clippy::missing_safety_doc
9)]
10#![cfg_attr(docsrs, feature(doc_cfg))]
11
12#[cfg(target_feature = "atomics")]
13compile_error!("This version of the CDK does not support multithreading.");
14
15pub mod api;
16pub mod bitcoin_canister;
17pub mod call;
18pub mod futures;
19mod macros;
20pub mod management_canister;
21mod printer;
22pub mod stable;
23pub mod storage;
24
25use std::{
26    future::Future,
27    sync::{Arc, Once},
28    task::{Context, Poll, Wake, Waker},
29};
30
31#[doc(inline)]
32pub use api::trap;
33
34#[doc(inline)]
35#[allow(deprecated)]
36pub use api::{
37    call::{call, notify},
38    caller, id, print,
39};
40
41#[doc(inline)]
42pub use macros::*;
43
44static SETUP: Once = Once::new();
45
46/// Setup the stdlib hooks.
47fn setup() {
48    SETUP.call_once(printer::hook);
49}
50
51/// Format and then print the formatted message
52#[cfg(target_family = "wasm")]
53#[macro_export]
54macro_rules! println {
55    ($fmt:expr) => ($crate::api::debug_print(format!($fmt)));
56    ($fmt:expr, $($arg:tt)*) => ($crate::api::debug_print(format!($fmt, $($arg)*)));
57}
58
59/// Format and then print the formatted message
60#[cfg(not(target_family = "wasm"))]
61#[macro_export]
62macro_rules! println {
63    ($fmt:expr) => (std::println!($fmt));
64    ($fmt:expr, $($arg:tt)*) => (std::println!($fmt, $($arg)*));
65}
66
67/// Format and then print the formatted message
68#[cfg(target_family = "wasm")]
69#[macro_export]
70macro_rules! eprintln {
71    ($fmt:expr) => ($crate::api::debug_print(format!($fmt)));
72    ($fmt:expr, $($arg:tt)*) => ($crate::api::debug_print(format!($fmt, $($arg)*)));
73}
74
75/// Format and then print the formatted message
76#[cfg(not(target_family = "wasm"))]
77#[macro_export]
78macro_rules! eprintln {
79    ($fmt:expr) => (std::eprintln!($fmt));
80    ($fmt:expr, $($arg:tt)*) => (std::eprintln!($fmt, $($arg)*));
81}
82
83#[doc(hidden)]
84#[deprecated(
85    since = "0.18.0",
86    note = "Use ic_cdk::futures::spawn. Compatibility notice: Code execution order will change, \
87        see https://github.com/dfinity/cdk-rs/blob/0.18.3/ic-cdk/V18_GUIDE.md#futures-ordering-changes"
88)]
89pub fn spawn<F: 'static + Future<Output = ()>>(fut: F) {
90    struct DummyWaker;
91    impl Wake for DummyWaker {
92        fn wake(self: Arc<Self>) {
93            panic!("Your code is incompatible with the ic_cdk::spawn compatibility adapter. Migrate to ic_cdk::futures::spawn. \
94                Notice: Code execution order will change, see https://github.com/dfinity/cdk-rs/blob/0.18.3/ic-cdk/V18_GUIDE.md#futures-ordering-changes")
95        }
96    }
97    // Emulated behavior: A spawned future is polled once immediately, then backgrounded and run at a normal pace.
98    // We poll it once with an unimplemented waker, then spawn it, which will poll it again with the real waker.
99    // In a correctly implemented future, this second poll should overwrite the fake waker with the real one.
100    // The only way to hit the fake waker's wake function is if the first poll calls wake.
101    // A more complex compat adapter will be needed to handle this case.
102    let mut pin = Box::pin(fut);
103    let poll = pin
104        .as_mut()
105        .poll(&mut Context::from_waker(&Waker::from(Arc::new(DummyWaker))));
106    match poll {
107        Poll::Ready(()) => {}
108        Poll::Pending => crate::futures::spawn(pin),
109    }
110}