rust-integration-services 0.5.26

A modern, fast, and lightweight integration library written in Rust, designed for memory safety and stability.
Documentation
use std::{marker::PhantomData, path::{Path, PathBuf}};

use bytes::Bytes;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio_util::io::ReaderStream;

use crate::common::stream::ByteStream;

pub struct Empty;
pub struct Write;
pub struct Read;
pub struct Copy;
pub struct Move;

pub struct FileClient<State> {
    path: Option<PathBuf>,
    _state: PhantomData<State>,
}

impl FileClient<Empty> {
    pub fn new() -> Self {
        FileClient  {
            path: None,
            _state: PhantomData
        }
    }

    pub fn write_to(&self, path: impl Into<PathBuf>) -> FileClient<Write> {
        FileClient {
            path: Some(path.into()),
            _state: PhantomData
        }
    }

    pub fn read_from(&self, path: impl Into<PathBuf>) -> FileClient<Read> {
        FileClient {
            path: Some(path.into()),
            _state: PhantomData
        }
    }

    pub fn copy_from(&self, path: impl Into<PathBuf>) -> FileClient<Copy> {
        FileClient {
            path: Some(path.into()),
            _state: PhantomData
        }
    }

    pub fn move_from(&self, path: impl Into<PathBuf>) -> FileClient<Move> {
        FileClient {
            path: Some(path.into()),
            _state: PhantomData
        }
    }

    pub async fn delete(&self, path: impl AsRef<Path>) -> anyhow::Result<()> {
        tokio::fs::remove_file(path.as_ref()).await?;

        Ok(())
    }
}

impl FileClient<Write> {
    pub async fn from_bytes(&self, bytes: impl Into<Bytes>) -> anyhow::Result<()> {
        let mut file = tokio::fs::File::create(&self.path.as_ref().unwrap()).await?;
        file.write_all(&bytes.into()).await?;
        file.flush().await?;

        Ok(())
    }

    pub async fn from_stream(&self, mut stream: ByteStream) -> anyhow::Result<()> {
        let mut file = tokio::fs::File::create(&self.path.as_ref().unwrap()).await?;

        while let Some(chunk) = stream.next().await {
            let chunk = chunk?;
            file.write_all(&chunk).await?;
        }

        file.flush().await?;
        Ok(())
    }
}

impl FileClient<Read> {
    pub async fn as_bytes(&self) -> anyhow::Result<Bytes> {
        let mut file = tokio::fs::File::open(&self.path.as_ref().unwrap()).await?;
        let mut buffer = Vec::new();
        file.read_to_end(&mut buffer).await?;

        Ok(Bytes::from(buffer))
    }

    pub async fn as_stream(&self) -> anyhow::Result<ByteStream> {
        let file = tokio::fs::File::open(&self.path.as_ref().unwrap()).await?;
        let reader = ReaderStream::new(file);

        Ok(ByteStream::new(reader))
    }
}

impl FileClient<Copy> {
    pub async fn copy_to(&self, path: impl AsRef<Path>) -> anyhow::Result<()> {
        tokio::fs::copy(&self.path.as_ref().unwrap(), path.as_ref()).await?;

        Ok(())
    }
}

impl FileClient<Move> {
    pub async fn move_to(&self, path: impl AsRef<Path>) -> anyhow::Result<()> {
        tokio::fs::copy(&self.path.as_ref().unwrap(), path.as_ref()).await?;
        tokio::fs::remove_file(&self.path.as_ref().unwrap()).await?;

        Ok(())
    }
}