mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-11 01:53:23 +01:00
Working new State encoding
This commit is contained in:
parent
f2679a3408
commit
fb8cbfc864
735
Cargo.lock
generated
735
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
32
Cargo.toml
32
Cargo.toml
@ -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" }
|
||||||
|
128
src/db/mod.rs
128
src/db/mod.rs
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -149,7 +149,7 @@ impl StateAccessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test_dis)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
61
src/lib.rs
61
src/lib.rs
@ -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() {
|
||||||
|
685
src/oid.rs
685
src/oid.rs
@ -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,45 +113,177 @@ 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>,
|
|
||||||
) -> Result<u8, ObjectIdentifierError> {
|
|
||||||
if let Some(first_child_node) = nodes.next() {
|
|
||||||
let first_child_node: u8 = first_child_node
|
let first_child_node: u8 = first_child_node
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?;
|
.map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?;
|
||||||
@ -152,65 +291,75 @@ fn parse_string_first_node(
|
|||||||
return Err(ObjectIdentifierError::IllegalFirstChildNode);
|
return Err(ObjectIdentifierError::IllegalFirstChildNode);
|
||||||
}
|
}
|
||||||
Ok(first_child_node)
|
Ok(first_child_node)
|
||||||
} else {
|
|
||||||
Err(ObjectIdentifierError::IllegalFirstChildNode)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_string_child_nodes(
|
fn parse_string_child_node(
|
||||||
nodes: &mut dyn Iterator<Item = &str>,
|
node_str: &str,
|
||||||
) -> Result<Vec<Node>, ObjectIdentifierError> {
|
out: &mut Vec<u8>
|
||||||
let mut result: Vec<Node> = vec![];
|
) -> Result<(), ObjectIdentifierError> {
|
||||||
while let Some(node) = nodes.next() {
|
let mut node: Node = node_str.parse()
|
||||||
result.push(
|
.map_err(|_| ObjectIdentifierError::IllegalChildNodeValue)?;
|
||||||
node.parse()
|
// TODO bench against !*node &= 0x80, compiler may already optimize better
|
||||||
.map_err(|_| ObjectIdentifierError::IllegalChildNodeValue)?,
|
if node <= 127 {
|
||||||
);
|
out.push(node as u8);
|
||||||
|
} else {
|
||||||
|
let vi: VarNode = node.into();
|
||||||
|
out.extend_from_slice(vi.as_bytes());
|
||||||
}
|
}
|
||||||
Ok(result)
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
|
||||||
match root_node_value {
|
|
||||||
Ok(root_node) => {
|
|
||||||
let root_node: Result<ObjectIdentifierRoot, _> = root_node.try_into();
|
|
||||||
match root_node {
|
|
||||||
Ok(root) => {
|
|
||||||
let first_node = parse_string_first_node(&mut nodes)?;
|
|
||||||
Ok(ObjectIdentifier {
|
|
||||||
root,
|
|
||||||
first_node,
|
|
||||||
child_nodes: parse_string_child_nodes(&mut nodes)?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
Err(_err) => Err(ObjectIdentifierError::IllegalRootNode),
|
}
|
||||||
}
|
|
||||||
}
|
fn convert_to_string(nodes: &[u8]) -> Result<String, ObjectIdentifierError> {
|
||||||
Err(_) => Err(ObjectIdentifierError::IllegalRootNode),
|
assert!(nodes.len() > 0);
|
||||||
}
|
let root = nodes[0] / 40;
|
||||||
}
|
let mut out = root.to_string();
|
||||||
None => Err(ObjectIdentifierError::IllegalRootNode),
|
|
||||||
|
out.push('.');
|
||||||
|
let first = nodes[0] % 40;
|
||||||
|
out.extend(first.to_string().chars());
|
||||||
|
|
||||||
|
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 {
|
||||||
|
// less than 7 bit of node value
|
||||||
|
out.push('.');
|
||||||
|
let nr = nodes[i].to_string();
|
||||||
|
out.extend(nr.chars());
|
||||||
|
} 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 {
|
||||||
|
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 {
|
|
||||||
use super::*;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
|
||||||
use serde_xml_rs;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bincode_serde_serialize() {
|
fn bincode_serde_roundtrip() {
|
||||||
let expected: Vec<u8> = vec![
|
let expected = ObjectIdentifier::build(
|
||||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08,
|
ObjectIdentifierRoot::ItuT,
|
||||||
0x0D, 0x15,
|
0x01,
|
||||||
];
|
vec![1, 2, 3, 5, 8, 13, 21],
|
||||||
let oid = ObjectIdentifier {
|
).unwrap();
|
||||||
root: ObjectIdentifierRoot::ItuT,
|
let buffer: Vec<u8> = bincode::serialize(&expected).unwrap();
|
||||||
first_node: 0x01,
|
let actual = bincode::deserialize(&buffer).unwrap();
|
||||||
child_nodes: vec![1, 2, 3, 5, 8, 13, 21],
|
|
||||||
};
|
|
||||||
let actual: Vec<u8> = bincode::serialize(&oid).unwrap();
|
|
||||||
assert_eq!(expected, actual);
|
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);
|
||||||
}
|
}
|
||||||
|
134
src/state/mod.rs
134
src/state/mod.rs
@ -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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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 {
|
||||||
|
( $y:ty, $z:ty ) => {
|
||||||
|
impl DeserializeDynOid for $y
|
||||||
|
where $y: for<'a> Deserialize<$z, (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::<$z>()).cast::<$z>();
|
||||||
|
ptr.write(self.deserialize(deserializer)?);
|
||||||
|
Ok(ptr as *mut ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_dynoid_metadata(&self, _: &mut dyn DynDeserializer) -> Result<<dyn
|
||||||
|
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}
|
||||||
|
|
||||||
|
impl TypeOid for $z {
|
||||||
|
fn get_type_oid() -> &'static ObjectIdentifier {
|
||||||
|
&$x
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_type_name() -> &'static str {
|
||||||
|
stringify!($y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_type_desc() -> &'static str {
|
||||||
|
"builtin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe impl RegisteredImpl for $z {
|
||||||
fn vtable() -> usize {
|
fn vtable() -> usize {
|
||||||
unsafe {
|
unsafe {
|
||||||
core::mem::transmute(ptr_meta::metadata(
|
core::mem::transmute(ptr_meta::metadata(
|
||||||
core::ptr::null::<bool>() as *const dyn DeserializeValue
|
core::ptr::null::<$z>() as *const dyn DeserializeValue
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
fn debug_info() -> ImplDebugInfo {
|
||||||
inventory::submit! {ImplEntry::new::<bool>()}
|
debug_info!()
|
||||||
|
|
||||||
#[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 {
|
inventory::submit! {ImplEntry::new::<$z>()}
|
||||||
fn from(e: $y) -> $x {
|
|
||||||
Self(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl $x {
|
|
||||||
pub fn new(e: $y) -> Self {
|
|
||||||
Self(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn into_inner(self) -> $y {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
valtype!(Bool, bool);
|
lazy_static::lazy_static! {
|
||||||
valtype!(UInt8, u8);
|
pub static ref OID_BOOL: ObjectIdentifier = {
|
||||||
valtype!(UInt16, u16);
|
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.1").unwrap()
|
||||||
valtype!(UInt32, u32);
|
};
|
||||||
valtype!(UInt64, u64);
|
pub static ref OID_U8: ObjectIdentifier = {
|
||||||
valtype!(UInt128, u128);
|
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.2").unwrap()
|
||||||
valtype!(Int8, i8);
|
};
|
||||||
valtype!(Int16, i16);
|
static ref OID_U16: ObjectIdentifier = {
|
||||||
valtype!(Int32, i32);
|
ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.3").unwrap()
|
||||||
valtype!(Int64, i64);
|
};
|
||||||
valtype!(Int128, i128);
|
static ref OID_U32: ObjectIdentifier = {
|
||||||
valtype!(RString, String);
|
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
155
src/varint.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user