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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// =============================================================================
// Copyright (c) 2026 Haixing Hu.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0.
// =============================================================================
use ;
/// Writer wrapper that mirrors accepted bytes into a branch writer.
///
/// `TeeWriter` writes to the primary writer first, then writes exactly the
/// accepted bytes into the branch writer with [`Write::write_all`]. If the
/// branch writer fails, the primary writer may already have accepted bytes and
/// the branch error is returned.
///
/// Seeking moves the primary writer first, then seeks the branch writer to the
/// primary writer's resulting absolute position. If the branch seek fails, the
/// primary writer may already have moved.
///
/// # Failure and retry semantics
///
/// A branch error does not roll back bytes already accepted by the primary
/// writer. Callers should therefore treat a branch write error as terminal
/// unless repeating the primary write is known to be safe. In particular, an
/// outer buffering layer may retain the entire failed chunk because
/// [`Write::write`] returned an error rather than a byte count. Retrying that
/// buffered chunk can duplicate data in the primary writer:
///
/// ```text
/// first attempt: primary accepts "abc", branch returns an error
/// retry: primary accepts "abc" again
/// result: primary may contain "abcabc"
/// ```
///
/// After a branch error, the primary and branch writers may be out of sync.
/// This wrapper does not record a sticky error or provide rollback.
///
/// # Examples
/// ```
/// use std::io::Write;
///
/// use qubit_io::TeeWriter;
///
/// let primary = Vec::new();
/// let branch = Vec::new();
/// let mut writer = TeeWriter::new(primary, branch);
///
/// writer.write_all(b"abc")?;
/// let (primary, branch) = writer.into_inner();
///
/// assert_eq!(b"abc", primary.as_slice());
/// assert_eq!(b"abc", branch.as_slice());
/// # Ok::<(), std::io::Error>(())
/// ```