Implement new traits structure

This commit is contained in:
Nadja von Reitzenstein Čerpnjak 2024-05-24 12:48:58 +02:00
parent 5400d7f799
commit 2acf35d54d
10 changed files with 176 additions and 46 deletions

10
Cargo.lock generated
View File

@ -489,6 +489,15 @@ version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "bffh-impl"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]
[[package]] [[package]]
name = "bitfield" name = "bitfield"
version = "0.13.2" version = "0.13.2"
@ -1052,6 +1061,7 @@ dependencies = [
"async-process", "async-process",
"async-trait", "async-trait",
"backtrace", "backtrace",
"bffh-impl",
"capnp", "capnp",
"capnp-rpc", "capnp-rpc",
"chrono", "chrono",

View File

@ -44,6 +44,9 @@ miette = { version = "4.7.1", features = ["fancy"] }
thiserror = "1.0.31" thiserror = "1.0.31"
toml = "0.5.8" toml = "0.5.8"
# Compilation proc-macros
bffh-impl = { path = "modules/impl" }
# Well-known paths/dirs for e.g. cache # Well-known paths/dirs for e.g. cache
dirs = "4.0.0" dirs = "4.0.0"

@ -1 +1 @@
Subproject commit cae56b00842362bd4599187b171ddf8a1030e248 Subproject commit 879bc578b20433c527cea34a5821cdccec9ee587

View File

@ -30,6 +30,7 @@ mod resources;
mod permissionsystem; mod permissionsystem;
mod user; mod user;
mod user_system; mod user_system;
mod traits;
pub struct APIServer { pub struct APIServer {
executor: Executor<'static>, executor: Executor<'static>,

View File

@ -3,9 +3,16 @@ use crate::resources::modules::fabaccess::{ArchivedStatus, Status};
use crate::resources::Resource; use crate::resources::Resource;
use crate::session::SessionHandle; use crate::session::SessionHandle;
use api::resource_capnp::resource; use api::resource_capnp::resource;
use api::claim_capnp::claimable; use api::claim_capnp::{claimable, claim};
use api::notify_capnp::notifiable;
use api::owned_capnp::owned;
use api::projects_capnp::project;
use capnp::capability::Promise; use capnp::capability::Promise;
use capnp::Error;
use capnp_rpc::pry; use capnp_rpc::pry;
use api::claim_capnp::claim::{DisownParams, DisownResults, TraitsParams, TraitsResults};
use api::claim_capnp::claimable::{ClaimParams, ClaimResults};
use api::owned_capnp::owned::{GetUserParams, GetUserResults};
#[derive(Clone)] #[derive(Clone)]
pub struct Machine { pub struct Machine {
@ -26,5 +33,38 @@ impl Machine {
impl claimable::Server for Machine { impl claimable::Server for Machine {
fn claim(&mut self, params: ClaimParams, mut results: ClaimResults) -> Promise<(), Error> {
let project = params.get().and_then(|r| r.get_project()).ok();
//self.resource.try_claim();
let claim = Claim::new(self.session.clone(), project, self.resource.clone());
pry!(results.get().set_ok(capnp_rpc::new_client(claim)));
Promise::ok(())
}
}
pub struct Claim {
session: SessionHandle,
project: Option<project::Client>,
resource: Resource,
}
impl Claim {
fn new(session: SessionHandle, project: Option<project::Client>, resource: Resource) -> Self {
Self { session, project, resource }
}
}
impl notifiable::Server for Claim {}
impl owned::Server for Claim {
fn get_user(&mut self, _: GetUserParams, mut results: GetUserResults) -> Promise<(), Error> {
let owner = User::new_self(self.session.clone());
results.get().set_owner(capnp_rpc::new_client(owner));
Promise::ok(())
}
}
impl claim::Server for Claim {
fn traits(&mut self, _: TraitsParams, _: TraitsResults) -> Promise<(), Error> {
todo!()
}
} }

View File

@ -0,0 +1,7 @@
use crate::oid;
use crate::utils::oid::ObjectIdentifier;
use api::traits::claimable_capnp::trait_claimable;
pub const CLAIMABLE_TRAIT_ID: ObjectIdentifier = oid!(1.3.6.1.4.1.61783.612.1.0);

View File

@ -0,0 +1,2 @@
mod claimable;
mod powerable;

View File

@ -0,0 +1,4 @@
use crate::oid;
use crate::utils::oid::ObjectIdentifier;
pub const TRAIT_ID_POWERABLE: ObjectIdentifier = oid!(1.3.6.1.4.1.61783.612.1.1);

View File

@ -132,7 +132,7 @@ pub trait SerializeDynOid {
/// ///
/// This OID will be serialized alongside the trait object and is used to retrieve the /// This OID will be serialized alongside the trait object and is used to retrieve the
/// correct vtable when loading the state from DB. /// correct vtable when loading the state from DB.
fn archived_type_oid(&self) -> &'static ObjectIdentifier; fn archived_type_oid(&self) -> &'static ObjectIdentifier<'static>;
/// Serialize this type into a [`DynSerializer`](trait@DynSerializer) /// Serialize this type into a [`DynSerializer`](trait@DynSerializer)
fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result<usize, DynError>; fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result<usize, DynError>;
@ -144,7 +144,7 @@ pub trait SerializeDynOid {
/// providing the OID that is serialized alongside the state object to be able to correctly cast /// providing the OID that is serialized alongside the state object to be able to correctly cast
/// it when accessing state from the DB. /// it when accessing state from the DB.
pub trait TypeOid { pub trait TypeOid {
fn type_oid() -> &'static ObjectIdentifier; fn type_oid() -> &'static ObjectIdentifier<'static>;
fn type_name() -> &'static str; fn type_name() -> &'static str;
} }
@ -153,7 +153,7 @@ where
T: for<'a> Serialize<dyn DynSerializer + 'a>, T: for<'a> Serialize<dyn DynSerializer + 'a>,
T::Archived: TypeOid, T::Archived: TypeOid,
{ {
fn archived_type_oid(&self) -> &'static ObjectIdentifier { fn archived_type_oid(&self) -> &'static ObjectIdentifier<'static> {
Archived::<T>::type_oid() Archived::<T>::type_oid()
} }
@ -172,7 +172,7 @@ impl ArchivePointee for dyn ArchivedStateValue {
impl ArchiveUnsized for dyn SerializeStateValue { impl ArchiveUnsized for dyn SerializeStateValue {
type Archived = dyn ArchivedStateValue; type Archived = dyn ArchivedStateValue;
type MetadataResolver = <ObjectIdentifier as Archive>::Resolver; type MetadataResolver = <ObjectIdentifier<'static> as Archive>::Resolver;
unsafe fn resolve_metadata( unsafe fn resolve_metadata(
&self, &self,
@ -203,7 +203,7 @@ impl<S: ScratchSpace + Serializer + ?Sized> SerializeUnsized<S> for dyn Serializ
#[derive(Debug)] #[derive(Debug)]
pub struct ArchivedStateValueMetadata { pub struct ArchivedStateValueMetadata {
pub type_oid: Archived<ObjectIdentifier>, pub type_oid: Archived<ObjectIdentifier<'static>>,
vtable_cache: AtomicUsize, vtable_cache: AtomicUsize,
} }

View File

@ -52,6 +52,7 @@
//! [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 std::borrow::Cow;
use crate::utils::varint::VarU128; use crate::utils::varint::VarU128;
use rkyv::ser::Serializer; use rkyv::ser::Serializer;
use rkyv::vec::{ArchivedVec, VecResolver}; use rkyv::vec::{ArchivedVec, VecResolver};
@ -114,16 +115,16 @@ pub enum ObjectIdentifierError {
/// Object Identifier (OID) /// Object Identifier (OID)
#[derive(Clone, Eq, PartialEq, Hash)] #[derive(Clone, Eq, PartialEq, Hash)]
#[repr(transparent)] #[repr(transparent)]
pub struct ObjectIdentifier { pub struct ObjectIdentifier<'a> {
nodes: Box<[u8]>, nodes: Cow<'a, [u8]>,
} }
impl ObjectIdentifier { impl<'a> ObjectIdentifier<'a> {
#[inline(always)] #[inline(always)]
pub const fn new_unchecked(nodes: Box<[u8]>) -> Self { pub const fn new_unchecked(nodes: Cow<'a, [u8]>) -> Self {
Self { nodes } Self { nodes }
} }
pub fn from_box(nodes: Box<[u8]>) -> Result<Self, ObjectIdentifierError> { pub fn from_box(nodes: Cow<'a, [u8]>) -> Result<Self, ObjectIdentifierError> {
if nodes.len() < 1 { if nodes.len() < 1 {
return Err(ObjectIdentifierError::IllegalRootNode); return Err(ObjectIdentifierError::IllegalRootNode);
}; };
@ -167,7 +168,7 @@ impl ObjectIdentifier {
vec.extend_from_slice(var.as_bytes()) vec.extend_from_slice(var.as_bytes())
} }
Ok(Self { Ok(Self {
nodes: vec.into_boxed_slice(), nodes: Cow::from(vec),
}) })
} }
@ -175,28 +176,29 @@ impl ObjectIdentifier {
pub fn root(&self) -> Result<ObjectIdentifierRoot, ObjectIdentifierError> { pub fn root(&self) -> Result<ObjectIdentifierRoot, ObjectIdentifierError> {
ObjectIdentifierRoot::try_from(self.nodes[0] / 40) ObjectIdentifierRoot::try_from(self.nodes[0] / 40)
} }
#[inline(always)] #[inline(always)]
pub const fn first_node(&self) -> u8 { pub fn first_node(&self) -> u8 {
self.nodes[0] % 40 self.nodes.as_ref()[0] % 40
} }
#[inline(always)] #[inline(always)]
pub fn child_nodes(&self) -> &[u8] { pub fn child_nodes(&self) -> &[u8] {
&self.nodes[1..] &self.nodes[1..]
} }
#[inline(always)] #[inline(always)]
pub const fn as_bytes(&self) -> &[u8] { pub fn as_bytes(&self) -> &[u8] {
&self.nodes &self.nodes
} }
} }
impl Deref for ObjectIdentifier { impl Deref for ObjectIdentifier<'_> {
type Target = [u8]; type Target = [u8];
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.nodes &self.nodes
} }
} }
impl FromStr for ObjectIdentifier { impl FromStr for ObjectIdentifier<'static> {
type Err = ObjectIdentifierError; type Err = ObjectIdentifierError;
fn from_str(value: &str) -> Result<Self, Self::Err> { fn from_str(value: &str) -> Result<Self, Self::Err> {
@ -230,13 +232,13 @@ impl FromStr for ObjectIdentifier {
} }
} }
impl fmt::Display for ObjectIdentifier { impl fmt::Display for ObjectIdentifier<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let show: String = self.into(); let show: String = self.into();
write!(f, "{}", show) write!(f, "{}", show)
} }
} }
impl fmt::Debug for ObjectIdentifier { impl fmt::Debug for ObjectIdentifier<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let show: String = self.into(); let show: String = self.into();
write!(f, "{}", show) write!(f, "{}", show)
@ -266,7 +268,7 @@ impl fmt::Debug for ArchivedObjectIdentifier {
} }
} }
impl Archive for ObjectIdentifier { impl Archive for ObjectIdentifier<'_> {
type Archived = ArchivedObjectIdentifier; type Archived = ArchivedObjectIdentifier;
type Resolver = VecResolver; type Resolver = VecResolver;
@ -275,7 +277,7 @@ impl Archive for ObjectIdentifier {
ArchivedVec::resolve_from_slice(self.nodes.as_ref(), pos + oid_pos, resolver, oid_out); ArchivedVec::resolve_from_slice(self.nodes.as_ref(), pos + oid_pos, resolver, oid_out);
} }
} }
impl Archive for &'static ObjectIdentifier { impl Archive for &'static ObjectIdentifier<'_> {
type Archived = ArchivedObjectIdentifier; type Archived = ArchivedObjectIdentifier;
type Resolver = VecResolver; type Resolver = VecResolver;
@ -285,7 +287,7 @@ impl Archive for &'static ObjectIdentifier {
} }
} }
impl<S: Serializer + ?Sized> Serialize<S> for ObjectIdentifier impl<S: Serializer + ?Sized> Serialize<S> for ObjectIdentifier<'_>
where where
[u8]: rkyv::SerializeUnsized<S>, [u8]: rkyv::SerializeUnsized<S>,
{ {
@ -304,8 +306,8 @@ fn parse_string_first_node(first_child_node: &str) -> Result<u8, ObjectIdentifie
Ok(first_child_node) Ok(first_child_node)
} }
impl ObjectIdentifier { impl ObjectIdentifier<'static> {
fn from_string<S>(value: S) -> Result<ObjectIdentifier, ObjectIdentifierError> fn from_string<S>(value: S) -> Result<Self, ObjectIdentifierError>
where where
S: AsRef<str>, S: AsRef<str>,
{ {
@ -350,55 +352,55 @@ fn convert_to_string(nodes: &[u8]) -> Result<String, ObjectIdentifierError> {
Ok(out) Ok(out)
} }
impl Into<String> for &ObjectIdentifier { impl Into<String> for &ObjectIdentifier<'_> {
fn into(self) -> String { fn into(self) -> String {
convert_to_string(&self.nodes).expect("Valid OID object couldn't be serialized.") convert_to_string(&self.nodes).expect("Valid OID object couldn't be serialized.")
} }
} }
impl Into<String> for ObjectIdentifier { impl Into<String> for ObjectIdentifier <'_>{
fn into(self) -> String { fn into(self) -> String {
(&self).into() (&self).into()
} }
} }
impl<'a> Into<&'a [u8]> for &'a ObjectIdentifier { impl<'a> Into<&'a [u8]> for &'a ObjectIdentifier<'_> {
fn into(self) -> &'a [u8] { fn into(self) -> &'a [u8] {
&self.nodes &self.nodes
} }
} }
impl Into<Vec<u8>> for ObjectIdentifier { impl Into<Vec<u8>> for ObjectIdentifier<'_> {
fn into(self) -> Vec<u8> { fn into(self) -> Vec<u8> {
self.nodes.into_vec() self.nodes.into()
} }
} }
impl TryFrom<&str> for ObjectIdentifier { impl TryFrom<&str> for ObjectIdentifier<'static> {
type Error = ObjectIdentifierError; type Error = ObjectIdentifierError;
fn try_from(value: &str) -> Result<ObjectIdentifier, Self::Error> { fn try_from(value: &str) -> Result<Self, Self::Error> {
ObjectIdentifier::from_string(value) ObjectIdentifier::from_string(value)
} }
} }
impl TryFrom<String> for ObjectIdentifier { impl TryFrom<String> for ObjectIdentifier<'static> {
type Error = ObjectIdentifierError; type Error = ObjectIdentifierError;
fn try_from(value: String) -> Result<ObjectIdentifier, Self::Error> { fn try_from(value: String) -> Result<Self, Self::Error> {
ObjectIdentifier::from_string(value) ObjectIdentifier::from_string(value)
} }
} }
impl TryFrom<&[u8]> for ObjectIdentifier { impl<'a> TryFrom<&'a [u8]> for ObjectIdentifier<'a> {
type Error = ObjectIdentifierError; type Error = ObjectIdentifierError;
fn try_from(nodes: &[u8]) -> Result<ObjectIdentifier, Self::Error> { fn try_from(nodes: &'a [u8]) -> Result<Self, Self::Error> {
Self::from_box(nodes.into()) Self::from_box(Cow::Borrowed(nodes))
} }
} }
impl TryFrom<Vec<u8>> for ObjectIdentifier { impl TryFrom<Vec<u8>> for ObjectIdentifier<'static> {
type Error = ObjectIdentifierError; type Error = ObjectIdentifierError;
fn try_from(value: Vec<u8>) -> Result<ObjectIdentifier, Self::Error> { fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
Self::from_box(value.into_boxed_slice()) Self::from_box(Cow::from(value))
} }
} }
@ -410,17 +412,17 @@ mod serde_support {
struct OidVisitor; struct OidVisitor;
impl<'de> de::Visitor<'de> for OidVisitor { impl<'de> de::Visitor<'de> for OidVisitor {
type Value = ObjectIdentifier; type Value = ObjectIdentifier<'de>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a valid buffer representing an OID") formatter.write_str("a valid buffer representing an OID")
} }
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
where where
E: de::Error, E: de::Error,
{ {
ObjectIdentifier::try_from(v).map_err(|err| { ObjectIdentifier::try_from(v).map_err(move |err| {
E::invalid_value( E::invalid_value(
de::Unexpected::Other(match err { de::Unexpected::Other(match err {
ObjectIdentifierError::IllegalRootNode => "illegal root node", ObjectIdentifierError::IllegalRootNode => "illegal root node",
@ -449,8 +451,8 @@ mod serde_support {
} }
} }
impl<'de> de::Deserialize<'de> for ObjectIdentifier { impl<'de> de::Deserialize<'de> for ObjectIdentifier<'de> {
fn deserialize<D>(deserializer: D) -> Result<ObjectIdentifier, D::Error> fn deserialize<D>(deserializer: D) -> Result<ObjectIdentifier<'de>, D::Error>
where where
D: de::Deserializer<'de>, D: de::Deserializer<'de>,
{ {
@ -462,7 +464,7 @@ mod serde_support {
} }
} }
impl ser::Serialize for ObjectIdentifier { impl ser::Serialize for ObjectIdentifier<'_> {
fn serialize<S>( fn serialize<S>(
&self, &self,
serializer: S, serializer: S,
@ -494,6 +496,67 @@ mod serde_support {
} }
} }
/// Helper macro to declare Object Identifiers at compile-time
///
/// Since the DER encoded oids are not very readable we provide a
/// procedural macro `oid!`. The macro can be used the following ways:
///
/// - `oid!(1.4.42.23)`: Create a const expression for the corresponding `Oid<'static>`
/// - `oid!(rel 42.23)`: Create a const expression for the corresponding relative `Oid<'static>`
/// - `oid!(raw 1.4.42.23)`/`oid!(raw rel 42.23)`: Obtain the DER encoded form as a byte array.
///
/// # Comparing oids
///
/// Comparing a parsed oid to a static oid is probably the most common
/// thing done with oids in your code. The `oid!` macro can be used in expression positions for
/// this purpose. For example
/// ```
/// use diflouroborane::oid;
/// use diflouroborane::utils::oid::ObjectIdentifier;
///
/// # let some_oid: ObjectIdentifier = oid!(1.2.456);
/// const SOME_STATIC_OID: ObjectIdentifier = oid!(1.2.456);
/// assert_eq!(some_oid, SOME_STATIC_OID)
/// ```
/// To get a relative Oid use `oid!(rel 1.2)`.
///
/// Because of limitations for procedural macros ([rust issue](https://github.com/rust-lang/rust/issues/54727))
/// and constants used in patterns ([rust issue](https://github.com/rust-lang/rust/issues/31434))
/// the `oid` macro can not directly be used in patterns, also not through constants.
/// You can do this, though:
/// ```
/// # use diflouroborane::oid;
/// # use diflouroborane::utils::oid::ObjectIdentifier;
/// # let some_oid: ObjectIdentifier<'static> = oid!(1.2.456);
/// const SOME_OID: ObjectIdentifier<'static> = oid!(1.2.456);
/// if some_oid == SOME_OID || some_oid == oid!(1.2.456) {
/// println!("match");
/// }
///
/// // Alternatively, compare the DER encoded form directly:
/// const SOME_OID_RAW: &[u8] = &oid!(raw 1.2.456);
/// match some_oid.as_bytes() {
/// SOME_OID_RAW => println!("match"),
/// _ => panic!("no match"),
/// }
/// ```
/// *Attention*, be aware that the latter version might not handle the case of a relative oid correctly. An
/// extra check might be necessary.
#[macro_export]
macro_rules! oid {
(raw $( $item:literal ).*) => {
::bffh_impl::encode_oid!( $( $item ).* )
};
(raw $items:expr) => {
::bffh_impl::encode_oid!($items)
};
($($item:literal ).*) => {
$crate::utils::oid::ObjectIdentifier::new_unchecked(::std::borrow::Cow::Borrowed(
&$crate::oid!(raw $( $item ).*),
))
};
}
#[cfg(test)] #[cfg(test)]
pub(crate) mod tests { pub(crate) mod tests {
use super::*; use super::*;