Skip to content

Commit

Permalink
persistence: add API to name stored data
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Jul 6, 2024
1 parent c837cdb commit f00e860
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 132 deletions.
109 changes: 8 additions & 101 deletions src/persistence/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,110 +19,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::path::Path;
use std::path::{Path, PathBuf};

use amplify::confinement::U32;
use strict_encoding::{DeserializeError, SerializeError, StrictDeserialize, StrictSerialize};
use strict_encoding::{DeserializeError, SerializeError};

use crate::persistence::{
IndexProvider, MemIndex, MemStash, MemState, StashProvider, StateProvider, Stock,
};
pub trait FsStored: Sized {
fn new(path: impl ToOwned<Owned = PathBuf>) -> Self;
fn load(path: impl ToOwned<Owned = PathBuf>) -> Result<Self, DeserializeError>;

pub trait LoadFs: Sized {
fn load(path: impl AsRef<Path>) -> Result<Self, DeserializeError>;
}
fn is_dirty(&self) -> bool;
fn filename(&self) -> &Path;
fn set_filename(&mut self, filename: impl ToOwned<Owned = PathBuf>) -> PathBuf;

pub trait StoreFs {
fn store(&self) -> Result<(), SerializeError>;
}

impl<S: StashProvider, H: StateProvider, I: IndexProvider> LoadFs for Stock<S, H, I>
where
S: LoadFs,
H: LoadFs,
I: LoadFs,
{
fn load(path: impl AsRef<Path>) -> Result<Self, DeserializeError> {
let path = path.as_ref();
let stash = S::load(path)?;
let state = H::load(path)?;
let index = I::load(path)?;

Ok(Stock::with(stash, state, index))
}
}

impl<S: StashProvider, H: StateProvider, I: IndexProvider> StoreFs for Stock<S, H, I>
where
S: StoreFs,
H: StoreFs,
I: StoreFs,
{
fn store(&self) -> Result<(), SerializeError> {
self.as_stash_provider().store()?;
self.as_state_provider().store()?;
self.as_index_provider().store()?;

Ok(())
}
}

impl LoadFs for MemStash {
fn load(path: impl AsRef<Path>) -> Result<Self, DeserializeError> {
let mut file = path.as_ref().to_owned();
file.push("stash.dat");
let mut me = Self::strict_deserialize_from_file::<U32>(&file)?;
me.set_filename(file);
Ok(me)
}
}

impl StoreFs for MemStash {
fn store(&self) -> Result<(), SerializeError> {
if self.is_dirty() {
self.strict_serialize_to_file::<U32>(&self.filename())
} else {
Ok(())
}
}
}

impl LoadFs for MemState {
fn load(path: impl AsRef<Path>) -> Result<Self, DeserializeError> {
let mut file = path.as_ref().to_owned();
file.push("state.dat");
let mut me = Self::strict_deserialize_from_file::<U32>(&file)?;
me.set_filename(file);
Ok(me)
}
}

impl StoreFs for MemState {
fn store(&self) -> Result<(), SerializeError> {
if self.is_dirty() {
self.strict_serialize_to_file::<U32>(&self.filename())
} else {
Ok(())
}
}
}

impl LoadFs for MemIndex {
fn load(path: impl AsRef<Path>) -> Result<Self, DeserializeError> {
let mut file = path.as_ref().to_owned();
file.push("index.dat");
let mut me = Self::strict_deserialize_from_file::<U32>(&file)?;
me.set_filename(file);
Ok(me)
}
}

impl StoreFs for MemIndex {
fn store(&self) -> Result<(), SerializeError> {
if self.is_dirty() {
self.strict_serialize_to_file::<U32>(&self.filename())
} else {
Ok(())
}
}
}
3 changes: 3 additions & 0 deletions src/persistence/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ impl<P: IndexProvider> Index<P> {
#[doc(hidden)]
pub fn as_provider(&self) -> &P { &self.provider }

#[doc(hidden)]
pub(super) fn as_provider_mut(&mut self) -> &mut P { &mut self.provider }

pub(super) fn index_consignment<const TRANSFER: bool>(
&mut self,
consignment: &Consignment<TRANSFER>,
Expand Down
151 changes: 120 additions & 31 deletions src/persistence/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use std::collections::BTreeSet;
use std::convert::Infallible;
#[cfg(feature = "fs")]
use std::path::{Path, PathBuf};
use std::path::PathBuf;

use aluvm::library::{Lib, LibId};
use amplify::confinement::{
Expand Down Expand Up @@ -86,16 +86,6 @@ pub struct MemStash {
impl StrictSerialize for MemStash {}
impl StrictDeserialize for MemStash {}

impl MemStash {
pub fn new() -> Self { MemStash::default() }

pub(crate) fn is_dirty(&self) -> bool { self.dirty }
#[cfg(feature = "fs")]
pub(crate) fn filename(&self) -> &Path { &self.filename }
#[cfg(feature = "fs")]
pub(crate) fn set_filename(&mut self, filename: PathBuf) { self.filename = filename }
}

impl StoreTransaction for MemStash {
type TransactionErr = confinement::Error;

Expand Down Expand Up @@ -446,16 +436,6 @@ pub struct MemState {
impl StrictSerialize for MemState {}
impl StrictDeserialize for MemState {}

impl MemState {
pub fn new() -> Self { MemState::default() }

pub(crate) fn is_dirty(&self) -> bool { self.dirty }
#[cfg(feature = "fs")]
pub(crate) fn filename(&self) -> &Path { &self.filename }
#[cfg(feature = "fs")]
pub(crate) fn set_filename(&mut self, filename: PathBuf) { self.filename = filename }
}

impl StoreTransaction for MemState {
type TransactionErr = confinement::Error;

Expand Down Expand Up @@ -560,16 +540,6 @@ pub struct MemIndex {
impl StrictSerialize for MemIndex {}
impl StrictDeserialize for MemIndex {}

impl MemIndex {
pub fn new() -> Self { MemIndex::default() }

pub(crate) fn is_dirty(&self) -> bool { self.dirty }
#[cfg(feature = "fs")]
pub(crate) fn filename(&self) -> &Path { &self.filename }
#[cfg(feature = "fs")]
pub(crate) fn set_filename(&mut self, filename: PathBuf) { self.filename = filename }
}

impl StoreTransaction for MemIndex {
type TransactionErr = confinement::Error;

Expand Down Expand Up @@ -830,3 +800,122 @@ impl IndexWriteProvider for MemIndex {
Ok(())
}
}

#[cfg(feature = "fs")]
mod fs {
use std::path::{Path, PathBuf};

use amplify::confinement::U32;
use strict_encoding::{DeserializeError, SerializeError, StrictDeserialize, StrictSerialize};

use crate::persistence::fs::FsStored;
use crate::persistence::{MemIndex, MemStash, MemState};

impl FsStored for MemStash {
fn new(filename: impl ToOwned<Owned = PathBuf>) -> Self {
Self {
dirty: true,
filename: filename.to_owned(),
..default!()
}
}

fn load(path: impl ToOwned<Owned = PathBuf>) -> Result<Self, DeserializeError> {
let path = path.to_owned();
let mut me = Self::strict_deserialize_from_file::<U32>(&path)?;
me.set_filename(path);
Ok(me)
}

fn is_dirty(&self) -> bool { self.dirty }

fn filename(&self) -> &Path { &self.filename }

fn set_filename(&mut self, filename: impl ToOwned<Owned = PathBuf>) -> PathBuf {
let prev = self.filename.to_owned();
self.filename = filename.to_owned();
self.dirty = self.filename != prev;
prev
}

fn store(&self) -> Result<(), SerializeError> {
if self.is_dirty() {
self.strict_serialize_to_file::<U32>(&self.filename())
} else {
Ok(())
}
}
}

impl FsStored for MemState {
fn new(filename: impl ToOwned<Owned = PathBuf>) -> Self {
Self {
dirty: true,
filename: filename.to_owned(),
..default!()
}
}

fn load(path: impl ToOwned<Owned = PathBuf>) -> Result<Self, DeserializeError> {
let path = path.to_owned();
let mut me = Self::strict_deserialize_from_file::<U32>(&path)?;
me.set_filename(path);
Ok(me)
}

fn is_dirty(&self) -> bool { self.dirty }

fn filename(&self) -> &Path { &self.filename }

fn set_filename(&mut self, filename: impl ToOwned<Owned = PathBuf>) -> PathBuf {
let prev = self.filename.to_owned();
self.filename = filename.to_owned();
self.dirty = self.filename != prev;
prev
}

fn store(&self) -> Result<(), SerializeError> {
if self.is_dirty() {
self.strict_serialize_to_file::<U32>(&self.filename())
} else {
Ok(())
}
}
}

impl FsStored for MemIndex {
fn new(filename: impl ToOwned<Owned = PathBuf>) -> Self {
Self {
dirty: true,
filename: filename.to_owned(),
..default!()
}
}

fn load(path: impl ToOwned<Owned = PathBuf>) -> Result<Self, DeserializeError> {
let path = path.to_owned();
let mut me = Self::strict_deserialize_from_file::<U32>(&path)?;
me.set_filename(path);
Ok(me)
}

fn is_dirty(&self) -> bool { self.dirty }

fn filename(&self) -> &Path { &self.filename }

fn set_filename(&mut self, filename: impl ToOwned<Owned = PathBuf>) -> PathBuf {
let prev = self.filename.to_owned();
self.filename = filename.to_owned();
self.dirty = self.filename != prev;
prev
}

fn store(&self) -> Result<(), SerializeError> {
if self.is_dirty() {
self.strict_serialize_to_file::<U32>(&self.filename())
} else {
Ok(())
}
}
}
}
3 changes: 3 additions & 0 deletions src/persistence/stash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ impl<P: StashProvider> Stash<P> {
#[doc(hidden)]
pub fn as_provider(&self) -> &P { &self.provider }

#[doc(hidden)]
pub(super) fn as_provider_mut(&mut self) -> &mut P { &mut self.provider }

pub(super) fn ifaces(&self) -> Result<impl Iterator<Item = &Iface> + '_, StashError<P>> {
self.provider.ifaces().map_err(StashError::ReadProvider)
}
Expand Down
Loading

0 comments on commit f00e860

Please sign in to comment.