1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
//---------------------------------------------------------------------------------------------------- Use
use anyhow::{anyhow,bail};
use std::path::PathBuf;
use crate::common;
use bincode2::config::*;
use crate::header::*;
use std::io::{Seek};
//use log::{info,error,warn,trace,debug};
//use serde::{Serialize,Deserialize};
use std::io::{
Read,Write,
BufReader,BufWriter,
};
use once_cell::sync::Lazy;
//---------------------------------------------------------------------------------------------------- Bincode
static ENCODING_OPTIONS: Lazy<Configuration> = Lazy::new(bincode2::config::standard);
crate::common::impl_macro_binary!(Bincode2, "bin");
/// [`Bincode2`](https://docs.rs/bincode/2.0.0-rc.3) (`2.x.x-rc.x`) (binary) file format
///
/// ## `2.x.x-rc.x`
/// [`bincode 2.0.0`](https://docs.rs/bincode/2.0.0-rc.3) (currently not stable) brings big performance improvements.
///
/// It also no longer requires `serde`, having it's own `Encode` and `Decode` traits.
///
/// This means your type must implement these as well, e.g:
/// ```rust,ignore
/// use bincode::{Encode, Decode};
///
/// #[derive(Encode, Decode)]
/// struct State;
/// ```
///
/// To implement `bincode 2.x.x`'s new traits, add it to `Cargo.toml`:
/// ```txt
/// bincode = "2.0.0-rc.3"
/// ```
/// and add `#[derive(Encode, Decode)]` to your types, like you would with `serde`.
///
/// ## Encoding
/// The encoding option used is:
/// ```txt
/// bincode::config::standard()
/// ```
///
/// File extension is `.bin`.
///
/// ## Safety
/// When manually implementing, you are **promising** that the `PATH`'s manually specified are correct.
pub unsafe trait Bincode2: bincode2::Encode + bincode2::Decode {
#[doc(hidden)]
#[inline(always)]
/// Internal function. Most efficient `from_file()` impl.
fn __from_file() -> Result <Self, anyhow::Error> {
let path = Self::absolute_path()?;
let mut file = std::fs::File::open(path)?;
Self::from_reader(&mut file)
}
#[inline(always)]
/// Create [`Self`] from bytes.
fn from_bytes(bytes: &[u8]) -> Result<Self, anyhow::Error> {
ensure_header!(bytes);
match bincode2::decode_from_slice(&bytes[25..], *ENCODING_OPTIONS) {
Ok((s, _)) => Ok(s),
Err(e) => Err(e)?,
}
}
#[inline(always)]
/// Convert [`Self`] to bytes.
fn to_bytes(&self) -> Result<Vec<u8>, anyhow::Error> {
let mut vec = match bincode2::encode_to_vec(self, *ENCODING_OPTIONS) {
Ok(v) => v,
Err(e) => Err(e)?,
};
header_return!(vec)
}
#[inline(always)]
/// Create [`Self`] directly from reader `R`.
fn from_reader<R>(reader: &mut R) -> Result<Self, anyhow::Error>
where
R: Read,
{
let mut bytes = [0_u8; 25];
let mut reader = BufReader::new(reader);
reader.read_exact(&mut bytes)?;
ensure_header!(bytes);
Ok(bincode2::decode_from_std_read(&mut reader, *ENCODING_OPTIONS)?)
}
#[inline(always)]
/// Convert [`Self`] directly to the given [`slice`].
///
/// The amount of bytes written is returned on success.
///
/// ## Error
/// The slice must be at least `25` bytes in length to holder the header
/// bytes and must be large enough to hold the resulting serialized bytes.
fn to_slice(&self, slice: &mut [u8]) -> Result<usize, anyhow::Error> {
let len = slice.len();
if len < 25 {
bail!("input slice length less than 25: {len}");
}
slice[..25].copy_from_slice(&Self::full_header());
Ok(bincode2::encode_into_slice(self, &mut slice[25..], *ENCODING_OPTIONS)?)
}
#[inline(always)]
/// Convert [`Self`] to directly to the writer `W` without intermediate bytes.
///
/// The amount of bytes written is returned on success.
fn to_writer<W>(&self, writer: &mut W) -> Result<usize, anyhow::Error>
where
W: Write,
{
let mut writer = BufWriter::new(writer);
writer.write_all(&Self::full_header())?;
Ok(bincode2::encode_into_std_write(self, &mut writer, *ENCODING_OPTIONS)?)
}
impl_header!();
common::impl_binary!("bincode2");
}
//---------------------------------------------------------------------------------------------------- TESTS
//#[cfg(test)]
//mod tests {
//}