Merge rust-bitcoin/rust-bitcoin#2899: Pass sigs and associated types by value

dc10a49876 api: Run just check-api (Tobin C. Harding)
5e8f204581 Pass sigs and associated types by value (Tobin C. Harding)

Pull request description:

  We should pass `Copy` types by value not by reference.

  Currently this is not done in secp, but lets do it here in bitcoin.

  Pass by value:

  - `SerializedSignature`
  - bitcoin sigs
  - secp sigs
  - secp `Message`

  This is a continuation of the work to split up #2404 into manageable PRs.

ACKs for top commit:
  apoelstra:
    ACK dc10a49876
  Kixunil:
    ACK dc10a49876

Tree-SHA512: 8736eba067c74edb951c92357f5b3d0fc99c4fa6dc3beea579c10b3150873b74e8ec46c2c01f18818b37fca6e77c6b6edddeb6340edde6a9d8c28a4e69164c8c
This commit is contained in:
merge-script 2024-06-28 23:48:03 +00:00
commit 7ca7128b19
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
9 changed files with 30 additions and 30 deletions

View File

@ -7067,7 +7067,7 @@ pub fn bitcoin::CompressedPublicKey::read_from<R: bitcoin_io::Read + core::marke
pub fn bitcoin::CompressedPublicKey::serialize<S: serde::ser::Serializer>(&self, s: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error>
pub fn bitcoin::CompressedPublicKey::to_bytes(&self) -> [u8; 33]
pub fn bitcoin::CompressedPublicKey::try_from(value: bitcoin::PublicKey) -> core::result::Result<Self, Self::Error>
pub fn bitcoin::CompressedPublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: &secp256k1::Message, sig: &bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::CompressedPublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: secp256k1::Message, sig: bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::CompressedPublicKey::wpubkey_hash(&self) -> bitcoin::WPubkeyHash
pub fn bitcoin::CompressedPublicKey::write_into<W: bitcoin_io::Write + core::marker::Sized>(&self, writer: &mut W) -> core::result::Result<(), bitcoin_io::error::Error>
pub fn bitcoin::EcdsaSighashType::clone(&self) -> bitcoin::EcdsaSighashType
@ -7167,7 +7167,7 @@ pub fn bitcoin::PublicKey::read_from<R: bitcoin_io::Read + core::marker::Sized>(
pub fn bitcoin::PublicKey::serialize<S: serde::ser::Serializer>(&self, s: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error>
pub fn bitcoin::PublicKey::to_bytes(self) -> alloc::vec::Vec<u8>
pub fn bitcoin::PublicKey::to_sort_key(self) -> bitcoin::key::SortKey
pub fn bitcoin::PublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: &secp256k1::Message, sig: &bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::PublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: secp256k1::Message, sig: bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::PublicKey::wpubkey_hash(&self) -> core::result::Result<bitcoin::WPubkeyHash, bitcoin::key::UncompressedPublicKeyError>
pub fn bitcoin::PublicKey::write_into<W: bitcoin_io::Write + core::marker::Sized>(&self, writer: &mut W) -> core::result::Result<(), bitcoin_io::error::Error>
pub fn bitcoin::SegwitV0Sighash::as_byte_array(&self) -> &Self::Bytes
@ -8609,10 +8609,10 @@ pub fn bitcoin::blockdata::witness::Witness::last(&self) -> core::option::Option
pub fn bitcoin::blockdata::witness::Witness::len(&self) -> usize
pub fn bitcoin::blockdata::witness::Witness::nth(&self, index: usize) -> core::option::Option<&[u8]>
pub fn bitcoin::blockdata::witness::Witness::p2tr_key_spend(signature: &bitcoin::taproot::Signature) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::p2wpkh(signature: &bitcoin::ecdsa::Signature, pubkey: secp256k1::key::PublicKey) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::p2wpkh(signature: bitcoin::ecdsa::Signature, pubkey: secp256k1::key::PublicKey) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::partial_cmp(&self, other: &bitcoin::blockdata::witness::Witness) -> core::option::Option<core::cmp::Ordering>
pub fn bitcoin::blockdata::witness::Witness::push<T: core::convert::AsRef<[u8]>>(&mut self, new_element: T)
pub fn bitcoin::blockdata::witness::Witness::push_ecdsa_signature(&mut self, signature: &bitcoin::ecdsa::Signature)
pub fn bitcoin::blockdata::witness::Witness::push_ecdsa_signature(&mut self, signature: bitcoin::ecdsa::Signature)
pub fn bitcoin::blockdata::witness::Witness::second_to_last(&self) -> core::option::Option<&[u8]>
pub fn bitcoin::blockdata::witness::Witness::serialize<S>(&self, serializer: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error> where S: serde::ser::Serializer
pub fn bitcoin::blockdata::witness::Witness::size(&self) -> usize
@ -9999,7 +9999,7 @@ pub fn bitcoin::taproot::serialized_signature::SerializedSignature::eq(&self, ot
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from(value: &'a bitcoin::taproot::Signature) -> Self
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from(value: bitcoin::taproot::Signature) -> Self
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from_signature(sig: &bitcoin::taproot::Signature) -> bitcoin::taproot::serialized_signature::SerializedSignature
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from_signature(sig: bitcoin::taproot::Signature) -> bitcoin::taproot::serialized_signature::SerializedSignature
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::hash<H: core::hash::Hasher>(&self, state: &mut H)
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::into_iter(self) -> Self::IntoIter
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::len(&self) -> usize

View File

@ -6759,7 +6759,7 @@ pub fn bitcoin::CompressedPublicKey::pubkey_hash(&self) -> bitcoin::PubkeyHash
pub fn bitcoin::CompressedPublicKey::read_from<R: bitcoin_io::Read + core::marker::Sized>(reader: &mut R) -> core::result::Result<Self, bitcoin_io::error::Error>
pub fn bitcoin::CompressedPublicKey::to_bytes(&self) -> [u8; 33]
pub fn bitcoin::CompressedPublicKey::try_from(value: bitcoin::PublicKey) -> core::result::Result<Self, Self::Error>
pub fn bitcoin::CompressedPublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: &secp256k1::Message, sig: &bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::CompressedPublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: secp256k1::Message, sig: bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::CompressedPublicKey::wpubkey_hash(&self) -> bitcoin::WPubkeyHash
pub fn bitcoin::CompressedPublicKey::write_into<W: bitcoin_io::Write + core::marker::Sized>(&self, writer: &mut W) -> core::result::Result<(), bitcoin_io::error::Error>
pub fn bitcoin::EcdsaSighashType::clone(&self) -> bitcoin::EcdsaSighashType
@ -6846,7 +6846,7 @@ pub fn bitcoin::PublicKey::pubkey_hash(&self) -> bitcoin::PubkeyHash
pub fn bitcoin::PublicKey::read_from<R: bitcoin_io::Read + core::marker::Sized>(reader: &mut R) -> core::result::Result<Self, bitcoin_io::error::Error>
pub fn bitcoin::PublicKey::to_bytes(self) -> alloc::vec::Vec<u8>
pub fn bitcoin::PublicKey::to_sort_key(self) -> bitcoin::key::SortKey
pub fn bitcoin::PublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: &secp256k1::Message, sig: &bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::PublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: secp256k1::Message, sig: bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::PublicKey::wpubkey_hash(&self) -> core::result::Result<bitcoin::WPubkeyHash, bitcoin::key::UncompressedPublicKeyError>
pub fn bitcoin::PublicKey::write_into<W: bitcoin_io::Write + core::marker::Sized>(&self, writer: &mut W) -> core::result::Result<(), bitcoin_io::error::Error>
pub fn bitcoin::SegwitV0Sighash::as_byte_array(&self) -> &Self::Bytes
@ -8199,10 +8199,10 @@ pub fn bitcoin::blockdata::witness::Witness::last(&self) -> core::option::Option
pub fn bitcoin::blockdata::witness::Witness::len(&self) -> usize
pub fn bitcoin::blockdata::witness::Witness::nth(&self, index: usize) -> core::option::Option<&[u8]>
pub fn bitcoin::blockdata::witness::Witness::p2tr_key_spend(signature: &bitcoin::taproot::Signature) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::p2wpkh(signature: &bitcoin::ecdsa::Signature, pubkey: secp256k1::key::PublicKey) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::p2wpkh(signature: bitcoin::ecdsa::Signature, pubkey: secp256k1::key::PublicKey) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::partial_cmp(&self, other: &bitcoin::blockdata::witness::Witness) -> core::option::Option<core::cmp::Ordering>
pub fn bitcoin::blockdata::witness::Witness::push<T: core::convert::AsRef<[u8]>>(&mut self, new_element: T)
pub fn bitcoin::blockdata::witness::Witness::push_ecdsa_signature(&mut self, signature: &bitcoin::ecdsa::Signature)
pub fn bitcoin::blockdata::witness::Witness::push_ecdsa_signature(&mut self, signature: bitcoin::ecdsa::Signature)
pub fn bitcoin::blockdata::witness::Witness::second_to_last(&self) -> core::option::Option<&[u8]>
pub fn bitcoin::blockdata::witness::Witness::size(&self) -> usize
pub fn bitcoin::blockdata::witness::Witness::tapscript(&self) -> core::option::Option<&bitcoin::blockdata::script::Script>
@ -9483,7 +9483,7 @@ pub fn bitcoin::taproot::serialized_signature::SerializedSignature::eq(&self, ot
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from(value: &'a bitcoin::taproot::Signature) -> Self
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from(value: bitcoin::taproot::Signature) -> Self
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from_signature(sig: &bitcoin::taproot::Signature) -> bitcoin::taproot::serialized_signature::SerializedSignature
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from_signature(sig: bitcoin::taproot::Signature) -> bitcoin::taproot::serialized_signature::SerializedSignature
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::hash<H: core::hash::Hasher>(&self, state: &mut H)
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::into_iter(self) -> Self::IntoIter
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::len(&self) -> usize

View File

@ -6125,7 +6125,7 @@ pub fn bitcoin::CompressedPublicKey::pubkey_hash(&self) -> bitcoin::PubkeyHash
pub fn bitcoin::CompressedPublicKey::read_from<R: bitcoin_io::Read + core::marker::Sized>(reader: &mut R) -> core::result::Result<Self, bitcoin_io::error::Error>
pub fn bitcoin::CompressedPublicKey::to_bytes(&self) -> [u8; 33]
pub fn bitcoin::CompressedPublicKey::try_from(value: bitcoin::PublicKey) -> core::result::Result<Self, Self::Error>
pub fn bitcoin::CompressedPublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: &secp256k1::Message, sig: &bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::CompressedPublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: secp256k1::Message, sig: bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::CompressedPublicKey::wpubkey_hash(&self) -> bitcoin::WPubkeyHash
pub fn bitcoin::CompressedPublicKey::write_into<W: bitcoin_io::Write + core::marker::Sized>(&self, writer: &mut W) -> core::result::Result<(), bitcoin_io::error::Error>
pub fn bitcoin::EcdsaSighashType::clone(&self) -> bitcoin::EcdsaSighashType
@ -6212,7 +6212,7 @@ pub fn bitcoin::PublicKey::pubkey_hash(&self) -> bitcoin::PubkeyHash
pub fn bitcoin::PublicKey::read_from<R: bitcoin_io::Read + core::marker::Sized>(reader: &mut R) -> core::result::Result<Self, bitcoin_io::error::Error>
pub fn bitcoin::PublicKey::to_bytes(self) -> alloc::vec::Vec<u8>
pub fn bitcoin::PublicKey::to_sort_key(self) -> bitcoin::key::SortKey
pub fn bitcoin::PublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: &secp256k1::Message, sig: &bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::PublicKey::verify<C: secp256k1::context::Verification>(&self, secp: &secp256k1::Secp256k1<C>, msg: secp256k1::Message, sig: bitcoin::ecdsa::Signature) -> core::result::Result<(), secp256k1::Error>
pub fn bitcoin::PublicKey::wpubkey_hash(&self) -> core::result::Result<bitcoin::WPubkeyHash, bitcoin::key::UncompressedPublicKeyError>
pub fn bitcoin::PublicKey::write_into<W: bitcoin_io::Write + core::marker::Sized>(&self, writer: &mut W) -> core::result::Result<(), bitcoin_io::error::Error>
pub fn bitcoin::SegwitV0Sighash::as_byte_array(&self) -> &Self::Bytes
@ -7540,10 +7540,10 @@ pub fn bitcoin::blockdata::witness::Witness::last(&self) -> core::option::Option
pub fn bitcoin::blockdata::witness::Witness::len(&self) -> usize
pub fn bitcoin::blockdata::witness::Witness::nth(&self, index: usize) -> core::option::Option<&[u8]>
pub fn bitcoin::blockdata::witness::Witness::p2tr_key_spend(signature: &bitcoin::taproot::Signature) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::p2wpkh(signature: &bitcoin::ecdsa::Signature, pubkey: secp256k1::key::PublicKey) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::p2wpkh(signature: bitcoin::ecdsa::Signature, pubkey: secp256k1::key::PublicKey) -> bitcoin::blockdata::witness::Witness
pub fn bitcoin::blockdata::witness::Witness::partial_cmp(&self, other: &bitcoin::blockdata::witness::Witness) -> core::option::Option<core::cmp::Ordering>
pub fn bitcoin::blockdata::witness::Witness::push<T: core::convert::AsRef<[u8]>>(&mut self, new_element: T)
pub fn bitcoin::blockdata::witness::Witness::push_ecdsa_signature(&mut self, signature: &bitcoin::ecdsa::Signature)
pub fn bitcoin::blockdata::witness::Witness::push_ecdsa_signature(&mut self, signature: bitcoin::ecdsa::Signature)
pub fn bitcoin::blockdata::witness::Witness::second_to_last(&self) -> core::option::Option<&[u8]>
pub fn bitcoin::blockdata::witness::Witness::size(&self) -> usize
pub fn bitcoin::blockdata::witness::Witness::tapscript(&self) -> core::option::Option<&bitcoin::blockdata::script::Script>
@ -8588,7 +8588,7 @@ pub fn bitcoin::taproot::serialized_signature::SerializedSignature::eq(&self, ot
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from(value: &'a bitcoin::taproot::Signature) -> Self
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from(value: bitcoin::taproot::Signature) -> Self
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from_signature(sig: &bitcoin::taproot::Signature) -> bitcoin::taproot::serialized_signature::SerializedSignature
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::from_signature(sig: bitcoin::taproot::Signature) -> bitcoin::taproot::serialized_signature::SerializedSignature
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::hash<H: core::hash::Hasher>(&self, state: &mut H)
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::into_iter(self) -> Self::IntoIter
pub fn bitcoin::taproot::serialized_signature::SerializedSignature::len(&self) -> usize

View File

@ -221,7 +221,7 @@ fn main() {
.enumerate()
.map(|(idx, input)| {
let (_, sig) = input.partial_sigs.iter().next().expect("we have one sig");
Witness::p2wpkh(sig, pk_inputs[idx].0)
Witness::p2wpkh(*sig, pk_inputs[idx].0)
})
.collect();
psbt.inputs.iter_mut().enumerate().for_each(|(idx, input)| {

View File

@ -47,7 +47,7 @@ fn compute_sighash_p2wpkh(raw_tx: &[u8], inp_idx: usize, value: u64) {
let msg = secp256k1::Message::from(sighash);
println!("Message is {:x}", msg);
let secp = secp256k1::Secp256k1::verification_only();
pk.verify(&secp, &msg, &sig).unwrap()
pk.verify(&secp, msg, sig).unwrap()
}
/// Computes sighash for a legacy multisig transaction input that spends either a p2sh or a p2ms output.

View File

@ -75,7 +75,7 @@ fn main() {
// Update the witness stack.
let signature = bitcoin::ecdsa::Signature { signature, sighash_type };
let pk = sk.public_key(&secp);
*sighasher.witness_mut(input_index).unwrap() = Witness::p2wpkh(&signature, pk);
*sighasher.witness_mut(input_index).unwrap() = Witness::p2wpkh(signature, pk);
// Get the signed transaction.
let tx = sighasher.into_transaction();

View File

@ -243,7 +243,7 @@ impl Witness {
/// serialized public key. Also useful for spending a P2SH-P2WPKH output.
///
/// It is expected that `pubkey` is related to the secret key used to create `signature`.
pub fn p2wpkh(signature: &ecdsa::Signature, pubkey: secp256k1::PublicKey) -> Witness {
pub fn p2wpkh(signature: ecdsa::Signature, pubkey: secp256k1::PublicKey) -> Witness {
let mut witness = Witness::new();
witness.push_slice(&signature.serialize());
witness.push_slice(&pubkey.serialize());
@ -355,7 +355,7 @@ impl Witness {
/// Pushes, as a new element on the witness, an ECDSA signature.
///
/// Pushes the DER encoded signature + sighash_type, requires an allocation.
pub fn push_ecdsa_signature(&mut self, signature: &ecdsa::Signature) {
pub fn push_ecdsa_signature(&mut self, signature: ecdsa::Signature) {
self.push_slice(&signature.serialize())
}
@ -657,7 +657,7 @@ mod test {
let signature = secp256k1::ecdsa::Signature::from_der(&sig_bytes).unwrap();
let mut witness = Witness::default();
let signature = crate::ecdsa::Signature { signature, sighash_type: EcdsaSighashType::All };
witness.push_ecdsa_signature(&signature);
witness.push_ecdsa_signature(signature);
let expected_witness = vec![hex!(
"304402207c800d698f4b0298c5aac830b822f011bb02df41eb114ade9a6702f364d5e39c0220366900d2a60cab903e77ef7dd415d46509b1f78ac78906e3296f495aa1b1b54101")
];

View File

@ -205,10 +205,10 @@ impl PublicKey {
pub fn verify<C: secp256k1::Verification>(
&self,
secp: &Secp256k1<C>,
msg: &secp256k1::Message,
sig: &ecdsa::Signature,
msg: secp256k1::Message,
sig: ecdsa::Signature,
) -> Result<(), secp256k1::Error> {
secp.verify_ecdsa(msg, &sig.signature, &self.inner)
secp.verify_ecdsa(&msg, &sig.signature, &self.inner)
}
}
@ -338,10 +338,10 @@ impl CompressedPublicKey {
pub fn verify<C: secp256k1::Verification>(
&self,
secp: &Secp256k1<C>,
msg: &secp256k1::Message,
sig: &ecdsa::Signature,
msg: secp256k1::Message,
sig: ecdsa::Signature,
) -> Result<(), secp256k1::Error> {
Ok(secp.verify_ecdsa(msg, &sig.signature, &self.0)?)
Ok(secp.verify_ecdsa(&msg, &sig.signature, &self.0)?)
}
}

View File

@ -109,11 +109,11 @@ impl<'a> IntoIterator for &'a SerializedSignature {
}
impl From<Signature> for SerializedSignature {
fn from(value: Signature) -> Self { Self::from_signature(&value) }
fn from(value: Signature) -> Self { Self::from_signature(value) }
}
impl<'a> From<&'a Signature> for SerializedSignature {
fn from(value: &'a Signature) -> Self { Self::from_signature(value) }
fn from(value: &'a Signature) -> Self { Self::from_signature(*value) }
}
impl TryFrom<SerializedSignature> for Signature {
@ -162,7 +162,7 @@ impl SerializedSignature {
/// Create a SerializedSignature from a Signature.
/// (this serializes it)
#[inline]
pub fn from_signature(sig: &Signature) -> SerializedSignature { sig.serialize() }
pub fn from_signature(sig: Signature) -> SerializedSignature { sig.serialize() }
/// Writes this serialized signature to a `writer`.
#[inline]