platform_switch/lib.rs
1// Copyright (c) Jake Swensen
2// SPDX-License-Identifier: MPL-2.0
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8//! Namespace facades for switching between platforms.
9//!
10//! # Motivation
11//! Sometimes code needs to be shared between a contrainted platform
12//! (such as an embedded system) and a target that has a more fully
13//! featured environment. This crate provides a series of module wrappers
14//! that can be used in combination with cargo manifest feature definitions
15//! to switch between options at compile time.
16//!
17//! # Example
18//! Using `thiserror` with `defmt` enabled on an embedded system:
19//!
20//! ```toml
21//! [features]
22//! default = ["std"]
23//! std = ["platform-switch/std_error"]
24//! mcu = ["platform-switch/core_error", "platform-switch/defmt"] # Requires nightly
25//! ```
26//!
27//! ```rust
28//! use platform_switch::log as log;
29//! use platform_switch::thiserror as thiserror;
30//!
31//! #[derive(thiserror::Error, Debug)]
32//! enum ExampleError {
33//! #[error("Error #1")]
34//! Error1,
35//! #[error("Error #2")]
36//! Error2,
37//! }
38//!
39//! fn error_logger() {
40//! log::trace!("Trace");
41//! log::debug!("Debug");
42//! log::info!("Info");
43//! log::warn!("Warn");
44//! log::error!("Error");
45//!
46//! log::error!("Error: {}", ExampleError::Error1);
47//! log::error!("Error: {}", ExampleError::Error2);
48//! }
49//! ```
50//!
51//! ## Stable Toolchain
52//! If a stable toolchain is required, `thiserror` can be disabled with the following features and attributes:
53//! ```toml
54//! [features]
55//! default = ["std"]
56//! std = ["thiserror", "platform-switch/std_error"]
57//! mcu = ["platform-switch/defmt"]
58//! thiserror = []
59//! ```
60//!
61//! ```rust
62//! use platform_switch::log as log;
63//! use platform_switch::thiserror as thiserror;
64//!
65//! #[derive(Debug)]
66//! #[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
67//! enum ExampleError {
68//! #[cfg_attr(feature = "thiserror", error("Error #1"))]
69//! Error1,
70//!
71//! #[cfg_attr(feature = "thiserror", error("Error #2"))]
72//! Error2,
73//! }
74//! ```
75
76#![cfg_attr(not(feature = "std"), no_std)]
77#![cfg_attr(all(not(any(feature = "std", test)), feature = "core_error"), feature(error_in_core))]
78
79/// A namespace facade around [`thiserror`].
80///
81/// Enables [`thiserror`] to be used in both [`std`] and `no_std` environments.
82/// If configured for `no_std`, this module will use `thiserror-core` (which requires
83/// a nightly toolchain).
84///
85/// ### Note
86/// This module will be marked deprecated once `error_in_core` is
87/// [stabilized](https://github.com/rust-lang/rust/issues/103765) and [`thiserror`]
88/// fully supports using [`core::error`].
89#[cfg(feature = "thiserror")]
90pub mod thiserror {
91 cfg_if::cfg_if! {
92 if #[cfg(not(feature = "core_error"))] {
93 pub use thiserror::*;
94 } else {
95 pub use thiserror_core::*;
96 }
97 }
98}
99
100/// A namespace facade around [`log`] and `defmt`.
101///
102/// Enabling the feature `defmt` will re-export the `defmt` macros for logging.
103/// Otherwise, the `log` macros will be re-exported.
104#[cfg(feature = "log")]
105pub mod log {
106 cfg_if::cfg_if! {
107 if #[cfg(feature = "defmt")] {
108 pub use defmt::debug as debug;
109 pub use defmt::error as error;
110 pub use defmt::info as info;
111 pub use defmt::trace as trace;
112 pub use defmt::warn as warn;
113 } else {
114 pub use log::debug as debug;
115 pub use log::error as error;
116 pub use log::info as info;
117 pub use log::trace as trace;
118 pub use log::warn as warn;
119 }
120 }
121}
122
123/// A namespace facade for formatting.
124pub mod fmt {
125 cfg_if::cfg_if! {
126 if #[cfg(feature = "std")] {
127 pub use std::fmt::Debug as Debug;
128 pub use std::fmt::Display as Display;
129 pub use std::fmt::Formatter as Formatter;
130 pub use std::fmt::Result as Result;
131 } else {
132 pub use core::fmt::Debug as Debug;
133 pub use core::fmt::Display as Display;
134 pub use core::fmt::Formatter as Formatter;
135 pub use core::fmt::Result as Result;
136 }
137 }
138}