Skip to content

Commit

Permalink
Add tar_x item spec crate skeleton.
Browse files Browse the repository at this point in the history
  • Loading branch information
azriel91 committed Nov 3, 2022
1 parent 632e347 commit 0f2950c
Show file tree
Hide file tree
Showing 15 changed files with 476 additions and 1 deletion.
7 changes: 6 additions & 1 deletion item_specs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,18 @@ test = false

[dependencies]
peace_item_spec_file_download = { path = "file_download", version = "0.0.3", optional = true }
peace_item_spec_tar_x = { path = "tar_x", version = "0.0.3", optional = true }

[dev-dependencies]
peace = { path = "..", version = "0.0.3" }

[features]
default = []
error_reporting = ["peace_item_spec_file_download?/error_reporting"]
error_reporting = [
"peace_item_spec_file_download?/error_reporting",
"peace_item_spec_tar_x?/error_reporting",
]

# Subcrates
file_download = ["dep:peace_item_spec_file_download"]
tar_x = ["dep:peace_item_spec_tar_x"]
2 changes: 2 additions & 0 deletions item_specs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@
// Re-exports
#[cfg(feature = "file_download")]
pub use peace_item_spec_file_download as file_download;
#[cfg(feature = "tar_x")]
pub use peace_item_spec_tar_x as tar_x;
43 changes: 43 additions & 0 deletions item_specs/tar_x/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[package]
name = "peace_item_spec_tar_x"
version = "0.0.3"
authors = ["Azriel Hoh <azriel91@gmail.com>"]
edition = "2021"
description = "Manages extracting a tar file for the peace framework"
repository = "https://github.com/azriel91/peace"
documentation = "https://docs.rs/peace_item_spec_tar_x/"
readme = "../../README.md"
categories = ["asynchronous", "config"]
keywords = ["automation"]
license = "MIT OR Apache-2.0"

[lib]
doctest = false
test = false

[dependencies]
# futures = "0.3.25"
miette = { workspace = true, optional = true }
peace = { path = "../..", version = "0.0.3" }
serde = { version = "1.0.147", features = ["derive"] }
# We use this instead of tokio-tar, because:
#
# * We expect tar extraction to be a compute operation.
# * tokio-tar is not actively maintained / released.
# * tokio-tar depends on tokio's "io" feature, which does not support WASM.
#
# Asynchronous IO can be handled using [SyncIoBridge].
#
# [SyncIoBridge]: https://docs.rs/tokio-util/latest/tokio_util/io/struct.SyncIoBridge.html
tar = "0.4.38"
thiserror = "1.0.37"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1.21.2", features = ["net", "time", "rt"] }

[target.'cfg(target_arch = "wasm32")'.dependencies]
tokio = { version = "1.21.2" }

[features]
default = []
error_reporting = ["peace/error_reporting"]
22 changes: 22 additions & 0 deletions item_specs/tar_x/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//! Manages extracting a tar file for the peace framework
pub use crate::{
tar_x_clean_op_spec::TarXCleanOpSpec, tar_x_data::TarXData,
tar_x_ensure_op_spec::TarXEnsureOpSpec, tar_x_error::TarXError, tar_x_item_spec::TarXItemSpec,
tar_x_params::TarXParams, tar_x_state::TarXState,
tar_x_state_current_fn_spec::TarXStateCurrentFnSpec,
tar_x_state_desired_fn_spec::TarXStateDesiredFnSpec, tar_x_state_diff::TarXStateDiff,
tar_x_state_diff_fn_spec::TarXStateDiffFnSpec,
};

mod tar_x_clean_op_spec;
mod tar_x_data;
mod tar_x_ensure_op_spec;
mod tar_x_error;
mod tar_x_item_spec;
mod tar_x_params;
mod tar_x_state;
mod tar_x_state_current_fn_spec;
mod tar_x_state_desired_fn_spec;
mod tar_x_state_diff;
mod tar_x_state_diff_fn_spec;
57 changes: 57 additions & 0 deletions item_specs/tar_x/src/tar_x_clean_op_spec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::marker::PhantomData;

#[nougat::gat(Data)]
use peace::cfg::CleanOpSpec;
use peace::cfg::{async_trait, nougat, state::Nothing, OpCheckStatus, State};

use crate::{TarXData, TarXError, TarXState};

