6 releases
0.2.2 | Mar 7, 2023 |
---|---|
0.2.1 | Mar 5, 2023 |
0.1.2 | Mar 5, 2023 |
#667 in Filesystem
Used in binroots-proc-macros
52KB
1K
SLoC
binroots
Binroots is a (cross-platform!) crate that provides a simple and efficient way to save Rust data structures to disk. It allows you to save each field of a struct or enum variant as a separate file, making it easy to store reactive data, allowing end-users and hackers to watch individual files for changes and automate command-line tools for your app.
Project Status
Writing the initial commit of this crate took me about 7 hours. There are no unit tests yet, and it requires nightly Rust. If you care about your code, please do not use this in production (yet!). I can't guarantee that your files will remain safe. If you're interested in the development of binroots, check out the planned features and follow my Twitter (no promises of whatever else you'll see on there)
Installation
Add it to your project using cargo add binroots
Setting up a struct
To save a struct, annotate it with #[binroots_struct]
:
use binroots::binroots_struct;
#[binroots_struct]
struct Status {
connections: usize,
is_online: bool,
activity: Activity,
}
#[binroots_struct]
Automatically derives Debug
, Default
and serde::Serialize
. It wraps each field in BinrootsField
, which allows saving of individual fields without having to serialize the entire struct.
Setting up an enum
In the struct above, we use an enum named Activity
. Here's how it can be defined:
use binroots::binroots_enum;
#[binroots_enum]
enum Activity {
None, // <- Automatically chosen as the default value
Playing(String),
}
#[binroots_enum]
Also automatically derives Debug
, Default
and serde::Serialize
. Wrapper types aren't needed.
In order to satisfy Default
, it also picks the first variant named either None
, Nothing
, Default
, or Empty
. If you wish to use a different default type, you may annotate the enum with #[binroots_enum(manual)]
, and mark a unit variant with #[default]
.
Saving data
In this example, we initialize status
using Status::default
(generated by #[binroots_struct]
)
When saving a struct annotated with #[binroots_struct]
, it will save to a subfolder named after the struct in kebab-case
. In this example, on Unix, it saves to /tmp/<crate name>/status
, and %LOCALAPPDATA\<crate name>\cache\status
on Windows.
use binroots::save::{RootType, SaveError};
fn main() -> Result<(), SaveError> {
let mut status = Status::default();
*status.is_online = true;
status.save()?; // <- Saves the entire struct to the disk
*status.activity = Activity::Playing("video gamb".into());
status.activity.save(Status::ROOT_FOLDER, RootType::InMemory)?; // <- Only saves status.activity to the disk
Ok(())
}
After saving, the status
folder should look like this:
/tmp/binroots/status
├── activity => "Playing"
├── activity.value => "video gamb"
├── connections => "0"
└── is_online => "true"
Planned Features
I'm most likely going to add these in order. If it's not on this list, it's either implemented or unconsidered.
- Setting
hFile = INVALID_HANDLE_VALUE
on Windows when using in-memory storage. Currently can only save to persistent storage on Windows. - Unit tests lol
- Union support
- Unify
#[binroots_*]
macros into a single#[binroots]
macro Self::enable_autosave(self) -> Self
for reactive dataDeserialize
Send + Sync
BinrootsField::watch(Fn(T))
for socket-ish behaviorSelf::enable_rx(self) -> Self
for true two-way reactive data- Async support?
- Dual free/commercial license
Dependencies
~0.8–1.5MB
~29K SLoC