mirror of
https://gitlab.com/fabinfra/fabaccess/bffh.git
synced 2024-11-10 17:43: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]
|
||||
futures = { version = "0.3.16", features = ["thread-pool", "compat"] }
|
||||
futures-util = "0.3.16"
|
||||
#futures-util = "0.3.16"
|
||||
futures-signals = "0.3.22"
|
||||
|
||||
smol = "1.2.5"
|
||||
@ -26,9 +26,9 @@ tracing = "0.1.28"
|
||||
|
||||
signal-hook = "0.3.9"
|
||||
|
||||
slog = { version = "2.7.0", features = ["max_level_trace"] }
|
||||
slog-term = "2.8.0"
|
||||
slog-async = "2.7.0"
|
||||
#slog = { version = "2.7.0", features = ["max_level_trace"] }
|
||||
#slog-term = "2.8.0"
|
||||
#slog-async = "2.7.0"
|
||||
|
||||
capnp = "0.14.3"
|
||||
capnpc = "0.14.4"
|
||||
@ -36,28 +36,29 @@ capnp-rpc = "0.14.1"
|
||||
capnp-futures = "0.14.1"
|
||||
|
||||
serde = { version = "1.0.130", features = ["derive"] }
|
||||
toml = "0.5.8"
|
||||
flexbuffers = "2.0.0"
|
||||
bincode = "2.0.0-dev"
|
||||
erased-serde = "0.3"
|
||||
#toml = "0.5.8"
|
||||
#flexbuffers = "2.0.0"
|
||||
|
||||
rkyv = "0.7"
|
||||
ptr_meta = "0.1"
|
||||
rkyv_typename = "0.7"
|
||||
rkyv_dyn = "0.7"
|
||||
inventory = "0.1"
|
||||
|
||||
serde_dhall = { version = "0.10.1", default-features = false }
|
||||
serde_json = "1.0"
|
||||
|
||||
uuid = { version = "0.8.2", features = ["serde", "v4"] }
|
||||
|
||||
clap = "2.33.3"
|
||||
#clap = "2.33.3"
|
||||
|
||||
# TODO update this if bindgen breaks (again)
|
||||
rsasl = "1.4.0"
|
||||
#rsasl = "1.4.0"
|
||||
#rsasl = { path = "../../rsasl" }
|
||||
|
||||
# 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"] }
|
||||
|
||||
@ -68,12 +69,12 @@ async-trait = "0.1.51"
|
||||
|
||||
lazy_static = "1.4.0"
|
||||
|
||||
rust-argon2 = "0.8.3"
|
||||
rand = "0.8.4"
|
||||
#rust-argon2 = "0.8.3"
|
||||
#rand = "0.8.4"
|
||||
|
||||
async-channel = "1.6.1"
|
||||
easy-parallel = "3.1.0"
|
||||
genawaiter = "0.99.1"
|
||||
#async-channel = "1.6.1"
|
||||
#easy-parallel = "3.1.0"
|
||||
#genawaiter = "0.99.1"
|
||||
|
||||
[build-dependencies]
|
||||
capnpc = "0.14.4"
|
||||
@ -83,6 +84,7 @@ walkdir = "2.3.2"
|
||||
[dev-dependencies]
|
||||
futures-test = "0.3.16"
|
||||
tempfile = "3.2"
|
||||
bincode = "2.0.0-dev"
|
||||
|
||||
[patch.crates-io]
|
||||
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 {
|
||||
use super::*;
|
||||
|
||||
|
61
src/lib.rs
61
src/lib.rs
@ -17,18 +17,18 @@ mod initiator;
|
||||
mod space;
|
||||
*/
|
||||
|
||||
use crate::oid::ObjectIdentifier;
|
||||
use std::convert::TryFrom;
|
||||
use crate::state::value::{UInt32, Vec3u8, SerializeDynOid};
|
||||
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 schema;
|
||||
mod state;
|
||||
mod db;
|
||||
mod network;
|
||||
mod oid;
|
||||
pub mod oid;
|
||||
mod varint;
|
||||
|
||||
/*
|
||||
|
||||
@ -55,35 +55,46 @@ pub fn main() {
|
||||
let db = db::StateDB::init("/tmp/state").unwrap();
|
||||
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;
|
||||
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 b2 = Box::new(false);
|
||||
let ent = state::value::Entry { oid: &boid, val: &b2 };
|
||||
let boid = &state::value::OID_BOOL;
|
||||
let b2 = false;
|
||||
let ent = state::Entry { oid: boid, val: &b2 };
|
||||
println!("ent {:?}", &ent);
|
||||
let s = serde_json::to_string(&ent).unwrap();
|
||||
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);
|
||||
|
||||
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 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();
|
||||
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() {
|
||||
|
703
src/oid.rs
703
src/oid.rs
@ -6,8 +6,8 @@
|
||||
//!
|
||||
//!
|
||||
//! ## Parsing OID String Representation
|
||||
//! ```rust
|
||||
//! use oid::prelude::*;
|
||||
//! ```ignore
|
||||
//! use crate::oid::prelude::*;
|
||||
//!
|
||||
//! fn main() -> Result<(), ObjectIdentifierError> {
|
||||
//! let oid = ObjectIdentifier::try_from("0.1.2.3")?;
|
||||
@ -16,8 +16,8 @@
|
||||
//! ```
|
||||
//!
|
||||
//! ## Parsing OID Binary Representation
|
||||
//! ```rust
|
||||
//! use oid::prelude::*;
|
||||
//! ```ignore
|
||||
//! use prelude::*;
|
||||
//!
|
||||
//! fn main() -> Result<(), ObjectIdentifierError> {
|
||||
//! let oid = ObjectIdentifier::try_from(vec![0x00, 0x01, 0x02, 0x03])?;
|
||||
@ -26,8 +26,8 @@
|
||||
//! ```
|
||||
//!
|
||||
//! ## Encoding OID as String Representation
|
||||
//! ```rust
|
||||
//! use oid::prelude::*;
|
||||
//! ```ignore
|
||||
//! use prelude::*;
|
||||
//!
|
||||
//! fn main() -> Result<(), ObjectIdentifierError> {
|
||||
//! let oid = ObjectIdentifier::try_from("0.1.2.3")?;
|
||||
@ -38,7 +38,7 @@
|
||||
//! ```
|
||||
//!
|
||||
//! ## Encoding OID as Binary Representation
|
||||
//! ```rust
|
||||
//! ```ignore
|
||||
//! use oid::prelude::*;
|
||||
//!
|
||||
//! fn main() -> Result<(), ObjectIdentifierError> {
|
||||
@ -52,13 +52,20 @@
|
||||
//! [Object Identifiers]: https://en.wikipedia.org/wiki/Object_identifier
|
||||
//! [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 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 = usize;
|
||||
type Node = u128;
|
||||
type VarNode = VarU128;
|
||||
|
||||
/// Convenience module for quickly importing the public interface (e.g., `use oid::prelude::*`)
|
||||
pub mod prelude {
|
||||
@ -106,111 +113,253 @@ pub enum ObjectIdentifierError {
|
||||
}
|
||||
|
||||
/// Object Identifier (OID)
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot,
|
||||
first_node: u8,
|
||||
child_nodes: Vec<Node>,
|
||||
nodes: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl ObjectIdentifier {
|
||||
const fn new(root: ObjectIdentifierRoot, first_node: u8, child_nodes: Vec<Node>)
|
||||
-> Self
|
||||
#[inline(always)]
|
||||
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 {
|
||||
type Archived = ArchivedVec<u8>;
|
||||
type Archived = ArchivedObjectIdentifier;
|
||||
type Resolver = VecResolver;
|
||||
|
||||
unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
|
||||
let vec: Vec<u8> = self.clone().into();
|
||||
vec.resolve(pos, resolver, out);
|
||||
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 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
|
||||
where Vec<u8>: Serialize<S>
|
||||
impl<S: Serializer + ?Sized> Serialize<S> for ObjectIdentifier
|
||||
where [u8]: rkyv::SerializeUnsized<S>
|
||||
{
|
||||
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
|
||||
let vec: Vec<u8> = self.clone().into();
|
||||
vec.serialize(serializer)
|
||||
ArchivedVec::serialize_from_slice(self.nodes.as_ref(), serializer)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_string_first_node(
|
||||
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
|
||||
.parse()
|
||||
.map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?;
|
||||
if first_child_node > 39 {
|
||||
return Err(ObjectIdentifierError::IllegalFirstChildNode);
|
||||
}
|
||||
Ok(first_child_node)
|
||||
fn parse_string_first_node(first_child_node: &str) -> Result<u8, ObjectIdentifierError> {
|
||||
let first_child_node: u8 = first_child_node
|
||||
.parse()
|
||||
.map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?;
|
||||
if first_child_node > 39 {
|
||||
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 {
|
||||
Err(ObjectIdentifierError::IllegalFirstChildNode)
|
||||
let vi: VarNode = node.into();
|
||||
out.extend_from_slice(vi.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_string_child_nodes(
|
||||
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)
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl ObjectIdentifier {
|
||||
fn from_string<S>(value: S) -> Result<ObjectIdentifier, ObjectIdentifierError>
|
||||
where
|
||||
S: Into<String>,
|
||||
S: AsRef<str>,
|
||||
{
|
||||
let value = value.into();
|
||||
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),
|
||||
}
|
||||
}
|
||||
Err(_) => Err(ObjectIdentifierError::IllegalRootNode),
|
||||
ObjectIdentifier::from_str(value.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_to_string(nodes: &[u8]) -> Result<String, ObjectIdentifierError> {
|
||||
assert!(nodes.len() > 0);
|
||||
let root = nodes[0] / 40;
|
||||
let mut out = root.to_string();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
None => Err(ObjectIdentifierError::IllegalRootNode),
|
||||
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 {
|
||||
fn into(self) -> String {
|
||||
let mut result: String = self.root.into();
|
||||
result.push_str(&format!(".{}", self.first_node));
|
||||
for node in &self.child_nodes {
|
||||
result.push_str(&format!(".{}", node));
|
||||
}
|
||||
result
|
||||
convert_to_string(&self.nodes)
|
||||
.expect("Valid OID object couldn't be serialized.")
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,34 +369,15 @@ impl Into<String> for ObjectIdentifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Vec<u8>> for &ObjectIdentifier {
|
||||
fn into(self) -> Vec<u8> {
|
||||
let mut result: Vec<u8> = vec![self.root as u8];
|
||||
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<'a> Into<&'a [u8]> for &'a ObjectIdentifier {
|
||||
fn into(self) -> &'a [u8] {
|
||||
&self.nodes
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<Vec<u8>> for ObjectIdentifier {
|
||||
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 {
|
||||
type Error = ObjectIdentifierError;
|
||||
fn try_from(value: &[u8]) -> Result<ObjectIdentifier, Self::Error> {
|
||||
if value.len() < 1 {
|
||||
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,
|
||||
})
|
||||
fn try_from(nodes: &[u8]) -> Result<ObjectIdentifier, Self::Error> {
|
||||
Self::from_box(nodes.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<u8>> for ObjectIdentifier {
|
||||
type Error = ObjectIdentifierError;
|
||||
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();
|
||||
serializer.serialize_str(&encoded)
|
||||
} else {
|
||||
let encoded: Vec<u8> = self.into();
|
||||
serializer.serialize_bytes(&encoded)
|
||||
serializer.serialize_bytes(self.as_bytes())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -391,125 +490,65 @@ mod serde_support {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::convert::TryInto;
|
||||
|
||||
mod serde_support {
|
||||
use super::*;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_xml_rs;
|
||||
|
||||
#[test]
|
||||
fn bincode_serde_serialize() {
|
||||
let expected: Vec<u8> = vec![
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08,
|
||||
0x0D, 0x15,
|
||||
];
|
||||
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]
|
||||
fn bincode_serde_roundtrip() {
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x01,
|
||||
vec![1, 2, 3, 5, 8, 13, 21],
|
||||
).unwrap();
|
||||
let buffer: Vec<u8> = bincode::serialize(&expected).unwrap();
|
||||
let actual = bincode::deserialize(&buffer).unwrap();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_binary_root_node_0() {
|
||||
let expected: Vec<u8> = vec![0];
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::ItuT,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
};
|
||||
let actual: Vec<u8> = (&oid).into();
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x00,
|
||||
vec![],
|
||||
).unwrap();
|
||||
let actual: Vec<u8> = oid.into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_binary_root_node_1() {
|
||||
let expected: Vec<u8> = vec![40];
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::Iso,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
};
|
||||
let actual: Vec<u8> = (&oid).into();
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::Iso,
|
||||
0x00,
|
||||
vec![],
|
||||
).unwrap();
|
||||
let actual: Vec<u8> = oid.into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_binary_root_node_2() {
|
||||
let expected: Vec<u8> = vec![80];
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::JointIsoItuT,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
};
|
||||
let actual: Vec<u8> = (&oid).into();
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::JointIsoItuT,
|
||||
0x00,
|
||||
vec![],
|
||||
).unwrap();
|
||||
let actual: Vec<u8> = oid.into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_binary_example_1() {
|
||||
let expected: Vec<u8> = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15];
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::ItuT,
|
||||
first_node: 0x01,
|
||||
child_nodes: vec![1, 2, 3, 5, 8, 13, 21],
|
||||
};
|
||||
let actual: Vec<u8> = (&oid).into();
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x01,
|
||||
vec![1, 2, 3, 5, 8, 13, 21],
|
||||
).unwrap();
|
||||
let actual: Vec<u8> = oid.into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
@ -519,35 +558,35 @@ mod tests {
|
||||
0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53,
|
||||
0x92, 0x30,
|
||||
];
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::JointIsoItuT,
|
||||
first_node: 39,
|
||||
child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
||||
};
|
||||
let actual: Vec<u8> = (&oid).into();
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::JointIsoItuT,
|
||||
39,
|
||||
vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
||||
).unwrap();
|
||||
let actual: Vec<u8> = (oid).into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_string_root_node_0() {
|
||||
let expected = "0.0";
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::ItuT,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
};
|
||||
let actual: String = (&oid).into();
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x00,
|
||||
vec![],
|
||||
).unwrap();
|
||||
let actual: String = (oid).into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn encode_string_root_node_1() {
|
||||
let expected = "1.0";
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::Iso,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
};
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::Iso,
|
||||
0x00,
|
||||
vec![],
|
||||
).unwrap();
|
||||
let actual: String = (&oid).into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
@ -555,11 +594,11 @@ mod tests {
|
||||
#[test]
|
||||
fn encode_string_root_node_2() {
|
||||
let expected = "2.0";
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::JointIsoItuT,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
};
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::JointIsoItuT,
|
||||
0x00,
|
||||
vec![],
|
||||
).unwrap();
|
||||
let actual: String = (&oid).into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
@ -567,11 +606,11 @@ mod tests {
|
||||
#[test]
|
||||
fn encode_string_example_1() {
|
||||
let expected = "0.1.1.2.3.5.8.13.21";
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::ItuT,
|
||||
first_node: 0x01,
|
||||
child_nodes: vec![1, 2, 3, 5, 8, 13, 21],
|
||||
};
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x01,
|
||||
vec![1, 2, 3, 5, 8, 13, 21],
|
||||
).unwrap();
|
||||
let actual: String = (&oid).into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
@ -579,66 +618,66 @@ mod tests {
|
||||
#[test]
|
||||
fn encode_string_example_2() {
|
||||
let expected = "2.39.42.2501.65535.2147483647.1235.2352";
|
||||
let oid = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::JointIsoItuT,
|
||||
first_node: 39,
|
||||
child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
||||
};
|
||||
let oid = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::JointIsoItuT,
|
||||
39,
|
||||
vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
||||
).unwrap();
|
||||
let actual: String = (&oid).into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_binary_root_node_0() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::ItuT,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x00,
|
||||
vec![],
|
||||
);
|
||||
let actual = vec![0x00].try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_binary_root_node_1() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::Iso,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::Iso,
|
||||
0x00,
|
||||
vec![],
|
||||
);
|
||||
let actual = vec![40].try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_binary_root_node_2() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::JointIsoItuT,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::JointIsoItuT,
|
||||
0x00,
|
||||
vec![],
|
||||
);
|
||||
let actual = vec![80].try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_binary_example_1() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::ItuT,
|
||||
first_node: 0x01,
|
||||
child_nodes: vec![1, 2, 3, 5, 8, 13, 21],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x01,
|
||||
vec![1, 2, 3, 5, 8, 13, 21],
|
||||
);
|
||||
let actual = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15].try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_binary_example_2() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::JointIsoItuT,
|
||||
first_node: 39,
|
||||
child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::JointIsoItuT,
|
||||
39,
|
||||
vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
||||
);
|
||||
let actual = vec![
|
||||
0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53,
|
||||
0x92, 0x30,
|
||||
@ -649,55 +688,55 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parse_string_root_node_0() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::ItuT,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x00,
|
||||
vec![],
|
||||
);
|
||||
let actual = "0.0".try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_string_root_node_1() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::Iso,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::Iso,
|
||||
0x00,
|
||||
vec![],
|
||||
);
|
||||
let actual = "1.0".try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_string_root_node_2() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::JointIsoItuT,
|
||||
first_node: 0x00,
|
||||
child_nodes: vec![],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::JointIsoItuT,
|
||||
0x00,
|
||||
vec![],
|
||||
);
|
||||
let actual = "2.0".try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_string_example_1() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::ItuT,
|
||||
first_node: 0x01,
|
||||
child_nodes: vec![1, 2, 3, 5, 8, 13, 21],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::ItuT,
|
||||
0x01,
|
||||
vec![1, 2, 3, 5, 8, 13, 21],
|
||||
);
|
||||
let actual = "0.1.1.2.3.5.8.13.21".try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_string_example_2() {
|
||||
let expected = Ok(ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::JointIsoItuT,
|
||||
first_node: 39,
|
||||
child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
||||
});
|
||||
let expected = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::JointIsoItuT,
|
||||
39,
|
||||
vec![42, 2501, 65535, 2147483647, 1235, 2352],
|
||||
);
|
||||
let actual = "2.39.42.2501.65535.2147483647.1235.2352".try_into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
@ -717,7 +756,7 @@ mod tests {
|
||||
for i in 40..core::u8::MAX {
|
||||
let string_val = format!("{}.2.3.4", i);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -727,17 +766,7 @@ mod tests {
|
||||
let expected = Err(ObjectIdentifierError::IllegalFirstChildNode);
|
||||
let string_val = String::new();
|
||||
let mut nodes_iter = string_val.split(".");
|
||||
let actual = parse_string_first_node(&mut nodes_iter);
|
||||
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);
|
||||
let actual = parse_string_first_node(nodes_iter.next().unwrap());
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
||||
@ -746,7 +775,7 @@ mod tests {
|
||||
let expected = Err(ObjectIdentifierError::IllegalFirstChildNode);
|
||||
let string_val = String::from("40");
|
||||
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);
|
||||
}
|
||||
|
||||
@ -814,11 +843,11 @@ mod tests {
|
||||
#[test]
|
||||
fn encode_to_string() {
|
||||
let expected = String::from("1.2.3.4");
|
||||
let actual: String = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::Iso,
|
||||
first_node: 2,
|
||||
child_nodes: vec![3, 4],
|
||||
}
|
||||
let actual: String = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::Iso,
|
||||
2,
|
||||
vec![3, 4],
|
||||
).unwrap()
|
||||
.into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
@ -826,11 +855,11 @@ mod tests {
|
||||
#[test]
|
||||
fn encode_to_bytes() {
|
||||
let expected = vec![0x2A, 0x03, 0x04];
|
||||
let actual: Vec<u8> = ObjectIdentifier {
|
||||
root: ObjectIdentifierRoot::Iso,
|
||||
first_node: 2,
|
||||
child_nodes: vec![3, 4],
|
||||
}
|
||||
let actual: Vec<u8> = ObjectIdentifier::build(
|
||||
ObjectIdentifierRoot::Iso,
|
||||
2,
|
||||
vec![3, 4],
|
||||
).unwrap()
|
||||
.into();
|
||||
assert_eq!(expected, actual);
|
||||
}
|
||||
|
134
src/state/mod.rs
134
src/state/mod.rs
@ -20,20 +20,18 @@ use rkyv::{
|
||||
out_field,
|
||||
};
|
||||
|
||||
use crate::oid::ObjectIdentifier;
|
||||
|
||||
pub mod value;
|
||||
pub use value::{
|
||||
SerializeDynValue,
|
||||
DeserializeDynValue,
|
||||
};
|
||||
|
||||
#[derive(Archive, Serialize, Deserialize)]
|
||||
pub struct StateEntry {
|
||||
key: ObjectIdentifier,
|
||||
val: Box<dyn SerializeDynValue>,
|
||||
}
|
||||
use value::{SerializeValue, RegisteredImpl};
|
||||
use crate::state::value::{TypeOid, DynVal, DynOwnedVal};
|
||||
use crate::oid::ObjectIdentifier;
|
||||
use serde::ser::SerializeMap;
|
||||
use std::ops::Deref;
|
||||
use std::fmt::Formatter;
|
||||
use serde::Deserializer;
|
||||
use serde::de::MapAccess;
|
||||
use serde::de::Error as _;
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Archive, Serialize, Deserialize)]
|
||||
/// State object of a resource
|
||||
///
|
||||
@ -43,44 +41,41 @@ pub struct StateEntry {
|
||||
/// 3. it is sendable and forwarded to all Actors and Notifys
|
||||
pub struct State {
|
||||
hash: u64,
|
||||
inner: Vec<StateEntry>,
|
||||
}
|
||||
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()
|
||||
}
|
||||
pub inner: Vec<OwnedEntry>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn build() -> StateBuilder {
|
||||
StateBuilder::new()
|
||||
}
|
||||
|
||||
pub fn hash(&self) -> u64 {
|
||||
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 {
|
||||
hasher: DefaultHasher,
|
||||
inner: Vec<StateEntry>
|
||||
inner: Vec<OwnedEntry>
|
||||
}
|
||||
|
||||
impl StateBuilder {
|
||||
@ -102,14 +97,71 @@ impl StateBuilder {
|
||||
/// 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
|
||||
/// call statically call its `hash` method.
|
||||
pub fn add<V>(mut self, key: ObjectIdentifier<>, val: Box<V>) -> Self
|
||||
where V: SerializeDynValue + Hash
|
||||
pub fn add<V>(mut self, oid: ObjectIdentifier, val: Box<V>) -> Self
|
||||
where V: SerializeValue + Hash + Archive,
|
||||
Archived<V>: TypeOid + RegisteredImpl,
|
||||
{
|
||||
// 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);
|
||||
self.inner.push(StateEntry { key, val });
|
||||
self.inner.push(OwnedEntry { oid, val });
|
||||
|
||||
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,
|
||||
any::Any,
|
||||
hash::Hash,
|
||||
ops::Deref,
|
||||
convert::TryFrom,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized, ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized};
|
||||
use rkyv_dyn::{archive_dyn, DynSerializer, DynError, DynDeserializer};
|
||||
use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized,
|
||||
ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized,
|
||||
};
|
||||
use rkyv_dyn::{DynSerializer, DynError, DynDeserializer};
|
||||
use rkyv_typename::TypeName;
|
||||
use ptr_meta::{DynMetadata, Pointee};
|
||||
|
||||
@ -24,8 +25,14 @@ use std::fmt::Formatter;
|
||||
use serde::de::Error as _;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
|
||||
pub trait Value: fmt::Debug + erased_serde::Serialize {
|
||||
/// Adding a custom type to BFFH state managenment:
|
||||
///
|
||||
/// 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`
|
||||
///
|
||||
/// 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>;
|
||||
}
|
||||
erased_serde::serialize_trait_object!(Value);
|
||||
erased_serde::serialize_trait_object!(SerializeValue);
|
||||
erased_serde::serialize_trait_object!(DeserializeValue);
|
||||
|
||||
impl<T> Value for T
|
||||
where T: fmt::Debug
|
||||
where T: Any + fmt::Debug
|
||||
+ erased_serde::Serialize
|
||||
+ for<'de> serde::Deserialize<'de>
|
||||
{
|
||||
@ -52,44 +61,32 @@ impl<T> Value for T
|
||||
}
|
||||
}
|
||||
|
||||
impl Pointee for dyn Value {
|
||||
type Metadata = DynMetadata<dyn Value>;
|
||||
}
|
||||
|
||||
#[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> {
|
||||
#[repr(transparent)]
|
||||
pub(super) struct DynVal<'a>(pub &'a dyn SerializeValue);
|
||||
impl<'a> serde::Serialize for DynVal<'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, self.val)?;
|
||||
let oid = self.0.archived_type_oid();
|
||||
ser.serialize_entry(oid, self.0)?;
|
||||
ser.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for OwnedEntry {
|
||||
#[repr(transparent)]
|
||||
pub(super) struct DynOwnedVal(pub Box<dyn SerializeValue>);
|
||||
impl<'de> serde::Deserialize<'de> for DynOwnedVal {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
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 {
|
||||
type Value = OwnedEntry;
|
||||
impl<'de> serde::de::Visitor<'de> for DynValVisitor {
|
||||
type Value = DynOwnedVal;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
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.
|
||||
let oid: ObjectIdentifier = map.next_key()?
|
||||
.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.
|
||||
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(
|
||||
serde::de::Unexpected::Other("unknown oid"),
|
||||
&"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.
|
||||
// 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
|
||||
// only way to put this usize into that spot is by having a valid vtable cast so it's
|
||||
// probably almost safe)
|
||||
@ -143,14 +139,14 @@ impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor {
|
||||
// the game yet. >:D
|
||||
let seed = InitIntoSelf(valbox);
|
||||
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 {
|
||||
type Value = Box<dyn DeserializeValue>;
|
||||
type Value = Box<dyn SerializeValue>;
|
||||
|
||||
fn deserialize<D>(mut self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
@ -171,39 +167,20 @@ impl<'de> serde::de::DeserializeSeed<'de> for InitIntoSelf {
|
||||
}
|
||||
|
||||
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 {
|
||||
fn serialize_unsized(&self, mut serializer: &mut S) -> Result<usize, S::Error> {
|
||||
self.serialize_dynoid(&mut serializer)
|
||||
.map_err(|e| *e.downcast::<S::Error>().unwrap())
|
||||
}
|
||||
|
||||
fn serialize_metadata(&self, mut serializer: &mut S) -> Result<Self::MetadataResolver, S::Error> {
|
||||
self.serialize_metadata(serializer)
|
||||
fn serialize_metadata(&self, serializer: &mut S) -> Result<Self::MetadataResolver, S::Error> {
|
||||
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
|
||||
pub trait SerializeDynOid {
|
||||
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
|
||||
@ -222,12 +199,12 @@ impl<T> SerializeDynOid for T
|
||||
serializer.serialize_value(self)
|
||||
}
|
||||
|
||||
fn archived_type_oid(&self) -> ObjectIdentifier {
|
||||
fn archived_type_oid(&self) -> &'static ObjectIdentifier {
|
||||
Archived::<T>::get_type_oid()
|
||||
}
|
||||
}
|
||||
|
||||
trait DeserializeDynOid {
|
||||
pub trait DeserializeDynOid {
|
||||
unsafe fn deserialize_dynoid(
|
||||
&self,
|
||||
deserializer: &mut dyn DynDeserializer,
|
||||
@ -243,7 +220,7 @@ trait DeserializeDynOid {
|
||||
#[ptr_meta::pointee]
|
||||
pub trait SerializeValue: Value + SerializeDynOid {}
|
||||
|
||||
impl<T: Archive + SerializeDynOid + Value> SerializeValue for T
|
||||
impl<T: Archive + Value + SerializeDynOid> SerializeValue for T
|
||||
where
|
||||
T::Archived: RegisteredImpl
|
||||
{}
|
||||
@ -258,9 +235,7 @@ impl ArchivePointee for dyn DeserializeValue {
|
||||
archived.pointer_metadata()
|
||||
}
|
||||
}
|
||||
impl<D: ?Sized> DeserializeUnsized<dyn SerializeValue, D> for dyn DeserializeValue
|
||||
where D: Fallible + DynDeserializer
|
||||
{
|
||||
impl<D: Fallible + ?Sized> DeserializeUnsized<dyn SerializeValue, D> for dyn DeserializeValue {
|
||||
unsafe fn deserialize_unsized(&self,
|
||||
mut deserializer: &mut D,
|
||||
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>) {
|
||||
let (oid_pos, oid) = out_field!(out.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 {
|
||||
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
|
||||
}
|
||||
|
||||
@ -307,41 +285,58 @@ impl ArchivedValueMetadata {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
struct ImplId<'a> {
|
||||
pub struct ImplId<'a> {
|
||||
type_oid: &'a [u8],
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
impl ImplId<'static> {
|
||||
fn new<T: TypeOid>() -> Self {
|
||||
let oid: Vec<u8> = T::get_type_oid().into();
|
||||
Self {
|
||||
type_oid: oid.leak()
|
||||
type_oid: &T::get_type_oid()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct ImplData {
|
||||
struct ImplData<'a> {
|
||||
pub vtable: usize,
|
||||
// TODO DebugImpl
|
||||
// TODO DebugInfo
|
||||
pub name: &'a str,
|
||||
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> {
|
||||
core::mem::transmute(self.vtable)
|
||||
}
|
||||
}
|
||||
|
||||
struct ImplEntry<'a> {
|
||||
pub struct ImplEntry<'a> {
|
||||
id: ImplId<'a>,
|
||||
data: ImplData,
|
||||
data: ImplData<'a>,
|
||||
}
|
||||
inventory::collect!(ImplEntry<'static>);
|
||||
|
||||
@ -352,13 +347,17 @@ impl ImplEntry<'_> {
|
||||
id: ImplId::new::<T>(),
|
||||
data: ImplData {
|
||||
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 {
|
||||
oid_to_data: HashMap<ImplId<'static>, ImplData>,
|
||||
oid_to_data: HashMap<ImplId<'static>, ImplData<'static>>,
|
||||
}
|
||||
|
||||
impl ImplRegistry {
|
||||
@ -368,6 +367,14 @@ impl ImplRegistry {
|
||||
|
||||
fn add_entry(&mut self, entry: &'static ImplEntry) {
|
||||
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());
|
||||
}
|
||||
|
||||
@ -389,101 +396,124 @@ lazy_static::lazy_static! {
|
||||
|
||||
pub unsafe trait RegisteredImpl {
|
||||
fn vtable() -> usize;
|
||||
fn debug_info() -> ImplDebugInfo;
|
||||
}
|
||||
|
||||
unsafe impl RegisteredImpl for bool {
|
||||
fn vtable() -> usize {
|
||||
unsafe {
|
||||
core::mem::transmute(ptr_meta::metadata(
|
||||
core::ptr::null::<bool>() as *const dyn DeserializeValue
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
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 ())
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> $y {
|
||||
self.0
|
||||
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}
|
||||
|
||||
valtype!(Bool, bool);
|
||||
valtype!(UInt8, u8);
|
||||
valtype!(UInt16, u16);
|
||||
valtype!(UInt32, u32);
|
||||
valtype!(UInt64, u64);
|
||||
valtype!(UInt128, u128);
|
||||
valtype!(Int8, i8);
|
||||
valtype!(Int16, i16);
|
||||
valtype!(Int32, i32);
|
||||
valtype!(Int64, i64);
|
||||
valtype!(Int128, i128);
|
||||
valtype!(RString, String);
|
||||
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 {
|
||||
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(Debug, Copy, Clone, PartialEq, Eq, Hash, Archive, Serialize, Deserialize)]
|
||||
#[archive_attr(derive(TypeName, Debug))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
|
||||
#[archive_attr(derive(TypeName, Debug, serde::Serialize, serde::Deserialize))]
|
||||
pub struct Vec3u8 {
|
||||
pub a: u8,
|
||||
pub b: u8,
|
||||
pub c: u8,
|
||||
}
|
||||
|
||||
#[archive_dyn(deserialize)]
|
||||
impl DynValue for Vec3u8 {}
|
||||
|
||||
impl DynValue for Archived<Vec3u8> {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {}
|
||||
oidvalue!(OID_VEC3U8, Vec3u8, ArchivedVec3u8);
|
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