reth_era/common/
file_ops.rs1use crate::e2s::{error::E2sError, types::Version};
4use std::{
5 fs::File,
6 io::{Read, Seek, Write},
7 path::Path,
8};
9
10pub trait EraFileFormat: Sized {
12 type EraGroup;
14
15 type Id: EraFileId;
17
18 fn version(&self) -> &Version;
20
21 fn group(&self) -> &Self::EraGroup;
23
24 fn id(&self) -> &Self::Id;
26
27 fn new(group: Self::EraGroup, id: Self::Id) -> Self;
29}
30
31pub trait EraFileId: Clone {
33 fn to_file_name(&self) -> String;
35
36 fn network_name(&self) -> &str;
38
39 fn start_number(&self) -> u64;
41
42 fn count(&self) -> u32;
44}
45
46pub trait StreamReader<R: Read + Seek>: Sized {
48 type File: EraFileFormat;
50
51 type Iterator;
53
54 fn new(reader: R) -> Self;
56
57 fn read(self, network_name: String) -> Result<Self::File, E2sError>;
59
60 fn iter(self) -> Self::Iterator;
62}
63
64pub trait FileReader: StreamReader<File> {
66 fn open<P: AsRef<Path>>(
68 path: P,
69 network_name: impl Into<String>,
70 ) -> Result<Self::File, E2sError> {
71 let file = File::open(path).map_err(E2sError::Io)?;
72 let reader = Self::new(file);
73 reader.read(network_name.into())
74 }
75}
76
77pub trait StreamWriter<W: Write>: Sized {
79 type File: EraFileFormat;
81
82 fn new(writer: W) -> Self;
84
85 fn write_version(&mut self) -> Result<(), E2sError>;
87
88 fn write_file(&mut self, file: &Self::File) -> Result<(), E2sError>;
90
91 fn flush(&mut self) -> Result<(), E2sError>;
93}
94
95pub trait FileWriter {
97 type File: EraFileFormat<Id: EraFileId>;
99
100 fn create<P: AsRef<Path>>(path: P, file: &Self::File) -> Result<(), E2sError>;
102
103 fn create_with_id<P: AsRef<Path>>(directory: P, file: &Self::File) -> Result<(), E2sError>;
105}
106
107impl<T: StreamWriter<File>> FileWriter for T {
108 type File = T::File;
109
110 fn create<P: AsRef<Path>>(path: P, file: &Self::File) -> Result<(), E2sError> {
112 let file_handle = File::create(path).map_err(E2sError::Io)?;
113 let mut writer = Self::new(file_handle);
114 writer.write_file(file)?;
115 Ok(())
116 }
117
118 fn create_with_id<P: AsRef<Path>>(directory: P, file: &Self::File) -> Result<(), E2sError> {
120 let filename = file.id().to_file_name();
121 let path = directory.as_ref().join(filename);
122 Self::create(path, file)
123 }
124}
125
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
128pub enum EraFileType {
129 Era,
132 Era1,
135}
136
137impl EraFileType {
138 pub const fn extension(&self) -> &'static str {
140 match self {
141 Self::Era => ".era",
142 Self::Era1 => ".era1",
143 }
144 }
145
146 pub fn from_filename(filename: &str) -> Option<Self> {
148 if filename.ends_with(".era") {
149 Some(Self::Era)
150 } else if filename.ends_with(".era1") {
151 Some(Self::Era1)
152 } else {
153 None
154 }
155 }
156
157 pub fn from_url(url: &str) -> Self {
160 if url.contains("era1") {
161 Self::Era1
162 } else {
163 Self::Era
164 }
165 }
166}