Skip to main content

hypershell_tokio_components/providers/
file.rs

1use core::marker::PhantomData;
2use std::path::Path;
3
4use cgp::extra::handler::{Handler, HandlerComponent};
5use cgp::prelude::*;
6use hypershell_components::components::CanExtractCommandArg;
7use hypershell_components::dsl::{ReadFile, WriteFile};
8use tokio::fs::File;
9use tokio::io::AsyncRead;
10
11#[cgp_new_provider]
12impl<Context, PathArg> Handler<Context, ReadFile<PathArg>, ()> for HandleReadFile
13where
14    Context: CanExtractCommandArg<PathArg> + CanRaiseAsyncError<std::io::Error>,
15    PathArg: Send,
16    Context::CommandArg: Send + AsRef<Path>,
17{
18    type Output = File;
19
20    async fn handle(
21        context: &Context,
22        _tag: PhantomData<ReadFile<PathArg>>,
23        _input: (),
24    ) -> Result<File, Context::Error> {
25        let file_path = context.extract_command_arg(PhantomData);
26
27        let file = File::open(file_path.as_ref())
28            .await
29            .map_err(Context::raise_error)?;
30
31        Ok(file)
32    }
33}
34
35#[cgp_new_provider]
36impl<Context, PathArg, Input> Handler<Context, WriteFile<PathArg>, Input> for HandleWriteFile
37where
38    Context: CanExtractCommandArg<PathArg> + CanRaiseAsyncError<std::io::Error>,
39    PathArg: Send,
40    Context::CommandArg: Send + AsRef<Path>,
41    Input: Send + AsyncRead + Unpin,
42{
43    type Output = ();
44
45    async fn handle(
46        context: &Context,
47        _tag: PhantomData<WriteFile<PathArg>>,
48        mut input: Input,
49    ) -> Result<(), Context::Error> {
50        let file_path = context.extract_command_arg(PhantomData);
51
52        let mut file = File::create(file_path.as_ref())
53            .await
54            .map_err(Context::raise_error)?;
55
56        tokio::io::copy(&mut input, &mut file)
57            .await
58            .map_err(Context::raise_error)?;
59
60        Ok(())
61    }
62}