Document cargo features

This documents cargo features in two ways: explictly in text and in code
using `#[doc(cfg(...))]` attribute where possible. Notably, this is
impossible for `serde` derives. The attribute is contitional and only
activated for docs.rs or explicit local builds.

This change also adds `package.metadata.docs.rs` field to `Cargo.toml`
which instructs docs.rs to build with relevant features and with
`docsrs` config activated enabling `#[doc(cfg(...))] attributes.

I also took the opportunity to fix a few missing spaces in nearby code.
This commit is contained in:
Martin Habovstiak 2021-07-28 21:38:58 +02:00
parent 57d7baf05b
commit 95fb4e01f9
20 changed files with 111 additions and 18 deletions

View File

@ -10,7 +10,7 @@ description = "General purpose library for using and interoperating with Bitcoin
keywords = [ "crypto", "bitcoin" ]
readme = "README.md"
# Please don't forget to add relevant features to docs.rs below
[features]
default = [ "std", "secp-recovery" ]
base64 = [ "base64-compat" ]
@ -28,6 +28,10 @@ secp-recovery = ["secp256k1/recovery"]
std = ["secp256k1/std", "bitcoin_hashes/std", "bech32/std"]
no-std = ["hashbrown", "core2/alloc", "bitcoin_hashes/alloc"]
[package.metadata.docs.rs]
features = [ "std", "secp-recovery", "base64", "rand", "use-serde", "bitcoinconsensus" ]
rustc-args = ["--cfg", "docsrs"]
[dependencies]
bech32 = { version = "0.8.1", default-features = false }
bitcoin_hashes = { version = "0.10.0", default-features = false }

View File

@ -715,6 +715,7 @@ impl From<u8> for All {
display_from_debug!(All);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl serde::Serialize for All {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -753,6 +754,7 @@ pub enum Class {
display_from_debug!(Class);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl serde::Serialize for Class {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where

View File

@ -120,12 +120,15 @@ pub enum Error {
/// Tried to read an array off the stack as a number when it was more than 4 bytes
NumericOverflow,
#[cfg(feature = "bitcoinconsensus")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))]
/// Error validating the script with bitcoinconsensus library
BitcoinConsensus(bitcoinconsensus::Error),
#[cfg(feature = "bitcoinconsensus")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))]
/// Can not find the spent output
UnknownSpentOutput(OutPoint),
#[cfg(feature = "bitcoinconsensus")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))]
/// Can not serialize the spending transaction
SerializationError
}
@ -148,6 +151,7 @@ impl fmt::Display for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {}
#[cfg(feature="bitcoinconsensus")]
@ -452,12 +456,14 @@ impl Script {
}
#[cfg(feature="bitcoinconsensus")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))]
/// Shorthand for [Self::verify_with_flags] with flag [bitcoinconsensus::VERIFY_ALL]
pub fn verify (&self, index: usize, amount: ::Amount, spending: &[u8]) -> Result<(), Error> {
self.verify_with_flags(index, amount, spending, ::bitcoinconsensus::VERIFY_ALL)
}
#[cfg(feature="bitcoinconsensus")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))]
/// Verify spend of an input script
/// # Parameters
/// * `index` - the input index in spending which is spending this transaction
@ -817,6 +823,7 @@ impl From<Vec<u8>> for Builder {
impl_index_newtype!(Builder, u8);
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> serde::Deserialize<'de> for Script {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: serde::Deserializer<'de>,
@ -876,6 +883,7 @@ impl<'de> serde::Deserialize<'de> for Script {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl serde::Serialize for Script {
/// User-facing serialization for `Script`.
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>

View File

@ -133,6 +133,7 @@ impl fmt::Display for ParseOutPointError {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl error::Error for ParseOutPointError {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
@ -501,6 +502,7 @@ impl Transaction {
}
#[cfg(feature="bitcoinconsensus")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))]
/// Shorthand for [Self::verify_with_flags] with flag [bitcoinconsensus::VERIFY_ALL]
pub fn verify<S>(&self, spent: S) -> Result<(), script::Error>
where S: FnMut(&OutPoint) -> Option<TxOut> {
@ -508,6 +510,7 @@ impl Transaction {
}
#[cfg(feature="bitcoinconsensus")]
#[cfg_attr(docsrs, doc(cfg(feature = "bitcoinconsensus")))]
/// Verify that this transaction is able to spend its inputs
/// The lambda spent should not return the same TxOut twice!
pub fn verify_with_flags<S, F>(&self, mut spent: S, flags: F) -> Result<(), script::Error>
@ -667,6 +670,7 @@ impl fmt::Display for NonStandardSigHashType {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl error::Error for NonStandardSigHashType {}
/// Hashtype of an input's signature, encoded in the last byte of the signature

View File

@ -106,6 +106,7 @@ impl fmt::Display for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {

View File

@ -167,6 +167,7 @@ macro_rules! hex_hash (($h:ident, $s:expr) => ($h::from_slice(&<$crate::prelude:
macro_rules! serde_string_impl {
($name:ident, $expecting:expr) => {
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> $crate::serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
where
@ -210,6 +211,7 @@ macro_rules! serde_string_impl {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> $crate::serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -226,6 +228,7 @@ macro_rules! serde_string_impl {
macro_rules! serde_struct_human_string_impl {
($name:ident, $expecting:expr, $($fe:ident),*) => (
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> $crate::serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<$name, D::Error>
where
@ -380,6 +383,7 @@ macro_rules! serde_struct_human_string_impl {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> $crate::serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -462,6 +466,7 @@ macro_rules! impl_bytes_newtype {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl $crate::serde::Serialize for $t {
fn serialize<S: $crate::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
@ -473,6 +478,7 @@ macro_rules! impl_bytes_newtype {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> $crate::serde::Deserialize<'de> for $t {
fn deserialize<D: $crate::serde::Deserializer<'de>>(d: D) -> Result<$t, D::Error> {
if d.is_human_readable() {
@ -576,6 +582,7 @@ macro_rules! user_enum {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> $crate::serde::Deserialize<'de> for $name {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@ -625,6 +632,7 @@ macro_rules! user_enum {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl $crate::serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where

View File

@ -22,12 +22,27 @@
//! safety, including ownership and lifetime, for financial and/or cryptographic
//! software.
//!
//! ## Available feature flags
//!
//! * `std` - the usual dependency on `std` (default).
//! * `secp-recovery` - enables calculating public key from a signature and message.
//! * `base64` - (dependency), enables encoding of PSBTs and message signatures.
//! * `unstable` - enables unstable features for testing.
//! * `rand` - (dependency) makes it more convenient to generate random values.
//! * `use-serde` - (dependency) implements `serde`-based serialization and
//! deserialization
//! * `secp-lowmemory` - optimizations for low-memory devices
//! * `no-std` - enables additional features required for this crate to be usable
//! without std. Does **not** disable `std`. Depends on `hashbrown`
//! and `core2`.
#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
// Experimental features we need
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
#![cfg_attr(docsrs, feature(doc_cfg))]
// Coding conventions
#![forbid(unsafe_code)]
#![deny(non_upper_case_globals)]
@ -60,7 +75,9 @@ pub extern crate bech32;
#[cfg(feature = "no-std")]
extern crate hashbrown;
#[cfg(feature = "base64")] pub extern crate base64;
#[cfg(feature = "base64")]
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
pub extern crate base64;
#[cfg(feature="bitcoinconsensus")] extern crate bitcoinconsensus;
#[cfg(feature = "serde")] #[macro_use] extern crate serde;

View File

@ -24,14 +24,30 @@ use core::fmt;
pub mod constants;
#[cfg(feature = "std")] pub mod address;
#[cfg(feature = "std")] pub use self::address::Address;
#[cfg(feature = "std")] pub mod message;
#[cfg(feature = "std")] pub mod message_blockdata;
#[cfg(feature = "std")] pub mod message_bloom;
#[cfg(feature = "std")] pub mod message_network;
#[cfg(feature = "std")] pub mod message_filter;
#[cfg(feature = "std")] pub mod stream_reader;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod address;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub use self::address::Address;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod message;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod message_blockdata;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod message_bloom;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod message_network;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod message_filter;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub mod stream_reader;
/// Network error
#[derive(Debug)]
@ -62,6 +78,7 @@ impl From<io::Error> for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {

View File

@ -96,6 +96,7 @@ impl fmt::Display for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {

View File

@ -114,6 +114,7 @@ impl fmt::Display for ParseAmountError {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for ParseAmountError {}
fn is_too_precise(s: &str, precision: usize) -> bool {
@ -902,6 +903,7 @@ mod private {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub mod serde {
// methods are implementation of a standardized serde-specific signature
#![allow(missing_docs)]
@ -1008,7 +1010,7 @@ pub mod serde {
}
pub mod as_sat {
//! Serialize and deserialize [Amount] as real numbers denominated in satoshi.
//! Serialize and deserialize [`Amount`](crate::Amount) as real numbers denominated in satoshi.
//! Use with `#[serde(with = "amount::serde::as_sat")]`.
use serde::{Deserializer, Serializer};
@ -1023,7 +1025,7 @@ pub mod serde {
}
pub mod opt {
//! Serialize and deserialize [Optoin<Amount>] as real numbers denominated in satoshi.
//! Serialize and deserialize [`Option<Amount>`](crate::Amount) as real numbers denominated in satoshi.
//! Use with `#[serde(default, with = "amount::serde::as_sat::opt")]`.
use serde::{Deserializer, Serializer, de};
@ -1071,7 +1073,7 @@ pub mod serde {
}
pub mod as_btc {
//! Serialize and deserialize [Amount] as JSON numbers denominated in BTC.
//! Serialize and deserialize [`Amount`](crate::Amount) as JSON numbers denominated in BTC.
//! Use with `#[serde(with = "amount::serde::as_btc")]`.
use serde::{Deserializer, Serializer};

View File

@ -59,6 +59,7 @@ impl fmt::Display for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {}
/// Vector-like object that holds the first 100 elements on the stack. If more space is needed it

View File

@ -75,6 +75,7 @@ pub enum Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {}
impl Display for Error {

View File

@ -194,6 +194,7 @@ impl FromStr for ChildNumber {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> serde::Deserialize<'de> for ChildNumber {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@ -204,6 +205,7 @@ impl<'de> serde::Deserialize<'de> for ChildNumber {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl serde::Serialize for ChildNumber {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -460,6 +462,7 @@ impl fmt::Display for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
if let Error::Secp256k1(ref e) = *self {

View File

@ -75,6 +75,7 @@ impl fmt::Display for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {

View File

@ -297,6 +297,7 @@ impl ops::Index<ops::RangeFull> for PrivateKey {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for PrivateKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
s.collect_str(self)
@ -304,6 +305,7 @@ impl ::serde::Serialize for PrivateKey {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for PrivateKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PrivateKey, D::Error> {
struct WifVisitor;
@ -339,6 +341,7 @@ impl<'de> ::serde::Deserialize<'de> for PrivateKey {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl ::serde::Serialize for PublicKey {
fn serialize<S: ::serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
@ -354,6 +357,7 @@ impl ::serde::Serialize for PublicKey {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> ::serde::Deserialize<'de> for PublicKey {
fn deserialize<D: ::serde::Deserializer<'de>>(d: D) -> Result<PublicKey, D::Error> {
if d.is_human_readable() {

View File

@ -45,6 +45,7 @@ impl fmt::Display for Error {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {

View File

@ -438,6 +438,7 @@ impl MerkleBlock {
/// Create a MerkleBlock from a block, that contains proofs for specific txids.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[deprecated(since="0.26.2", note="use from_block_with_predicate")]
pub fn from_block(block: &Block, match_txids: &::std::collections::HashSet<Txid>) -> Self {
Self::from_block_with_predicate(block, |t| match_txids.contains(t))
@ -466,6 +467,7 @@ impl MerkleBlock {
/// Create a MerkleBlock from the block's header and txids, that should contain proofs for match_txids.
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
#[deprecated(since="0.26.2", note="use from_header_txids_with_predicate")]
pub fn from_header_txids(
header: &BlockHeader,

View File

@ -24,6 +24,7 @@ use blockdata::opcodes;
use consensus::{encode, Encodable};
#[cfg(feature = "secp-recovery")]
#[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))]
pub use self::message_signing::{MessageSignature, MessageSignatureError};
/// The prefix for signed messages using Bitcoin's message signing protocol.
@ -43,6 +44,7 @@ mod message_signing {
use util::address::{Address, AddressType};
/// An error used for dealing with Bitcoin Signed Messages.
#[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))]
#[derive(Debug, PartialEq, Eq)]
pub enum MessageSignatureError {
/// Signature is expected to be 65 bytes.
@ -64,6 +66,7 @@ mod message_signing {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl error::Error for MessageSignatureError {
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
@ -86,6 +89,7 @@ mod message_signing {
/// `fmt::Display` and `str::FromStr` implementations, the `base64` feature
/// must be enabled.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "secp-recovery")))]
pub struct MessageSignature {
/// The inner recoverable signature.
pub signature: RecoverableSignature,
@ -169,6 +173,7 @@ mod message_signing {
}
#[cfg(feature = "base64")]
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
/// Convert a signature from base64 encoding.
pub fn from_base64(s: &str) -> Result<MessageSignature, MessageSignatureError> {
let bytes = ::base64::decode(s).map_err(|_| MessageSignatureError::InvalidBase64)?;
@ -176,6 +181,7 @@ mod message_signing {
}
#[cfg(feature = "base64")]
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
/// Convert to base64 encoding.
pub fn to_base64(&self) -> String {
::base64::encode(&self.serialize()[..])
@ -183,6 +189,7 @@ mod message_signing {
}
#[cfg(feature = "base64")]
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
impl fmt::Display for MessageSignature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let bytes = self.serialize();
@ -193,6 +200,7 @@ mod message_signing {
}
#[cfg(feature = "base64")]
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
impl ::core::str::FromStr for MessageSignature {
type Err = MessageSignatureError;
fn from_str(s: &str) -> Result<MessageSignature, MessageSignatureError> {

View File

@ -104,6 +104,7 @@ mod display_from_str {
/// Error happening during PSBT decoding from Base64 string
#[derive(Debug)]
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
pub enum PsbtParseError {
/// Error in internal PSBT data structure
PsbtEncoding(Error),
@ -121,14 +122,17 @@ mod display_from_str {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for PsbtParseError { }
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
impl Display for PartiallySignedTransaction {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", Base64Display::with_config(&encode::serialize(self), ::base64::STANDARD))
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
impl FromStr for PartiallySignedTransaction {
type Err = PsbtParseError;
@ -139,6 +143,7 @@ mod display_from_str {
}
}
#[cfg(feature = "base64")]
#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
pub use self::display_from_str::PsbtParseError;
impl Encodable for PartiallySignedTransaction {

View File

@ -430,6 +430,7 @@ macro_rules! construct_uint {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl $crate::serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@ -446,6 +447,7 @@ macro_rules! construct_uint {
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de> $crate::serde::Deserialize<'de> for $name {
fn deserialize<D: $crate::serde::Deserializer<'de>>(
deserializer: D,
@ -510,6 +512,7 @@ impl ::core::fmt::Display for ParseLengthError {
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl ::std::error::Error for ParseLengthError {}
impl Uint256 {