1use embedded_io::Error;
2
3use crate::io::{Read, Write};
4
5pub fn try_read_full<R: Read>(mut read: R, buf: &mut [u8]) -> Result<usize, (R::Error, usize)> {
6 let mut offset = 0;
7 let mut size = 0;
8
9 loop {
10 let size_read = read.read(&mut buf[offset..]).map_err(|e| (e, size))?;
11
12 offset += size_read;
13 size += size_read;
14
15 if size_read == 0 || size == buf.len() {
16 break;
17 }
18 }
19
20 Ok(size)
21}
22
23#[derive(Debug)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub enum CopyError<R, W> {
26 Read(R),
27 Write(W),
28}
29
30impl<R: core::fmt::Debug, W: core::fmt::Debug> core::fmt::Display for CopyError<R, W> {
31 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32 write!(f, "{self:?}")
33 }
34}
35
36impl<R: core::fmt::Debug, W: core::fmt::Debug> core::error::Error for CopyError<R, W> {}
37
38impl<R, W> Error for CopyError<R, W>
39where
40 R: Error,
41 W: Error,
42{
43 fn kind(&self) -> embedded_io::ErrorKind {
44 match self {
45 Self::Read(e) => e.kind(),
46 Self::Write(e) => e.kind(),
47 }
48 }
49}
50
51pub fn copy<R, W>(read: R, write: W, buf: &mut [u8]) -> Result<u64, CopyError<R::Error, W::Error>>
52where
53 R: Read,
54 W: Write,
55{
56 copy_len(read, write, buf, u64::MAX)
57}
58
59pub fn copy_len<R, W>(
60 read: R,
61 write: W,
62 buf: &mut [u8],
63 len: u64,
64) -> Result<u64, CopyError<R::Error, W::Error>>
65where
66 R: Read,
67 W: Write,
68{
69 copy_len_with_progress(read, write, buf, len, |_, _| {})
70}
71
72pub fn copy_len_with_progress<R, W, P>(
73 mut read: R,
74 mut write: W,
75 buf: &mut [u8],
76 mut len: u64,
77 progress: P,
78) -> Result<u64, CopyError<R::Error, W::Error>>
79where
80 R: Read,
81 W: Write,
82 P: Fn(u64, u64),
83{
84 let mut copied = 0;
85
86 while len > 0 {
87 progress(copied, len);
88
89 let size_read = read.read(buf).map_err(CopyError::Read)?;
90 if size_read == 0 {
91 break;
92 }
93
94 write
95 .write_all(&buf[0..size_read])
96 .map_err(CopyError::Write)?;
97
98 copied += size_read as u64;
99 len -= size_read as u64;
100 }
101
102 progress(copied, len);
103
104 Ok(copied)
105}
106
107pub mod asynch {
108 use crate::io::asynch::{Read, Write};
109
110 pub use super::CopyError;
111
112 pub async fn try_read_full<R: Read>(
113 mut read: R,
114 buf: &mut [u8],
115 ) -> Result<usize, (R::Error, usize)> {
116 let mut offset = 0;
117 let mut size = 0;
118
119 loop {
120 let size_read = read.read(&mut buf[offset..]).await.map_err(|e| (e, size))?;
121
122 offset += size_read;
123 size += size_read;
124
125 if size_read == 0 || size == buf.len() {
126 break;
127 }
128 }
129
130 Ok(size)
131 }
132
133 pub async fn copy<R, W>(
134 read: R,
135 write: W,
136 buf: &mut [u8],
137 ) -> Result<u64, CopyError<R::Error, W::Error>>
138 where
139 R: Read,
140 W: Write,
141 {
142 copy_len(read, write, buf, u64::MAX).await
143 }
144
145 pub async fn copy_len<R, W>(
146 read: R,
147 write: W,
148 buf: &mut [u8],
149 len: u64,
150 ) -> Result<u64, CopyError<R::Error, W::Error>>
151 where
152 R: Read,
153 W: Write,
154 {
155 copy_len_with_progress(read, write, buf, len, |_, _| {}).await
156 }
157
158 pub async fn copy_len_with_progress<R, W, P>(
159 mut read: R,
160 mut write: W,
161 buf: &mut [u8],
162 mut len: u64,
163 progress: P,
164 ) -> Result<u64, CopyError<R::Error, W::Error>>
165 where
166 R: Read,
167 W: Write,
168 P: Fn(u64, u64),
169 {
170 let mut copied = 0;
171
172 while len > 0 {
173 progress(copied, len);
174
175 let size_read = read.read(buf).await.map_err(CopyError::Read)?;
176 if size_read == 0 {
177 break;
178 }
179
180 write
181 .write_all(&buf[0..size_read])
182 .await
183 .map_err(CopyError::Write)?;
184
185 copied += size_read as u64;
186 len -= size_read as u64;
187 }
188
189 progress(copied, len);
190
191 Ok(copied)
192 }
193}