Skip to content

Commit

Permalink
refactor!(macros/message): move vtable ctor out of proc-macro
Browse files Browse the repository at this point in the history
  • Loading branch information
loyd committed May 25, 2024
1 parent a55d923 commit 43b0b4e
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 62 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- next-header -->

## [Unreleased] - ReleaseDate
### Changed
- **BREAKING** macros: remove the `network` feature.

## [0.2.0-alpha.15] - 2024-05-13
### Added
Expand Down
2 changes: 1 addition & 1 deletion elfo-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ workspace = true

[features]
test-util = ["tokio/test-util"]
network = ["rmp-serde", "elfo-macros/network"]
network = ["rmp-serde"]
unstable = []
unstable-stuck-detection = ["dep:thread_local"]

Expand Down
2 changes: 1 addition & 1 deletion elfo-core/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub trait Message:
#[doc(hidden)]
#[inline(always)]
fn labels(&self) -> &'static [Label] {
self._vtable().labels
&self._vtable().labels
}

#[doc(hidden)]
Expand Down
81 changes: 56 additions & 25 deletions elfo-core/src/message/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,36 +89,39 @@ impl MessageRepr {
// Reexported in `elfo::_priv`.
/// Message Virtual Table.
pub struct MessageVTable {
pub repr_layout: alloc::Layout, // of `MessageRepr<M>`
pub name: &'static str,
pub protocol: &'static str,
pub labels: &'static [Label],
pub dumping_allowed: bool, // TODO: introduce `DumpingMode`.
pub(super) repr_layout: alloc::Layout, // of `MessageRepr<M>`
pub(super) name: &'static str,
pub(super) protocol: &'static str,
pub(super) labels: [Label; 2],
pub(super) dumping_allowed: bool, // TODO: introduce `DumpingMode`.
// TODO: field ordering (better for cache)
// TODO:
// pub deserialize_any: fn(&mut dyn erased_serde::Deserializer<'_>) -> Result<AnyMessage,
// erased_serde::Error>,
// pub(super) deserialize_any: fn(&mut dyn erased_serde::Deserializer<'_>) ->
// Result<AnyMessage, erased_serde::Error>,
#[cfg(feature = "network")]
pub read_msgpack: unsafe fn(&[u8], NonNull<MessageRepr>) -> Result<(), decode::Error>,
pub(super) read_msgpack: unsafe fn(&[u8], NonNull<MessageRepr>) -> Result<(), decode::Error>,
#[cfg(feature = "network")]
#[allow(clippy::type_complexity)]
pub write_msgpack:
pub(super) write_msgpack:
unsafe fn(NonNull<MessageRepr>, &mut Vec<u8>, usize) -> Result<(), encode::Error>,
pub debug: unsafe fn(NonNull<MessageRepr>, &mut fmt::Formatter<'_>) -> fmt::Result,
pub clone: unsafe fn(NonNull<MessageRepr>, NonNull<MessageRepr>),
pub erase: unsafe fn(NonNull<MessageRepr>) -> dumping::ErasedMessage,
pub deserialize_any: unsafe fn(
pub(super) debug: unsafe fn(NonNull<MessageRepr>, &mut fmt::Formatter<'_>) -> fmt::Result,
pub(super) clone: unsafe fn(NonNull<MessageRepr>, NonNull<MessageRepr>),
pub(super) erase: unsafe fn(NonNull<MessageRepr>) -> dumping::ErasedMessage,
pub(super) deserialize_any: unsafe fn(
deserializer: &mut dyn erased_serde::Deserializer<'_>,
out_ptr: NonNull<MessageRepr>,
) -> Result<(), erased_serde::Error>,
pub drop: unsafe fn(NonNull<MessageRepr>),
pub(super) drop: unsafe fn(NonNull<MessageRepr>),
}

static VTABLE_ANY: &MessageVTable = &MessageVTable {
repr_layout: alloc::Layout::new::<()>(),
name: "",
protocol: "",
labels: &[],
labels: [
Label::from_static_parts("", ""),
Label::from_static_parts("", ""),
],
dumping_allowed: false,
#[cfg(feature = "network")]
read_msgpack: |_, _| unreachable!(),
Expand All @@ -131,36 +134,64 @@ static VTABLE_ANY: &MessageVTable = &MessageVTable {
drop: |_| unreachable!(),
};

// For monomorphization in the `#[message]` macro.
// Reeexported in `elfo::_priv`.
pub mod vtablefns {
impl MessageVTable {
// Reexported in `elfo::_priv`.
#[doc(hidden)]
pub const fn new<M: Message>(
name: &'static str,
protocol: &'static str,
dumping_allowed: bool,
) -> Self {
Self {
repr_layout: alloc::Layout::new::<MessageRepr<M>>(),
name,
protocol,
labels: [
Label::from_static_parts("message", name),
Label::from_static_parts("protocol", protocol),
],
dumping_allowed,
debug: vtablefns::debug::<M>,
clone: vtablefns::clone::<M>,
erase: vtablefns::erase::<M>,
deserialize_any: vtablefns::deserialize_any::<M>,
drop: vtablefns::drop::<M>,
#[cfg(feature = "network")]
read_msgpack: vtablefns::read_msgpack::<M>,
#[cfg(feature = "network")]
write_msgpack: vtablefns::write_msgpack::<M>,
}
}
}

mod vtablefns {
use super::*;

pub unsafe fn drop<M>(ptr: NonNull<MessageRepr>) {
pub(super) unsafe fn drop<M>(ptr: NonNull<MessageRepr>) {
ptr::drop_in_place(ptr.cast::<MessageRepr<M>>().as_ptr());
}

pub unsafe fn clone<M: Clone>(ptr: NonNull<MessageRepr>, out_ptr: NonNull<MessageRepr>) {
pub(super) unsafe fn clone<M: Clone>(ptr: NonNull<MessageRepr>, out_ptr: NonNull<MessageRepr>) {
ptr::write(
out_ptr.cast::<MessageRepr<M>>().as_ptr(),
ptr.cast::<MessageRepr<M>>().as_ref().clone(),
);
}

pub unsafe fn debug<M: fmt::Debug>(
pub(super) unsafe fn debug<M: fmt::Debug>(
ptr: NonNull<MessageRepr>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
let data = &ptr.cast::<MessageRepr<M>>().as_ref().data;
fmt::Debug::fmt(data, f)
}

pub unsafe fn erase<M: Message>(ptr: NonNull<MessageRepr>) -> dumping::ErasedMessage {
pub(super) unsafe fn erase<M: Message>(ptr: NonNull<MessageRepr>) -> dumping::ErasedMessage {
let data = ptr.cast::<MessageRepr<M>>().as_ref().data.clone();
smallbox!(data)
}

pub unsafe fn deserialize_any<M: Message>(
pub(super) unsafe fn deserialize_any<M: Message>(
deserializer: &mut dyn erased_serde::Deserializer<'_>,
out_ptr: NonNull<MessageRepr>,
) -> Result<(), erased_serde::Error> {
Expand All @@ -173,7 +204,7 @@ pub mod vtablefns {
}

cfg_network!({
pub unsafe fn read_msgpack<M: Message>(
pub(super) unsafe fn read_msgpack<M: Message>(
buffer: &[u8],
out_ptr: NonNull<MessageRepr>,
) -> Result<(), decode::Error> {
Expand All @@ -185,7 +216,7 @@ pub mod vtablefns {
Ok(())
}

pub unsafe fn write_msgpack<M: Message>(
pub(super) unsafe fn write_msgpack<M: Message>(
ptr: NonNull<MessageRepr>,
out: &mut Vec<u8>,
limit: usize,
Expand Down
3 changes: 0 additions & 3 deletions elfo-macros-impl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ readme.workspace = true
[lints]
workspace = true

[features]
network = []

[dependencies]
proc-macro2 = "1.0.24"
quote = "1.0.9"
Expand Down
37 changes: 8 additions & 29 deletions elfo-macros-impl/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,6 @@ pub fn message_impl(
// TODO: pass to `_elfo_Wrapper`.
let dumping_allowed = args.dumping_allowed.unwrap_or(true);

let network_fns = cfg!(feature = "network").then(|| {
quote! {
read_msgpack: #internal::vtablefns::read_msgpack::<#name>,
write_msgpack: #internal::vtablefns::write_msgpack::<#name>,
}
});

let protocol = if let Some(protocol) = &args.protocol {
quote! { #protocol }
} else {
Expand All @@ -227,24 +220,13 @@ pub fn message_impl(
fn _touch(&self) {}
}

#[linkme::distributed_slice(MESSAGE_VTABLES_LIST)]
#[linkme(crate = linkme)]
static VTABLE: &#internal::MessageVTable = &#internal::MessageVTable {
repr_layout: ::std::alloc::Layout::new::<#internal::MessageRepr<#name>>(),
name: #name_str,
protocol: #protocol,
labels: &[
#internal::metrics::Label::from_static_parts("message", #name_str),
#internal::metrics::Label::from_static_parts("protocol", #protocol),
],
dumping_allowed: #dumping_allowed,
debug: #internal::vtablefns::debug::<#name>,
clone: #internal::vtablefns::clone::<#name>,
erase: #internal::vtablefns::erase::<#name>,
deserialize_any: #internal::vtablefns::deserialize_any::<#name>,
drop: #internal::vtablefns::drop::<#name>,
#network_fns
};
#[#internal::linkme::distributed_slice(#internal::MESSAGE_VTABLES_LIST)]
#[linkme(crate = #internal::linkme)]
static VTABLE: &#internal::MessageVTable = &#internal::MessageVTable::new::<#name>(
#name_str,
#protocol,
#dumping_allowed
);
}
});

Expand Down Expand Up @@ -287,6 +269,7 @@ pub fn message_impl(
let impl_debug =
(args.transparent && args.not.iter().all(|x| x != "Debug")).then(|| gen_impl_debug(&input));

// Don't add `use` statements here to avoid possible collisions with user code.
let expanded = quote! {
#derive_debug
#derive_clone
Expand All @@ -300,10 +283,6 @@ pub fn message_impl(
#[allow(non_snake_case)]
#[allow(unreachable_code)] // for `enum Impossible {}`
const _: () = {
// Keep this list as minimal as possible to avoid possible collisions with `#name`.
// Especially avoid `PascalCase`.
use #internal::{MESSAGE_VTABLES_LIST, linkme}; // TODO: remove

#impl_message
#impl_request
#impl_debug
Expand Down
3 changes: 0 additions & 3 deletions elfo-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ workspace = true
[lib]
proc-macro = true

[features]
network = ["elfo-macros-impl/network"]

[dependencies]
elfo-macros-impl = { version = "0.2.0-alpha.15", path = "../elfo-macros-impl" }

Expand Down

0 comments on commit 43b0b4e

Please sign in to comment.