reth_era/
era_file_ops.rs

1//! Represents reading and writing operations' era file
2
3use crate::{e2s_types::Version, E2sError};
4use std::{
5    fs::File,
6    io::{Read, Seek, Write},
7    path::Path,
8};
9
10/// Represents era file with generic content and identifier types
11pub trait EraFileFormat: Sized {
12    /// Content group type
13    type EraGroup;
14
15    /// The identifier type
16    type Id: EraFileId;
17
18    /// Get the version
19    fn version(&self) -> &Version;
20
21    /// Get the content group
22    fn group(&self) -> &Self::EraGroup;
23
24    /// Get the file identifier
25    fn id(&self) -> &Self::Id;
26
27    /// Create a new instance
28    fn new(group: Self::EraGroup, id: Self::Id) -> Self;
29}
30
31/// Era file identifiers
32pub trait EraFileId: Clone {
33    /// Convert to standardized file name
34    fn to_file_name(&self) -> String;
35
36    /// Get the network name
37    fn network_name(&self) -> &str;
38
39    /// Get the starting number (block or slot)
40    fn start_number(&self) -> u64;
41
42    /// Get the count of items
43    fn count(&self) -> u32;
44}
45
46/// [`StreamReader`] for reading era-format files
47pub trait StreamReader<R: Read + Seek>: Sized {
48    /// The file type the reader produces
49    type File: EraFileFormat;
50
51    /// The iterator type for streaming data
52    type Iterator;
53
54    /// Create a new reader
55    fn new(reader: R) -> Self;
56
57    /// Read and parse the complete file
58    fn read(self, network_name: String) -> Result<Self::File, E2sError>;
59
60    /// Get an iterator for streaming processing
61    fn iter(self) -> Self::Iterator;
62}
63
64/// [`FileReader`] provides reading era file operations for era files
65pub trait FileReader: StreamReader<File> {
66    /// Opens and reads an era file from the given path
67    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
77/// [`StreamWriter`] for writing era-format files
78pub trait StreamWriter<W: Write>: Sized {
79    /// The file type this writer handles
80    type File: EraFileFormat;
81
82    /// Create a new writer
83    fn new(writer: W) -> Self;
84
85    /// Writer version
86    fn write_version(&mut self) -> Result<(), E2sError>;
87
88    /// Write a complete era file
89    fn write_file(&mut self, file: &Self::File) -> Result<(), E2sError>;
90
91    /// Flush any buffered data
92    fn flush(&mut self) -> Result<(), E2sError>;
93}
94
95/// [`StreamWriter`] provides writing file operations for era files
96pub trait FileWriter {
97    /// Era file type the writer handles
98    type File: EraFileFormat<Id: EraFileId>;
99
100    /// Creates a new file at the specified path and writes the era file to it
101    fn create<P: AsRef<Path>>(path: P, file: &Self::File) -> Result<(), E2sError>;
102
103    /// Creates a file in the directory using standardized era naming
104    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    /// Creates a new file at the specified path and writes the era file to it
111    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    /// Creates a file in the directory using standardized era naming
119    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}