Skip to content

Commit

Permalink
Pre-release cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
wojciech-graj committed Nov 11, 2024
1 parent 51dc21f commit 9b9d77c
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 66 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Require unquoted expressions in attributes
- Use nested metas for all lists in attributes
- Add `#[protocol(ctx_generics(...))]`
- Improve attribute parsing and validation
- Impose `non_exhaustive` on `Error`
# v0.5.0
- Split `Protocol` into `ProtocolRead` and `ProtocolWrite`
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Add this to your `Cargo.toml`:

```toml
[dependencies]
bin-proto = "0.5"
bin-proto = "0.6"
```

And then define a type with the `#[derive(bin_proto::ProtocolRead, bin_proto::ProtocolWrite)]` attributes.
Expand All @@ -33,11 +33,11 @@ And then define a type with the `#[derive(bin_proto::ProtocolRead, bin_proto::Pr
use bin_proto::{ProtocolRead, ProtocolWrite, ProtocolNoCtx};

#[derive(Debug, ProtocolRead, ProtocolWrite, PartialEq)]
#[protocol(discriminant_type = "u8")]
#[protocol(discriminant_type = u8)]
#[protocol(bits = 4)]
enum E {
V1 = 1,
#[protocol(discriminant = "4")]
#[protocol(discriminant = 4)]
V4,
}

Expand All @@ -48,11 +48,11 @@ struct S {
#[protocol(bits = 3)]
bitfield: u8,
enum_: E,
#[protocol(write_value = "self.arr.len() as u8")]
#[protocol(write_value = self.arr.len() as u8)]
arr_len: u8,
#[protocol(tag = "arr_len as usize")]
#[protocol(tag = arr_len as usize)]
arr: Vec<u8>,
#[protocol(tag(type = "u16", write_value = "self.prefixed_arr.len() as u16"))]
#[protocol(tag_type = u16, tag_value = self.prefixed_arr.len() as u16)]
prefixed_arr: Vec<u8>,
#[protocol(flexible_array_member)]
read_to_end: Vec<u8>,
Expand All @@ -65,7 +65,7 @@ assert_eq!(
| 0b0001, // enum_: V1 (0001)
0x02, // arr_len: 2
0x21, 0x37, // arr: [0x21, 0x37]
0x00, 0x01, 0x33, // prefixed_arr: [0x33]
0x00, 0x01, 0x33, // prefixed_arr: [0x33]
0x01, 0x02, 0x03, // read_to_end: [0x01, 0x02, 0x03]
], bin_proto::ByteOrder::BigEndian).unwrap(),
S {
Expand Down Expand Up @@ -113,7 +113,7 @@ impl ProtocolWrite<Ctx> for NeedsCtx {
}

#[derive(ProtocolRead, ProtocolWrite)]
#[protocol(ctx = "Ctx")]
#[protocol(ctx = Ctx)]
pub struct WithCtx(NeedsCtx);

WithCtx(NeedsCtx)
Expand Down
2 changes: 1 addition & 1 deletion bench/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ publish = false

[dependencies]
bin-proto = { path = "../bin-proto" }
deku = "0.17"
deku = "0.18.1"
46 changes: 28 additions & 18 deletions bin-proto-derive/src/attr.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::fmt;

use proc_macro2::TokenStream;
use syn::{parenthesized, punctuated::Punctuated, spanned::Spanned, Error, Result, Token};
use proc_macro2::{Span, TokenStream};
use syn::{parenthesized, punctuated::Punctuated, Error, Result, Token};

#[derive(Default)]
pub struct Attrs {
Expand Down Expand Up @@ -47,7 +47,7 @@ impl fmt::Display for AttrKind {
}
}

macro_rules! validate_attr_kind {
macro_rules! expect_attr_kind {
($pat:pat, $kind:expr, $meta:expr, $attr:expr) => {
if let Some(kind) = $kind {
if !matches!(kind, $pat) {
Expand All @@ -70,7 +70,7 @@ impl Attrs {
}

#[allow(clippy::too_many_lines)]
pub fn for_kind(attrs: &[syn::Attribute], kind: Option<AttrKind>) -> Result<Self> {
pub fn parse(attrs: &[syn::Attribute], kind: Option<AttrKind>, span: Span) -> Result<Self> {
let mut attribs = Attrs::default();

let mut tag = None;
Expand All @@ -84,19 +84,19 @@ impl Attrs {
if attr.path().is_ident("protocol") {
attr.parse_nested_meta(|meta| {
if meta.path.is_ident("flexible_array_member") {
validate_attr_kind!(AttrKind::Field, kind, meta, "flexible_array_member");
expect_attr_kind!(AttrKind::Field, kind, meta, "flexible_array_member");
attribs.flexible_array_member = true;
} else if meta.path.is_ident("discriminant_type") {
validate_attr_kind!(AttrKind::Enum, kind, meta, "discriminant_type");
expect_attr_kind!(AttrKind::Enum, kind, meta, "discriminant_type");
attribs.discriminant_type = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("discriminant") {
validate_attr_kind!(AttrKind::Variant, kind, meta, "discriminant");
expect_attr_kind!(AttrKind::Variant, kind, meta, "discriminant");
attribs.discriminant = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("ctx") {
validate_attr_kind!(AttrKind::Enum | AttrKind::Struct, kind, meta, "ctx");
expect_attr_kind!(AttrKind::Enum | AttrKind::Struct, kind, meta, "ctx");
ctx = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("ctx_generics") {
validate_attr_kind!(
expect_attr_kind!(
AttrKind::Enum | AttrKind::Struct,
kind,
meta,
Expand All @@ -112,7 +112,7 @@ impl Attrs {
.collect(),
);
} else if meta.path.is_ident("ctx_bounds") {
validate_attr_kind!(
expect_attr_kind!(
AttrKind::Enum | AttrKind::Struct,
kind,
meta,
Expand All @@ -128,19 +128,19 @@ impl Attrs {
.collect(),
);
} else if meta.path.is_ident("bits") {
validate_attr_kind!(AttrKind::Enum | AttrKind::Field, kind, meta, "bits");
expect_attr_kind!(AttrKind::Enum | AttrKind::Field, kind, meta, "bits");
attribs.bits = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("write_value") {
validate_attr_kind!(AttrKind::Field, kind, meta, "write_value");
expect_attr_kind!(AttrKind::Field, kind, meta, "write_value");
attribs.write_value = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("tag") {
validate_attr_kind!(AttrKind::Field, kind, meta, "tag");
expect_attr_kind!(AttrKind::Field, kind, meta, "tag");
tag = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("tag_type") {
validate_attr_kind!(AttrKind::Field, kind, meta, "tag_type");
expect_attr_kind!(AttrKind::Field, kind, meta, "tag_type");
tag_type = Some(meta.value()?.parse()?);
} else if meta.path.is_ident("tag_value") {
validate_attr_kind!(AttrKind::Field, kind, meta, "tag_value");
expect_attr_kind!(AttrKind::Field, kind, meta, "tag_value");
tag_value = Some(meta.value()?.parse()?);
} else {
return Err(meta.error("unrecognized protocol"));
Expand All @@ -159,14 +159,24 @@ impl Attrs {
});
}
(None, None, None) => {}
_ => return Err(Error::new(attrs[0].span(), "TODO")),
_ => {
return Err(Error::new(
span,
"invalid configuration of 'tag', 'tag_type', or 'tag_value' attributes.",
))
}
}

match (ctx, ctx_bounds) {
(Some(ctx), None) => attribs.ctx = Some(Ctx::Concrete(ctx)),
(None, Some(ctx_bounds)) => attribs.ctx = Some(Ctx::Bounds(ctx_bounds)),
(None, None) => {}
_ => return Err(Error::new(attrs[0].span(), "TODO")),
_ => {
return Err(Error::new(
span,
"use of mutually exclusive 'ctx' and 'ctx_bounds' attributes.",
))
}
}

if [
Expand All @@ -180,7 +190,7 @@ impl Attrs {
> 1
{
return Err(Error::new(
attrs[0].span(),
span,
"bits, flexible_array_member, and tag are mutually-exclusive attributes",
));
}
Expand Down
4 changes: 2 additions & 2 deletions bin-proto-derive/src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ fn read_named_fields(fields_named: &syn::FieldsNamed) -> (TokenStream, TokenStre
}

fn read(field: &syn::Field) -> TokenStream {
let attribs = match Attrs::for_kind(field.attrs.as_slice(), Some(AttrKind::Field)) {
let attribs = match Attrs::parse(field.attrs.as_slice(), Some(AttrKind::Field), field.span()) {
Ok(attribs) => attribs,
Err(e) => return e.to_compile_error(),
};
Expand Down Expand Up @@ -92,7 +92,7 @@ fn read(field: &syn::Field) -> TokenStream {
}

fn write(field: &syn::Field, field_name: &TokenStream) -> TokenStream {
let attribs = match Attrs::for_kind(field.attrs.as_slice(), Some(AttrKind::Field)) {
let attribs = match Attrs::parse(field.attrs.as_slice(), Some(AttrKind::Field), field.span()) {
Ok(attribs) => attribs,
Err(e) => return e.to_compile_error(),
};
Expand Down
4 changes: 2 additions & 2 deletions bin-proto-derive/src/codegen/trait_impl.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::attr::{Attrs, Ctx};

use proc_macro2::{Span, TokenStream};
use syn::{parse_quote, punctuated::Punctuated, Token};
use syn::{parse_quote, punctuated::Punctuated, spanned::Spanned, Token};

pub enum TraitImplType {
ProtocolRead,
Expand All @@ -17,7 +17,7 @@ pub fn impl_trait_for(
typ: &TraitImplType,
) -> TokenStream {
let name = &ast.ident;
let attribs = match Attrs::for_kind(ast.attrs.as_slice(), None) {
let attribs = match Attrs::parse(ast.attrs.as_slice(), None, ast.span()) {
Ok(attribs) => attribs,
Err(e) => return e.to_compile_error(),
};
Expand Down
6 changes: 3 additions & 3 deletions bin-proto-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mod plan;
use attr::{AttrKind, Attrs};
use codegen::trait_impl::{impl_trait_for, TraitImplType};
use proc_macro2::TokenStream;
use syn::parse_macro_input;
use syn::{parse_macro_input, spanned::Spanned};

use crate::codegen::enums::{read_discriminant, variant_discriminant, write_discriminant};

Expand Down Expand Up @@ -46,7 +46,7 @@ fn impl_for_struct(
strukt: &syn::DataStruct,
protocol_type: Operation,
) -> TokenStream {
let attribs = match Attrs::for_kind(ast.attrs.as_slice(), Some(AttrKind::Struct)) {
let attribs = match Attrs::parse(ast.attrs.as_slice(), Some(AttrKind::Struct), ast.span()) {
Ok(attribs) => attribs,
Err(e) => return e.to_compile_error(),
};
Expand Down Expand Up @@ -100,7 +100,7 @@ fn impl_for_enum(
Ok(plan) => plan,
Err(e) => return e.to_compile_error(),
};
let attribs = match Attrs::for_kind(ast.attrs.as_slice(), Some(AttrKind::Enum)) {
let attribs = match Attrs::parse(ast.attrs.as_slice(), Some(AttrKind::Enum), ast.span()) {
Ok(attribs) => attribs,
Err(e) => return e.to_compile_error(),
};
Expand Down
8 changes: 6 additions & 2 deletions bin-proto-derive/src/plan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,19 @@ pub struct EnumVariant {

impl Enum {
pub fn try_new(ast: &syn::DeriveInput, e: &syn::DataEnum) -> Result<Self> {
let attrs = Attrs::for_kind(ast.attrs.as_slice(), Some(AttrKind::Enum))?;
let attrs = Attrs::parse(ast.attrs.as_slice(), Some(AttrKind::Enum), ast.span())?;

let plan = Self {
discriminant_ty: attrs.discriminant_type.unwrap(),
variants: e
.variants
.iter()
.map(|variant| {
let attrs = Attrs::for_kind(variant.attrs.as_slice(), Some(AttrKind::Variant))?;
let attrs = Attrs::parse(
variant.attrs.as_slice(),
Some(AttrKind::Variant),
variant.span(),
)?;

let discriminant_value = match variant.discriminant.as_ref().map(|a| &a.1) {
Some(expr_lit) => expr_lit.clone(),
Expand Down
4 changes: 4 additions & 0 deletions bin-proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ repository = "https://github.com/wojciech-graj/bin-proto"
documentation = "https://docs.rs/bin-proto"
keywords = ["protocol", "binary", "bit", "codec", "serde"]

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[features]
default = ["derive"]
derive = ["bin-proto-derive"]
Expand Down
4 changes: 2 additions & 2 deletions bin-proto/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ mod tests {
use super::*;

#[allow(unused)]
trait IsSized: Sized {}
trait IsSizedSendSync: Sized + Send + Sync {}

impl IsSized for Error {}
impl IsSizedSendSync for Error {}
}
Loading

0 comments on commit 9b9d77c

Please sign in to comment.