From 89601f1c3c4291b494b381329bcc2260bae803bb Mon Sep 17 00:00:00 2001 From: Avril Date: Fri, 20 Nov 2020 01:09:52 +0000 Subject: [PATCH] ext --- Cargo.lock | 1 + Cargo.toml | 3 ++ build.rs | 24 ++++++++++ src/ext.rs | 106 +++++++++++++++++++++++++++++++++++++++++++-- src/main.rs | 1 + src/server/data.rs | 28 +++++++++++- src/server/user.rs | 2 + 7 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 build.rs diff --git a/Cargo.lock b/Cargo.lock index 0bca956..31f80e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -242,6 +242,7 @@ dependencies = [ "pretty_env_logger", "rand 0.7.3", "regex", + "rustc_version", "serde", "serde_cbor", "smallmap", diff --git a/Cargo.toml b/Cargo.toml index 980475e..88b6a91 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,3 +41,6 @@ stack-vec = "0.1.0" tokio = {version = "0.2", features = ["full"]} uuid = {version = "0.8.1", features = ["v4","serde"]} warp = "0.2.5" + +[build-dependencies] +rustc_version = "0.2" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..6399463 --- /dev/null +++ b/build.rs @@ -0,0 +1,24 @@ + +extern crate rustc_version; +use rustc_version::{version, version_meta, Channel}; + +fn main() { + // Assert we haven't travelled back in time + assert!(version().unwrap().major >= 1); + + // Set cfg flags depending on release channel + match version_meta().unwrap().channel { + Channel::Stable => { + println!("cargo:rustc-cfg=stable"); + } + Channel::Beta => { + println!("cargo:rustc-cfg=beta"); + } + Channel::Nightly => { + println!("cargo:rustc-cfg=nightly"); + } + Channel::Dev => { + println!("cargo:rustc-cfg=dev"); + } + } +} diff --git a/src/ext.rs b/src/ext.rs index c7fa93c..27467aa 100644 --- a/src/ext.rs +++ b/src/ext.rs @@ -135,7 +135,7 @@ pub type GenericID = uuid::Uuid; ($name:ident $(: $doc:literal)?) => ($crate::id_type!{pub(self) $name $(: $doc)?}); ($vis:vis $name:ident $(: $doc:literal)?) => { $(#[doc=$doc])? - #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] + #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] $vis struct $name($crate::ext::GenericID); impl $name @@ -187,12 +187,110 @@ pub type GenericID = uuid::Uuid; if cfg!(debug_assertions) { #[cold] unreachable!() } else { - unsafe { ::std::hint::unreachable_unchecked() } + ::std::hint::unreachable_unchecked() } }; } -fn a() -> ! + +/// Dirty debugging macro to get the compiler to print an error message telling you the size of a type. +/// ``` +/// check_size!((u8, u8)); // Expected ... found one with *2* elements +/// ``` +/// Can also be used to statically assert the size of a type +/// ``` +/// # use datse::ext::check_size; +/// check_size!(u16 as 2; "u16 should be 2 bytes"); +/// ``` +#[macro_export] macro_rules! check_size { + ($t:ty) => { + const _: [(); 0] = [(); ::std::mem::size_of::<$t>()]; + }; + ($t:ty as $n:literal $(; $msg:literal)?) => { + const _: [(); $n] = [(); ::std::mem::size_of::<$t>()]; + } +} + +/// Assert the output of a constant boolean expression is `true` at compile time. +#[macro_export] macro_rules! static_assert { + ($val:expr $(; $msg:literal)?) => { + const _: [(); 1] = [(); ($val as bool) as usize]; + } +} + +/// Assert a trait is object safe. This will produce a compiler error if the trait is not object safe +#[macro_export] macro_rules! assert_object_safe { + ($trait:path $(; $msg:literal)?) => { + const _:() = { + #[cold] fn __assert_object_safe() -> ! + { + let _: &dyn $trait; + unsafe { + debug_unreachable!() + } + } + }; + } +} + +assert_object_safe!(AsRef; "object safety assertion test"); +static_assert!(1+1==2; "static assertion test"); + + +pub trait UnwrapInfallible +{ + fn unwrap_infallible(self) -> T; +} + +impl UnwrapInfallible for Result +{ + /// Unwrap with 0 overhead for values that cannot possibly be `Err`. + #[inline(always)] fn unwrap_infallible(self) -> T { + match self { + Ok(v) => v, + #[cold] Err(_) => unsafe { debug_unreachable!() }, + } + } +} + +#[cfg(nightly)] +impl UnwrapInfallible for Result +{ + /// Unwrap with 0 overhead for values that cannot possibly be `Err`. + #[inline(always)] fn unwrap_infallible(self) -> T { + match self { + Ok(v) => v, + #[cold] Err(_) => unsafe { debug_unreachable!() }, + } + } +} + + +pub trait UnwrapErrInfallible +{ + fn unwrap_err_infallible(self) -> T; +} + +impl UnwrapErrInfallible for Result +{ + /// Unwrap with 0 overhead for values that cannot possibly be `Ok`. + #[inline(always)] fn unwrap_err_infallible(self) -> T { + match self { + Err(v) => v, + #[cold] Ok(_) => unsafe { debug_unreachable!() }, + } + } +} + + +#[cfg(nightly)] +impl UnwrapErrInfallible for Result { - debug_unreachable!() + /// Unwrap with 0 overhead for values that cannot possibly be `Ok`. + #[inline(always)] fn unwrap_err_infallible(self) -> T { + match self { + Err(v) => v, + #[cold] Ok(_) => unsafe { debug_unreachable!() }, + } + } } diff --git a/src/main.rs b/src/main.rs index f43acc3..920815a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +#![cfg_attr(nightly, feature(never_type))] #![allow(dead_code)] #![allow(unused_imports)] diff --git a/src/server/data.rs b/src/server/data.rs index 98c659b..9bfb43b 100644 --- a/src/server/data.rs +++ b/src/server/data.rs @@ -340,10 +340,34 @@ impl PartialEq for Datamap /// A value in a datamap, contains the information about the value and the value itself. /// -/// May also contain previous versions of this atom +/// May also contain previous versions of this atom. +/// +/// # Note +/// `Atom` boxes most of itself. It's not needed to box `Atom` itself. +// Box these first two together, since they are hueg. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Atom(MaybeEncrypted, Info, Vec); +pub struct Atom(Box<(MaybeEncrypted, Info)>, Vec); /// An identifier for an item in a `Datamap`, or an item nested within many `Datamap`s. #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Serialize, Deserialize)] pub struct Identifier(String); + +#[cfg(test)] +mod tests +{ + #[test] + fn data_me_sync() + { + let data = super::Data::SI(-120); + let aes = super::aes::AesKey::generate().unwrap(); + + println!("Data: {:?}", data); + let enc = super::MaybeEncrypted::new_encrypted(data.clone(), &aes).expect("Couldn't encrypt"); + println!("M/Enc: {:?}", enc); + let dec = enc.clone().into_unencrypted(Some(&aes)).expect("Couldn't decrypt"); + println!("M/Dec: {:?}", dec); + let out = dec.into_data(Some(&aes)).unwrap(); + + assert_eq!(data, out); + } +} diff --git a/src/server/user.rs b/src/server/user.rs index 78ec710..05a98c6 100644 --- a/src/server/user.rs +++ b/src/server/user.rs @@ -151,6 +151,7 @@ pub trait AsEntityId { fn entity_id(&self) -> Cow<'_, EntityID>; } +assert_object_safe!(AsEntityId); impl AsEntityId for EntityID { @@ -197,6 +198,7 @@ pub trait Entity /// This does not flatten inherited groups, that needs to be performed later fn groups(&self) -> &[GroupID]; } +assert_object_safe!(Entity); impl Entity for User {