Change tor-persist to use json instead of toml.

The limitations with toml seemed to be reaching a head, and I wasn't
able to refactor the guardmgr code enough to actually have its state
be serializable as toml.  Json's limitations are much narrower.
This commit is contained in:
Nick Mathewson 2021-10-07 09:23:35 -04:00
parent 6c6785c04d
commit 7e68883a27
5 changed files with 23 additions and 21 deletions

2
Cargo.lock generated
View File

@ -2684,9 +2684,9 @@ dependencies = [
"fslock", "fslock",
"sanitize-filename", "sanitize-filename",
"serde", "serde",
"serde_json",
"tempfile", "tempfile",
"thiserror", "thiserror",
"toml",
] ]
[[package]] [[package]]

View File

@ -15,7 +15,7 @@ testing = []
[dependencies] [dependencies]
serde = { version = "1.0.124" } serde = { version = "1.0.124" }
toml = "0.5.8" serde_json = "1.0.59"
sanitize-filename = "0.3.0" sanitize-filename = "0.3.0"
thiserror = "1.0.24" thiserror = "1.0.24"

View File

@ -1,4 +1,4 @@
//! Filesystem + Toml implementation of StateMgr. //! Filesystem + JSON implementation of StateMgr.
use crate::{Error, Result, StateMgr}; use crate::{Error, Result, StateMgr};
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
@ -8,7 +8,7 @@ use std::sync::{Arc, Mutex};
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
use std::os::unix::fs::DirBuilderExt; use std::os::unix::fs::DirBuilderExt;
/// Implementation of StateMgr that stores state as Toml files on disk. /// Implementation of StateMgr that stores state as JSON files on disk.
/// ///
/// # Locking /// # Locking
/// ///
@ -21,10 +21,9 @@ use std::os::unix::fs::DirBuilderExt;
/// ///
/// # Limitations /// # Limitations
/// ///
/// 1) This manager only accepts objects that can be serialized as Toml /// 1) This manager only accepts objects that can be serialized as
/// documents. Some types (like strings or lists) serialize to Toml /// JSON documents. Some types (like maps with non-string keys) can't
/// types that cannot appear at the head of a document. You'll be /// be serialized as JSON.
/// able to store them, but reloading them later on will fail.
/// ///
/// 2) This manager normalizes keys to an fs-safe format before saving /// 2) This manager normalizes keys to an fs-safe format before saving
/// data with them. This keeps you from accidentally creating or /// data with them. This keeps you from accidentally creating or
@ -81,7 +80,7 @@ impl FsStateMgr {
fn filename(&self, key: &str) -> PathBuf { fn filename(&self, key: &str) -> PathBuf {
self.inner self.inner
.statepath .statepath
.join(sanitize_filename::sanitize(key) + ".toml") .join(sanitize_filename::sanitize(key) + ".json")
} }
} }
@ -123,7 +122,7 @@ impl StateMgr for FsStateMgr {
} }
}; };
Ok(Some(toml::from_str(&string)?)) Ok(Some(serde_json::from_str(&string)?))
} }
fn store<S>(&self, key: &str, val: &S) -> Result<()> fn store<S>(&self, key: &str, val: &S) -> Result<()>
@ -136,7 +135,7 @@ impl StateMgr for FsStateMgr {
let fname = self.filename(key); let fname = self.filename(key);
let output = toml::ser::to_string(val)?; let output = serde_json::to_string_pretty(val)?;
let fname_tmp = fname.with_extension("tmp"); let fname_tmp = fname.with_extension("tmp");
std::fs::write(&fname_tmp, (&output).as_bytes())?; std::fs::write(&fname_tmp, (&output).as_bytes())?;

View File

@ -113,13 +113,9 @@ pub enum Error {
#[error("Storage not locked")] #[error("Storage not locked")]
NoLock, NoLock,
/// Unable to serialize data as TOML. /// Problem when serializing or deserializing JSON data.
#[error("Toml serialization error")] #[error("JSON serialization error")]
TomlWriteError(#[from] toml::ser::Error), JsonError(#[source] Arc<serde_json::Error>),
/// Unable to deserialize data from TOML
#[error("Toml deserialization error")]
TomlReadError(#[from] toml::de::Error),
} }
impl From<std::io::Error> for Error { impl From<std::io::Error> for Error {
@ -127,3 +123,9 @@ impl From<std::io::Error> for Error {
Error::IoError(Arc::new(e)) Error::IoError(Arc::new(e))
} }
} }
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Error {
Error::JsonError(Arc::new(e))
}
}

View File

@ -24,7 +24,7 @@ struct TestingStateMgrInner {
/// True if we are pretending that someone else is holding the /// True if we are pretending that someone else is holding the
/// simulated write lock on the state. /// simulated write lock on the state.
lock_blocked: bool, lock_blocked: bool,
/// Map from key to toml-encoded values. /// Map from key to JSON-encoded values.
/// ///
/// We serialize our values here for conveinence (so that we don't /// We serialize our values here for conveinence (so that we don't
/// have to use `Any`) and to try to detect any /// have to use `Any`) and to try to detect any
@ -66,7 +66,7 @@ impl StateMgr for TestingStateMgr {
{ {
let inner = self.inner.lock().expect("Lock poisoned."); let inner = self.inner.lock().expect("Lock poisoned.");
match inner.entries.get(key) { match inner.entries.get(key) {
Some(value) => Ok(Some(toml::from_str(value)?)), Some(value) => Ok(Some(serde_json::from_str(value)?)),
None => Ok(None), None => Ok(None),
} }
} }
@ -80,7 +80,8 @@ impl StateMgr for TestingStateMgr {
return Err(Error::NoLock); return Err(Error::NoLock);
} }
let val = toml::ser::to_string(val)?; let val = serde_json::to_string_pretty(val)?;
inner.entries.insert(key.to_string(), val); inner.entries.insert(key.to_string(), val);
Ok(()) Ok(())
} }