use burn_core::store::{ModuleRecord, RecordError};
use burn_optim::OptimizerRecord;
use burn_optim::lr_scheduler::LrSchedulerRecord;
use burn_std::Bytes;
use std::path::PathBuf;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum CheckpointerError {
#[error("I/O Error: `{0}`")]
IOError(std::io::Error),
#[error("Record error: `{0}`")]
Record(RecordError),
#[error("Unknown error: `{0}`")]
Unknown(String),
}
pub trait Checkpoint: Sized + Send + 'static {
fn save(self, path: PathBuf) -> Result<(), CheckpointerError>;
fn load(path: PathBuf) -> Result<Self, CheckpointerError>;
fn checkpoint_from_bytes(bytes: Bytes) -> Result<Self, RecordError>;
fn checkpoint_into_bytes(self) -> Result<Bytes, RecordError>;
}
impl Checkpoint for () {
fn save(self, _path: PathBuf) -> Result<(), CheckpointerError> {
Ok(())
}
fn load(_path: PathBuf) -> Result<Self, CheckpointerError> {
Ok(())
}
fn checkpoint_from_bytes(_bytes: Bytes) -> Result<Self, RecordError> {
Ok(())
}
fn checkpoint_into_bytes(self) -> Result<Bytes, RecordError> {
Ok(Bytes::from_bytes_vec(vec![0]))
}
}
impl Checkpoint for ModuleRecord {
fn save(self, path: PathBuf) -> Result<(), CheckpointerError> {
ModuleRecord::save(self, path).map_err(CheckpointerError::Record)
}
fn load(path: PathBuf) -> Result<Self, CheckpointerError> {
ModuleRecord::load(path).map_err(CheckpointerError::Record)
}
fn checkpoint_into_bytes(self) -> Result<Bytes, RecordError> {
self.into_bytes()
}
fn checkpoint_from_bytes(bytes: Bytes) -> Result<Self, RecordError> {
ModuleRecord::from_bytes(bytes)
}
}
impl Checkpoint for OptimizerRecord {
fn save(self, path: PathBuf) -> Result<(), CheckpointerError> {
OptimizerRecord::save(self, path).map_err(CheckpointerError::Record)
}
fn load(path: PathBuf) -> Result<Self, CheckpointerError> {
OptimizerRecord::load(path).map_err(CheckpointerError::Record)
}
fn checkpoint_from_bytes(bytes: Bytes) -> Result<Self, RecordError> {
OptimizerRecord::from_bytes(bytes)
}
fn checkpoint_into_bytes(self) -> Result<Bytes, RecordError> {
self.into_bytes()
}
}
impl Checkpoint for LrSchedulerRecord {
fn save(self, path: PathBuf) -> Result<(), CheckpointerError> {
LrSchedulerRecord::save(self, path).map_err(CheckpointerError::Record)
}
fn load(path: PathBuf) -> Result<Self, CheckpointerError> {
LrSchedulerRecord::load(path).map_err(CheckpointerError::Record)
}
fn checkpoint_from_bytes(bytes: Bytes) -> Result<Self, RecordError> {
LrSchedulerRecord::from_bytes(bytes)
}
fn checkpoint_into_bytes(self) -> Result<Bytes, RecordError> {
self.into_bytes()
}
}
pub trait Checkpointer<R>: Send + Sync
where
R: Checkpoint,
{
fn save(&self, epoch: usize, record: R) -> Result<(), CheckpointerError>;
fn delete(&self, epoch: usize) -> Result<(), CheckpointerError>;
fn restore(&self, epoch: usize) -> Result<R, CheckpointerError>;
}