/// `CleanOpSpec` for the tar to extract.
#[derive(Debug, Default)]
pub struct TarXCleanOpSpec<Id>(PhantomData<Id>);

#[async_trait(?Send)]
#[nougat::gat]
impl<Id> CleanOpSpec for TarXCleanOpSpec<Id>
where
Id: Send + Sync + 'static,
{
type Data<'op> = TarXData<'op, Id>
where Self: 'op;
type Error = TarXError;
type StateLogical = TarXState;
type StatePhysical = Nothing;

async fn check(
_tar_x_data: TarXData<'_, Id>,
_state: &State<TarXState, Nothing>,
) -> Result<OpCheckStatus, TarXError> {
todo!()
}

async fn exec_dry(
_tar_x_data: TarXData<'_, Id>,
_state: &State<TarXState, Nothing>,
) -> Result<(), TarXError> {
Ok(())
}

#[cfg(not(target_arch = "wasm32"))]
async fn exec(
_tar_x_data: TarXData<'_, Id>,
_state: &State<TarXState, Nothing>,
) -> Result<(), TarXError> {
todo!()
}

#[cfg(target_arch = "wasm32")]
async fn exec(
tar_x_data: TarXData<'_, Id>,
State {
logical: file_state,
..
}: &State<TarXState, Nothing>,
) -> Result<(), TarXError> {
todo!()
}
}
54 changes: 54 additions & 0 deletions item_specs/tar_x/src/tar_x_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#[cfg(target_arch = "wasm32")]
use peace::rt_model::Storage;

use peace::data::{Data, R};

use crate::TarXParams;

/// Data used to extract a tar file.
///
/// # Type Parameters
///
/// * `Id`: A zero-sized type used to distinguish different tar extraction
/// parameters from each other.
#[derive(Data, Debug)]
pub struct TarXData<'op, Id>
where
Id: Send + Sync + 'static,
{
/// Url of the tar to extract.
tar_x_params: R<'op, TarXParams<Id>>,

/// For wasm, we write to web storage through the `Storage` object.
///
/// Presumably we should be able to use this for `NativeStorage` as well.
#[cfg(target_arch = "wasm32")]
storage: R<'op, Storage>,
}

impl<'op, Id> TarXData<'op, Id>
where
Id: Send + Sync + 'static,
{
#[cfg(not(target_arch = "wasm32"))]
pub fn new(tar_x_params: R<'op, TarXParams<Id>>) -> Self {
Self { tar_x_params }
}

#[cfg(target_arch = "wasm32")]
pub fn new(tar_x_params: R<'op, TarXParams<Id>>, storage: R<'op, Storage>) -> Self {
Self {
tar_x_params,
storage,
}
}

pub fn tar_x_params(&self) -> &TarXParams<Id> {
&self.tar_x_params
}

#[cfg(target_arch = "wasm32")]
pub fn storage(&self) -> &Storage {
&*self.storage
}
}
54 changes: 54 additions & 0 deletions item_specs/tar_x/src/tar_x_ensure_op_spec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::marker::PhantomData;

use peace::cfg::state::Nothing;

#[nougat::gat(Data)]
use peace::cfg::EnsureOpSpec;
use peace::cfg::{async_trait, nougat, OpCheckStatus, State};

use crate::{TarXData, TarXError, TarXState, TarXStateDiff};

/// Ensure OpSpec for the tar to extract.
#[derive(Debug)]
pub struct TarXEnsureOpSpec<Id>(PhantomData<Id>);

#[async_trait(?Send)]
#[nougat::gat]
impl<Id> EnsureOpSpec for TarXEnsureOpSpec<Id>
where
Id: Send + Sync + 'static,
{
type Data<'op> = TarXData<'op, Id>
where Self: 'op;
type Error = TarXError;
type StateDiff = TarXStateDiff;
type StateLogical = TarXState;
type StatePhysical = Nothing;

async fn check(
_tar_x_data: TarXData<'_, Id>,
_file_state_current: &State<TarXState, Nothing>,
_file_state_desired: &TarXState,
_diff: &TarXStateDiff,
) -> Result<OpCheckStatus, TarXError> {
todo!();
}

async fn exec_dry(
_tar_x_data: TarXData<'_, Id>,
_state: &State<TarXState, Nothing>,
_file_state_desired: &TarXState,
_diff: &TarXStateDiff,
) -> Result<Nothing, TarXError> {
Ok(Nothing)
}

async fn exec(
_tar_x_data: TarXData<'_, Id>,
_state: &State<TarXState, Nothing>,
_file_state_desired: &TarXState,
_diff: &TarXStateDiff,
) -> Result<Nothing, TarXError> {
todo!();
}
}
17 changes: 17 additions & 0 deletions item_specs/tar_x/src/tar_x_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#[cfg(feature = "error_reporting")]
use peace::miette;

