Some documentation; wrapper functions moved into own module
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
//! Error returned by Corona serializer.
|
||||
|
||||
use serde::ser;
|
||||
use thiserror::Error;
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
//! Convenience functions to be used with Corona.
|
||||
|
||||
use crate::ser::{SerResult, Corona};
|
||||
use crate::error::CoronaError;
|
||||
use serde::Serialize;
|
||||
|
||||
/// Write generated Rust code to the provided [`Write`][std::io::Write] implementation.
|
||||
pub fn write(value: impl Serialize, target: impl std::io::Write) -> SerResult {
|
||||
value.serialize(&mut Corona::new(target))
|
||||
}
|
||||
|
||||
/// Writes generated Rust code to file.
|
||||
///
|
||||
/// This is probably the most common way to use `corona`. When Cargo runs your crate's build task,
|
||||
/// it sets the `OUT_DIR` environment variable to the path to build target directory (see
|
||||
/// [Cargo reference](https://doc.rust-lang.org/cargo/reference/environment-variables.html) for more).
|
||||
/// So, you can use it in two steps:
|
||||
/// 1. Generate the Rust code and write it to temporary file:
|
||||
/// ```no_run
|
||||
/// # let value = ();
|
||||
/// let path: std::path::PathBuf = [
|
||||
/// std::env::var("OUT_DIR").expect("No build target path set"),
|
||||
/// "file_name.rs".into()
|
||||
/// ].iter().collect();
|
||||
/// corona::to_file(value, path).expect("Write failed");
|
||||
/// ```
|
||||
/// 2. [Include][include] the generated Rust code wherever it is needed:
|
||||
/// ```ignore
|
||||
/// let value = include!(concat!(env!(OUT_DIR), "/file_name.rs"));
|
||||
/// ```
|
||||
///
|
||||
/// [include]: https://doc.rust-lang.org/stable/std/macro.include.html
|
||||
pub fn to_file(value: impl Serialize, target: impl AsRef<std::path::Path>) -> SerResult {
|
||||
value.serialize(&mut Corona::new(std::fs::File::create(target)?))
|
||||
}
|
||||
|
||||
/// Convenience wrapper around [`to_file`].
|
||||
///
|
||||
/// This function finds out where the output directory is by looking at `OUT_DIR` environment variable
|
||||
/// and creates the file with the provided name there.
|
||||
pub fn to_out_dir(value: impl Serialize, file_name: impl AsRef<str>) -> SerResult {
|
||||
let path: std::path::PathBuf = [
|
||||
std::env::var("OUT_DIR").expect("OUT_DIR not set, check if you're running this from the build script"),
|
||||
file_name.as_ref().into()
|
||||
].iter().collect();
|
||||
value.serialize(&mut Corona::new(std::fs::File::create(path)?))
|
||||
}
|
||||
|
||||
/// Obtain string with generated Rust code.
|
||||
pub fn to_string(value: impl Serialize) -> Result<String, CoronaError> {
|
||||
let mut out = Vec::new();
|
||||
value.serialize(&mut Corona::new(&mut out))?;
|
||||
Ok(String::from_utf8(out)?)
|
||||
}
|
||||
+36
-16
@@ -1,19 +1,39 @@
|
||||
use crate::ser::SerResult;
|
||||
use serde::Serialize;
|
||||
//! Serde serializer generating Rust code.
|
||||
//!
|
||||
//! This crate can be used to "embed" something into code, having only some serialized
|
||||
//! data, like JSON or YAML. This way, you'll mostly escape runtime cost of deserialization,
|
||||
//! nearly as if you've written the same data directly in code by hand.
|
||||
//! Of course, in most cases this cost is already negligible, but for crates which use
|
||||
//! large blobs of data this crate can come in handy, improving startup times.
|
||||
//!
|
||||
//! ## Usage
|
||||
//! In general, to embed some code into crate, you have to use the build script
|
||||
//! and [`include!`][include] macro. Inside the build script, you'll generate
|
||||
//! some code with one of the [functions][funcs] provided by `corona`,
|
||||
//! and then include the generated file, like this:
|
||||
//! ```ignore
|
||||
//! let value = include!(concat!(env!(OUT_DIR), "/file_name.rs"));
|
||||
//! ```
|
||||
//!
|
||||
//! ## Limitations
|
||||
//! There are some cases when `corona` will be unable to generate valid code. Namely:
|
||||
//! 1. Since Serde doesn't provide us the full path to the type in question (and in most cases it's simply unable to),
|
||||
//! all the structs and enums used during value construction must be in scope.
|
||||
//! As a consequence, all of them must have distinct names - otherwise, there will be name clashes.
|
||||
//! 2. This serializer is intended for use with derived implementation. It may return bogus results
|
||||
//! when used with customized `Serialize`.
|
||||
//! 3. It is impossible to consume code for the type with private fields outside from the module it is defined in.
|
||||
//! In fact, to be able to use this type with `corona`, you'll have to distribute two copies of your crate,
|
||||
//! one of which would only export the definition with derived `Serialize` to be used by serializer
|
||||
//! during the build-time of the second copy. (Isn't this a bit too complex?)
|
||||
//! 4. It is impossible to use empty tuple structs (i.e. `Empty()`).
|
||||
//! From the Serde's point of view, they are indistinguishable from unit structs (i.e. `Unit`),
|
||||
//! but the same Rust syntax can't be used for both, and, since ordinary unit structs are much
|
||||
//! more common, it was decided to correctly handle them.
|
||||
//!
|
||||
//! [include]: https://doc.rust-lang.org/stable/std/macro.include.html
|
||||
|
||||
pub mod error;
|
||||
pub mod ser;
|
||||
|
||||
pub fn write(value: impl Serialize, target: impl std::io::Write) -> SerResult {
|
||||
value.serialize(&mut ser::Corona::new(target))
|
||||
}
|
||||
|
||||
pub fn to_file(value: impl Serialize, target: impl AsRef<std::path::Path>) -> SerResult {
|
||||
value.serialize(&mut ser::Corona::new(std::fs::File::create(target)?))
|
||||
}
|
||||
|
||||
pub fn to_string(value: impl Serialize) -> Result<String, error::CoronaError> {
|
||||
let mut out = Vec::new();
|
||||
value.serialize(&mut ser::Corona::new(&mut out))?;
|
||||
Ok(String::from_utf8(out)?)
|
||||
}
|
||||
pub mod funcs;
|
||||
pub use funcs::{to_file, to_out_dir, to_string, write};
|
||||
@@ -1,9 +1,15 @@
|
||||
//! Implementation of the Corona serializer.
|
||||
|
||||
use crate::error::CoronaError;
|
||||
use serde::ser;
|
||||
use std::io::Write;
|
||||
|
||||
pub(crate) type SerResult = Result<(), CoronaError>;
|
||||
|
||||
/// Main serializer implementation.
|
||||
///
|
||||
/// Users are usually encouraged to use [`to_out_dir`][crate::funcs::to_out_dir] or, in special cases,
|
||||
/// [`to_file`][crate::funcs::to_file], [`write`][crate::funcs::write] or [`to_string`][crate::funcs::to_string].
|
||||
pub struct Corona<W: Write> {
|
||||
writer: W,
|
||||
inside: bool,
|
||||
|
||||
Reference in New Issue
Block a user