Skip to content

Commit

Permalink
as_ref for fields
Browse files Browse the repository at this point in the history
  • Loading branch information
wyatt-herkamp committed Sep 2, 2023
1 parent a20513f commit 21a55bf
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 14 deletions.
4 changes: 2 additions & 2 deletions digestible/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "digestible"
version = "0.2.0"
version = "0.2.1"
edition = "2021"
authors = ["Wyatt Herkamp <[email protected]>"]
description = "A more dynamic Hash and Hasher trait for Rust"
Expand All @@ -16,7 +16,7 @@ rust-version="1.70"
[dependencies]
digest_0_10 = {package = "digest", version = "0.10", optional = true }
byteorder = "1"
digestible-macros= {path="../macros",optional = true, version = "0.2.0" }
digestible-macros= {path="../macros",optional = true, version = "0.2.1" }
base64 = { version = "0.21", optional = true }
bytes = { version = "1" , optional = true}
[dev-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions digestible/src/digester_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ impl<'a, T: DigestWriter> DigestWriter for &'a mut T {
#[cfg(feature = "alloc")]
mod has_alloc {
use crate::DigestWriter;
use alloc::vec::Vec;
use alloc::boxed::Box;
use alloc::vec::Vec;

impl DigestWriter for Vec<u8> {
fn write(&mut self, data: &[u8]) {
Expand All @@ -179,4 +179,4 @@ impl DigestWriter for bytes::BytesMut {
fn write(&mut self, data: &[u8]) {
self.extend_from_slice(data);
}
}
}
2 changes: 2 additions & 0 deletions digestible/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ pub use digester_writer::DigestWriter;
/// ```
/// ### digest_with
/// Function provided in the [digest_with](crate::digest_with) module Example: `#[digestible(digest_with = digest_with_hash)]`
/// ### as_ref
/// Will call as_ref on the field before digesting it. Example: `#[digestible(as_ref = TargetType)]`
pub use digestible_macros::Digestible;
#[cfg(feature = "base64")]
#[doc(inline)]
Expand Down
1 change: 0 additions & 1 deletion digestible/src/to_base64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,4 @@ where
fn digest<B: ByteOrder>(self, data: &impl Digestible) -> Self::Target {
Self::encode_base64(self.0.digest::<B>(data))
}

}
10 changes: 9 additions & 1 deletion digestible/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ pub fn test_base64() {
pub struct TupleStruct(String);
#[derive(Digestible)]
#[digestible(hash = LittleEndian, type_header = None)]
pub struct NoHeader{
pub struct NoHeader {
pub name: String,
pub id: u32,
#[digestible(as_ref = u32)]
pub as_ref_test: Data<u32>,
}
#[derive(Digestible)]
#[digestible(hash = LittleEndian)]
Expand All @@ -69,6 +71,12 @@ pub enum EnumExample {
None,
Unit(String),
}
pub struct Data<T>(T);
impl<T> AsRef<T> for Data<T> {
fn as_ref(&self) -> &T {
&self.0
}
}
#[test]
pub fn hash_test() {
let test = EnumExample::One {
Expand Down
2 changes: 1 addition & 1 deletion macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "digestible-macros"
version = "0.2.0"
version = "0.2.1"
edition = "2021"
authors = ["Wyatt Herkamp <[email protected]>"]
description = "Macros for generating digest implementations"
Expand Down
33 changes: 26 additions & 7 deletions macros/src/fields.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,25 @@ use crate::consts::{digest_with_path, digestible_path};
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote, ToTokens};
use syn::parse::{Parse, ParseStream};
use syn::Path;
use syn::{parse_quote, Expr, Path, Type};

mod keywords {
use syn::custom_keyword;
custom_keyword!(skip);
custom_keyword!(with);
custom_keyword!(digest_with);
custom_keyword!(as_ref);
}
#[derive(Debug, Default)]
pub struct FieldAttr {
pub skip: bool,
pub as_ref: Option<Type>,
pub digest_with: Option<Path>,
}
impl Parse for FieldAttr {
fn parse(input: ParseStream) -> syn::Result<Self> {
let mut skip = false;
let mut as_ref = None;
let mut digest_with: Option<Path> = None;
while !input.is_empty() {
let lookahead = input.lookahead1();
Expand All @@ -34,12 +37,20 @@ impl Parse for FieldAttr {

let internal_digest_with_path = digest_with_path(input.parse()?);
digest_with = Some(internal_digest_with_path);
} else if lookahead.peek(keywords::as_ref) {
let _ = input.parse::<keywords::as_ref>()?;
let _: syn::Token![=] = input.parse()?;
as_ref = Some(input.parse()?);
} else {
return Err(lookahead.error());
}
}

let attr = Self { skip, digest_with };
let attr = Self {
skip,
as_ref,
digest_with,
};
Ok(attr)
}
}
Expand Down Expand Up @@ -88,18 +99,26 @@ impl ToTokens for Field<'_> {
}
let digestible = digestible_path();
let ident = &self.ident;
let ty = &self.ty;
let ty = if let Some(as_ref) = &self.attr.as_ref {
as_ref
} else {
&self.ty
};
let endian = self.endian;
let writer = self.writer;
let variable_ref: Expr = if self.attr.as_ref.is_some() {
parse_quote! {#ident.as_ref()}
} else {
parse_quote! {#ident}
};
let result = if let Some(digest_with) = &self.attr.digest_with {
quote! {
#digest_with::<#endian,_>(#ident, #writer);
#digest_with::<#endian,_>(#variable_ref, #writer);
}
} else {
quote! {
<#ty as #digestible>::digest::<#endian, _>(#ident, #writer);
}
quote! {<#ty as #digestible>::digest::<#endian, _>(#variable_ref,#writer);}
};

tokens.extend(result);
}
}

0 comments on commit 21a55bf

Please sign in to comment.