/// Error while managing tar extraction.
#[cfg_attr(feature = "error_reporting", derive(peace::miette::Diagnostic))]
#[derive(Debug, thiserror::Error)]
pub enum TarXError {
// === Framework errors === //
/// A `peace` runtime error occurred.
#[error("A `peace` runtime error occurred.")]
PeaceRtError(
#[cfg_attr(feature = "error_reporting", diagnostic_source)]
#[source]
#[from]
peace::rt_model::Error,
),
}
62 changes: 62 additions & 0 deletions item_specs/tar_x/src/tar_x_item_spec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use std::marker::PhantomData;

use peace::{
cfg::{async_trait, state::Nothing, ItemSpec, ItemSpecId},
resources::{resources::ts::Empty, Resources},
};

use crate::{
TarXCleanOpSpec, TarXEnsureOpSpec, TarXError, TarXState, TarXStateCurrentFnSpec,
TarXStateDesiredFnSpec, TarXStateDiff, TarXStateDiffFnSpec,
};

/// Item spec for extracting a tar file.
///
/// The `Id` type parameter is needed for each tar extraction params to be a
/// distinct type.
///
/// # Type Parameters
///
/// * `Id`: A zero-sized type used to distinguish different tar extraction
/// parameters from each other.
#[derive(Debug)]
pub struct TarXItemSpec<Id> {
/// ID of the item spec to extract the tar.
item_spec_id: ItemSpecId,
/// Marker for unique tar extraction parameters type.
marker: PhantomData<Id>,
}

impl<Id> TarXItemSpec<Id> {
/// Returns a new `TarXItemSpec`.
pub fn new(item_spec_id: ItemSpecId) -> Self {
Self {
item_spec_id,
marker: PhantomData,
}
}
}

#[async_trait(?Send)]
impl<Id> ItemSpec for TarXItemSpec<Id>
where
Id: Send + Sync + 'static,
{
type CleanOpSpec = TarXCleanOpSpec<Id>;
type EnsureOpSpec = TarXEnsureOpSpec<Id>;
type Error = TarXError;
type StateCurrentFnSpec = TarXStateCurrentFnSpec<Id>;
type StateDesiredFnSpec = TarXStateDesiredFnSpec<Id>;
type StateDiff = TarXStateDiff;
type StateDiffFnSpec = TarXStateDiffFnSpec;
type StateLogical = TarXState;
type StatePhysical = Nothing;

fn id(&self) -> ItemSpecId {
self.item_spec_id.clone()
}

async fn setup(&self, _resources: &mut Resources<Empty>) -> Result<(), TarXError> {
Ok(())
}
}
51 changes: 51 additions & 0 deletions item_specs/tar_x/src/tar_x_params.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use std::{
fmt,
marker::PhantomData,
path::{Path, PathBuf},
};

use serde::{Deserialize, Serialize};

// TODO: params for:
//
// * keep or remove unknown files
// * force re-extraction
/// Tar extraction parameters.
///
/// The `Id` type parameter is needed for each tar extraction params to be a
/// distinct type.
///
/// # Type Parameters
///
/// * `Id`: A zero-sized type used to distinguish different tar extraction
/// parameters from each other.
#[derive(Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct TarXParams<Id> {
/// Path of the file to extract.
dest: PathBuf,
/// Marker for unique tar extraction parameters type.
marker: PhantomData<Id>,
}

impl<Id> TarXParams<Id> {
/// Returns new `TarXParams`.
pub fn new(dest: PathBuf) -> Self {
Self {
dest,
marker: PhantomData,
}
}

/// Returns the file path to write to.
pub fn dest(&self) -> &Path {
&self.dest
}
}

impl<Id> fmt::Debug for TarXParams<Id> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TarXParams")
.field("dest", &self.dest)
.finish()
}
}
Loading

0 comments on commit 0f2950c

Please sign in to comment.