cobble_core/minecraft/log_files/
log_file.rs1use crate::error::CobbleResult;
2use async_zip::read::seek::ZipFileReader;
3use std::path::{Path, PathBuf};
4use time::OffsetDateTime;
5use tokio::fs::{remove_file, File};
6
7#[cfg_attr(doc_cfg, doc(cfg(feature = "log-files")))]
10#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
11#[derive(Clone, Debug)]
12pub struct LogFile {
13 pub name: String,
15 pub path: PathBuf,
17 pub _type: LogFileType,
19 #[cfg_attr(feature = "serde", serde(with = "time::serde::rfc3339::option"))]
21 pub modified: Option<OffsetDateTime>,
22}
23
24impl LogFile {
25 #[instrument(
29 name = "remove_log_file",
30 level = "trace",
31 skip_all,
32 fields(
33 path = %self.path.to_string_lossy(),
34 )
35 )]
36 pub async fn remove(self) -> CobbleResult<()> {
37 remove_file(&self.path).await?;
38 Ok(())
39 }
40
41 #[instrument(
44 name = "extract_log_file",
45 level = "trace",
46 skip_all,
47 fields(
48 source = %self.path.to_string_lossy(),
49 target = %target.as_ref().to_string_lossy(),
50 )
51 )]
52 pub async fn unpack(&self, target: impl AsRef<Path> + Send) -> CobbleResult<()> {
53 match self._type {
54 LogFileType::Plain => {
55 trace!("Copying file to target location");
56 tokio::fs::copy(&self.path, target).await?;
57 }
58 LogFileType::GzipCompressed => {
59 trace!("Extracting log file to target location");
60 let mut file = File::open(&self.path).await?;
61 let mut archive = ZipFileReader::new(&mut file).await?;
62
63 let entry_reader = archive.entry_reader(0).await?;
64
65 let mut out_file = File::create(target).await?;
66 entry_reader.copy_to_end_crc(&mut out_file, 64000).await?;
67 }
68 }
69
70 Ok(())
71 }
72}
73
74#[cfg_attr(doc_cfg, doc(cfg(feature = "log-files")))]
76#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
77#[derive(Clone, Copy, Debug)]
78pub enum LogFileType {
79 Plain,
81 GzipCompressed,
83}