versatiles_core/utils/io/data_writer_file.rs
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
//! This module provides functionality for writing data to files.
//!
//! # Overview
//!
//! The `DataWriterFile` struct allows for writing data to files on the filesystem.
//! It implements the `DataWriterTrait` to provide methods for appending data, writing data from the start,
//! and managing the write position. The module ensures the file path is absolute before attempting to create or write to the file.
//!
//! # Examples
//!
//! ```rust
//! use versatiles::{utils::io::{DataWriterFile, DataWriterTrait}, types::{Blob, ByteRange}};
//! use anyhow::Result;
//! use std::path::Path;
//!
//! #[tokio::main]
//! async fn main() -> Result<()> {
//! let path = std::env::current_dir()?.join("../testdata/temp.txt");
//! let mut writer = DataWriterFile::from_path(&path)?;
//! let data = Blob::from(vec![1, 2, 3, 4]);
//!
//! // Appending data
//! writer.append(&data)?;
//! assert_eq!(writer.get_position()?, 4);
//!
//! // Writing data from the start
//! writer.write_start(&Blob::from(vec![5, 6, 7, 8]))?;
//! writer.set_position(0)?;
//! assert_eq!(writer.get_position()?, 0);
//!
//! Ok(())
//! }
//! ```
use super::DataWriterTrait;
use crate::types::{Blob, ByteRange};
use anyhow::{ensure, Result};
use async_trait::async_trait;
use std::{
fs::File,
io::{BufWriter, Seek, SeekFrom, Write},
path::Path,
};
/// A struct that provides writing capabilities to a file.
pub struct DataWriterFile {
writer: BufWriter<File>,
}
impl DataWriterFile {
/// Creates a `DataWriterFile` from a file path.
///
/// # Arguments
///
/// * `path` - A reference to the file path to create and write to.
///
/// # Returns
///
/// * A Result containing the new `DataWriterFile` instance or an error.
pub fn from_path(path: &Path) -> Result<DataWriterFile> {
ensure!(path.is_absolute(), "path {path:?} must be absolute");
Ok(DataWriterFile {
writer: BufWriter::new(File::create(path)?),
})
}
}
#[async_trait]
impl DataWriterTrait for DataWriterFile {
/// Appends data to the file.
///
/// # Arguments
///
/// * `blob` - A reference to the `Blob` to append.
///
/// # Returns
///
/// * A Result containing a `ByteRange` indicating the position and length of the appended data, or an error.
fn append(&mut self, blob: &Blob) -> Result<ByteRange> {
let pos = self.writer.stream_position()?;
let len = self.writer.write(blob.as_slice())?;
Ok(ByteRange::new(pos, len as u64))
}
/// Writes data from the start of the file.
///
/// # Arguments
///
/// * `blob` - A reference to the `Blob` to write.
///
/// # Returns
///
/// * A Result indicating success or an error.
fn write_start(&mut self, blob: &Blob) -> Result<()> {
let pos = self.writer.stream_position()?;
self.writer.rewind()?;
self.writer.write_all(blob.as_slice())?;
self.writer.seek(SeekFrom::Start(pos))?;
Ok(())
}
/// Gets the current write position.
///
/// # Returns
///
/// * A Result containing the current write position in bytes or an error.
fn get_position(&mut self) -> Result<u64> {
Ok(self.writer.stream_position()?)
}
/// Sets the write position.
///
/// # Arguments
///
/// * `position` - The position to set in bytes.
///
/// # Returns
///
/// * A Result indicating success or an error.
fn set_position(&mut self, position: u64) -> Result<()> {
self.writer.seek(SeekFrom::Start(position))?;
Ok(())
}
}