1use std::error;
6use std::fmt::Display;
7use std::marker;
8use std::pin::Pin;
9use std::str::FromStr;
10
11use crate::error::Error;
12use crate::error::VfsResult;
13use crate::prelude::*;
14use crate::std_types::FileString;
15#[cfg(feature = "async")]
16use crate::traits::asy::FromRefForWriterAsync;
17#[cfg(feature = "async")]
18use crate::traits::async_vfs::VfsAsync;
19#[cfg(feature = "async")]
20use crate::traits::async_vfs::WriteSupportingVfsAsync;
21use crate::traits::sync::FromRefForWriter;
22use crate::traits::sync::NewtypeToInner;
23use crate::traits::vfs;
24use crate::traits::vfs::PathType;
25#[cfg(feature = "async")]
26use crate::traits::vfs::VfsCore;
27
28#[cfg_attr(feature = "derive", doc = "```rust")]
36#[cfg_attr(not(feature = "derive"), doc = "```rust,compile_fail")]
37#[cfg_attr(feature = "assert_eq", derive(assert_eq::AssertEq))]
68pub struct FmtWrapper<T>(pub T);
69
70impl<T> NewtypeToInner for FmtWrapper<T> {
71 type Inner = T;
72
73 fn into_inner(self) -> Self::Inner {
74 self.0
75 }
76}
77
78impl<'a, T, Vfs: vfs::Vfs<'a>> ReadFrom<'a, Vfs> for FmtWrapper<T>
79where
80 T: FromStr + 'a,
81 T::Err: Into<Box<dyn error::Error + Send + Sync>>,
82{
83 fn read_from(path: &Vfs::Path, vfs: Pin<&'a Vfs>) -> VfsResult<Self, Vfs>
84 where
85 Self: Sized,
86 {
87 let contents = FileString::read_from(path, vfs)?.0;
88 match contents.parse::<T>() {
89 Ok(v) => Ok(Self(v)),
90 Err(e) => Err(Error::Parse(path.owned(), e.into())),
91 }
92 }
93}
94
95#[cfg(feature = "async")]
96#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
97impl<'a, T, Vfs: VfsAsync + 'static> ReadFromAsync<'a, Vfs> for FmtWrapper<T>
98where
99 T: FromStr + Send + 'static,
100 T::Err: Into<Box<dyn error::Error + Send + Sync>>,
101{
102 type Future = Pin<Box<dyn Future<Output = VfsResult<Self, Vfs>> + Send + 'a>>;
103
104 fn read_from_async(
105 path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
106 vfs: Pin<&'a Vfs>,
107 ) -> Self::Future {
108 Box::pin(async move {
109 let contents = FileString::read_from_async(path.clone(), vfs).await?.0;
110 match contents.parse::<T>() {
111 Ok(v) => Ok(Self(v)),
112 Err(e) => Err(Error::Parse(path, e.into())),
113 }
114 })
115 }
116}
117
118impl<'vfs, T, Vfs: vfs::WriteSupportingVfs<'vfs>> WriteTo<'vfs, Vfs> for FmtWrapper<T>
119where
120 T: Display,
121{
122 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<(), Vfs> {
123 Self::from_ref_for_writer(&self.0).write_to(path, vfs)
124 }
125}
126
127#[cfg(feature = "async")]
128#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
129impl<'a, T, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs> for FmtWrapper<T>
130where
131 T: Display + Send + Sync + 'static,
132{
133 type Future = <FileString as WriteToAsync<'a, Vfs>>::Future;
134
135 fn write_to_async(
136 self,
137 path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
138 vfs: Pin<&'a Vfs>,
139 ) -> Self::Future {
140 let s = self.0.to_string();
141 FileString::new(s).write_to_async(path, vfs)
142 }
143}
144
145#[cfg(feature = "async")]
146#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
147impl<'a, T, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsyncRef<'a, Vfs> for FmtWrapper<T>
148where
149 T: Display + Send + Sync + 'a,
150{
151 type Future<'b>
152 = <FileString as WriteToAsync<'b, Vfs>>::Future
153 where
154 Self: 'b,
155 'a: 'b,
156 Vfs: 'b;
157
158 fn write_to_async_ref<'b>(
159 &'b self,
160 path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
161 vfs: Pin<&'b Vfs>,
162 ) -> Self::Future<'b>
163 where
164 'a: 'b,
165 {
166 let s = self.0.to_string();
167 FileString::new(s).write_to_async(path, vfs)
168 }
169}
170
171impl<'a, 'vfs, T, Vfs: vfs::WriteSupportingVfs<'vfs>> FromRefForWriter<'a, 'vfs, Vfs>
172 for FmtWrapper<T>
173where
174 T: Display + 'a,
175 Vfs: 'vfs,
176 'vfs: 'a,
177{
178 type Inner = T;
179 type Wr = FmtWrapperRefWr<'a, 'vfs, T, Vfs>;
180
181 fn from_ref_for_writer(value: &'a Self::Inner) -> Self::Wr {
182 FmtWrapperRefWr(value, marker::PhantomData)
183 }
184}
185
186#[cfg(feature = "async")]
187#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
188impl<'a, T, Vfs: WriteSupportingVfsAsync + 'static> FromRefForWriterAsync<'a, Vfs> for FmtWrapper<T>
189where
190 T: Display + Send + 'a,
191{
192 type Inner = T;
193 type Wr = FmtWrapperRefWr<'a, 'a, T, Vfs>;
194
195 fn from_ref_for_writer_async(value: &'a Self::Inner) -> Self::Wr {
196 FmtWrapperRefWr(value, marker::PhantomData)
197 }
198}
199
200pub struct FmtWrapperRefWr<'a, 'vfs, T: Display + ?Sized, Vfs: 'vfs>(
203 pub &'a T,
204 marker::PhantomData<&'vfs Vfs>,
205);
206
207impl<'a, 'vfs, T, Vfs: vfs::WriteSupportingVfs<'vfs> + 'vfs> WriteTo<'vfs, Vfs>
208 for FmtWrapperRefWr<'a, 'vfs, T, Vfs>
209where
210 T: Display + ?Sized,
211 'vfs: 'a,
212{
213 fn write_to(&self, path: &Vfs::Path, vfs: Pin<&'vfs Vfs>) -> VfsResult<(), Vfs> {
214 FileString::new(self.0.to_string()).write_to(path, vfs)
215 }
216}
217
218#[cfg(feature = "async")]
219#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
220impl<'a, 'vfs, T, Vfs: WriteSupportingVfsAsync + 'static> WriteToAsync<'a, Vfs>
221 for FmtWrapperRefWr<'a, 'vfs, T, Vfs>
222where
223 T: Display + Send + 'a,
224 'vfs: 'a,
225{
226 type Future = <FileString as WriteToAsync<'a, Vfs>>::Future;
227
228 fn write_to_async(
229 self,
230 path: <<Vfs as VfsCore>::Path as PathType>::OwnedPath,
231 vfs: Pin<&'a Vfs>,
232 ) -> Self::Future {
233 let s = self.0.to_string();
234 FileString::new(s).write_to_async(path, vfs)
235 }
236}