1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! A clone that is allowed to fail.
//!
//! WHY: `Clone` is all-or-nothing. A type with even one non-clonable variant —
//! a handle to a single-shot stream, a file descriptor, a moved-once resource —
//! cannot implement it at all. Callers who need a copy are then left to
//! hand-roll a `match` at every call site, and they are free to disagree about
//! which variants are safe. That disagreement is a real defect class: one such
//! call site in the SSE reconnect path dropped a request body entirely, sending
//! a bodyless POST that the server rejected with 400.
//!
//! WHAT: [`TryClone`], a fallible clone whose error explains the refusal, and
//! [`TryCloneError`] as a ready-made error for the common "this is backed by a
//! single-shot source" case. Implementors are free to use their own error type.
//!
//! HOW: implement `TryClone` on the type that knows which of its states can be
//! duplicated, so that judgement lives in one place instead of at every caller.
//!
//! ```
//! use foundation_core::traits::{TryClone, TryCloneError};
//!
//! enum Payload {
//! Owned(Vec<u8>),
//! Streaming,
//! }
//!
//! impl TryClone for Payload {
//! type Error = TryCloneError;
//!
//! fn try_clone(&self) -> Result<Self, Self::Error> {
//! match self {
//! Self::Owned(bytes) => Ok(Self::Owned(bytes.clone())),
//! Self::Streaming => Err(TryCloneError::NotReplayable("Payload::Streaming")),
//! }
//! }
//! }
//!
//! assert!(Payload::Owned(vec![1, 2]).try_clone().is_ok());
//! assert!(Payload::Streaming.try_clone().is_err());
//! ```
/// Why a value could not be cloned.
///
/// WHY: a bare `Option` cannot distinguish "there was nothing to clone" from
/// "this refuses to be cloned", and the two call for opposite handling. Naming
/// the offending variant also turns an otherwise mystifying log line into one
/// that points at the source.
/// A clone that is allowed to fail.
///
/// Implement this when some — but not all — states of a type can be duplicated.
/// See the [module docs](self) for the rationale and an example.