#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#![deny(unsafe_code)]
#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![deny(dead_code)]
#![deny(unused_imports)]
#![deny(missing_docs)]
#[cfg(target_pointer_width = "16")]
compile_error!(
"rust-miniscript currently only supports architectures with pointers wider than 16 bits"
);
pub use bitcoin;
#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
#[cfg(not(feature = "std"))]
extern crate hashbrown;
#[cfg(any(feature = "std", test))]
extern crate core;
#[cfg(feature = "serde")]
pub use actual_serde as serde;
#[cfg(all(test, feature = "unstable"))]
extern crate test;
#[macro_use]
mod macros;
#[macro_use]
mod pub_macros;
pub mod descriptor;
pub mod expression;
pub mod interpreter;
pub mod miniscript;
pub mod policy;
pub mod psbt;
#[cfg(test)]
mod test_utils;
mod util;
use core::str::FromStr;
use core::{fmt, hash, str};
#[cfg(feature = "std")]
use std::error;
use bitcoin::blockdata::{opcodes, script};
use bitcoin::hashes::{hash160, ripemd160, sha256, Hash};
pub use crate::descriptor::{DefiniteDescriptorKey, Descriptor, DescriptorPublicKey};
pub use crate::interpreter::Interpreter;
pub use crate::miniscript::analyzable::{AnalysisError, ExtParams};
pub use crate::miniscript::context::{BareCtx, Legacy, ScriptContext, Segwitv0, SigType, Tap};
pub use crate::miniscript::decode::Terminal;
pub use crate::miniscript::satisfy::{Preimage32, Satisfier};
pub use crate::miniscript::{hash256, Miniscript};
use crate::prelude::*;
pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash {
fn is_uncompressed(&self) -> bool {
false
}
fn is_x_only_key(&self) -> bool {
false
}
type Sha256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
type Hash256: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
type Ripemd160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
type Hash160: Clone + Eq + Ord + fmt::Display + fmt::Debug + hash::Hash;
}
impl MiniscriptKey for bitcoin::secp256k1::PublicKey {
type Sha256 = sha256::Hash;
type Hash256 = hash256::Hash;
type Ripemd160 = ripemd160::Hash;
type Hash160 = hash160::Hash;
}
impl MiniscriptKey for bitcoin::PublicKey {
fn is_uncompressed(&self) -> bool {
!self.compressed
}
type Sha256 = sha256::Hash;
type Hash256 = hash256::Hash;
type Ripemd160 = ripemd160::Hash;
type Hash160 = hash160::Hash;
}
impl MiniscriptKey for bitcoin::secp256k1::XOnlyPublicKey {
type Sha256 = sha256::Hash;
type Hash256 = hash256::Hash;
type Ripemd160 = ripemd160::Hash;
type Hash160 = hash160::Hash;
fn is_x_only_key(&self) -> bool {
true
}
}
impl MiniscriptKey for String {
type Sha256 = String; type Hash256 = String;
type Ripemd160 = String;
type Hash160 = String;
}
pub trait ToPublicKey: MiniscriptKey {
fn to_public_key(&self) -> bitcoin::PublicKey;
fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey {
let pk = self.to_public_key();
bitcoin::secp256k1::XOnlyPublicKey::from(pk.inner)
}
fn to_pubkeyhash(&self, sig_type: SigType) -> hash160::Hash {
match sig_type {
SigType::Ecdsa => hash160::Hash::hash(&self.to_public_key().to_bytes()),
SigType::Schnorr => hash160::Hash::hash(&self.to_x_only_pubkey().serialize()),
}
}
fn to_sha256(hash: &<Self as MiniscriptKey>::Sha256) -> sha256::Hash;
fn to_hash256(hash: &<Self as MiniscriptKey>::Hash256) -> hash256::Hash;
fn to_ripemd160(hash: &<Self as MiniscriptKey>::Ripemd160) -> ripemd160::Hash;
fn to_hash160(hash: &<Self as MiniscriptKey>::Hash160) -> hash160::Hash;
}
impl ToPublicKey for bitcoin::PublicKey {
fn to_public_key(&self) -> bitcoin::PublicKey {
*self
}
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
*hash
}
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
*hash
}
fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash {
*hash
}
fn to_hash160(hash: &hash160::Hash) -> hash160::Hash {
*hash
}
}
impl ToPublicKey for bitcoin::secp256k1::PublicKey {
fn to_public_key(&self) -> bitcoin::PublicKey {
bitcoin::PublicKey::new(*self)
}
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
*hash
}
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
*hash
}
fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash {
*hash
}
fn to_hash160(hash: &hash160::Hash) -> hash160::Hash {
*hash
}
}
impl ToPublicKey for bitcoin::secp256k1::XOnlyPublicKey {
fn to_public_key(&self) -> bitcoin::PublicKey {
let mut data: Vec<u8> = vec![0x02];
data.extend(self.serialize().iter());
bitcoin::PublicKey::from_slice(&data)
.expect("Failed to construct 33 Publickey from 0x02 appended x-only key")
}
fn to_x_only_pubkey(&self) -> bitcoin::secp256k1::XOnlyPublicKey {
*self
}
fn to_sha256(hash: &sha256::Hash) -> sha256::Hash {
*hash
}
fn to_hash256(hash: &hash256::Hash) -> hash256::Hash {
*hash
}
fn to_ripemd160(hash: &ripemd160::Hash) -> ripemd160::Hash {
*hash
}
fn to_hash160(hash: &hash160::Hash) -> hash160::Hash {
*hash
}
}
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Default)]
pub struct DummyKey;
impl str::FromStr for DummyKey {
type Err = &'static str;
fn from_str(x: &str) -> Result<DummyKey, &'static str> {
if x.is_empty() {
Ok(DummyKey)
} else {
Err("non empty dummy key")
}
}
}
impl MiniscriptKey for DummyKey {
type Sha256 = DummySha256Hash;
type Hash256 = DummyHash256Hash;
type Ripemd160 = DummyRipemd160Hash;
type Hash160 = DummyHash160Hash;
}
impl hash::Hash for DummyKey {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
"DummyKey".hash(state);
}
}
impl fmt::Display for DummyKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("")
}
}
impl ToPublicKey for DummyKey {
fn to_public_key(&self) -> bitcoin::PublicKey {
bitcoin::PublicKey::from_str(
"0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352",
)
.unwrap()
}
fn to_sha256(_hash: &DummySha256Hash) -> sha256::Hash {
sha256::Hash::from_str("50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352")
.unwrap()
}
fn to_hash256(_hash: &DummyHash256Hash) -> hash256::Hash {
hash256::Hash::from_str("50863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352")
.unwrap()
}
fn to_ripemd160(_: &DummyRipemd160Hash) -> ripemd160::Hash {
ripemd160::Hash::from_str("f54a5851e9372b87810a8e60cdd2e7cfd80b6e31").unwrap()
}
fn to_hash160(_: &DummyHash160Hash) -> hash160::Hash {
hash160::Hash::from_str("f54a5851e9372b87810a8e60cdd2e7cfd80b6e31").unwrap()
}
}
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Default)]
pub struct DummyKeyHash;
impl str::FromStr for DummyKeyHash {
type Err = &'static str;
fn from_str(x: &str) -> Result<DummyKeyHash, &'static str> {
if x.is_empty() {
Ok(DummyKeyHash)
} else {
Err("non empty dummy key")
}
}
}
impl fmt::Display for DummyKeyHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("")
}
}
impl hash::Hash for DummyKeyHash {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
"DummyKeyHash".hash(state);
}
}
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Default)]
pub struct DummySha256Hash;
impl str::FromStr for DummySha256Hash {
type Err = &'static str;
fn from_str(x: &str) -> Result<DummySha256Hash, &'static str> {
if x.is_empty() {
Ok(DummySha256Hash)
} else {
Err("non empty dummy hash")
}
}
}
impl fmt::Display for DummySha256Hash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("")
}
}
impl hash::Hash for DummySha256Hash {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
"DummySha256Hash".hash(state);
}
}
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Default)]
pub struct DummyHash256Hash;
impl str::FromStr for DummyHash256Hash {
type Err = &'static str;
fn from_str(x: &str) -> Result<DummyHash256Hash, &'static str> {
if x.is_empty() {
Ok(DummyHash256Hash)
} else {
Err("non empty dummy hash")
}
}
}
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Default)]
pub struct DummyRipemd160Hash;
impl str::FromStr for DummyRipemd160Hash {
type Err = &'static str;
fn from_str(x: &str) -> Result<DummyRipemd160Hash, &'static str> {
if x.is_empty() {
Ok(DummyRipemd160Hash)
} else {
Err("non empty dummy hash")
}
}
}
impl fmt::Display for DummyHash256Hash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("")
}
}
impl fmt::Display for DummyRipemd160Hash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("")
}
}
impl hash::Hash for DummyHash256Hash {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
"DummySha256Hash".hash(state);
}
}
impl hash::Hash for DummyRipemd160Hash {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
"DummyRipemd160Hash".hash(state);
}
}
#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Default)]
pub struct DummyHash160Hash;
impl str::FromStr for DummyHash160Hash {
type Err = &'static str;
fn from_str(x: &str) -> Result<DummyHash160Hash, &'static str> {
if x.is_empty() {
Ok(DummyHash160Hash)
} else {
Err("non empty dummy hash")
}
}
}
impl fmt::Display for DummyHash160Hash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("")
}
}
impl hash::Hash for DummyHash160Hash {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
"DummyHash160Hash".hash(state);
}
}
pub trait Translator<P, Q, E>
where
P: MiniscriptKey,
Q: MiniscriptKey,
{
fn pk(&mut self, pk: &P) -> Result<Q, E>;
fn sha256(&mut self, sha256: &P::Sha256) -> Result<Q::Sha256, E>;
fn hash256(&mut self, hash256: &P::Hash256) -> Result<Q::Hash256, E>;
fn ripemd160(&mut self, ripemd160: &P::Ripemd160) -> Result<Q::Ripemd160, E>;
fn hash160(&mut self, hash160: &P::Hash160) -> Result<Q::Hash160, E>;
}
pub trait TranslatePk<P, Q>
where
P: MiniscriptKey,
Q: MiniscriptKey,
{
type Output;
fn translate_pk<T, E>(&self, translator: &mut T) -> Result<Self::Output, E>
where
T: Translator<P, Q, E>;
}
pub trait ForEachKey<Pk: MiniscriptKey> {
fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
where
Pk: 'a;
fn for_any_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
where
Pk: 'a,
{
!self.for_each_key(|key| !pred(key))
}
}
#[derive(Debug, PartialEq)]
pub enum Error {
InvalidOpcode(opcodes::All),
NonMinimalVerify(String),
InvalidPush(Vec<u8>),
Script(script::Error),
AddrError(bitcoin::util::address::Error),
CmsTooManyKeys(u32),
MultiATooManyKeys(u32),
Unprintable(u8),
ExpectedChar(char),
UnexpectedStart,
Unexpected(String),
MultiColon(String),
MultiAt(String),
AtOutsideOr(String),
LikelyFalse,
UnknownWrapper(char),
NonTopLevel(String),
Trailing(String),
BadPubkey(bitcoin::util::key::Error),
MissingHash(sha256::Hash),
MissingSig(bitcoin::PublicKey),
RelativeLocktimeNotMet(u32),
AbsoluteLocktimeNotMet(u32),
CouldNotSatisfy,
TypeCheck(String),
BadDescriptor(String),
Secp(bitcoin::secp256k1::Error),
#[cfg(feature = "compiler")]
CompilerError(crate::policy::compiler::CompilerError),
PolicyError(policy::concrete::PolicyError),
LiftError(policy::LiftError),
ContextError(miniscript::context::ScriptContextError),
MaxRecursiveDepthExceeded,
ScriptSizeTooLarge,
NonStandardBareScript,
AnalysisError(miniscript::analyzable::AnalysisError),
ImpossibleSatisfaction,
BareDescriptorAddr,
PubKeyCtxError(miniscript::decode::KeyParseError, &'static str),
TaprootSpendInfoUnavialable,
TrNoScriptCode,
TrNoExplicitScript,
}
const MAX_RECURSION_DEPTH: u32 = 402;
const MAX_SCRIPT_SIZE: u32 = 10000;
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::InvalidOpcode(op) => write!(f, "invalid opcode {}", op),
Error::NonMinimalVerify(ref tok) => write!(f, "{} VERIFY", tok),
Error::InvalidPush(ref push) => write!(f, "invalid push {:?}", push), Error::Script(ref e) => fmt::Display::fmt(e, f),
Error::AddrError(ref e) => fmt::Display::fmt(e, f),
Error::CmsTooManyKeys(n) => write!(f, "checkmultisig with {} keys", n),
Error::Unprintable(x) => write!(f, "unprintable character 0x{:02x}", x),
Error::ExpectedChar(c) => write!(f, "expected {}", c),
Error::UnexpectedStart => f.write_str("unexpected start of script"),
Error::Unexpected(ref s) => write!(f, "unexpected «{}»", s),
Error::MultiColon(ref s) => write!(f, "«{}» has multiple instances of «:»", s),
Error::MultiAt(ref s) => write!(f, "«{}» has multiple instances of «@»", s),
Error::AtOutsideOr(ref s) => write!(f, "«{}» contains «@» in non-or() context", s),
Error::LikelyFalse => write!(f, "0 is not very likely (use «u:0»)"),
Error::UnknownWrapper(ch) => write!(f, "unknown wrapper «{}:»", ch),
Error::NonTopLevel(ref s) => write!(f, "non-T miniscript: {}", s),
Error::Trailing(ref s) => write!(f, "trailing tokens: {}", s),
Error::MissingHash(ref h) => write!(f, "missing preimage of hash {}", h),
Error::MissingSig(ref pk) => write!(f, "missing signature for key {:?}", pk),
Error::RelativeLocktimeNotMet(n) => {
write!(f, "required relative locktime CSV of {} blocks, not met", n)
}
Error::AbsoluteLocktimeNotMet(n) => write!(
f,
"required absolute locktime CLTV of {} blocks, not met",
n
),
Error::CouldNotSatisfy => f.write_str("could not satisfy"),
Error::BadPubkey(ref e) => fmt::Display::fmt(e, f),
Error::TypeCheck(ref e) => write!(f, "typecheck: {}", e),
Error::BadDescriptor(ref e) => write!(f, "Invalid descriptor: {}", e),
Error::Secp(ref e) => fmt::Display::fmt(e, f),
Error::ContextError(ref e) => fmt::Display::fmt(e, f),
#[cfg(feature = "compiler")]
Error::CompilerError(ref e) => fmt::Display::fmt(e, f),
Error::PolicyError(ref e) => fmt::Display::fmt(e, f),
Error::LiftError(ref e) => fmt::Display::fmt(e, f),
Error::MaxRecursiveDepthExceeded => write!(
f,
"Recursive depth over {} not permitted",
MAX_RECURSION_DEPTH
),
Error::ScriptSizeTooLarge => write!(
f,
"Standardness rules imply bitcoin than {} bytes",
MAX_SCRIPT_SIZE
),
Error::NonStandardBareScript => write!(
f,
"Anything but c:pk(key) (P2PK), c:pk_h(key) (P2PKH), and thresh_m(k,...) \
up to n=3 is invalid by standardness (bare).
"
),
Error::AnalysisError(ref e) => e.fmt(f),
Error::ImpossibleSatisfaction => write!(f, "Impossible to satisfy Miniscript"),
Error::BareDescriptorAddr => write!(f, "Bare descriptors don't have address"),
Error::PubKeyCtxError(ref pk, ref ctx) => {
write!(f, "Pubkey error: {} under {} scriptcontext", pk, ctx)
}
Error::MultiATooManyKeys(k) => write!(f, "MultiA too many keys {}", k),
Error::TaprootSpendInfoUnavialable => write!(f, "Taproot Spend Info not computed."),
Error::TrNoScriptCode => write!(f, "No script code for Tr descriptors"),
Error::TrNoExplicitScript => write!(f, "No script code for Tr descriptors"),
}
}
}
#[cfg(feature = "std")]
impl error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
use self::Error::*;
match self {
InvalidOpcode(_)
| NonMinimalVerify(_)
| InvalidPush(_)
| CmsTooManyKeys(_)
| MultiATooManyKeys(_)
| Unprintable(_)
| ExpectedChar(_)
| UnexpectedStart
| Unexpected(_)
| MultiColon(_)
| MultiAt(_)
| AtOutsideOr(_)
| LikelyFalse
| UnknownWrapper(_)
| NonTopLevel(_)
| Trailing(_)
| MissingHash(_)
| MissingSig(_)
| RelativeLocktimeNotMet(_)
| AbsoluteLocktimeNotMet(_)
| CouldNotSatisfy
| TypeCheck(_)
| BadDescriptor(_)
| MaxRecursiveDepthExceeded
| ScriptSizeTooLarge
| NonStandardBareScript
| ImpossibleSatisfaction
| BareDescriptorAddr
| TaprootSpendInfoUnavialable
| TrNoScriptCode
| TrNoExplicitScript => None,
Script(e) => Some(e),
AddrError(e) => Some(e),
BadPubkey(e) => Some(e),
Secp(e) => Some(e),
#[cfg(feature = "compiler")]
CompilerError(e) => Some(e),
PolicyError(e) => Some(e),
LiftError(e) => Some(e),
ContextError(e) => Some(e),
AnalysisError(e) => Some(e),
PubKeyCtxError(e, _) => Some(e),
}
}
}
#[doc(hidden)]
impl<Pk, Ctx> From<miniscript::types::Error<Pk, Ctx>> for Error
where
Pk: MiniscriptKey,
Ctx: ScriptContext,
{
fn from(e: miniscript::types::Error<Pk, Ctx>) -> Error {
Error::TypeCheck(e.to_string())
}
}
#[doc(hidden)]
impl From<policy::LiftError> for Error {
fn from(e: policy::LiftError) -> Error {
Error::LiftError(e)
}
}
#[doc(hidden)]
impl From<miniscript::context::ScriptContextError> for Error {
fn from(e: miniscript::context::ScriptContextError) -> Error {
Error::ContextError(e)
}
}
#[doc(hidden)]
impl From<miniscript::analyzable::AnalysisError> for Error {
fn from(e: miniscript::analyzable::AnalysisError) -> Error {
Error::AnalysisError(e)
}
}
#[doc(hidden)]
impl From<bitcoin::secp256k1::Error> for Error {
fn from(e: bitcoin::secp256k1::Error) -> Error {
Error::Secp(e)
}
}
#[doc(hidden)]
impl From<bitcoin::util::address::Error> for Error {
fn from(e: bitcoin::util::address::Error) -> Error {
Error::AddrError(e)
}
}
#[doc(hidden)]
#[cfg(feature = "compiler")]
impl From<crate::policy::compiler::CompilerError> for Error {
fn from(e: crate::policy::compiler::CompilerError) -> Error {
Error::CompilerError(e)
}
}
#[doc(hidden)]
impl From<policy::concrete::PolicyError> for Error {
fn from(e: policy::concrete::PolicyError) -> Error {
Error::PolicyError(e)
}
}
fn errstr(s: &str) -> Error {
Error::Unexpected(s.to_owned())
}
pub fn script_num_size(n: usize) -> usize {
match n {
n if n <= 0x10 => 1, n if n < 0x80 => 2, n if n < 0x8000 => 3, n if n < 0x800000 => 4, n if n < 0x80000000 => 5, _ => 6, }
}
fn push_opcode_size(script_size: usize) -> usize {
if script_size < 76 {
1
} else if script_size < 0x100 {
2
} else if script_size < 0x10000 {
3
} else {
5
}
}
#[cfg(test)]
fn hex_script(s: &str) -> bitcoin::Script {
let v: Vec<u8> = bitcoin::hashes::hex::FromHex::from_hex(s).unwrap();
bitcoin::Script::from(v)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn regression_bitcoin_key_hash() {
use bitcoin::PublicKey;
let pk = PublicKey::from_str(
"042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"
).unwrap();
let want = hash160::Hash::from_str("ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a").unwrap();
let got = pk.to_pubkeyhash(SigType::Ecdsa);
assert_eq!(got, want)
}
#[test]
fn regression_secp256k1_key_hash() {
use bitcoin::secp256k1::PublicKey;
let pk = PublicKey::from_str(
"032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
)
.unwrap();
let want = hash160::Hash::from_str("9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4").unwrap();
let got = pk.to_pubkeyhash(SigType::Ecdsa);
assert_eq!(got, want)
}
#[test]
fn regression_xonly_key_hash() {
use bitcoin::secp256k1::XOnlyPublicKey;
let pk = XOnlyPublicKey::from_str(
"cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
)
.unwrap();
let want = hash160::Hash::from_str("eb8ac65f971ae688a94aeabf223506865e7e08f2").unwrap();
let got = pk.to_pubkeyhash(SigType::Schnorr);
assert_eq!(got, want)
}
}
#[allow(unused_imports)] mod prelude {
#[cfg(all(not(feature = "std"), not(test)))]
mod mutex {
use core::cell::{RefCell, RefMut};
use core::ops::{Deref, DerefMut};
pub type LockResult<Guard> = Result<Guard, ()>;
pub struct Mutex<T: ?Sized> {
inner: RefCell<T>,
}
#[must_use = "if unused the Mutex will immediately unlock"]
pub struct MutexGuard<'a, T: ?Sized + 'a> {
lock: RefMut<'a, T>,
}
impl<T: ?Sized> Deref for MutexGuard<'_, T> {
type Target = T;
fn deref(&self) -> &T {
&self.lock.deref()
}
}
impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
fn deref_mut(&mut self) -> &mut T {
self.lock.deref_mut()
}
}
impl<T> Mutex<T> {
pub fn new(inner: T) -> Mutex<T> {
Mutex {
inner: RefCell::new(inner),
}
}
pub fn lock<'a>(&'a self) -> LockResult<MutexGuard<'a, T>> {
Ok(MutexGuard {
lock: self.inner.borrow_mut(),
})
}
}
}
#[cfg(all(not(feature = "std"), not(test)))]
pub use alloc::{
borrow::{Borrow, Cow, ToOwned},
boxed::Box,
collections::{vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap},
rc, slice,
string::{String, ToString},
sync,
vec::Vec,
};
#[cfg(any(feature = "std", test))]
pub use std::{
borrow::{Borrow, ToOwned},
boxed::Box,
collections::{vec_deque::VecDeque, BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet},
string::{String, ToString},
sync,
sync::Mutex,
vec::Vec,
};
#[cfg(all(not(feature = "std"), not(test)))]
pub use hashbrown::{HashMap, HashSet};
#[cfg(all(not(feature = "std"), not(test)))]
pub use self::mutex::Mutex;
}