partial_default/
lib.rs

1//
2// Copyright 2023 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6#![doc = include_str!("../README.md")]
7#![no_std]
8#![cfg_attr(docsrs, feature(doc_auto_cfg))]
9
10#[cfg(feature = "derive")]
11pub use partial_default_derive::PartialDefault;
12
13/// A trait for giving a type a *non*-useful default value.
14///
15/// The standard [`Default`] trait documents its purpose as providing a "useful" default value.
16/// However, some types (such as a Credential) don't have meaningful defaults, and yet there are
17/// still uses for a known-initialized value:
18///
19/// - serde's hidden [`Deserializer::deserialize_in_place`][deserialize_in_place], which is
20///   generally more efficient than the usual `deserialize`
21/// - subtle's [`ConditionallySelectable::conditional_assign`][conditional_assign], for repeated
22///   assignments with at least one success
23/// - APIs that must produce results even when signalling an error out of band (like JNI functions)
24///
25/// `PartialDefault` satisfies this niche. A type that implements `PartialDefault` can provide a
26/// value that is safe to drop or assign over, but promises nothing else about that value. Using it
27/// in any other way may panic or produce unexpected results, though it should not be possible to
28/// violate memory safety. That is, [`partial_default`][Self::partial_default] should always be a
29/// "safe" function in the Rust sense.
30///
31/// The name "PartialDefault" is by analogy to [`PartialEq`]/[`Eq`] and [`PartialOrd`]/[`Ord`] in
32/// the standard library: just as `PartialEq` provides weaker guarantees than `Eq` and `PartialOrd`
33/// provides weaker guarantees than `Ord`, `PartialDefault` provides weaker guarantees than
34/// `Default`. And just as every `Eq`-implementing type provides `PartialEq`, every
35/// `Default`-implementing type provides `PartialDefault`.
36///
37/// # Derivable
38///
39/// Like [`Default`], `PartialDefault` supports `#[derive]` if all fields implement
40/// `PartialDefault`. The value used for a field can be overridden using the
41/// `#[partial_default(value = "alternative()")]` syntax, where `alternative()` is a Rust expression
42/// that evaluates to the correct type.
43///
44/// By default, all generic parameters must implement `PartialDefault` to support deriving
45/// `PartialDefault`. You can override this by adding `#[partial_default(bound = "T: MyTrait")]` to
46/// the type, which replaces any bounds inferred by `PartialDefault`. Use an empty string to impose
47/// no restrictions at all.
48///
49/// [deserialize_in_place]: https://docs.rs/serde/1.0.189/src/serde/de/mod.rs.html#546-568
50/// [conditional_assign]: https://docs.rs/subtle/2.5.0/subtle/trait.ConditionallySelectable.html
51pub trait PartialDefault: Sized {
52    /// Returns a value that can be safely dropped or assigned over.
53    fn partial_default() -> Self;
54}
55
56/// If a type does implement `Default`, its `PartialDefault` implementation will match.
57impl<T: Default> PartialDefault for T {
58    fn partial_default() -> Self {
59        Self::default()
60    }
61}