Working new State encoding

This commit is contained in:
Nadja Reitzenstein 2021-10-18 10:39:31 +02:00
parent f2679a3408
commit fb8cbfc864
9 changed files with 879 additions and 1433 deletions

735
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ lmdb = []
[dependencies] [dependencies]
futures = { version = "0.3.16", features = ["thread-pool", "compat"] } futures = { version = "0.3.16", features = ["thread-pool", "compat"] }
futures-util = "0.3.16" #futures-util = "0.3.16"
futures-signals = "0.3.22" futures-signals = "0.3.22"
smol = "1.2.5" smol = "1.2.5"
@ -26,9 +26,9 @@ tracing = "0.1.28"
signal-hook = "0.3.9" signal-hook = "0.3.9"
slog = { version = "2.7.0", features = ["max_level_trace"] } #slog = { version = "2.7.0", features = ["max_level_trace"] }
slog-term = "2.8.0" #slog-term = "2.8.0"
slog-async = "2.7.0" #slog-async = "2.7.0"
capnp = "0.14.3" capnp = "0.14.3"
capnpc = "0.14.4" capnpc = "0.14.4"
@ -36,28 +36,29 @@ capnp-rpc = "0.14.1"
capnp-futures = "0.14.1" capnp-futures = "0.14.1"
serde = { version = "1.0.130", features = ["derive"] } serde = { version = "1.0.130", features = ["derive"] }
toml = "0.5.8" erased-serde = "0.3"
flexbuffers = "2.0.0" #toml = "0.5.8"
bincode = "2.0.0-dev" #flexbuffers = "2.0.0"
rkyv = "0.7" rkyv = "0.7"
ptr_meta = "0.1" ptr_meta = "0.1"
rkyv_typename = "0.7" rkyv_typename = "0.7"
rkyv_dyn = "0.7" rkyv_dyn = "0.7"
inventory = "0.1"
serde_dhall = { version = "0.10.1", default-features = false } serde_dhall = { version = "0.10.1", default-features = false }
serde_json = "1.0" serde_json = "1.0"
uuid = { version = "0.8.2", features = ["serde", "v4"] } uuid = { version = "0.8.2", features = ["serde", "v4"] }
clap = "2.33.3" #clap = "2.33.3"
# TODO update this if bindgen breaks (again) # TODO update this if bindgen breaks (again)
rsasl = "1.4.0" #rsasl = "1.4.0"
#rsasl = { path = "../../rsasl" } #rsasl = { path = "../../rsasl" }
# rumqtt needs tokio which I'm trying to get away from # rumqtt needs tokio which I'm trying to get away from
paho-mqtt = { git = "https://github.com/dequbed/paho.mqtt.rust.git", branch = "master", features = ["build_bindgen"] } #paho-mqtt = { git = "https://github.com/dequbed/paho.mqtt.rust.git", branch = "master", features = ["build_bindgen"] }
#mlua = { version = "0.4", features = ["async", "luajit"] } #mlua = { version = "0.4", features = ["async", "luajit"] }
@ -68,12 +69,12 @@ async-trait = "0.1.51"
lazy_static = "1.4.0" lazy_static = "1.4.0"
rust-argon2 = "0.8.3" #rust-argon2 = "0.8.3"
rand = "0.8.4" #rand = "0.8.4"
async-channel = "1.6.1" #async-channel = "1.6.1"
easy-parallel = "3.1.0" #easy-parallel = "3.1.0"
genawaiter = "0.99.1" #genawaiter = "0.99.1"
[build-dependencies] [build-dependencies]
capnpc = "0.14.4" capnpc = "0.14.4"
@ -83,6 +84,7 @@ walkdir = "2.3.2"
[dev-dependencies] [dev-dependencies]
futures-test = "0.3.16" futures-test = "0.3.16"
tempfile = "3.2" tempfile = "3.2"
bincode = "2.0.0-dev"
[patch.crates-io] [patch.crates-io]
bincode = { git = "https://github.com/dequbed/bincode.git", branch = "feature/in_place_buffer" } bincode = { git = "https://github.com/dequbed/bincode.git", branch = "feature/in_place_buffer" }

View File

@ -90,131 +90,3 @@ impl<V: Serialize<Ser>> Adapter for AllocAdapter<V> {
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use std::result::Result;
use std::ops::Deref;
use lmdb::{
EnvironmentFlags as EF,
DatabaseFlags as DF,
WriteFlags as WF,
};
pub struct TempEnv {
dir: tempfile::TempDir,
env: Arc<Environment>,
}
impl Deref for TempEnv {
type Target = Arc<Environment>;
fn deref(&self) -> &Self::Target {
&self.env
}
}
pub fn open_test_env() -> TempEnv {
let dir = tempfile::tempdir().expect("Failed to create tempdir for testdb");
let env = Environment::new()
.set_flags(EF::NO_SYNC | EF::WRITE_MAP)
.open(dir.path()).expect("Failed to open lmdb");
let env = Arc::new(env);
TempEnv { dir, env }
}
struct TestAdapter;
#[derive(Debug)]
enum TestErr {
Utf8(std::str::Utf8Error),
Binc(Box<bincode::ErrorKind>),
LMDB(lmdb::Error),
}
impl From<lmdb::Error> for TestErr {
fn from(e: lmdb::Error) -> TestErr {
TestErr::LMDB(e)
}
}
impl From<std::str::Utf8Error> for TestErr {
fn from(e: std::str::Utf8Error) -> TestErr {
TestErr::Utf8(e)
}
}
impl From<bincode::Error> for TestErr {
fn from(e: bincode::Error) -> TestErr {
TestErr::Binc(e)
}
}
impl DatabaseAdapter for TestAdapter {
type Key = str;
type Err = TestErr;
fn serialize_key(key: &Self::Key) -> &[u8] {
key.as_bytes()
}
fn deserialize_key<'de>(input: &'de [u8]) -> Result<&'de Self::Key, Self::Err> {
std::str::from_utf8(input).map_err(|e| e.into())
}
}
type TestDB<'txn> = Objectstore<'txn, TestAdapter, &'txn str>;
#[test]
fn simple_get() {
let e = open_test_env();
let ldb = e.create_db(None, DF::empty()).expect("Failed to create lmdb db");
let db = DB::new(e.env.clone(), ldb);
let testdb = TestDB::new(db.clone());
let mut val = "value";
let mut txn = db.begin_rw_txn().expect("Failed to being rw txn");
testdb.put(&mut txn, "key", &val, WF::empty()).expect("Failed to insert");
testdb.put(&mut txn, "key2", &val, WF::empty()).expect("Failed to insert");
testdb.put(&mut txn, "key3", &val, WF::empty()).expect("Failed to insert");
testdb.put(&mut txn, "key4", &val, WF::empty()).expect("Failed to insert");
testdb.put(&mut txn, "key5", &val, WF::empty()).expect("Failed to insert");
txn.commit().expect("commit failed");
{
let txn;
txn = db.begin_ro_txn().unwrap();
let val = testdb.get(&txn, "key").expect("Failed to retrieve");
assert_eq!(Some("value"), val);
}
{
let val2 = "longer_value";
let mut txn = db.begin_rw_txn().unwrap();
testdb.put(&mut txn, "key", &val2, WF::empty()).expect("Failed to update");
txn.commit().unwrap();
}
{
let txn = db.begin_ro_txn().unwrap();
let found = testdb.get_in_place(&txn, "key", &mut val).expect("Failed to retrieve update");
assert!(found);
assert_eq!("longer_value", val);
}
{
let txn = db.begin_ro_txn().unwrap();
let mut it = testdb.iter(&txn).unwrap();
assert_eq!("longer_value", it.next().unwrap().unwrap());
let mut i = 0;
while let Some(e) = it.next() {
assert_eq!("value", e.unwrap());
i += 1;
}
assert_eq!(i, 4)
}
}
}

View File

