use std::{collections::HashMap, path::Path}; use async_trait::async_trait; use droplet_rs::manifest::{Manifest, ManifestWriterFactory, generate_manifest_rusty}; use indicatif::{ProgressBar, ProgressStyle}; use log::info; use serde::{Deserialize, Serialize}; use tokio::io::AsyncWrite; #[derive(Serialize, Deserialize)] pub struct DepotManifest { content: HashMap, } #[derive(Serialize, Deserialize)] struct DepotManifestGameData { version_id: String, compression: CompressionOption, } #[derive(Serialize, Deserialize)] pub enum CompressionOption { None, Gzip, Zstd, } impl DepotManifest { pub fn new() -> Self { Self { content: HashMap::new(), } } pub fn append(&mut self, game_id: String, version_id: String, compression: CompressionOption) { self.content.insert( game_id, DepotManifestGameData { version_id, compression, }, ); } } pub struct ClosureFactory where Writer: AsyncWrite + Unpin, Factory: AsyncFn(String) -> Writer, Closer: AsyncFn(Writer), { writer: Factory, closer: Closer, } #[async_trait] impl< W: AsyncWrite + Unpin + Send + Sync, F: AsyncFn(String) -> W + Send + Sync + 'static, C: AsyncFn(W) + Send + Sync, > ManifestWriterFactory for ClosureFactory where for<'a> F::CallRefFuture<'a>: Send, for<'b> C::CallRefFuture<'b>: Send, { type Writer = W; async fn create(&self, id: String) -> anyhow::Result { let func = &self.writer; let output = func(id).await; Ok(output) } async fn close(&self, writer: Self::Writer) -> anyhow::Result<()> { let func = &self.closer; func(writer).await; Ok(()) } } impl< W: AsyncWrite + Unpin + Send + Sync, F: AsyncFn(String) -> W + Send + Sync + 'static, C: AsyncFn(W) + Sync, > ClosureFactory where for<'a> F::CallRefFuture<'a>: Send, for<'b> C::CallRefFuture<'b>: Send, { pub fn new(f: F, c: C) -> Self { Self { writer: f, closer: c, } } } pub async fn generate_v2_manifest(dir: &Path, factory: Factory) -> anyhow::Result where Factory: ManifestWriterFactory, { let progress_bar = ProgressBar::new(10_000).with_style( ProgressStyle::default_bar() .template("[{elapsed_precise}] [ETA {eta}] {bar} {percent_precise}%") .unwrap(), ); generate_manifest_rusty( dir, |progress| { let progress_int = (progress * 100f32).round() as u64; progress_bar.set_position(progress_int); }, |log| progress_bar.suspend(|| info!("{}", log)), Some(&factory), None, ) .await }