ptr_meta_derive-0.3.0/.cargo_vcs_info.json0000644000000001550000000000100142060ustar { "git": { "sha1": "3e8aed87089acfa5218465c79bcbba993e269d07" }, "path_in_vcs": "ptr_meta_derive" }ptr_meta_derive-0.3.0/Cargo.toml0000644000000025320000000000100122050ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.81" name = "ptr_meta_derive" version = "0.3.0" authors = ["David Koloski "] build = false autobins = false autoexamples = false autotests = false autobenches = false description = "Proc macros for ptr_meta" documentation = "https://docs.rs/ptr_meta_derive" readme = "README.md" keywords = ["no_std"] categories = [ "no-std", "no-std::no-alloc", ] license = "MIT" repository = "https://github.com/rkyv/ptr_meta" [lib] name = "ptr_meta_derive" path = "src/lib.rs" proc-macro = true [dependencies.proc-macro2] version = "1" features = ["proc-macro"] default-features = false [dependencies.quote] version = "1" features = ["proc-macro"] default-features = false [dependencies.syn] version = "2" features = [ "clone-impls", "derive", "full", "parsing", "printing", "proc-macro", ] default-features = false ptr_meta_derive-0.3.0/Cargo.toml.orig000064400000000000000000000013311046102023000156620ustar 00000000000000[package] name = "ptr_meta_derive" description = "Proc macros for ptr_meta" version.workspace = true authors.workspace = true edition.workspace = true rust-version.workspace = true license.workspace = true readme.workspace = true repository.workspace = true keywords.workspace = true categories.workspace = true documentation = "https://docs.rs/ptr_meta_derive" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] proc-macro = true [dependencies] proc-macro2 = { workspace = true, features = ["proc-macro"] } syn = { workspace = true, features = ["clone-impls", "derive", "full", "parsing", "printing", "proc-macro"] } quote = { workspace = true, features = ["proc-macro"] } ptr_meta_derive-0.3.0/LICENSE000064400000000000000000000020351046102023000140020ustar 00000000000000Copyright 2021 David Koloski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ptr_meta_derive-0.3.0/README.md000064400000000000000000000040101046102023000142470ustar 00000000000000# `ptr_meta` [![crates.io badge]][crates.io] [![docs badge]][docs] [![license badge]][license] [crates.io badge]: https://img.shields.io/crates/v/ptr_meta.svg [crates.io]: https://crates.io/crates/ptr_meta [docs badge]: https://img.shields.io/docsrs/ptr_meta [docs]: https://docs.rs/ptr_meta [license badge]: https://img.shields.io/badge/license-MIT-blue.svg [license]: https://github.com/rkyv/ptr_meta/blob/master/LICENSE A radioactive stabilization of the [`ptr_meta` RFC]. [`ptr_meta` RFC]: https://rust-lang.github.io/rfcs/2580-ptr-meta.html ## Documentation - [ptr_meta](https://docs.rs/ptr_meta), the core library - [ptr_meta_derive](https://docs.rs/ptr_meta_derive), proc macros for implementing `Pointee` for structs and trait objects ## Example ```rust // Get the associated metadata for pointers let str = "hello world"; assert_eq!(ptr_meta::metadata(str), str.len()); let slice = &[1, 2, 3, 4, 5] as &[i32]; assert_eq!(ptr_meta::metadata(slice), slice.len()); // Make your own wide pointers from data pointers and metadata let bytes = [b'h', b'e', b'l', b'l', b'o']; let ptr = ptr_meta::from_raw_parts::(bytes.as_ptr().cast(), 5); println!("{} world!", unsafe { &*ptr }); // prints "hello world!" // Derive Pointee on your own types #[derive(ptr_meta::Pointee)] #[repr(transparent)] struct CoolStr { inner: str, } impl CoolStr { fn print_cool(&self) { println!("😎 {} 😎", &self.inner); } } let ptr = ptr_meta::from_raw_parts::(bytes.as_ptr().cast(), 5); let cool = unsafe { &*ptr }; cool.print_cool(); // prints "😎 hello 😎" // Implement Pointee for trait objects #[ptr_meta::pointee] trait Printable { fn print(&self); } impl Printable for i32 { fn print(&self) { println!("i32: {self}"); } } let i32_vtable = ptr_meta::metadata(&0i32 as &dyn Printable); let one_hundred = 100i32; let printable = ptr_meta::from_raw_parts::( (&one_hundred as *const i32).cast(), i32_vtable, ); unsafe { (*printable).print(); // prints "i32: 100" } ``` ptr_meta_derive-0.3.0/src/attributes.rs000064400000000000000000000035561046102023000163310ustar 00000000000000use quote::ToTokens; use syn::{ meta::ParseNestedMeta, parse_quote, AttrStyle, Attribute, Error, Path, Token, }; fn try_set_attribute( attribute: &mut Option, value: T, name: &'static str, ) -> Result<(), Error> { if attribute.is_none() { *attribute = Some(value); Ok(()) } else { Err(Error::new_spanned( value, format!("{} already specified", name), )) } } #[derive(Default)] pub struct Attributes { crate_path: Option, } impl Attributes { pub fn parse_meta( &mut self, meta: ParseNestedMeta<'_>, ) -> Result<(), Error> { if meta.path.is_ident("crate") { if meta.input.parse::().is_ok() { let path = meta.input.parse::()?; try_set_attribute(&mut self.crate_path, path, "crate") } else if meta.input.is_empty() || meta.input.peek(Token![,]) { try_set_attribute( &mut self.crate_path, parse_quote! { crate }, "crate", ) } else { Err(meta.error("expected `crate` or `crate = ...`")) } } else { Err(meta.error("unrecognized ptr_meta argument")) } } pub fn parse(attrs: &[Attribute]) -> Result { let mut result = Self::default(); for attr in attrs.iter() { if !matches!(attr.style, AttrStyle::Outer) { continue; } if attr.path().is_ident("ptr_meta") { attr.parse_nested_meta(|nested| result.parse_meta(nested))?; } } Ok(result) } pub fn crate_path(&self) -> Path { self.crate_path .clone() .unwrap_or_else(|| parse_quote! { ::ptr_meta }) } } ptr_meta_derive-0.3.0/src/lib.rs000064400000000000000000000071261046102023000147060ustar 00000000000000mod attributes; use proc_macro2::TokenStream; use quote::quote; use syn::{ meta, parse_macro_input, parse_quote, Data, DeriveInput, Error, ItemTrait, }; use self::attributes::Attributes; /// Derives `Pointee` for the labeled struct which has a trailing DST. /// /// # Attributes /// /// Additional arguments can be specified using attributes. /// /// `#[ptr_meta(...)]` accepts the following arguments: /// /// - `crate = ...`: Chooses an alternative crate path to import ptr_meta from. #[proc_macro_derive(Pointee, attributes(ptr_meta))] pub fn derive_pointee( input: proc_macro::TokenStream, ) -> proc_macro::TokenStream { let derive_input = parse_macro_input!(input as DeriveInput); match derive_pointee_impl(derive_input) { Ok(result) => result.into(), Err(e) => e.to_compile_error().into(), } } fn derive_pointee_impl(mut input: DeriveInput) -> Result { let attributes = Attributes::parse(&input.attrs)?; let ident = &input.ident; let crate_path = attributes.crate_path(); let fields = match &input.data { Data::Struct(data) => &data.fields, Data::Enum(_) => { return Err(Error::new( ident.span(), "enums always have a provided `Pointee` impl because they \ cannot be dynamically-sized", )) } Data::Union(_) => { return Err(Error::new( ident.span(), "unions always have an provided `Pointee` impl because they \ cannot be dynamically-sized", )) } }; let Some(last_field) = fields.iter().last() else { return Err(Error::new( ident.span(), "fieldless structs always have a provided `Poitnee` impl because they cannot be dynamically-sized", )); }; let last_field_ty = &last_field.ty; let where_clause = input.generics.make_where_clause(); where_clause .predicates .push(parse_quote! { #last_field_ty: #crate_path::Pointee }); let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); Ok(quote! { unsafe impl #impl_generics #crate_path::Pointee for #ident #ty_generics #where_clause { type Metadata = <#last_field_ty as #crate_path::Pointee>::Metadata; } }) } /// Generates a `Pointee` implementation for trait object of the labeled trait. /// /// # Arguments /// /// `#[pointee(...)]` takes the following arguments: /// /// - `crate = ...`: Chooses an alternative crate path to import ptr_meta from. #[proc_macro_attribute] pub fn pointee( attr: proc_macro::TokenStream, item: proc_macro::TokenStream, ) -> proc_macro::TokenStream { let mut attributes = Attributes::default(); let meta_parser = meta::parser(|nested| attributes.parse_meta(nested)); parse_macro_input!(attr with meta_parser); let item = parse_macro_input!(item as ItemTrait); match pointee_impl(attributes, item) { Ok(result) => result.into(), Err(e) => e.to_compile_error().into(), } } fn pointee_impl( attributes: Attributes, item: ItemTrait, ) -> Result { let ident = &item.ident; let crate_path = attributes.crate_path(); let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl(); Ok(quote! { #item unsafe impl #impl_generics #crate_path::Pointee for (dyn #ident #ty_generics + '_) #where_clause { type Metadata = #crate_path::DynMetadata; } }) }