mirror of
https://github.com/Drop-OSS/dropbreak.git
synced 2026-07-19 20:43:35 -04:00
Use thiserror
This commit is contained in:
+6
-1
@@ -16,9 +16,9 @@ version = "2.0.0-rc3"
|
||||
all-features = true
|
||||
|
||||
[dependencies]
|
||||
failure = "0.1.1"
|
||||
serde = "1"
|
||||
tempfile = "3"
|
||||
thiserror = "1.0.20"
|
||||
|
||||
[dependencies.ron]
|
||||
optional = true
|
||||
@@ -40,6 +40,10 @@ version = "0.8.5"
|
||||
optional = true
|
||||
version = "0.7"
|
||||
|
||||
[dependencies.anyhow]
|
||||
optional = true
|
||||
version = "1.0.32"
|
||||
|
||||
[dev-dependencies]
|
||||
lazy_static = "1"
|
||||
serde_derive = "1"
|
||||
@@ -49,5 +53,6 @@ default = []
|
||||
ron_enc = ["ron"]
|
||||
bin_enc = ["bincode", "base64"]
|
||||
yaml_enc = ["serde_yaml"]
|
||||
other_errors = ["anyhow"]
|
||||
mmap = ["memmap"]
|
||||
|
||||
|
||||
@@ -41,12 +41,11 @@ features = ["ron_enc"] # You can also use "yaml_enc" or "bin_enc"
|
||||
```
|
||||
|
||||
```rust
|
||||
extern crate failure;
|
||||
extern crate rustbreak;
|
||||
use std::collections::HashMap;
|
||||
use rustbreak::{MemoryDatabase, deser::Ron};
|
||||
|
||||
fn main() -> Result<(), failure::Error> {
|
||||
fn main() -> rustbreak::Result<()> {
|
||||
let db = MemoryDatabase::<HashMap<u32, String>, Ron>::memory(HashMap::new())?;
|
||||
|
||||
println!("Writing to Database");
|
||||
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
use failure;
|
||||
|
||||
use rustbreak::deser::Ron;
|
||||
use rustbreak::FileDatabase;
|
||||
@@ -17,7 +16,7 @@ struct Person {
|
||||
country: Country,
|
||||
}
|
||||
|
||||
fn do_main() -> Result<(), failure::Error> {
|
||||
fn do_main() -> Result<(), rustbreak::RustbreakError> {
|
||||
use std::collections::HashMap;
|
||||
|
||||
let db = FileDatabase::<HashMap<String, Person>, Ron>::load_from_path_or_default("test.ron")?;
|
||||
@@ -58,7 +57,7 @@ fn do_main() -> Result<(), failure::Error> {
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = do_main() {
|
||||
eprintln!("An error has occurred at: \n{}", e.backtrace());
|
||||
eprintln!("An error has occurred at: \n{}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
use failure;
|
||||
|
||||
use rustbreak::deser::{Ron, Yaml};
|
||||
use rustbreak::{backend::FileBackend, FileDatabase};
|
||||
@@ -17,7 +16,7 @@ struct Person {
|
||||
country: Country,
|
||||
}
|
||||
|
||||
fn do_main() -> Result<(), failure::Error> {
|
||||
fn do_main() -> Result<(), rustbreak::RustbreakError> {
|
||||
use std::collections::HashMap;
|
||||
|
||||
let db = FileDatabase::<HashMap<String, Person>, Ron>::load_from_path_or_default("test.ron")?;
|
||||
@@ -56,7 +55,7 @@ fn do_main() -> Result<(), failure::Error> {
|
||||
|
||||
fn main() {
|
||||
if let Err(e) = do_main() {
|
||||
eprintln!("An error has occurred at: \n{}", e.backtrace());
|
||||
eprintln!("An error has occurred at: \n{}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-21
@@ -1,5 +1,3 @@
|
||||
use failure::ResultExt;
|
||||
|
||||
use super::Backend;
|
||||
|
||||
use crate::error;
|
||||
@@ -32,11 +30,11 @@ impl Mmap {
|
||||
}
|
||||
|
||||
/// Copies data to mmap and modifies data's end cursor.
|
||||
fn write(&mut self, data: &[u8]) -> Result<(), failure::Error> {
|
||||
fn write(&mut self, data: &[u8]) -> error::BackendResult<()> {
|
||||
if data.len() > self.len {
|
||||
return Err(failure::err_msg(
|
||||
"Unexpected write beyond mmap's backend capacity. This is a rustbreak's bug",
|
||||
));
|
||||
return Err(error::BackendError::Internal(format!(
|
||||
"Unexpected write beyond mmap's backend capacity."
|
||||
)));
|
||||
}
|
||||
self.end = data.len();
|
||||
self.as_mut_slice().copy_from_slice(data);
|
||||
@@ -59,7 +57,7 @@ impl Mmap {
|
||||
}
|
||||
}
|
||||
|
||||
/// A backend that uses anonymous mmap.
|
||||
/// A backend that uses an nonymous mmap.
|
||||
///
|
||||
/// The `Backend` automatically creates bigger map
|
||||
/// on demand using following strategy:
|
||||
@@ -77,38 +75,32 @@ pub struct MmapStorage {
|
||||
|
||||
impl MmapStorage {
|
||||
/// Creates new storage with 1024 bytes.
|
||||
pub fn new() -> error::Result<Self> {
|
||||
pub fn new() -> error::BackendResult<Self> {
|
||||
Self::with_size(1024)
|
||||
}
|
||||
|
||||
/// Creates new storage with custom size.
|
||||
pub fn with_size(len: usize) -> error::Result<Self> {
|
||||
let mmap = Mmap::new(len).context(error::RustbreakErrorKind::Backend)?;
|
||||
pub fn with_size(len: usize) -> error::BackendResult<Self> {
|
||||
let mmap = Mmap::new(len)?;
|
||||
|
||||
Ok(Self { mmap })
|
||||
}
|
||||
}
|
||||
|
||||
impl Backend for MmapStorage {
|
||||
fn get_data(&mut self) -> error::Result<Vec<u8>> {
|
||||
fn get_data(&mut self) -> error::BackendResult<Vec<u8>> {
|
||||
let mmap = self.mmap.as_slice();
|
||||
let mut buffer = Vec::with_capacity(mmap.len());
|
||||
buffer.extend_from_slice(mmap);
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn put_data(&mut self, data: &[u8]) -> error::Result<()> {
|
||||
fn put_data(&mut self, data: &[u8]) -> error::BackendResult<()> {
|
||||
if self.mmap.len < data.len() {
|
||||
self.mmap
|
||||
.resize_no_copy(data.len())
|
||||
.context(error::RustbreakErrorKind::Backend)?;
|
||||
self.mmap.resize_no_copy(data.len())?;
|
||||
}
|
||||
self.mmap
|
||||
.write(data)
|
||||
.context(error::RustbreakErrorKind::Backend)?;
|
||||
self.mmap
|
||||
.flush()
|
||||
.context(error::RustbreakErrorKind::Backend)?;
|
||||
self.mmap.write(data)?;
|
||||
self.mmap.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
+29
-45
@@ -10,9 +10,7 @@
|
||||
//! Implementing your own Backend should be straightforward. Check the `Backend`
|
||||
//! documentation for details.
|
||||
|
||||
use failure::ResultExt;
|
||||
|
||||
use crate::error::{self, RustbreakErrorKind as ErrorKind};
|
||||
use crate::error;
|
||||
|
||||
/// The Backend Trait.
|
||||
///
|
||||
@@ -21,31 +19,31 @@ use crate::error::{self, RustbreakErrorKind as ErrorKind};
|
||||
/// same dataset.
|
||||
pub trait Backend {
|
||||
/// Read the all data from the backend.
|
||||
fn get_data(&mut self) -> error::Result<Vec<u8>>;
|
||||
fn get_data(&mut self) -> error::BackendResult<Vec<u8>>;
|
||||
|
||||
/// Write the whole slice to the backend.
|
||||
fn put_data(&mut self, data: &[u8]) -> error::Result<()>;
|
||||
fn put_data(&mut self, data: &[u8]) -> error::BackendResult<()>;
|
||||
}
|
||||
|
||||
impl Backend for Box<dyn Backend> {
|
||||
fn get_data(&mut self) -> error::Result<Vec<u8>> {
|
||||
fn get_data(&mut self) -> error::BackendResult<Vec<u8>> {
|
||||
use std::ops::DerefMut;
|
||||
self.deref_mut().get_data()
|
||||
}
|
||||
|
||||
fn put_data(&mut self, data: &[u8]) -> error::Result<()> {
|
||||
fn put_data(&mut self, data: &[u8]) -> error::BackendResult<()> {
|
||||
use std::ops::DerefMut;
|
||||
self.deref_mut().put_data(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Backend> Backend for Box<T> {
|
||||
fn get_data(&mut self) -> error::Result<Vec<u8>> {
|
||||
fn get_data(&mut self) -> error::BackendResult<Vec<u8>> {
|
||||
use std::ops::DerefMut;
|
||||
self.deref_mut().get_data()
|
||||
}
|
||||
|
||||
fn put_data(&mut self, data: &[u8]) -> error::Result<()> {
|
||||
fn put_data(&mut self, data: &[u8]) -> error::BackendResult<()> {
|
||||
use std::ops::DerefMut;
|
||||
self.deref_mut().put_data(data)
|
||||
}
|
||||
@@ -64,28 +62,22 @@ pub use path::PathBackend;
|
||||
pub struct FileBackend(std::fs::File);
|
||||
|
||||
impl Backend for FileBackend {
|
||||
fn get_data(&mut self) -> error::Result<Vec<u8>> {
|
||||
fn get_data(&mut self) -> error::BackendResult<Vec<u8>> {
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
|
||||
let mut buffer = vec![];
|
||||
self.0
|
||||
.seek(SeekFrom::Start(0))
|
||||
.context(ErrorKind::Backend)?;
|
||||
self.0
|
||||
.read_to_end(&mut buffer)
|
||||
.context(ErrorKind::Backend)?;
|
||||
self.0.seek(SeekFrom::Start(0))?;
|
||||
self.0.read_to_end(&mut buffer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
fn put_data(&mut self, data: &[u8]) -> error::Result<()> {
|
||||
fn put_data(&mut self, data: &[u8]) -> error::BackendResult<()> {
|
||||
use std::io::{Seek, SeekFrom, Write};
|
||||
|
||||
self.0
|
||||
.seek(SeekFrom::Start(0))
|
||||
.context(ErrorKind::Backend)?;
|
||||
self.0.set_len(0).context(ErrorKind::Backend)?;
|
||||
self.0.write_all(data).context(ErrorKind::Backend)?;
|
||||
self.0.sync_all().context(ErrorKind::Backend)?;
|
||||
self.0.seek(SeekFrom::Start(0))?;
|
||||
self.0.set_len(0)?;
|
||||
self.0.write_all(data)?;
|
||||
self.0.sync_all()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -107,23 +99,19 @@ impl FileBackend {
|
||||
impl FileBackend {
|
||||
/// Opens a new [`FileBackend`] for a given path.
|
||||
/// Errors when the file doesn't yet exist.
|
||||
pub fn from_path_or_fail<P: AsRef<std::path::Path>>(path: P) -> error::Result<Self> {
|
||||
pub fn from_path_or_fail<P: AsRef<std::path::Path>>(path: P) -> error::BackendResult<Self> {
|
||||
use std::fs::OpenOptions;
|
||||
|
||||
Ok(Self(
|
||||
OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open(path)
|
||||
.context(ErrorKind::Backend)?,
|
||||
))
|
||||
Ok(Self(OpenOptions::new().read(true).write(true).open(path)?))
|
||||
}
|
||||
|
||||
/// Opens a new [`FileBackend`] for a given path.
|
||||
/// Creates a file if it doesn't yet exist.
|
||||
///
|
||||
/// Returns the [`FileBackend`] and whether the file already existed.
|
||||
pub fn from_path_or_create<P: AsRef<std::path::Path>>(path: P) -> error::Result<(Self, bool)> {
|
||||
pub fn from_path_or_create<P: AsRef<std::path::Path>>(
|
||||
path: P,
|
||||
) -> error::BackendResult<(Self, bool)> {
|
||||
use std::fs::OpenOptions;
|
||||
|
||||
let exists = path.as_ref().is_file();
|
||||
@@ -133,8 +121,7 @@ impl FileBackend {
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path)
|
||||
.context(ErrorKind::Backend)?,
|
||||
.open(path)?,
|
||||
),
|
||||
exists,
|
||||
))
|
||||
@@ -142,7 +129,7 @@ impl FileBackend {
|
||||
|
||||
/// Opens a new [`FileBackend`] for a given path.
|
||||
/// Creates a file if it doesn't yet exist, and calls `closure` with it.
|
||||
pub fn from_path_or_create_and<P, C>(path: P, closure: C) -> error::Result<Self>
|
||||
pub fn from_path_or_create_and<P, C>(path: P, closure: C) -> error::BackendResult<Self>
|
||||
where
|
||||
C: FnOnce(&mut std::fs::File),
|
||||
P: AsRef<std::path::Path>,
|
||||
@@ -171,12 +158,12 @@ impl MemoryBackend {
|
||||
}
|
||||
|
||||
impl Backend for MemoryBackend {
|
||||
fn get_data(&mut self) -> error::Result<Vec<u8>> {
|
||||
fn get_data(&mut self) -> error::BackendResult<Vec<u8>> {
|
||||
println!("Returning data: {:?}", &self.0);
|
||||
Ok(self.0.clone())
|
||||
}
|
||||
|
||||
fn put_data(&mut self, data: &[u8]) -> error::Result<()> {
|
||||
fn put_data(&mut self, data: &[u8]) -> error::BackendResult<()> {
|
||||
println!("Writing data: {:?}", data);
|
||||
self.0 = data.to_owned();
|
||||
Ok(())
|
||||
@@ -186,7 +173,6 @@ impl Backend for MemoryBackend {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Backend, FileBackend, MemoryBackend};
|
||||
use failure::Fail;
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
@@ -263,13 +249,11 @@ mod tests {
|
||||
file_path.push("rustbreak_path_db.db");
|
||||
let err =
|
||||
FileBackend::from_path_or_fail(file_path).expect_err("should fail with file not found");
|
||||
assert_eq!(crate::error::RustbreakErrorKind::Backend, err.kind());
|
||||
let io_err = err
|
||||
.cause()
|
||||
.expect("error has no cause")
|
||||
.downcast_ref::<std::io::Error>()
|
||||
.expect("error is not an io error");
|
||||
assert_eq!(std::io::ErrorKind::NotFound, io_err.kind());
|
||||
if let crate::error::BackendError::Io(io_err) = &err {
|
||||
assert_eq!(std::io::ErrorKind::NotFound, io_err.kind());
|
||||
} else {
|
||||
panic!("Wrong kind of error returned: {}", err);
|
||||
};
|
||||
dir.close().expect("Error while deleting temp directory!");
|
||||
}
|
||||
|
||||
|
||||
+19
-35
@@ -7,8 +7,6 @@
|
||||
|
||||
use super::Backend;
|
||||
use crate::error;
|
||||
use crate::error::RustbreakErrorKind as ErrorKind;
|
||||
use failure::ResultExt;
|
||||
use std::fs::OpenOptions;
|
||||
use std::path::{Path, PathBuf};
|
||||
use tempfile::NamedTempFile;
|
||||
@@ -25,11 +23,8 @@ pub struct PathBackend {
|
||||
impl PathBackend {
|
||||
/// Opens a new [`PathBackend`] for a given path.
|
||||
/// Errors when the file doesn't yet exist.
|
||||
pub fn from_path_or_fail(path: PathBuf) -> error::Result<Self> {
|
||||
OpenOptions::new()
|
||||
.read(true)
|
||||
.open(path.as_path())
|
||||
.context(ErrorKind::Backend)?;
|
||||
pub fn from_path_or_fail(path: PathBuf) -> error::BackendResult<Self> {
|
||||
OpenOptions::new().read(true).open(path.as_path())?;
|
||||
Ok(Self { path })
|
||||
}
|
||||
|
||||
@@ -37,19 +32,18 @@ impl PathBackend {
|
||||
/// Creates a file if it doesn't yet exist.
|
||||
///
|
||||
/// Returns the [`PathBackend`] and whether the file already existed.
|
||||
pub fn from_path_or_create(path: PathBuf) -> error::Result<(Self, bool)> {
|
||||
pub fn from_path_or_create(path: PathBuf) -> error::BackendResult<(Self, bool)> {
|
||||
let exists = path.as_path().is_file();
|
||||
OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path.as_path())
|
||||
.context(ErrorKind::Backend)?;
|
||||
.open(path.as_path())?;
|
||||
Ok((Self { path }, exists))
|
||||
}
|
||||
|
||||
/// Opens a new [`PathBackend`] for a given path.
|
||||
/// Creates a file if it doesn't yet exist, and calls `closure` with it.
|
||||
pub fn from_path_or_create_and<C>(path: PathBuf, closure: C) -> error::Result<Self>
|
||||
pub fn from_path_or_create_and<C>(path: PathBuf, closure: C) -> error::BackendResult<Self>
|
||||
where
|
||||
C: FnOnce(&mut std::fs::File),
|
||||
{
|
||||
@@ -58,8 +52,7 @@ impl PathBackend {
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.open(path.as_path())
|
||||
.context(ErrorKind::Backend)?;
|
||||
.open(path.as_path())?;
|
||||
if !exists {
|
||||
closure(&mut file)
|
||||
}
|
||||
@@ -68,15 +61,12 @@ impl PathBackend {
|
||||
}
|
||||
|
||||
impl Backend for PathBackend {
|
||||
fn get_data(&mut self) -> error::Result<Vec<u8>> {
|
||||
fn get_data(&mut self) -> error::BackendResult<Vec<u8>> {
|
||||
use std::io::Read;
|
||||
|
||||
let mut file = OpenOptions::new()
|
||||
.read(true)
|
||||
.open(self.path.as_path())
|
||||
.context(ErrorKind::Backend)?;
|
||||
let mut file = OpenOptions::new().read(true).open(self.path.as_path())?;
|
||||
let mut buffer = vec![];
|
||||
file.read_to_end(&mut buffer).context(ErrorKind::Backend)?;
|
||||
file.read_to_end(&mut buffer)?;
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
@@ -84,17 +74,14 @@ impl Backend for PathBackend {
|
||||
///
|
||||
/// This won't corrupt the existing database file if the program panics
|
||||
/// during the save.
|
||||
fn put_data(&mut self, data: &[u8]) -> error::Result<()> {
|
||||
fn put_data(&mut self, data: &[u8]) -> error::BackendResult<()> {
|
||||
use std::io::Write;
|
||||
|
||||
#[allow(clippy::or_fun_call)] // `Path::new` is a zero cost conversion
|
||||
let mut tempf = NamedTempFile::new_in(self.path.parent().unwrap_or(Path::new(".")))
|
||||
.context(ErrorKind::Backend)?;
|
||||
tempf.write_all(data).context(ErrorKind::Backend)?;
|
||||
tempf.as_file().sync_all().context(ErrorKind::Backend)?;
|
||||
tempf
|
||||
.persist(self.path.as_path())
|
||||
.context(ErrorKind::Backend)?;
|
||||
let mut tempf = NamedTempFile::new_in(self.path.parent().unwrap_or(Path::new(".")))?;
|
||||
tempf.write_all(data)?;
|
||||
tempf.as_file().sync_all()?;
|
||||
tempf.persist(self.path.as_path())?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -102,7 +89,6 @@ impl Backend for PathBackend {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Backend, PathBackend};
|
||||
use failure::Fail;
|
||||
use std::io::Write;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
@@ -155,13 +141,11 @@ mod tests {
|
||||
file_path.push("rustbreak_path_db.db");
|
||||
let err =
|
||||
PathBackend::from_path_or_fail(file_path).expect_err("should fail with file not found");
|
||||
assert_eq!(crate::error::RustbreakErrorKind::Backend, err.kind());
|
||||
let io_err = err
|
||||
.cause()
|
||||
.expect("error has no cause")
|
||||
.downcast_ref::<std::io::Error>()
|
||||
.expect("error is not an io error");
|
||||
assert_eq!(std::io::ErrorKind::NotFound, io_err.kind());
|
||||
if let crate::error::BackendError::Io(io_err) = &err {
|
||||
assert_eq!(std::io::ErrorKind::NotFound, io_err.kind());
|
||||
} else {
|
||||
panic!("Wrong kind of error returned: {}", err);
|
||||
};
|
||||
dir.close().expect("Error while deleting temp directory!");
|
||||
}
|
||||
|
||||
|
||||
+18
-15
@@ -1,6 +1,7 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
use crate::error;
|
||||
use std::io::Read;
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
@@ -26,11 +27,10 @@ pub use self::bincode::Bincode;
|
||||
///
|
||||
/// ```rust
|
||||
/// extern crate rustbreak;
|
||||
/// extern crate thiserror;
|
||||
/// extern crate serde;
|
||||
/// #[macro_use]
|
||||
/// extern crate failure;
|
||||
///
|
||||
/// use failure::{Backtrace, Context, Fail};
|
||||
/// use serde::de::Deserialize;
|
||||
/// use serde::Serialize;
|
||||
/// use std::io::Read;
|
||||
@@ -38,8 +38,8 @@ pub use self::bincode::Bincode;
|
||||
/// use rustbreak::deser::DeSerializer;
|
||||
/// use rustbreak::error;
|
||||
///
|
||||
/// #[derive(Fail, Debug)]
|
||||
/// #[fail(display = "A FrobnarError ocurred")]
|
||||
/// #[derive(Clone, Debug, thiserror::Error)]
|
||||
/// #[error("A frobnarizer could not splagrle.")]
|
||||
/// struct FrobnarError;
|
||||
///
|
||||
/// fn to_frobnar<T: Serialize>(input: &T) -> Vec<u8> {
|
||||
@@ -57,12 +57,12 @@ pub use self::bincode::Bincode;
|
||||
/// where
|
||||
/// for<'de> T: Deserialize<'de>,
|
||||
/// {
|
||||
/// fn serialize(&self, val: &T) -> Result<Vec<u8>, failure::Error> {
|
||||
/// fn serialize(&self, val: &T) -> rustbreak::DeSerResult<Vec<u8>> {
|
||||
/// Ok(to_frobnar(val))
|
||||
/// }
|
||||
///
|
||||
/// fn deserialize<R: Read>(&self, s: R) -> Result<T, failure::Error> {
|
||||
/// Ok(from_frobnar(&s)?)
|
||||
/// fn deserialize<R: Read>(&self, s: R) -> rustbreak::DeSerResult<T> {
|
||||
/// Ok(from_frobnar(&s).map_err(|e| error::DeSerError::Other(e.into()))?)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
@@ -72,9 +72,9 @@ pub trait DeSerializer<T: Serialize + DeserializeOwned>:
|
||||
std::default::Default + Send + Sync + Clone
|
||||
{
|
||||
/// Serializes a given value to a [`String`].
|
||||
fn serialize(&self, val: &T) -> Result<Vec<u8>, failure::Error>;
|
||||
fn serialize(&self, val: &T) -> error::DeSerResult<Vec<u8>>;
|
||||
/// Deserializes a [`String`] to a value.
|
||||
fn deserialize<R: Read>(&self, s: R) -> Result<T, failure::Error>;
|
||||
fn deserialize<R: Read>(&self, s: R) -> error::DeSerResult<T>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "ron_enc")]
|
||||
@@ -89,16 +89,17 @@ mod ron {
|
||||
use ron::ser::PrettyConfig;
|
||||
|
||||
use crate::deser::DeSerializer;
|
||||
use crate::error;
|
||||
|
||||
/// The Struct that allows you to use `ron` the Rusty Object Notation.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Ron;
|
||||
|
||||
impl<T: Serialize + DeserializeOwned> DeSerializer<T> for Ron {
|
||||
fn serialize(&self, val: &T) -> Result<Vec<u8>, failure::Error> {
|
||||
fn serialize(&self, val: &T) -> error::DeSerResult<Vec<u8>> {
|
||||
Ok(to_ron_string(val, PrettyConfig::default()).map(String::into_bytes)?)
|
||||
}
|
||||
fn deserialize<R: Read>(&self, s: R) -> Result<T, failure::Error> {
|
||||
fn deserialize<R: Read>(&self, s: R) -> error::DeSerResult<T> {
|
||||
Ok(from_ron_string(s)?)
|
||||
}
|
||||
}
|
||||
@@ -113,16 +114,17 @@ mod yaml {
|
||||
use serde_yaml::{from_reader as from_yaml_string, to_string as to_yaml_string};
|
||||
|
||||
use crate::deser::DeSerializer;
|
||||
use crate::error;
|
||||
|
||||
/// The struct that allows you to use yaml.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Yaml;
|
||||
|
||||
impl<T: Serialize + DeserializeOwned> DeSerializer<T> for Yaml {
|
||||
fn serialize(&self, val: &T) -> Result<Vec<u8>, failure::Error> {
|
||||
fn serialize(&self, val: &T) -> error::DeSerResult<Vec<u8>> {
|
||||
Ok(to_yaml_string(val).map(String::into_bytes)?)
|
||||
}
|
||||
fn deserialize<R: Read>(&self, s: R) -> Result<T, failure::Error> {
|
||||
fn deserialize<R: Read>(&self, s: R) -> error::DeSerResult<T> {
|
||||
Ok(from_yaml_string(s)?)
|
||||
}
|
||||
}
|
||||
@@ -137,16 +139,17 @@ mod bincode {
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::deser::DeSerializer;
|
||||
use crate::error;
|
||||
|
||||
/// The struct that allows you to use bincode
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Bincode;
|
||||
|
||||
impl<T: Serialize + DeserializeOwned> DeSerializer<T> for Bincode {
|
||||
fn serialize(&self, val: &T) -> Result<Vec<u8>, failure::Error> {
|
||||
fn serialize(&self, val: &T) -> error::DeSerResult<Vec<u8>> {
|
||||
Ok(serialize(val)?)
|
||||
}
|
||||
fn deserialize<R: Read>(&self, s: R) -> Result<T, failure::Error> {
|
||||
fn deserialize<R: Read>(&self, s: R) -> error::DeSerResult<T> {
|
||||
Ok(deserialize_from(s)?)
|
||||
}
|
||||
}
|
||||
|
||||
+49
-80
@@ -2,97 +2,66 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use failure::{Backtrace, Context, Fail};
|
||||
use std::fmt::{self, Display};
|
||||
/// An error returned by a DeSer implementor
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum DeSerError {
|
||||
#[cfg(feature = "yaml_enc")]
|
||||
/// An error occured with Yaml
|
||||
#[error("An error with yaml occured")]
|
||||
Yaml(#[from] serde_yaml::Error),
|
||||
#[cfg(feature = "ron_enc")]
|
||||
/// An error occured with Ron
|
||||
#[error("An error with Ron occured")]
|
||||
Ron(#[from] ron::Error),
|
||||
#[cfg(feature = "bin_enc")]
|
||||
/// An error occured with Bincode
|
||||
#[error("An error with Bincode occured")]
|
||||
Bincode(#[from] std::boxed::Box<bincode::ErrorKind>),
|
||||
#[cfg(feature = "other_errors")]
|
||||
/// An error occured with Bincode
|
||||
#[error(transparent)]
|
||||
Other(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
/// An error returned by a Backend implementor
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum BackendError {
|
||||
/// An error occured from the tempfile
|
||||
#[error("An error while persisting the file occured")]
|
||||
TempFile(#[from] tempfile::PersistError),
|
||||
/// An I/O Error occured
|
||||
#[error("An I/O Error occured")]
|
||||
Io(#[from] std::io::Error),
|
||||
/// An internal error to Rustbreak occured
|
||||
#[error("An internal error to rustbreak occured, please report it to the maintainers")]
|
||||
Internal(String),
|
||||
}
|
||||
|
||||
/// The different kinds of errors that can be returned
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Fail)]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum RustbreakErrorKind {
|
||||
/// A context error when a serialization failed
|
||||
#[fail(display = "Could not serialize the value")]
|
||||
Serialization,
|
||||
/// A context error when a deserialization failed
|
||||
#[fail(display = "Could not deserialize the value")]
|
||||
Deserialization,
|
||||
pub enum RustbreakError {
|
||||
/// A context error when a DeSerialization failed
|
||||
#[error("Could not deserialize the value")]
|
||||
DeSerialization(#[from] DeSerError),
|
||||
/// This error is returned if the `Database` is poisoned. See
|
||||
/// `Database::write` for details
|
||||
#[fail(display = "The database has been poisoned")]
|
||||
#[error("The database has been poisoned")]
|
||||
Poison,
|
||||
/// An error in the backend happened
|
||||
#[fail(display = "The backend has encountered an error")]
|
||||
Backend,
|
||||
#[error("The backend has encountered an error")]
|
||||
Backend(#[from] BackendError),
|
||||
/// If `Database::write_safe` is used and the closure panics, this error is
|
||||
/// returned
|
||||
#[fail(display = "The write operation paniced but got caught")]
|
||||
#[error("The write operation paniced but got caught")]
|
||||
WritePanic,
|
||||
}
|
||||
|
||||
/// The main error type that gets returned for errors that happen while
|
||||
/// interacting with a `Database`.
|
||||
#[derive(Debug)]
|
||||
pub struct RustbreakError {
|
||||
inner: Context<RustbreakErrorKind>,
|
||||
}
|
||||
|
||||
impl Fail for RustbreakError {
|
||||
fn cause(&self) -> Option<&dyn Fail> {
|
||||
self.inner.cause()
|
||||
}
|
||||
|
||||
fn backtrace(&self) -> Option<&Backtrace> {
|
||||
self.inner.backtrace()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for RustbreakError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Display::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl RustbreakError {
|
||||
/// Get the kind of this error
|
||||
pub fn kind(&self) -> RustbreakErrorKind {
|
||||
*self.inner.get_context()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RustbreakErrorKind> for RustbreakError {
|
||||
fn from(kind: RustbreakErrorKind) -> Self {
|
||||
Self {
|
||||
inner: Context::new(kind),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Context<RustbreakErrorKind>> for RustbreakError {
|
||||
fn from(inner: Context<RustbreakErrorKind>) -> Self {
|
||||
Self { inner }
|
||||
}
|
||||
}
|
||||
|
||||
/// A simple type alias for errors
|
||||
pub type Result<T> = std::result::Result<T, RustbreakError>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{RustbreakError, RustbreakErrorKind};
|
||||
use failure::Context;
|
||||
use std::any::Any;
|
||||
|
||||
#[test]
|
||||
fn static_errorkind_impl_any() {
|
||||
let err = RustbreakErrorKind::Backend;
|
||||
let boxed: Box<dyn Any> = Box::new(err);
|
||||
assert!(boxed.is::<RustbreakErrorKind>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn static_error_impl_any() {
|
||||
let context = RustbreakErrorKind::Serialization;
|
||||
let err: RustbreakError = Context::new(context).into();
|
||||
let boxed: Box<dyn Any> = Box::new(err);
|
||||
assert!(boxed.is::<RustbreakError>());
|
||||
}
|
||||
}
|
||||
/// The type alias used for backends
|
||||
pub type BackendResult<T> = std::result::Result<T, BackendError>;
|
||||
/// The type alias used for DeSers
|
||||
pub type DeSerResult<T> = std::result::Result<T, DeSerError>;
|
||||
|
||||
+53
-75
@@ -81,13 +81,12 @@
|
||||
//! ```
|
||||
//!
|
||||
//! ```rust
|
||||
//! # extern crate failure;
|
||||
//! # extern crate rustbreak;
|
||||
//! # use std::collections::HashMap;
|
||||
//! use rustbreak::{deser::Ron, MemoryDatabase};
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! # let func = || -> Result<(), failure::Error> {
|
||||
//! # let func = || -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! let db = MemoryDatabase::<HashMap<u32, String>, Ron>::memory(HashMap::new())?;
|
||||
//!
|
||||
//! println!("Writing to Database");
|
||||
@@ -108,13 +107,12 @@
|
||||
//!
|
||||
//! Or alternatively:
|
||||
//! ```rust
|
||||
//! # extern crate failure;
|
||||
//! # extern crate rustbreak;
|
||||
//! # use std::collections::HashMap;
|
||||
//! use rustbreak::{deser::Ron, MemoryDatabase};
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! # let func = || -> Result<(), failure::Error> {
|
||||
//! # let func = || -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! let db = MemoryDatabase::<HashMap<u32, String>, Ron>::memory(HashMap::new())?;
|
||||
//!
|
||||
//! println!("Writing to Database");
|
||||
@@ -137,9 +135,6 @@
|
||||
//! fail case as [`error::RustbreakError`]. This means that you can now either
|
||||
//! continue bubbling up said error case, or handle it yourself.
|
||||
//!
|
||||
//! You can simply call its `.kind()` method, giving you all the information you
|
||||
//! need to continue.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use rustbreak::{deser::Ron, error::RustbreakError, MemoryDatabase};
|
||||
//! let db = match MemoryDatabase::<usize, Ron>::memory(0) {
|
||||
@@ -194,7 +189,6 @@
|
||||
//! [daybreak]: https://propublica.github.io/daybreak
|
||||
//! [examples]: https://github.com/TheNeikos/rustbreak/tree/master/examples
|
||||
//! [ron]: https://github.com/ron-rs/ron
|
||||
//! [failure]: https://boats.gitlab.io/failure/intro.html
|
||||
//! [features]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#choosing-features
|
||||
|
||||
pub mod backend;
|
||||
@@ -206,14 +200,11 @@ pub mod error;
|
||||
/// The `DeSerializer` trait used by serialization structs
|
||||
pub use crate::deser::DeSerializer;
|
||||
/// The general error used by the Rustbreak Module
|
||||
pub use crate::error::RustbreakError;
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
use failure::ResultExt;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -221,7 +212,7 @@ use serde::Serialize;
|
||||
use crate::backend::MmapStorage;
|
||||
use crate::backend::{Backend, FileBackend, MemoryBackend, PathBackend};
|
||||
|
||||
use crate::error::RustbreakErrorKind as ErrorKind;
|
||||
pub use crate::error::*;
|
||||
|
||||
/// The Central Database to Rustbreak.
|
||||
///
|
||||
@@ -236,7 +227,7 @@ use crate::error::RustbreakErrorKind as ErrorKind;
|
||||
///
|
||||
/// If the backend or the de/serialization panics, the database is poisoned.
|
||||
/// This means that any subsequent writes/reads will fail with an
|
||||
/// [`error::RustbreakErrorKind::Poison`]. You can only recover from this by
|
||||
/// [`error::RustbreakError::Poison`]. You can only recover from this by
|
||||
/// re-creating the Database Object.
|
||||
#[derive(Debug)]
|
||||
pub struct Database<Data, Back, DeSer> {
|
||||
@@ -261,7 +252,7 @@ where
|
||||
///
|
||||
/// If you panic in the closure, the database is poisoned. This means that
|
||||
/// any subsequent writes/reads will fail with an
|
||||
/// [`error::RustbreakErrorKind::Poison`]. You can only recover from
|
||||
/// [`error::RustbreakError::Poison`]. You can only recover from
|
||||
/// this by re-creating the Database Object.
|
||||
///
|
||||
/// If you do not have full control over the code being written, and cannot
|
||||
@@ -275,7 +266,6 @@ where
|
||||
/// # extern crate rustbreak;
|
||||
/// # extern crate serde;
|
||||
/// # extern crate tempfile;
|
||||
/// # extern crate failure;
|
||||
/// use rustbreak::{deser::Ron, FileDatabase};
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -284,7 +274,7 @@ where
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let func = || -> Result<(), failure::Error> {
|
||||
/// # let func = || -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// # let file = tempfile::tempfile()?;
|
||||
/// let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;
|
||||
///
|
||||
@@ -305,7 +295,7 @@ where
|
||||
where
|
||||
T: FnOnce(&mut Data) -> R,
|
||||
{
|
||||
let mut lock = self.data.write().map_err(|_| ErrorKind::Poison)?;
|
||||
let mut lock = self.data.write().map_err(|_| RustbreakError::Poison)?;
|
||||
Ok(task(&mut lock))
|
||||
}
|
||||
|
||||
@@ -329,7 +319,7 @@ where
|
||||
/// # Panics
|
||||
///
|
||||
/// When the closure panics, it is caught and a
|
||||
/// [`error::RustbreakErrorKind::WritePanic`] will be returned.
|
||||
/// [`error::RustbreakError::WritePanic`] will be returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -338,10 +328,9 @@ where
|
||||
/// # extern crate rustbreak;
|
||||
/// # extern crate serde;
|
||||
/// # extern crate tempfile;
|
||||
/// # extern crate failure;
|
||||
/// use rustbreak::{
|
||||
/// deser::Ron,
|
||||
/// error::{RustbreakError, RustbreakErrorKind},
|
||||
/// error::RustbreakError,
|
||||
/// FileDatabase,
|
||||
/// };
|
||||
///
|
||||
@@ -351,7 +340,7 @@ where
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let func = || -> Result<(), failure::Error> {
|
||||
/// # let func = || -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// # let file = tempfile::tempfile()?;
|
||||
/// let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;
|
||||
///
|
||||
@@ -362,8 +351,8 @@ where
|
||||
/// })
|
||||
/// .expect_err("This should have been caught");
|
||||
///
|
||||
/// match result.kind() {
|
||||
/// RustbreakErrorKind::WritePanic => {
|
||||
/// match result {
|
||||
/// RustbreakError::WritePanic => {
|
||||
/// // We can now handle this, in this example we will just ignore it
|
||||
/// }
|
||||
/// e => {
|
||||
@@ -388,12 +377,12 @@ where
|
||||
where
|
||||
T: FnOnce(&mut Data) + std::panic::UnwindSafe,
|
||||
{
|
||||
let mut lock = self.data.write().map_err(|_| ErrorKind::Poison)?;
|
||||
let mut lock = self.data.write().map_err(|_| RustbreakError::Poison)?;
|
||||
let mut data = lock.clone();
|
||||
std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| {
|
||||
task(&mut data);
|
||||
}))
|
||||
.map_err(|_| ErrorKind::WritePanic)?;
|
||||
.map_err(|_| RustbreakError::WritePanic)?;
|
||||
*lock = data;
|
||||
Ok(())
|
||||
}
|
||||
@@ -407,19 +396,19 @@ where
|
||||
///
|
||||
/// May return:
|
||||
///
|
||||
/// - [`error::RustbreakErrorKind::Backend`]
|
||||
/// - [`error::RustbreakError::Backend`]
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If you panic in the closure, the database is poisoned. This means that
|
||||
/// any subsequent writes/reads will fail with an
|
||||
/// [`error::RustbreakErrorKind::Poison`]. You can only recover from
|
||||
/// [`error::RustbreakError::Poison`]. You can only recover from
|
||||
/// this by re-creating the Database Object.
|
||||
pub fn read<T, R>(&self, task: T) -> error::Result<R>
|
||||
where
|
||||
T: FnOnce(&Data) -> R,
|
||||
{
|
||||
let mut lock = self.data.read().map_err(|_| ErrorKind::Poison)?;
|
||||
let mut lock = self.data.read().map_err(|_| RustbreakError::Poison)?;
|
||||
Ok(task(&mut lock))
|
||||
}
|
||||
|
||||
@@ -435,7 +424,6 @@ where
|
||||
/// # extern crate rustbreak;
|
||||
/// # extern crate serde;
|
||||
/// # extern crate tempfile;
|
||||
/// # extern crate failure;
|
||||
/// use rustbreak::{deser::Ron, FileDatabase};
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -444,7 +432,7 @@ where
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let func = || -> Result<(), failure::Error> {
|
||||
/// # let func = || -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// # let file = tempfile::tempfile()?;
|
||||
/// let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;
|
||||
///
|
||||
@@ -461,7 +449,7 @@ where
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn borrow_data<'a>(&'a self) -> error::Result<RwLockReadGuard<'a, Data>> {
|
||||
self.data.read().map_err(|_| ErrorKind::Poison.into())
|
||||
self.data.read().map_err(|_| RustbreakError::Poison.into())
|
||||
}
|
||||
|
||||
/// Write lock the database and get access to the underlying struct.
|
||||
@@ -473,7 +461,7 @@ where
|
||||
///
|
||||
/// If you panic while holding this reference, the database is poisoned.
|
||||
/// This means that any subsequent writes/reads will fail with an
|
||||
/// [`error::RustbreakErrorKind::Poison`]. You can only recover from
|
||||
/// [`error::RustbreakError::Poison`]. You can only recover from
|
||||
/// this by re-creating the Database Object.
|
||||
///
|
||||
/// If you do not have full control over the code being written, and cannot
|
||||
@@ -487,7 +475,6 @@ where
|
||||
/// # extern crate rustbreak;
|
||||
/// # extern crate serde;
|
||||
/// # extern crate tempfile;
|
||||
/// # extern crate failure;
|
||||
/// use rustbreak::{deser::Ron, FileDatabase};
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -496,7 +483,7 @@ where
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let func = || -> Result<(), failure::Error> {
|
||||
/// # let func = || -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// # let file = tempfile::tempfile()?;
|
||||
/// let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;
|
||||
///
|
||||
@@ -514,26 +501,24 @@ where
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn borrow_data_mut<'a>(&'a self) -> error::Result<RwLockWriteGuard<'a, Data>> {
|
||||
self.data.write().map_err(|_| ErrorKind::Poison.into())
|
||||
self.data.write().map_err(|_| RustbreakError::Poison.into())
|
||||
}
|
||||
|
||||
/// Load data from backend and return this data.
|
||||
fn load_from_backend(backend: &mut Back, deser: &DeSer) -> error::Result<Data> {
|
||||
let new_data = deser
|
||||
.deserialize(&backend.get_data()?[..])
|
||||
.context(ErrorKind::Deserialization)?;
|
||||
let new_data = deser.deserialize(&backend.get_data()?[..])?;
|
||||
|
||||
Ok(new_data)
|
||||
}
|
||||
|
||||
/// Like [`Self::load`] but returns the write lock to data it used.
|
||||
fn load_get_data_lock(&self) -> error::Result<RwLockWriteGuard<'_, Data>> {
|
||||
let mut backend_lock = self.backend.lock().map_err(|_| ErrorKind::Poison)?;
|
||||
let mut backend_lock = self.backend.lock().map_err(|_| RustbreakError::Poison)?;
|
||||
|
||||
let fresh_data = Self::load_from_backend(&mut backend_lock, &self.deser)?;
|
||||
drop(backend_lock);
|
||||
|
||||
let mut data_write_lock = self.data.write().map_err(|_| ErrorKind::Poison)?;
|
||||
let mut data_write_lock = self.data.write().map_err(|_| RustbreakError::Poison)?;
|
||||
*data_write_lock = fresh_data;
|
||||
Ok(data_write_lock)
|
||||
}
|
||||
@@ -545,20 +530,17 @@ where
|
||||
|
||||
/// Like [`Self::save`] but with explicit read (or write) lock to data.
|
||||
fn save_data_locked<L: Deref<Target = Data>>(&self, lock: L) -> error::Result<()> {
|
||||
let ser = self
|
||||
.deser
|
||||
.serialize(lock.deref())
|
||||
.context(ErrorKind::Serialization)?;
|
||||
let ser = self.deser.serialize(lock.deref())?;
|
||||
drop(lock);
|
||||
|
||||
let mut backend = self.backend.lock().map_err(|_| ErrorKind::Poison)?;
|
||||
let mut backend = self.backend.lock().map_err(|_| RustbreakError::Poison)?;
|
||||
backend.put_data(&ser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Flush the data structure to the backend.
|
||||
pub fn save(&self) -> error::Result<()> {
|
||||
let data = self.data.read().map_err(|_| ErrorKind::Poison)?;
|
||||
let data = self.data.read().map_err(|_| RustbreakError::Poison)?;
|
||||
self.save_data_locked(data)
|
||||
}
|
||||
|
||||
@@ -570,7 +552,7 @@ where
|
||||
let data = if load {
|
||||
self.load_get_data_lock()?
|
||||
} else {
|
||||
self.data.write().map_err(|_| ErrorKind::Poison)?
|
||||
self.data.write().map_err(|_| RustbreakError::Poison)?
|
||||
};
|
||||
Ok(data.clone())
|
||||
}
|
||||
@@ -579,7 +561,7 @@ where
|
||||
///
|
||||
/// To save the data afterwards, call with `save` true.
|
||||
pub fn put_data(&self, new_data: Data, save: bool) -> error::Result<()> {
|
||||
let mut data = self.data.write().map_err(|_| ErrorKind::Poison)?;
|
||||
let mut data = self.data.write().map_err(|_| RustbreakError::Poison)?;
|
||||
*data = new_data;
|
||||
if save {
|
||||
self.save_data_locked(data)
|
||||
@@ -600,8 +582,10 @@ where
|
||||
/// Break a database into its individual parts.
|
||||
pub fn into_inner(self) -> error::Result<(Data, Back, DeSer)> {
|
||||
Ok((
|
||||
self.data.into_inner().map_err(|_| ErrorKind::Poison)?,
|
||||
self.backend.into_inner().map_err(|_| ErrorKind::Poison)?,
|
||||
self.data.into_inner().map_err(|_| RustbreakError::Poison)?,
|
||||
self.backend
|
||||
.into_inner()
|
||||
.map_err(|_| RustbreakError::Poison)?,
|
||||
self.deser,
|
||||
))
|
||||
}
|
||||
@@ -619,7 +603,6 @@ where
|
||||
/// # extern crate rustbreak;
|
||||
/// # extern crate serde;
|
||||
/// # extern crate tempfile;
|
||||
/// # extern crate failure;
|
||||
/// use rustbreak::{deser::Ron, FileDatabase};
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@@ -628,7 +611,7 @@ where
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let func = || -> Result<(), failure::Error> {
|
||||
/// # let func = || -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// # let file = tempfile::tempfile()?;
|
||||
/// let db = FileDatabase::<Data, Ron>::from_file(file, Data { level: 0 })?;
|
||||
///
|
||||
@@ -650,7 +633,7 @@ where
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn try_clone(&self) -> error::Result<MemoryDatabase<Data, DeSer>> {
|
||||
let lock = self.data.read().map_err(|_| ErrorKind::Poison)?;
|
||||
let lock = self.data.read().map_err(|_| RustbreakError::Poison)?;
|
||||
|
||||
Ok(Database {
|
||||
data: RwLock::new(lock.clone()),
|
||||
@@ -698,7 +681,7 @@ where
|
||||
let (mut backend, exists) = FileBackend::from_path_or_create(path)?;
|
||||
let deser = DeSer::default();
|
||||
if !exists {
|
||||
let ser = deser.serialize(&data).context(ErrorKind::Serialization)?;
|
||||
let ser = deser.serialize(&data)?;
|
||||
backend.put_data(&ser)?;
|
||||
}
|
||||
|
||||
@@ -732,7 +715,7 @@ where
|
||||
} else {
|
||||
let data = closure();
|
||||
|
||||
let ser = deser.serialize(&data).context(ErrorKind::Serialization)?;
|
||||
let ser = deser.serialize(&data)?;
|
||||
backend.put_data(&ser)?;
|
||||
|
||||
data
|
||||
@@ -759,7 +742,7 @@ where
|
||||
let (mut backend, exists) = FileBackend::from_path_or_create(path)?;
|
||||
let deser = DeSer::default();
|
||||
if !exists {
|
||||
let ser = deser.serialize(&data).context(ErrorKind::Serialization)?;
|
||||
let ser = deser.serialize(&data)?;
|
||||
backend.put_data(&ser)?;
|
||||
}
|
||||
|
||||
@@ -833,7 +816,7 @@ where
|
||||
let (mut backend, exists) = PathBackend::from_path_or_create(path)?;
|
||||
let deser = DeSer::default();
|
||||
if !exists {
|
||||
let ser = deser.serialize(&data).context(ErrorKind::Serialization)?;
|
||||
let ser = deser.serialize(&data)?;
|
||||
backend.put_data(&ser)?;
|
||||
}
|
||||
|
||||
@@ -866,7 +849,7 @@ where
|
||||
} else {
|
||||
let data = closure();
|
||||
|
||||
let ser = deser.serialize(&data).context(ErrorKind::Serialization)?;
|
||||
let ser = deser.serialize(&data)?;
|
||||
backend.put_data(&ser)?;
|
||||
|
||||
data
|
||||
@@ -890,7 +873,7 @@ where
|
||||
let (mut backend, exists) = PathBackend::from_path_or_create(path)?;
|
||||
let deser = DeSer::default();
|
||||
if !exists {
|
||||
let ser = deser.serialize(&data).context(ErrorKind::Serialization)?;
|
||||
let ser = deser.serialize(&data)?;
|
||||
backend.put_data(&ser)?;
|
||||
}
|
||||
|
||||
@@ -1026,7 +1009,6 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use failure::Fail;
|
||||
use std::collections::HashMap;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
@@ -1154,7 +1136,7 @@ mod tests {
|
||||
panic!("Panic should be catched")
|
||||
})
|
||||
.expect_err("Did not error on panic in safe write!");
|
||||
assert_eq!(ErrorKind::WritePanic, err.kind());
|
||||
assert!(matches!(err, RustbreakError::WritePanic));
|
||||
|
||||
assert_eq!(
|
||||
"Hello World",
|
||||
@@ -1436,13 +1418,11 @@ mod tests {
|
||||
file_path.push("rustbreak_path_db.db");
|
||||
let err = TestDb::<PathBackend>::load_from_path(file_path)
|
||||
.expect_err("should fail with file not found");
|
||||
assert_eq!(ErrorKind::Backend, err.kind());
|
||||
let io_err = err
|
||||
.cause()
|
||||
.expect("error has no cause")
|
||||
.downcast_ref::<std::io::Error>()
|
||||
.expect("error is not an io error");
|
||||
assert_eq!(std::io::ErrorKind::NotFound, io_err.kind());
|
||||
if let RustbreakError::Backend(BackendError::Io(io_err)) = &err {
|
||||
assert_eq!(std::io::ErrorKind::NotFound, io_err.kind());
|
||||
} else {
|
||||
panic!("Wrong error: {}", err)
|
||||
};
|
||||
|
||||
dir.close().expect("Error while deleting temp directory!");
|
||||
}
|
||||
@@ -1455,13 +1435,11 @@ mod tests {
|
||||
file_path.push("rustbreak_path_db.db");
|
||||
let err = TestDb::<FileBackend>::load_from_path(file_path)
|
||||
.expect_err("should fail with file not found");
|
||||
assert_eq!(ErrorKind::Backend, err.kind());
|
||||
let io_err = err
|
||||
.cause()
|
||||
.expect("error has no cause")
|
||||
.downcast_ref::<std::io::Error>()
|
||||
.expect("error is not an io error");
|
||||
assert_eq!(std::io::ErrorKind::NotFound, io_err.kind());
|
||||
if let RustbreakError::Backend(BackendError::Io(io_err)) = &err {
|
||||
assert_eq!(std::io::ErrorKind::NotFound, io_err.kind());
|
||||
} else {
|
||||
panic!("Wrong error: {}", err)
|
||||
};
|
||||
|
||||
dir.close().expect("Error while deleting temp directory!");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user