@ -149,7 +149,7 @@ impl StateAccessor {
} }
} }
#[cfg(test)] #[cfg(test_dis)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -17,18 +17,18 @@ mod initiator;
mod space; mod space;
*/ */
use crate::oid::ObjectIdentifier;
use std::convert::TryFrom;
use crate::state::value::{UInt32, Vec3u8, SerializeDynOid};
use rkyv::ser::serializers::AllocSerializer; use rkyv::ser::serializers::AllocSerializer;
use rkyv::SerializeUnsized; use rkyv::{SerializeUnsized, archived_value, Infallible, Deserialize};
use crate::oid::ObjectIdentifier;
use std::str::FromStr;
mod resource; mod resource;
mod schema; mod schema;
mod state; mod state;
mod db; mod db;
mod network; mod network;
mod oid; pub mod oid;
mod varint;
/* /*
@ -55,35 +55,46 @@ pub fn main() {
let db = db::StateDB::init("/tmp/state").unwrap(); let db = db::StateDB::init("/tmp/state").unwrap();
println!("{:#?}", db); println!("{:#?}", db);
let s = state::StateBuilder::new();
let state = s.add(
ObjectIdentifier::try_from("1.3.6.1.4.1.48398.612.1").unwrap(),
Box::new(UInt32(0)))
.add(
ObjectIdentifier::try_from("1.3.6.1.4.1.48398.612.2").unwrap(),
Box::new(Vec3u8 { a: 1, b: 2, c: 3})
)
.finish();
println!("{:?}", state);
let b = true; let b = true;
println!("{:?}", b.archived_type_oid()); //println!("{}", b.archived_type_oid());
let boid = ObjectIdentifier::try_from("1.3.6.1.4.1.48398.612.1.1").unwrap(); let boid = &state::value::OID_BOOL;
let b2 = Box::new(false); let b2 = false;
let ent = state::value::Entry { oid: &boid, val: &b2 }; let ent = state::Entry { oid: boid, val: &b2 };
println!("ent {:?}", &ent); println!("ent {:?}", &ent);
let s = serde_json::to_string(&ent).unwrap(); let s = serde_json::to_string(&ent).unwrap();
println!("{}", &s); println!("{}", &s);
let ent2: state::value::OwnedEntry = serde_json::from_str(&s).unwrap(); let ent2: state::OwnedEntry = serde_json::from_str(&s).unwrap();
println!("ent2: {:?}", ent2); println!("ent2: {:?}", ent2);
let mut ser = AllocSerializer::<1024>::default(); println!("Hello");
let mut ser = AllocSerializer::<32>::default();
//let b3 = Box::new(u32::from_ne_bytes([0xDE, 0xAD, 0xBE, 0xEF])) as Box<dyn state::value::SerializeValue>;
let b3 = Box::new(true) as Box<dyn state::value::SerializeValue>; let b3 = Box::new(true) as Box<dyn state::value::SerializeValue>;
let pos = b3.serialize_unsized(&mut ser).unwrap(); let pos3 = b3.serialize_unsized(&mut ser).unwrap();
let pos4 = 0;
//let pos4 = b4.serialize_unsized(&mut ser).unwrap();
let buf = ser.into_serializer().into_inner(); let buf = ser.into_serializer().into_inner();
println!("Serialized {} bytes: {:?}", pos, buf.as_slice()); println!("({}) {:?} | {:?}", pos3, &buf[..pos3], &buf[pos3..]);
//println!("Serialized {} bytes: {:?} | {:?} | {:?}", pos4, &buf[..pos3], &buf[pos3+12..pos4], &buf[pos4+12..]);
let r3 = unsafe {
archived_value::<Box<dyn state::value::SerializeValue>>(&buf.as_slice(), pos3)
};
let v3: Box<dyn state::value::SerializeValue> = r3.deserialize(&mut Infallible).unwrap();
println!("{:?}", v3);
let koid = ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.2.1").unwrap();
let state = state::State::build()
.add(koid, Box::new(0xDEADBEEFu32))
.finish();
println!("{:?}", state);
let json = serde_json::to_string(&state).unwrap();
println!("{}", json);
let state_back: state::State = serde_json::from_str(&json).unwrap();
println!("{:?}", state_back);
let val = state_back.inner;
} }
/*fn main() { /*fn main() {

View File

@ -6,8 +6,8 @@
//! //!
//! //!
//! ## Parsing OID String Representation //! ## Parsing OID String Representation
//! ```rust //! ```ignore
//! use oid::prelude::*; //! use crate::oid::prelude::*;
//! //!
//! fn main() -> Result<(), ObjectIdentifierError> { //! fn main() -> Result<(), ObjectIdentifierError> {
//! let oid = ObjectIdentifier::try_from("0.1.2.3")?; //! let oid = ObjectIdentifier::try_from("0.1.2.3")?;
@ -16,8 +16,8 @@
//! ``` //! ```
//! //!
//! ## Parsing OID Binary Representation //! ## Parsing OID Binary Representation
//! ```rust //! ```ignore
//! use oid::prelude::*; //! use prelude::*;
//! //!
//! fn main() -> Result<(), ObjectIdentifierError> { //! fn main() -> Result<(), ObjectIdentifierError> {
//! let oid = ObjectIdentifier::try_from(vec![0x00, 0x01, 0x02, 0x03])?; //! let oid = ObjectIdentifier::try_from(vec![0x00, 0x01, 0x02, 0x03])?;
@ -26,8 +26,8 @@
//! ``` //! ```
//! //!
//! ## Encoding OID as String Representation //! ## Encoding OID as String Representation
//! ```rust //! ```ignore
//! use oid::prelude::*; //! use prelude::*;
//! //!
//! fn main() -> Result<(), ObjectIdentifierError> { //! fn main() -> Result<(), ObjectIdentifierError> {
//! let oid = ObjectIdentifier::try_from("0.1.2.3")?; //! let oid = ObjectIdentifier::try_from("0.1.2.3")?;
@ -38,7 +38,7 @@
//! ``` //! ```
//! //!
//! ## Encoding OID as Binary Representation //! ## Encoding OID as Binary Representation
//! ```rust //! ```ignore
//! use oid::prelude::*; //! use oid::prelude::*;
//! //!
//! fn main() -> Result<(), ObjectIdentifierError> { //! fn main() -> Result<(), ObjectIdentifierError> {
@ -52,13 +52,20 @@
//! [Object Identifiers]: https://en.wikipedia.org/wiki/Object_identifier //! [Object Identifiers]: https://en.wikipedia.org/wiki/Object_identifier
//! [ITU]: https://en.wikipedia.org/wiki/International_Telecommunications_Union //! [ITU]: https://en.wikipedia.org/wiki/International_Telecommunications_Union
use core::convert::{TryFrom, TryInto}; use core::convert::{TryFrom };
use rkyv::{Archive, Serialize, Fallible}; use rkyv::{Archive, Serialize};
use rkyv::vec::{ArchivedVec, VecResolver}; use rkyv::vec::{ArchivedVec, VecResolver};
use std::ops::Deref;
use std::fmt;
use std::fmt::Formatter;
use rkyv::ser::Serializer;
use std::str::FromStr;
use crate::varint::VarU128;
use std::convert::TryInto;
// OID spec doesn't specify the maximum integer size of each node, so we default to usize type Node = u128;
type Node = usize; type VarNode = VarU128;
/// Convenience module for quickly importing the public interface (e.g., `use oid::prelude::*`) /// Convenience module for quickly importing the public interface (e.g., `use oid::prelude::*`)
pub mod prelude { pub mod prelude {
@ -106,111 +113,253 @@ pub enum ObjectIdentifierError {
} }
/// Object Identifier (OID) /// Object Identifier (OID)
#[derive(Clone, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Eq, PartialEq, Hash)]
#[repr(transparent)]
pub struct ObjectIdentifier { pub struct ObjectIdentifier {
root: ObjectIdentifierRoot, nodes: Box<[u8]>,
first_node: u8,
child_nodes: Vec<Node>,
} }
impl ObjectIdentifier { impl ObjectIdentifier {
const fn new(root: ObjectIdentifierRoot, first_node: u8, child_nodes: Vec<Node>) #[inline(always)]
-> Self pub const fn new_unchecked(nodes: Box<[u8]>) -> Self {
Self { nodes }
}
pub fn from_box(nodes: Box<[u8]>) -> Result<Self, ObjectIdentifierError> {
if nodes.len() < 1 {
return Err(ObjectIdentifierError::IllegalRootNode);
};
ObjectIdentifierRoot::try_from(nodes[0] / 40)?;
let mut parsing_big_int = false;
let mut big_int: Node = 0;
for i in 1..nodes.len() {
if !parsing_big_int && nodes[i] < 128 {} else {
if big_int > 0 {
if big_int >= Node::MAX >> 7 {
return Err(ObjectIdentifierError::IllegalChildNodeValue);
}
big_int <<= 7;
};
big_int |= (nodes[i] & !0x80) as Node;
parsing_big_int = nodes[i] & 0x80 != 0;
}
if big_int > 0 && !parsing_big_int {
big_int = 0;
}
}
Ok(Self { nodes })
}
pub fn build<B: AsRef<[Node]>>(root: ObjectIdentifierRoot, first: u8, children: B)
-> Result<Self, ObjectIdentifierError>
{ {
Self { root, first_node, child_nodes } if first > 40 {
return Err(ObjectIdentifierError::IllegalFirstChildNode);
}
let children = children.as_ref();
let mut vec = Vec::with_capacity(children.len() + 1);
vec.push((root as u8) * 40 + first);
for child in children {
let var: VarNode = child.into();
vec.extend_from_slice(var.as_bytes())
}
Ok(Self { nodes: vec.into_boxed_slice() })
}
#[inline(always)]
pub fn root(&self) -> Result<ObjectIdentifierRoot, ObjectIdentifierError> {
ObjectIdentifierRoot::try_from(self.nodes[0] / 40)
}
#[inline(always)]
pub const fn first_node(&self) -> u8 {
self.nodes[0] % 40
}
#[inline(always)]
pub fn child_nodes(&self) -> &[u8] {
&self.nodes[1..]
}
#[inline(always)]
pub const fn as_bytes(&self) -> &[u8] {
&self.nodes
} }
} }
impl Deref for ObjectIdentifier {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.nodes
}
}
impl FromStr for ObjectIdentifier {
type Err = ObjectIdentifierError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
let mut nodes = value.split(".");
let root = nodes.next()
.and_then(|n| n.parse::<u8>().ok())
.and_then(|n| n.try_into().ok())
.ok_or(ObjectIdentifierError::IllegalRootNode)?;
let first = nodes.next()
.and_then(|n| parse_string_first_node(n).ok())
.ok_or(ObjectIdentifierError::IllegalFirstChildNode)?;
let mut children = if let (_, Some(hint)) = nodes.size_hint() {
Vec::with_capacity(hint)
} else {
Vec::new()
};
for child in nodes.map(|n| n.parse().ok()) {
if let Some(c) = child {
children.push(c);
} else {
return Err(ObjectIdentifierError::IllegalChildNodeValue);
}
}
ObjectIdentifier::build(root, first, children)
}
}
impl fmt::Display for ObjectIdentifier {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let show: String = self.into();
write!(f, "{}", show)
}
}
impl fmt::Debug for ObjectIdentifier {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let show: String = self.into();
write!(f, "{}", show)
}
}
#[repr(transparent)]
pub struct ArchivedObjectIdentifier {
archived: ArchivedVec<u8>
}
impl Deref for ArchivedObjectIdentifier {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.archived.as_slice()
}
}
impl fmt::Debug for ArchivedObjectIdentifier {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", &convert_to_string(self.archived.as_slice())
.unwrap_or_else(|e| format!("Invalid OID: {:?}", e)))
}
}
impl Archive for ObjectIdentifier { impl Archive for ObjectIdentifier {
type Archived = ArchivedVec<u8>; type Archived = ArchivedObjectIdentifier;
type Resolver = VecResolver; type Resolver = VecResolver;
unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) { unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
let vec: Vec<u8> = self.clone().into(); let (oid_pos, oid_out) = rkyv::out_field!(out.archived);
vec.resolve(pos, resolver, out); ArchivedVec::resolve_from_slice(self.nodes.as_ref(), pos + oid_pos, resolver, oid_out);
}
}
impl Archive for &'static ObjectIdentifier {
type Archived = ArchivedObjectIdentifier;
type Resolver = VecResolver;
unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
let (oid_pos, oid_out) = rkyv::out_field!(out.archived);
ArchivedVec::resolve_from_slice(self.nodes.as_ref(), pos + oid_pos, resolver, oid_out);
} }
} }
impl<S: Fallible> Serialize<S> for ObjectIdentifier impl<S: Serializer + ?Sized> Serialize<S> for ObjectIdentifier
where Vec<u8>: Serialize<S> where [u8]: rkyv::SerializeUnsized<S>
{ {
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> { fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
let vec: Vec<u8> = self.clone().into(); ArchivedVec::serialize_from_slice(self.nodes.as_ref(), serializer)
vec.serialize(serializer)
} }
} }
fn parse_string_first_node( fn parse_string_first_node(first_child_node: &str) -> Result<u8, ObjectIdentifierError> {
nodes: &mut dyn Iterator<Item = &str>, let first_child_node: u8 = first_child_node
) -> Result<u8, ObjectIdentifierError> { .parse()
if let Some(first_child_node) = nodes.next() { .map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?;
let first_child_node: u8 = first_child_node if first_child_node > 39 {
.parse() return Err(ObjectIdentifierError::IllegalFirstChildNode);
.map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?; }
if first_child_node > 39 { Ok(first_child_node)
return Err(ObjectIdentifierError::IllegalFirstChildNode); }
}
Ok(first_child_node) fn parse_string_child_node(
node_str: &str,
out: &mut Vec<u8>
) -> Result<(), ObjectIdentifierError> {
let mut node: Node = node_str.parse()
.map_err(|_| ObjectIdentifierError::IllegalChildNodeValue)?;
// TODO bench against !*node &= 0x80, compiler may already optimize better
if node <= 127 {
out.push(node as u8);
} else { } else {
Err(ObjectIdentifierError::IllegalFirstChildNode) let vi: VarNode = node.into();
out.extend_from_slice(vi.as_bytes());
} }
}
fn parse_string_child_nodes( Ok(())
nodes: &mut dyn Iterator<Item = &str>,
) -> Result<Vec<Node>, ObjectIdentifierError> {
let mut result: Vec<Node> = vec![];
while let Some(node) = nodes.next() {
result.push(
node.parse()
.map_err(|_| ObjectIdentifierError::IllegalChildNodeValue)?,
);
}
Ok(result)
} }
impl ObjectIdentifier { impl ObjectIdentifier {
fn from_string<S>(value: S) -> Result<ObjectIdentifier, ObjectIdentifierError> fn from_string<S>(value: S) -> Result<ObjectIdentifier, ObjectIdentifierError>
where where
S: Into<String>, S: AsRef<str>,
{ {
let value = value.into(); ObjectIdentifier::from_str(value.as_ref())
let mut nodes = value.split("."); }
match &nodes.next() { }
Some(root_node_value) => {
let root_node_value: Result<u8, _> = root_node_value.parse(); fn convert_to_string(nodes: &[u8]) -> Result<String, ObjectIdentifierError> {
match root_node_value { assert!(nodes.len() > 0);
Ok(root_node) => { let root = nodes[0] / 40;
let root_node: Result<ObjectIdentifierRoot, _> = root_node.try_into(); let mut out = root.to_string();
match root_node {
Ok(root) => { out.push('.');
let first_node = parse_string_first_node(&mut nodes)?; let first = nodes[0] % 40;
Ok(ObjectIdentifier { out.extend(first.to_string().chars());
root,
first_node, let mut parsing_big_int = false;
child_nodes: parse_string_child_nodes(&mut nodes)?, let mut big_int: Node = 0;
}) for i in 1..nodes.len() {
} if !parsing_big_int && nodes[i] < 128 {
Err(_err) => Err(ObjectIdentifierError::IllegalRootNode), // less than 7 bit of node value
} out.push('.');
} let nr = nodes[i].to_string();
Err(_) => Err(ObjectIdentifierError::IllegalRootNode), out.extend(nr.chars());
} else {
if big_int > 0 {
if big_int >= Node::MAX >> 7 {
return Err(ObjectIdentifierError::IllegalChildNodeValue);
} }
} big_int <<= 7;
None => Err(ObjectIdentifierError::IllegalRootNode), };
big_int += (nodes[i] & !0x80) as Node;
parsing_big_int = nodes[i] & 0x80 != 0;
}
if big_int > 0 && !parsing_big_int {
out.push('.');
out.extend(big_int.to_string().chars());
big_int = 0;
} }
} }
Ok(out)
} }
impl Into<String> for &ObjectIdentifier { impl Into<String> for &ObjectIdentifier {
fn into(self) -> String { fn into(self) -> String {
let mut result: String = self.root.into(); convert_to_string(&self.nodes)
result.push_str(&format!(".{}", self.first_node)); .expect("Valid OID object couldn't be serialized.")
for node in &self.child_nodes {
result.push_str(&format!(".{}", node));
}
result
} }
} }
@ -220,34 +369,15 @@ impl Into<String> for ObjectIdentifier {
} }
} }
impl Into<Vec<u8>> for &ObjectIdentifier { impl<'a> Into<&'a [u8]> for &'a ObjectIdentifier {
fn into(self) -> Vec<u8> { fn into(self) -> &'a [u8] {
let mut result: Vec<u8> = vec![self.root as u8]; &self.nodes
result[0] = result[0] * 40 + self.first_node;
for node in self.child_nodes.iter() {
// TODO bench against !*node &= 0x80, compiler may already optimize better
if *node <= 127 {
result.push(*node as u8);
} else {
let mut value = *node;
let mut mask: Node = 0;
let mut encoded: Vec<u8> = vec![];
while value > 0x80 {
encoded.insert(0, (value & 0x7f | mask) as u8);
value >>= 7;
mask = 0x80;
}
encoded.insert(0, (value | mask) as u8);
result.append(&mut encoded);
}
}
result
} }
} }
impl Into<Vec<u8>> for ObjectIdentifier { impl Into<Vec<u8>> for ObjectIdentifier {
fn into(self) -> Vec<u8> { fn into(self) -> Vec<u8> {
(&self).into() self.nodes.into_vec()
} }
} }
@ -267,45 +397,15 @@ impl TryFrom<String> for ObjectIdentifier {
impl TryFrom<&[u8]> for ObjectIdentifier { impl TryFrom<&[u8]> for ObjectIdentifier {
type Error = ObjectIdentifierError; type Error = ObjectIdentifierError;
fn try_from(value: &[u8]) -> Result<ObjectIdentifier, Self::Error> { fn try_from(nodes: &[u8]) -> Result<ObjectIdentifier, Self::Error> {
if value.len() < 1 { Self::from_box(nodes.into())
return Err(ObjectIdentifierError::IllegalRootNode);
};
let root = ObjectIdentifierRoot::try_from(value[0] / 40)?;
let first_node = value[0] % 40;
let mut child_nodes = vec![];
let mut parsing_big_int = false;
let mut big_int: Node = 0;
for i in 1..value.len() {
if !parsing_big_int && value[i] < 128 {
child_nodes.push(value[i] as Node);
} else {
if big_int > 0 {
if big_int >= Node::max_value() >> 7 {
return Err(ObjectIdentifierError::IllegalChildNodeValue);
}
big_int <<= 7;
};
big_int |= (value[i] & !0x80) as Node;
parsing_big_int = value[i] & 0x80 != 0;
}
if big_int > 0 && !parsing_big_int {
child_nodes.push(big_int);
big_int = 0;
}
}
Ok(ObjectIdentifier {
root,
first_node,
child_nodes,
})
} }
} }
impl TryFrom<Vec<u8>> for ObjectIdentifier { impl TryFrom<Vec<u8>> for ObjectIdentifier {
type Error = ObjectIdentifierError; type Error = ObjectIdentifierError;
fn try_from(value: Vec<u8>) -> Result<ObjectIdentifier, Self::Error> { fn try_from(value: Vec<u8>) -> Result<ObjectIdentifier, Self::Error> {
value.as_slice().try_into() Self::from_box(value.into_boxed_slice())
} }
} }
@ -381,8 +481,7 @@ mod serde_support {
let encoded: String = self.into(); let encoded: String = self.into();
serializer.serialize_str(&encoded) serializer.serialize_str(&encoded)
} else { } else {
let encoded: Vec<u8> = self.into(); serializer.serialize_bytes(self.as_bytes())
serializer.serialize_bytes(&encoded)
} }
} }
} }
@ -391,125 +490,65 @@ mod serde_support {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::convert::TryInto;
mod serde_support { #[test]
use super::*; fn bincode_serde_roundtrip() {
use serde_derive::{Deserialize, Serialize}; let expected = ObjectIdentifier::build(
use serde_xml_rs; ObjectIdentifierRoot::ItuT,
0x01,
#[test] vec![1, 2, 3, 5, 8, 13, 21],
fn bincode_serde_serialize() { ).unwrap();
let expected: Vec<u8> = vec![ let buffer: Vec<u8> = bincode::serialize(&expected).unwrap();
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, let actual = bincode::deserialize(&buffer).unwrap();
0x0D, 0x15, assert_eq!(expected, actual);
];
let oid = ObjectIdentifier {
root: ObjectIdentifierRoot::ItuT,
first_node: 0x01,
child_nodes: vec![1, 2, 3, 5, 8, 13, 21],
};
let actual: Vec<u8> = bincode::serialize(&oid).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn bincode_serde_deserialize() {
let expected = ObjectIdentifier {
root: ObjectIdentifierRoot::ItuT,
first_node: 0x01,
child_nodes: vec![1, 2, 3, 5, 8, 13, 21],
};
let actual: ObjectIdentifier = bincode::deserialize(&[
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08,
0x0D, 0x15,
])
.unwrap();
assert_eq!(expected, actual);
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
struct MyStruct {
oid: ObjectIdentifier
}
#[test]
fn xml_serde_serialize() {
let mydata = MyStruct {
oid: ObjectIdentifier::try_from("1.2.3.5.8.13.21").unwrap()
};
let expected = r#"<MyStruct><oid>1.2.3.5.8.13.21</oid></MyStruct>"#;
let actual = serde_xml_rs::to_string(&mydata).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn xml_serde_deserialize_element() {
let src = r#"<mystruct><oid>1.2.3.5.8.13.21</oid></mystruct>"#;
let expected = MyStruct {
oid: ObjectIdentifier::try_from("1.2.3.5.8.13.21").unwrap()
};
let actual: MyStruct = serde_xml_rs::from_str(&src).unwrap();
assert_eq!(expected, actual);
}
#[test]
fn xml_serde_deserialize_attribute() {
let src = r#"<mystruct oid="1.2.3.5.8.13.21" />"#;
let expected = MyStruct {
oid: ObjectIdentifier::try_from("1.2.3.5.8.13.21").unwrap()
};
let actual: MyStruct = serde_xml_rs::from_str(&src).unwrap();
assert_eq!(expected, actual);
}
} }
#[test] #[test]
fn encode_binary_root_node_0() { fn encode_binary_root_node_0() {
let expected: Vec<u8> = vec![0]; let expected: Vec<u8> = vec![0];
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::ItuT, ObjectIdentifierRoot::ItuT,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}; ).unwrap();
let actual: Vec<u8> = (&oid).into(); let actual: Vec<u8> = oid.into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn encode_binary_root_node_1() { fn encode_binary_root_node_1() {
let expected: Vec<u8> = vec![40]; let expected: Vec<u8> = vec![40];
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::Iso, ObjectIdentifierRoot::Iso,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}; ).unwrap();
let actual: Vec<u8> = (&oid).into(); let actual: Vec<u8> = oid.into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn encode_binary_root_node_2() { fn encode_binary_root_node_2() {
let expected: Vec<u8> = vec![80]; let expected: Vec<u8> = vec![80];
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::JointIsoItuT, ObjectIdentifierRoot::JointIsoItuT,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}; ).unwrap();
let actual: Vec<u8> = (&oid).into(); let actual: Vec<u8> = oid.into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn encode_binary_example_1() { fn encode_binary_example_1() {
let expected: Vec<u8> = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15]; let expected: Vec<u8> = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15];
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::ItuT, ObjectIdentifierRoot::ItuT,
first_node: 0x01, 0x01,
child_nodes: vec![1, 2, 3, 5, 8, 13, 21], vec![1, 2, 3, 5, 8, 13, 21],
}; ).unwrap();
let actual: Vec<u8> = (&oid).into(); let actual: Vec<u8> = oid.into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
@ -519,35 +558,35 @@ mod tests {
0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53, 0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53,
0x92, 0x30, 0x92, 0x30,
]; ];
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::JointIsoItuT, ObjectIdentifierRoot::JointIsoItuT,
first_node: 39, 39,
child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352], vec![42, 2501, 65535, 2147483647, 1235, 2352],
}; ).unwrap();
let actual: Vec<u8> = (&oid).into(); let actual: Vec<u8> = (oid).into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn encode_string_root_node_0() { fn encode_string_root_node_0() {
let expected = "0.0"; let expected = "0.0";
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::ItuT, ObjectIdentifierRoot::ItuT,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}; ).unwrap();
let actual: String = (&oid).into(); let actual: String = (oid).into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn encode_string_root_node_1() { fn encode_string_root_node_1() {
let expected = "1.0"; let expected = "1.0";
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::Iso, ObjectIdentifierRoot::Iso,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}; ).unwrap();
let actual: String = (&oid).into(); let actual: String = (&oid).into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
@ -555,11 +594,11 @@ mod tests {
#[test] #[test]
fn encode_string_root_node_2() { fn encode_string_root_node_2() {
let expected = "2.0"; let expected = "2.0";
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::JointIsoItuT, ObjectIdentifierRoot::JointIsoItuT,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}; ).unwrap();
let actual: String = (&oid).into(); let actual: String = (&oid).into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
@ -567,11 +606,11 @@ mod tests {
#[test] #[test]
fn encode_string_example_1() { fn encode_string_example_1() {
let expected = "0.1.1.2.3.5.8.13.21"; let expected = "0.1.1.2.3.5.8.13.21";
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::ItuT, ObjectIdentifierRoot::ItuT,
first_node: 0x01, 0x01,
child_nodes: vec![1, 2, 3, 5, 8, 13, 21], vec![1, 2, 3, 5, 8, 13, 21],
}; ).unwrap();
let actual: String = (&oid).into(); let actual: String = (&oid).into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
@ -579,66 +618,66 @@ mod tests {
#[test] #[test]
fn encode_string_example_2() { fn encode_string_example_2() {
let expected = "2.39.42.2501.65535.2147483647.1235.2352"; let expected = "2.39.42.2501.65535.2147483647.1235.2352";
let oid = ObjectIdentifier { let oid = ObjectIdentifier::build(
root: ObjectIdentifierRoot::JointIsoItuT, ObjectIdentifierRoot::JointIsoItuT,
first_node: 39, 39,
child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352], vec![42, 2501, 65535, 2147483647, 1235, 2352],
}; ).unwrap();
let actual: String = (&oid).into(); let actual: String = (&oid).into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_binary_root_node_0() { fn parse_binary_root_node_0() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::ItuT, ObjectIdentifierRoot::ItuT,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}); );
let actual = vec![0x00].try_into(); let actual = vec![0x00].try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_binary_root_node_1() { fn parse_binary_root_node_1() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::Iso, ObjectIdentifierRoot::Iso,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}); );
let actual = vec![40].try_into(); let actual = vec![40].try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_binary_root_node_2() { fn parse_binary_root_node_2() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::JointIsoItuT, ObjectIdentifierRoot::JointIsoItuT,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}); );
let actual = vec![80].try_into(); let actual = vec![80].try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_binary_example_1() { fn parse_binary_example_1() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::ItuT, ObjectIdentifierRoot::ItuT,
first_node: 0x01, 0x01,
child_nodes: vec![1, 2, 3, 5, 8, 13, 21], vec![1, 2, 3, 5, 8, 13, 21],
}); );
let actual = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15].try_into(); let actual = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15].try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_binary_example_2() { fn parse_binary_example_2() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::JointIsoItuT, ObjectIdentifierRoot::JointIsoItuT,
first_node: 39, 39,
child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352], vec![42, 2501, 65535, 2147483647, 1235, 2352],
}); );
let actual = vec![ let actual = vec![
0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53, 0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53,
0x92, 0x30, 0x92, 0x30,
@ -649,55 +688,55 @@ mod tests {
#[test] #[test]
fn parse_string_root_node_0() { fn parse_string_root_node_0() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::ItuT, ObjectIdentifierRoot::ItuT,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}); );
let actual = "0.0".try_into(); let actual = "0.0".try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_string_root_node_1() { fn parse_string_root_node_1() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::Iso, ObjectIdentifierRoot::Iso,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}); );
let actual = "1.0".try_into(); let actual = "1.0".try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_string_root_node_2() { fn parse_string_root_node_2() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::JointIsoItuT, ObjectIdentifierRoot::JointIsoItuT,
first_node: 0x00, 0x00,
child_nodes: vec![], vec![],
}); );
let actual = "2.0".try_into(); let actual = "2.0".try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_string_example_1() { fn parse_string_example_1() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::ItuT, ObjectIdentifierRoot::ItuT,
first_node: 0x01, 0x01,
child_nodes: vec![1, 2, 3, 5, 8, 13, 21], vec![1, 2, 3, 5, 8, 13, 21],
}); );
let actual = "0.1.1.2.3.5.8.13.21".try_into(); let actual = "0.1.1.2.3.5.8.13.21".try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test] #[test]
fn parse_string_example_2() { fn parse_string_example_2() {
let expected = Ok(ObjectIdentifier { let expected = ObjectIdentifier::build(
root: ObjectIdentifierRoot::JointIsoItuT, ObjectIdentifierRoot::JointIsoItuT,
first_node: 39, 39,
child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352], vec![42, 2501, 65535, 2147483647, 1235, 2352],
}); );
let actual = "2.39.42.2501.65535.2147483647.1235.2352".try_into(); let actual = "2.39.42.2501.65535.2147483647.1235.2352".try_into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
@ -717,7 +756,7 @@ mod tests {
for i in 40..core::u8::MAX { for i in 40..core::u8::MAX {
let string_val = format!("{}.2.3.4", i); let string_val = format!("{}.2.3.4", i);
let mut nodes_iter = string_val.split("."); let mut nodes_iter = string_val.split(".");
let actual = parse_string_first_node(&mut nodes_iter); let actual = parse_string_first_node(nodes_iter.next().unwrap());
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
} }
@ -727,17 +766,7 @@ mod tests {
let expected = Err(ObjectIdentifierError::IllegalFirstChildNode); let expected = Err(ObjectIdentifierError::IllegalFirstChildNode);
let string_val = String::new(); let string_val = String::new();
let mut nodes_iter = string_val.split("."); let mut nodes_iter = string_val.split(".");
let actual = parse_string_first_node(&mut nodes_iter); let actual = parse_string_first_node(nodes_iter.next().unwrap());
assert_eq!(expected, actual);
}
#[test]
fn illegal_first_node_none() {
let expected = Err(ObjectIdentifierError::IllegalFirstChildNode);
let string_val = String::new();
let mut nodes_iter = string_val.split(".");
let _ = nodes_iter.next();
let actual = parse_string_first_node(&mut nodes_iter);
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
@ -746,7 +775,7 @@ mod tests {
let expected = Err(ObjectIdentifierError::IllegalFirstChildNode); let expected = Err(ObjectIdentifierError::IllegalFirstChildNode);
let string_val = String::from("40"); let string_val = String::from("40");
let mut nodes_iter = string_val.split("."); let mut nodes_iter = string_val.split(".");
let actual = parse_string_first_node(&mut nodes_iter); let actual = parse_string_first_node(nodes_iter.next().unwrap());
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
@ -814,11 +843,11 @@ mod tests {
#[test] #[test]
fn encode_to_string() { fn encode_to_string() {
let expected = String::from("1.2.3.4"); let expected = String::from("1.2.3.4");
let actual: String = ObjectIdentifier { let actual: String = ObjectIdentifier::build(
root: ObjectIdentifierRoot::Iso, ObjectIdentifierRoot::Iso,
first_node: 2, 2,
child_nodes: vec![3, 4], vec![3, 4],
} ).unwrap()
.into(); .into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
@ -826,11 +855,11 @@ mod tests {
#[test] #[test]
fn encode_to_bytes() { fn encode_to_bytes() {
let expected = vec![0x2A, 0x03, 0x04]; let expected = vec![0x2A, 0x03, 0x04];
let actual: Vec<u8> = ObjectIdentifier { let actual: Vec<u8> = ObjectIdentifier::build(
root: ObjectIdentifierRoot::Iso, ObjectIdentifierRoot::Iso,
first_node: 2, 2,
child_nodes: vec![3, 4], vec![3, 4],
} ).unwrap()
.into(); .into();
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }

View File

@ -20,20 +20,18 @@ use rkyv::{
out_field, out_field,
}; };
use crate::oid::ObjectIdentifier;
pub mod value; pub mod value;
pub use value::{ use value::{SerializeValue, RegisteredImpl};
SerializeDynValue, use crate::state::value::{TypeOid, DynVal, DynOwnedVal};
DeserializeDynValue, use crate::oid::ObjectIdentifier;
}; use serde::ser::SerializeMap;
use std::ops::Deref;
#[derive(Archive, Serialize, Deserialize)] use std::fmt::Formatter;
pub struct StateEntry { use serde::Deserializer;
key: ObjectIdentifier, use serde::de::MapAccess;
val: Box<dyn SerializeDynValue>, use serde::de::Error as _;
}
#[derive(serde::Serialize, serde::Deserialize)]
#[derive(Archive, Serialize, Deserialize)] #[derive(Archive, Serialize, Deserialize)]
/// State object of a resource /// State object of a resource
/// ///
@ -43,44 +41,41 @@ pub struct StateEntry {
/// 3. it is sendable and forwarded to all Actors and Notifys /// 3. it is sendable and forwarded to all Actors and Notifys
pub struct State { pub struct State {
hash: u64, hash: u64,
inner: Vec<StateEntry>, pub inner: Vec<OwnedEntry>,
}
impl PartialEq for State {
fn eq(&self, other: &Self) -> bool {
self.hash == other.hash
}
}
impl PartialEq<Archived<State>> for State {
fn eq(&self, other: &Archived<State>) -> bool {
self.hash == other.hash
}
}
impl Eq for State {}
impl fmt::Debug for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut sf = f.debug_struct("State");
for StateEntry { key, val } in self.inner.iter() {
let k: String = key.into();
sf.field(k.as_ref(), val);
}
sf.finish()
}
} }
impl State { impl State {
pub fn build() -> StateBuilder { pub fn build() -> StateBuilder {
StateBuilder::new() StateBuilder::new()
} }
pub fn hash(&self) -> u64 { pub fn hash(&self) -> u64 {
self.hash self.hash
} }
} }
impl PartialEq for State {
fn eq(&self, other: &Self) -> bool {
self.hash == other.hash
}
}
impl Eq for State {}
impl fmt::Debug for State {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut sf = f.debug_struct("State");
for OwnedEntry { oid, val } in self.inner.iter() {
let k: String = oid.into();
sf.field(k.as_ref(), val);
}
sf.finish()
}
}
pub struct StateBuilder { pub struct StateBuilder {
hasher: DefaultHasher, hasher: DefaultHasher,
inner: Vec<StateEntry> inner: Vec<OwnedEntry>
} }
impl StateBuilder { impl StateBuilder {
@ -102,14 +97,71 @@ impl StateBuilder {
/// to `Hash`. Specifically, you can't have a trait object of `Hash` because `Hash` depends on /// to `Hash`. Specifically, you can't have a trait object of `Hash` because `Hash` depends on
/// `Self`. In this function however the compiler still knows the exact type of `V` and can /// `Self`. In this function however the compiler still knows the exact type of `V` and can
/// call statically call its `hash` method. /// call statically call its `hash` method.
pub fn add<V>(mut self, key: ObjectIdentifier<>, val: Box<V>) -> Self pub fn add<V>(mut self, oid: ObjectIdentifier, val: Box<V>) -> Self
where V: SerializeDynValue + Hash where V: SerializeValue + Hash + Archive,
Archived<V>: TypeOid + RegisteredImpl,
{ {
// Hash before creating the StateEntry struct which removes the type information // Hash before creating the StateEntry struct which removes the type information
key.hash(&mut self.hasher); oid.hash(&mut self.hasher);
val.hash(&mut self.hasher); val.hash(&mut self.hasher);
self.inner.push(StateEntry { key, val }); self.inner.push(OwnedEntry { oid, val });
self self
} }
} }
#[derive(Debug)]
pub struct Entry<'a> {
pub oid: &'a ObjectIdentifier,
pub val: &'a dyn SerializeValue,
}
#[derive(Debug, Archive, Serialize, Deserialize)]
pub struct OwnedEntry {
pub oid: ObjectIdentifier,
pub val: Box<dyn SerializeValue>,
}
impl<'a> serde::Serialize for Entry<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer
{
let mut ser = serializer.serialize_map(Some(1))?;
ser.serialize_entry(&self.oid, &DynVal(self.val))?;
ser.end()
}
}
impl serde::Serialize for OwnedEntry {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer
{
let mut ser = serializer.serialize_map(Some(1))?;
ser.serialize_entry(&self.oid, &DynVal(self.val.deref()))?;
ser.end()
}
}
impl<'de> serde::Deserialize<'de> for OwnedEntry {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
deserializer.deserialize_map(OwnedEntryVisitor)
}
}
struct OwnedEntryVisitor;
impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor {
type Value = OwnedEntry;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "an one entry map from OID to some value object")
}
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error>
{
let oid: ObjectIdentifier = map.next_key()?
.ok_or(A::Error::missing_field("oid"))?;
let val: DynOwnedVal = map.next_value()?;
Ok(OwnedEntry { oid, val: val.0 })
}
}

View File

@ -5,12 +5,13 @@ use std::{
fmt, fmt,
any::Any, any::Any,
hash::Hash, hash::Hash,
ops::Deref, str::FromStr,
convert::TryFrom,
}; };
use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized, ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized}; use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized,
use rkyv_dyn::{archive_dyn, DynSerializer, DynError, DynDeserializer}; ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized,
};
use rkyv_dyn::{DynSerializer, DynError, DynDeserializer};
use rkyv_typename::TypeName; use rkyv_typename::TypeName;
use ptr_meta::{DynMetadata, Pointee}; use ptr_meta::{DynMetadata, Pointee};
@ -24,8 +25,14 @@ use std::fmt::Formatter;
use serde::de::Error as _; use serde::de::Error as _;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
/// Adding a custom type to BFFH state managenment:
pub trait Value: fmt::Debug + erased_serde::Serialize { ///
/// 1. Implement `serde`'s [`Serialize`](serde::Serialize) and [`Deserialize`](serde::Deserialize)
/// - `derive()`d instances work just fine, but keep stability over releases in mind.
/// 2. Implement rkyv's [`Serialize`](rkyv::Serialize).
/// 3. Implement TypeOid on your Archived type (i.e. `<T as Archive>::Archived`)
/// 4. Implement this
pub trait Value: Any + fmt::Debug + erased_serde::Serialize {
/// Initialize `&mut self` from `deserializer` /// Initialize `&mut self` from `deserializer`
/// ///
/// At the point this is called &mut self is of undefined value but guaranteed to be well /// At the point this is called &mut self is of undefined value but guaranteed to be well
@ -38,9 +45,11 @@ pub trait Value: fmt::Debug + erased_serde::Serialize {
-> Result<(), erased_serde::Error>; -> Result<(), erased_serde::Error>;
} }
erased_serde::serialize_trait_object!(Value); erased_serde::serialize_trait_object!(Value);
erased_serde::serialize_trait_object!(SerializeValue);
erased_serde::serialize_trait_object!(DeserializeValue);
impl<T> Value for T impl<T> Value for T
where T: fmt::Debug where T: Any + fmt::Debug
+ erased_serde::Serialize + erased_serde::Serialize
+ for<'de> serde::Deserialize<'de> + for<'de> serde::Deserialize<'de>
{ {
@ -52,44 +61,32 @@ impl<T> Value for T
} }
} }
impl Pointee for dyn Value { #[repr(transparent)]
type Metadata = DynMetadata<dyn Value>; pub(super) struct DynVal<'a>(pub &'a dyn SerializeValue);
} impl<'a> serde::Serialize for DynVal<'a> {
#[derive(Debug)]
pub struct Entry<'a> {
pub oid: &'a ObjectIdentifier,
pub val: &'a dyn Value,
}
#[derive(Debug)]
pub struct OwnedEntry {
pub oid: ObjectIdentifier,
pub val: Box<dyn DeserializeValue>,
}
impl<'a> serde::Serialize for Entry<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::Serializer where S: serde::Serializer
{ {
let mut ser = serializer.serialize_map(Some(1))?; let mut ser = serializer.serialize_map(Some(1))?;
ser.serialize_entry(self.oid, self.val)?; let oid = self.0.archived_type_oid();
ser.serialize_entry(oid, self.0)?;
ser.end() ser.end()
} }
} }
#[repr(transparent)]
impl<'de> serde::Deserialize<'de> for OwnedEntry { pub(super) struct DynOwnedVal(pub Box<dyn SerializeValue>);
impl<'de> serde::Deserialize<'de> for DynOwnedVal {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: serde::Deserializer<'de> where D: serde::Deserializer<'de>
{ {
deserializer.deserialize_map(OwnedEntryVisitor) deserializer.deserialize_map(DynValVisitor)
} }
} }
struct OwnedEntryVisitor; struct DynValVisitor;
impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor { impl<'de> serde::de::Visitor<'de> for DynValVisitor {
type Value = OwnedEntry; type Value = DynOwnedVal;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "an one entry map from OID to some value object") write!(formatter, "an one entry map from OID to some value object")
@ -104,10 +101,9 @@ impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor {
// Get OID first. That's easy, we know it's the key, we know how to read it. // Get OID first. That's easy, we know it's the key, we know how to read it.
let oid: ObjectIdentifier = map.next_key()? let oid: ObjectIdentifier = map.next_key()?
.ok_or(A::Error::missing_field("oid"))?; .ok_or(A::Error::missing_field("oid"))?;
let b: Vec<u8> = oid.clone().into();
// Get the Value vtable for that OID. Or fail because we don't know that OID, either works. // Get the Value vtable for that OID. Or fail because we don't know that OID, either works.
let valimpl = IMPL_REGISTRY.get(ImplId::from_type_oid(&b)) let valimpl = IMPL_REGISTRY.get(ImplId::from_type_oid(&oid))
.ok_or(serde::de::Error::invalid_value( .ok_or(serde::de::Error::invalid_value(
serde::de::Unexpected::Other("unknown oid"), serde::de::Unexpected::Other("unknown oid"),
&"oid an implementation was registered for", &"oid an implementation was registered for",
@ -115,7 +111,7 @@ impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor {
// Casting random usize you find on the side of the road as vtable on unchecked pointers. // Casting random usize you find on the side of the road as vtable on unchecked pointers.
// What could possibly go wrong? >:D // What could possibly go wrong? >:D
let valbox: MaybeUninit<Box<dyn DeserializeValue>> = unsafe { let valbox: MaybeUninit<Box<dyn SerializeValue>> = unsafe {
// "recreate" vtable as fat ptr metadata (we literally just cast an `usize` but the // "recreate" vtable as fat ptr metadata (we literally just cast an `usize` but the
// only way to put this usize into that spot is by having a valid vtable cast so it's // only way to put this usize into that spot is by having a valid vtable cast so it's
// probably almost safe) // probably almost safe)
@ -143,14 +139,14 @@ impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor {
// the game yet. >:D // the game yet. >:D
let seed = InitIntoSelf(valbox); let seed = InitIntoSelf(valbox);
let val = map.next_value_seed(seed)?; let val = map.next_value_seed(seed)?;
Ok(OwnedEntry { oid, val }) Ok(DynOwnedVal(val))
} }
} }
struct InitIntoSelf(MaybeUninit<Box<dyn DeserializeValue>>); struct InitIntoSelf(MaybeUninit<Box<dyn SerializeValue>>);
impl<'de> serde::de::DeserializeSeed<'de> for InitIntoSelf { impl<'de> serde::de::DeserializeSeed<'de> for InitIntoSelf {
type Value = Box<dyn DeserializeValue>; type Value = Box<dyn SerializeValue>;
fn deserialize<D>(mut self, deserializer: D) -> Result<Self::Value, D::Error> fn deserialize<D>(mut self, deserializer: D) -> Result<Self::Value, D::Error>
where D: serde::Deserializer<'de> where D: serde::Deserializer<'de>
@ -171,39 +167,20 @@ impl<'de> serde::de::DeserializeSeed<'de> for InitIntoSelf {
} }
pub trait TypeOid { pub trait TypeOid {
fn get_type_oid() -> ObjectIdentifier; fn get_type_oid() -> &'static ObjectIdentifier;
fn get_type_name() -> &'static str;
fn get_type_desc() -> &'static str;
} }
impl TypeOid for Archived<bool> {
fn get_type_oid() -> ObjectIdentifier {
ObjectIdentifier::try_from("1.3.6.1.4.1.48398.612.1.1").unwrap()
}
}
impl DeserializeDynOid for Archived<bool>
where Archived<bool>: for<'a> Deserialize<bool, (dyn DynDeserializer + 'a)>
{
unsafe fn deserialize_dynoid(&self, deserializer: &mut dyn DynDeserializer, alloc: &mut dyn FnMut(Layout) -> *mut u8) -> Result<*mut (), DynError> {
let ptr = alloc(Layout::new::<bool>()).cast::<bool>();
ptr.write(self.deserialize(deserializer)?);
Ok(ptr as *mut ())
}
fn deserialize_dynoid_metadata(&self, deserializer: &mut dyn DynDeserializer) -> Result<<dyn SerializeValue as Pointee>::Metadata, DynError> {
unsafe {
Ok(core::mem::transmute(ptr_meta::metadata(
core::ptr::null::<bool>() as *const dyn SerializeValue
)))
}
}
}
impl<S: ScratchSpace + Serializer + ?Sized> SerializeUnsized<S> for dyn SerializeValue { impl<S: ScratchSpace + Serializer + ?Sized> SerializeUnsized<S> for dyn SerializeValue {
fn serialize_unsized(&self, mut serializer: &mut S) -> Result<usize, S::Error> { fn serialize_unsized(&self, mut serializer: &mut S) -> Result<usize, S::Error> {
self.serialize_dynoid(&mut serializer) self.serialize_dynoid(&mut serializer)
.map_err(|e| *e.downcast::<S::Error>().unwrap()) .map_err(|e| *e.downcast::<S::Error>().unwrap())
} }
fn serialize_metadata(&self, mut serializer: &mut S) -> Result<Self::MetadataResolver, S::Error> { fn serialize_metadata(&self, serializer: &mut S) -> Result<Self::MetadataResolver, S::Error> {
self.serialize_metadata(serializer) let oid = self.archived_type_oid();
oid.serialize(serializer)
} }
} }
@ -211,7 +188,7 @@ impl<S: ScratchSpace + Serializer + ?Sized> SerializeUnsized<S> for dyn Serializ
/// Serialize dynamic types by storing an OID alongside /// Serialize dynamic types by storing an OID alongside
pub trait SerializeDynOid { pub trait SerializeDynOid {
fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result<usize, DynError>; fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result<usize, DynError>;
fn archived_type_oid(&self) -> ObjectIdentifier; fn archived_type_oid(&self) -> &'static ObjectIdentifier;
} }
impl<T> SerializeDynOid for T impl<T> SerializeDynOid for T
@ -222,12 +199,12 @@ impl<T> SerializeDynOid for T
serializer.serialize_value(self) serializer.serialize_value(self)
} }
fn archived_type_oid(&self) -> ObjectIdentifier { fn archived_type_oid(&self) -> &'static ObjectIdentifier {
Archived::<T>::get_type_oid() Archived::<T>::get_type_oid()
} }
} }
trait DeserializeDynOid { pub trait DeserializeDynOid {
unsafe fn deserialize_dynoid( unsafe fn deserialize_dynoid(
&self, &self,
deserializer: &mut dyn DynDeserializer, deserializer: &mut dyn DynDeserializer,
@ -243,7 +220,7 @@ trait DeserializeDynOid {
#[ptr_meta::pointee] #[ptr_meta::pointee]
pub trait SerializeValue: Value + SerializeDynOid {} pub trait SerializeValue: Value + SerializeDynOid {}
impl<T: Archive + SerializeDynOid + Value> SerializeValue for T impl<T: Archive + Value + SerializeDynOid> SerializeValue for T
where where
T::Archived: RegisteredImpl T::Archived: RegisteredImpl
{} {}
@ -258,9 +235,7 @@ impl ArchivePointee for dyn DeserializeValue {
archived.pointer_metadata() archived.pointer_metadata()
} }
} }
impl<D: ?Sized> DeserializeUnsized<dyn SerializeValue, D> for dyn DeserializeValue impl<D: Fallible + ?Sized> DeserializeUnsized<dyn SerializeValue, D> for dyn DeserializeValue {
where D: Fallible + DynDeserializer
{
unsafe fn deserialize_unsized(&self, unsafe fn deserialize_unsized(&self,
mut deserializer: &mut D, mut deserializer: &mut D,
mut alloc: impl FnMut(Layout) -> *mut u8 mut alloc: impl FnMut(Layout) -> *mut u8
@ -282,7 +257,7 @@ impl ArchiveUnsized for dyn SerializeValue {
unsafe fn resolve_metadata(&self, pos: usize, resolver: Self::MetadataResolver, out: *mut ArchivedMetadata<Self>) { unsafe fn resolve_metadata(&self, pos: usize, resolver: Self::MetadataResolver, out: *mut ArchivedMetadata<Self>) {
let (oid_pos, oid) = out_field!(out.type_oid); let (oid_pos, oid) = out_field!(out.type_oid);
let type_oid = self.archived_type_oid(); let type_oid = self.archived_type_oid();
type_oid.resolve(oid_pos, resolver, oid); type_oid.resolve(pos + oid_pos, resolver, oid);
} }
} }
@ -297,7 +272,10 @@ impl ArchivedValueMetadata {
pub fn vtable(&self) -> usize { pub fn vtable(&self) -> usize {
IMPL_REGISTRY IMPL_REGISTRY
.get(ImplId::from_type_oid(&self.type_oid)).expect("Unregistered type oid") .get(ImplId::from_type_oid(&self.type_oid)).expect(&format!("Unregistered \
type \
oid \
{:?}", self.type_oid))
.vtable .vtable
} }
@ -307,41 +285,58 @@ impl ArchivedValueMetadata {
} }
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
struct ImplId<'a> { pub struct ImplId<'a> {
type_oid: &'a [u8], type_oid: &'a [u8],
} }
impl<'a> ImplId<'a> { impl<'a> ImplId<'a> {
fn from_type_oid(type_oid: &'a [u8]) -> Self { pub fn from_type_oid(type_oid: &'a [u8]) -> Self {
Self { type_oid } Self { type_oid }
} }
} }
impl ImplId<'static> { impl ImplId<'static> {
fn new<T: TypeOid>() -> Self { fn new<T: TypeOid>() -> Self {
let oid: Vec<u8> = T::get_type_oid().into();
Self { Self {
type_oid: oid.leak() type_oid: &T::get_type_oid()
} }
} }
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
struct ImplData { struct ImplData<'a> {
pub vtable: usize, pub vtable: usize,
// TODO DebugImpl pub name: &'a str,
// TODO DebugInfo pub desc: &'a str,
pub info: ImplDebugInfo,
} }
impl ImplData { #[derive(Copy, Clone, Debug)]
#[doc(hidden)]
pub struct ImplDebugInfo {
pub file: &'static str,
pub line: u32,
pub column: u32,
}
macro_rules! debug_info {
() => {
ImplDebugInfo {
file: core::file!(),
line: core::line!(),
column: core::column!(),
}
}
}
impl ImplData<'_> {
pub unsafe fn pointer_metadata<T: ?Sized>(&self) -> DynMetadata<T> { pub unsafe fn pointer_metadata<T: ?Sized>(&self) -> DynMetadata<T> {
core::mem::transmute(self.vtable) core::mem::transmute(self.vtable)
} }
} }
struct ImplEntry<'a> { pub struct ImplEntry<'a> {
id: ImplId<'a>, id: ImplId<'a>,
data: ImplData, data: ImplData<'a>,
} }
inventory::collect!(ImplEntry<'static>); inventory::collect!(ImplEntry<'static>);
@ -352,13 +347,17 @@ impl ImplEntry<'_> {
id: ImplId::new::<T>(), id: ImplId::new::<T>(),
data: ImplData { data: ImplData {
vtable: <T as RegisteredImpl>::vtable(), vtable: <T as RegisteredImpl>::vtable(),
name: <T as TypeOid>::get_type_name(),
desc: <T as TypeOid>::get_type_desc(),
info: <T as RegisteredImpl>::debug_info(),
}, },
} }
} }
} }
#[derive(Debug)]
struct ImplRegistry { struct ImplRegistry {
oid_to_data: HashMap<ImplId<'static>, ImplData>, oid_to_data: HashMap<ImplId<'static>, ImplData<'static>>,
} }
impl ImplRegistry { impl ImplRegistry {
@ -368,6 +367,14 @@ impl ImplRegistry {
fn add_entry(&mut self, entry: &'static ImplEntry) { fn add_entry(&mut self, entry: &'static ImplEntry) {
let old_val = self.oid_to_data.insert(entry.id, entry.data); let old_val = self.oid_to_data.insert(entry.id, entry.data);
if let Some(old) = old_val {
eprintln!("Value impl oid conflict for {:?}", entry.id.type_oid);
eprintln!("Existing impl registered at {}:{}:{}",
old.info.file, old.info.line, old.info.column);
eprintln!("New impl registered at {}:{}:{}",
entry.data.info.file, entry.data.info.line, entry.data.info.column);
}
assert!(old_val.is_none()); assert!(old_val.is_none());
} }
@ -389,101 +396,124 @@ lazy_static::lazy_static! {
pub unsafe trait RegisteredImpl { pub unsafe trait RegisteredImpl {
fn vtable() -> usize; fn vtable() -> usize;
fn debug_info() -> ImplDebugInfo;
} }
unsafe impl RegisteredImpl for bool { macro_rules! oiddeser {
fn vtable() -> usize { ( $y:ty, $z:ty ) => {
unsafe { impl DeserializeDynOid for $y
core::mem::transmute(ptr_meta::metadata( where $y: for<'a> Deserialize<$z, (dyn DynDeserializer + 'a)>
core::ptr::null::<bool>() as *const dyn DeserializeValue {
)) unsafe fn deserialize_dynoid(&self, deserializer: &mut dyn DynDeserializer, alloc: &mut dyn FnMut(Layout) -> *mut u8) -> Result<*mut (), DynError> {
} let ptr = alloc(Layout::new::<$z>()).cast::<$z>();
} ptr.write(self.deserialize(deserializer)?);
} Ok(ptr as *mut ())
inventory::submit! {ImplEntry::new::<bool>()}
#[archive_dyn(deserialize)]
/// Trait to be implemented by any value in the state map.
///
/// A value can be any type not having dangling references (with the added
/// restriction that it has to implement `Debug` for debugger QoL).
/// In fact Value *also* needs to implement Hash since BFFH checks if the state
/// is different to before on input and output before updating the resource re.
/// notifying actors and notifys. This dependency is not expressable via
/// supertraits since it is not possible to make Hash into a trait object.
/// To solve this [`State`] uses the [`StateBuilder`] which adds an `Hash`
/// requirement for inputs on [`add`](struct::StateBuilder::add). The hash is
/// being created over all inserted values and then used to check for equality.
/// Note that in addition to collisions, Hash is not guaranteed stable over
/// ordering and will additionally not track overwrites, so if the order of
/// insertions changes or values are set and later overwritten then two equal
/// States can and are likely to have different hashes.
pub trait DynValue: Any + fmt::Debug {}
macro_rules! valtype {
( $x:ident, $y:ident ) => {
#[repr(transparent)]
#[derive(Debug, PartialEq, Eq, Hash)]
#[derive(Archive, Serialize, Deserialize)]
#[derive(serde::Serialize, serde::Deserialize)]
#[archive_attr(derive(TypeName, Debug))]
pub struct $x(pub $y);
#[archive_dyn(deserialize)]
impl DynValue for $x {}
impl DynValue for Archived<$x> {}
impl Deref for $x {
type Target = $y;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<$y> for $x {
fn from(e: $y) -> $x {
Self(e)
}
}
impl $x {
pub fn new(e: $y) -> Self {
Self(e)
} }
pub fn into_inner(self) -> $y { fn deserialize_dynoid_metadata(&self, _: &mut dyn DynDeserializer) -> Result<<dyn
self.0 SerializeValue as Pointee>::Metadata, DynError> {
unsafe {
Ok(core::mem::transmute(ptr_meta::metadata(
core::ptr::null::<$z>() as *const dyn SerializeValue
)))
}
} }
} }
} }
} }
macro_rules! oidvalue {
( $x:ident, $y:ty ) => {
oidvalue! {$x, $y, $y}
};
( $x:ident, $y:ty, $z:ty ) => {
oiddeser! {$z, $y}
valtype!(Bool, bool); impl TypeOid for $z {
valtype!(UInt8, u8); fn get_type_oid() -> &'static ObjectIdentifier {
valtype!(UInt16, u16); &$x
valtype!(UInt32, u32); }
valtype!(UInt64, u64);
valtype!(UInt128, u128); fn get_type_name() -> &'static str {
valtype!(Int8, i8); stringify!($y)
valtype!(Int16, i16); }
valtype!(Int32, i32);
valtype!(Int64, i64); fn get_type_desc() -> &'static str {
valtype!(Int128, i128); "builtin"
valtype!(RString, String); }
}
unsafe impl RegisteredImpl for $z {
fn vtable() -> usize {
unsafe {
core::mem::transmute(ptr_meta::metadata(
core::ptr::null::<$z>() as *const dyn DeserializeValue
))
}
}
fn debug_info() -> ImplDebugInfo {
debug_info!()
}
}
inventory::submit! {ImplEntry::new::<$z>()}
}
}
lazy_static::lazy_static! {
pub static ref OID_BOOL: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.1").unwrap()
};
pub static ref OID_U8: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.2").unwrap()
};
static ref OID_U16: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.3").unwrap()
};
static ref OID_U32: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.4").unwrap()
};
static ref OID_U64: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.5").unwrap()
};
static ref OID_U128: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.6").unwrap()
};
static ref OID_I8: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.7").unwrap()
};
static ref OID_I16: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.8").unwrap()
};
static ref OID_I32: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.9").unwrap()
};
static ref OID_I64: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.10").unwrap()
};
static ref OID_I128: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.11").unwrap()
};
static ref OID_VEC3U8: ObjectIdentifier = {
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.13").unwrap()
};
}
oidvalue!(OID_BOOL, bool);
oidvalue!(OID_U8, u8);
oidvalue!(OID_U16, u16);
oidvalue!(OID_U32, u32);
oidvalue!(OID_U64, u64);
oidvalue!(OID_U128, u128);
oidvalue!(OID_I8, i8);
oidvalue!(OID_I16, i16);
oidvalue!(OID_I32, i32);
oidvalue!(OID_I64, i64);
oidvalue!(OID_I128, i128);
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Archive, Serialize, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
#[archive_attr(derive(TypeName, Debug))] #[archive_attr(derive(TypeName, Debug, serde::Serialize, serde::Deserialize))]
pub struct Vec3u8 { pub struct Vec3u8 {
pub a: u8, pub a: u8,
pub b: u8, pub b: u8,
pub c: u8, pub c: u8,
} }
oidvalue!(OID_VEC3U8, Vec3u8, ArchivedVec3u8);
#[archive_dyn(deserialize)]
impl DynValue for Vec3u8 {}
impl DynValue for Archived<Vec3u8> {}
#[cfg(test)]
mod tests {}

155
src/varint.rs Normal file
View File

@ -0,0 +1,155 @@
use std::default::Default;
use std::ops::{Deref};
pub struct VarUInt<const N: usize> {
offset: usize,
bytes: [u8; N],
}
impl<const N: usize> VarUInt<N> {
#[inline(always)]
const fn new(bytes: [u8; N], offset: usize) -> Self {
Self { bytes, offset }
}
#[inline(always)]
pub fn as_bytes(&self) -> &[u8] {
&self.bytes[self.offset..]
}
#[inline(always)]
fn as_mut_bytes(&mut self) -> &mut [u8] {
&mut self.bytes[..]
}
#[inline(always)]
pub const fn into_bytes(self) -> [u8; N] {
self.bytes
}
}
impl<const N: usize> Default for VarUInt<N> {
fn default() -> Self {
Self::new([0u8; N], N)
}
}
impl<const N: usize> Deref for VarUInt<N> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_bytes()
}
}
macro_rules! convert_from {
( $x:ty ) => {
fn from(inp: $x) -> Self {
let mut num = inp;
let mut this = Self::default();
let bytes = this.as_mut_bytes();
let mut more = 0u8;
let mut idx: usize = bytes.len()-1;
while num > 0x7f {
bytes[idx] = ((num & 0x7f) as u8 | more);
num >>= 7;
more = 0x80;
idx -= 1;
}
bytes[idx] = (num as u8) | more;
this.offset = idx;
this
}
}
}
macro_rules! convert_into {
( $x:ty ) => {
fn into(self) -> $x {
let mut out = 0;
// [0,1,2,3,4,5,6,7,8,9]
// ^ 0
// ^offset = 5
// ^ len = 10
// ^---------^ # of valid bytes = (len - offset)
// for i in offset..len ⇒ all valid idx
let bytes = self.as_bytes();
let len = bytes.len();
let mut shift = 0;
for neg in 1..=len {
let idx = len-neg;
let val = (bytes[idx] & 0x7f) as $x;
let shifted = val << shift;
out |= shifted;
shift += 7;
}
out
}
}
}
macro_rules! impl_convert_from_to {
( $num:ty, $req:literal, $nt:ident ) => {
pub type $nt = VarUInt<$req>;
impl From<$num> for VarUInt<$req> {
convert_from! { $num }
}
impl Into<$num> for VarUInt<$req> {
convert_into! { $num }
}
}
}
impl_convert_from_to!(u8, 2, VarU8);
impl_convert_from_to!(u32, 5, VarU32);
impl_convert_from_to!(u64, 10, VarU64);
impl_convert_from_to!(u128, 19, VarU128);
impl<T, const N: usize> From<&T> for VarUInt<N>
where T: Copy,
VarUInt<N>: From<T>
{
fn from(t: &T) -> Self {
(*t).into()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_varuint() {
let inp = u64::MAX;
let vi: VarU64 = inp.into();
println!("Encoded {} into {:?}", inp, vi.as_bytes());
let outp: u64 = vi.into();
assert_eq!(inp, outp);
let inp = 0x80;
let vi: VarUInt<10> = inp.into();
println!("Encoded {} into {:?}", inp, vi.as_bytes());
let outp: u64 = vi.into();
assert_eq!(inp, outp);
}
#[test]
fn minimal() {
let a = 5u8;
assert_eq!(VarU8::from(a).as_bytes(), &[a]);
let a = 200u8;
assert_eq!(VarU8::from(a).as_bytes(), &[129, 72]);
let inp = 128;
let vi: VarU32 = inp.into();
let expected: &[u8] = &[129, 0];
assert_eq!(vi.as_bytes(), expected)
}
}