Skip to content

Commit 0c2b17e

Browse files
stash
1 parent df34e73 commit 0c2b17e

File tree

7 files changed

+32
-37
lines changed

7 files changed

+32
-37
lines changed

borsh-derive/src/internals/attributes/item/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use proc_macro2::Span;
33
use quote::ToTokens;
44
use syn::{spanned::Spanned, Attribute, DeriveInput, Error, Expr, ItemEnum, Path, TypePath};
55

6-
use super::{get_one_attribute, parsing, TAG_WIDTH};
6+
use super::{get_one_attribute, parsing, RUST_REPR, TAG_WIDTH};
77

88
pub fn check_attributes(derive_input: &DeriveInput) -> Result<(), Error> {
99
let borsh = get_one_attribute(&derive_input.attrs)?;
@@ -75,6 +75,16 @@ pub(crate) fn contains_use_discriminant(input: &ItemEnum) -> Result<bool, syn::E
7575
Ok(use_discriminant.unwrap_or(false))
7676
}
7777

78+
pub(crate) fn get_may_be_repr(inpute: &ItemEnum) -> Result<Option<(TypePath, Span)>, syn::Error> {
79+
inpute
80+
.attrs
81+
.iter()
82+
.find(|attr| attr.path() == RUST_REPR)
83+
.map(|attr| attr.parse_args::<TypePath>().map(|value| (attr, value)))
84+
.transpose()
85+
.map(|(attr, value)| value.map(|value| (value, attr.unwrap().span())))
86+
}
87+
7888
pub(crate) fn get_maybe_borsh_tag_width(
7989
input: &ItemEnum,
8090
) -> Result<Option<(u8, Span)>, syn::Error> {

borsh-derive/src/internals/attributes/item/snapshots/check_attrs_borsh_invalid_on_whole_item.snap.new

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
source: borsh-derive/src/internals/attributes/item/mod.rs
3-
assertion_line: 243
3+
assertion_line: 247
44
expression: actual.unwrap_err()
55
---
66
Error(

borsh-derive/src/internals/attributes/item/snapshots/check_attrs_borsh_skip_on_whole_item.snap.new

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
source: borsh-derive/src/internals/attributes/item/mod.rs
3-
assertion_line: 229
3+
assertion_line: 233
44
expression: actual.unwrap_err()
55
---
66
Error(

borsh-derive/src/internals/attributes/item/snapshots/check_attrs_init_function_wrong_format.snap.new

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
source: borsh-derive/src/internals/attributes/item/mod.rs
3-
assertion_line: 328
3+
assertion_line: 332
44
expression: actual.unwrap_err()
55
---
66
Error(

borsh-derive/src/internals/attributes/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ pub const CRATE: Symbol = Symbol("crate", "crate = ...");
3333
/// tag_width - sub-borsh nested meta, item-level only attribute in `BorshSerialize`, `BorshDeserialize`, `BorshSchema` contexts
3434
pub const TAG_WIDTH: Symbol = Symbol("tag_width", "tag_width = ...");
3535

36+
pub const RUST_REPR: Symbol = Symbol("repr", "repr(...)");
37+
3638
#[cfg(feature = "schema")]
3739
pub mod schema_keys {
3840
use super::Symbol;

borsh-derive/src/internals/enum_discriminant.rs

+11-30
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
//!
2+
//! Algorithm of finding out tag width:
3+
//! 1. Rust `repr(...)` and `borsh(tag_width = ...) attributes are read
4+
//! 2. If repr is signed, transparent or variable with *size, borsh errors with unsupported
5+
//! 2.1. NOTE: signed to be supported
16
use core::convert::TryInto;
27
use std::collections::HashMap;
38
use std::convert::TryFrom;
@@ -17,26 +22,11 @@ impl Discriminants {
1722
let mut map = HashMap::new();
1823
let mut next_discriminant_if_not_specified = quote! {0};
1924

20-
fn bytes_needed(value: usize) -> usize {
21-
let bits_needed = std::mem::size_of::<usize>() * 8 - value.leading_zeros() as usize;
22-
(bits_needed + 7) / 8
23-
}
24-
2525
let min_tag_width: u8 = bytes_needed(variants.len())
2626
.try_into()
2727
.expect("variants cannot be bigger u64");
2828

29-
let mut min = 0;
30-
let mut max = 0;
31-
3229
for variant in variants {
33-
if let Some(discriminant) = &variant.discriminant {
34-
let value = discriminant.1.to_token_stream().to_string();
35-
let value = value.parse::<i128>().unwrap();
36-
min = value.min(min);
37-
max = value.max(max);
38-
}
39-
4030
let this_discriminant = variant.discriminant.clone().map_or_else(
4131
|| quote! { #next_discriminant_if_not_specified },
4232
|(_, e)| quote! { #e },
@@ -46,15 +36,6 @@ impl Discriminants {
4636
map.insert(variant.ident.clone(), this_discriminant);
4737
}
4838

49-
let min: u64 = min.abs().try_into().expect("variants cannot be bigger u64");
50-
let max: u64 = max.try_into().expect("variants cannot be bigger u64");
51-
if min > 0 {
52-
return Err(syn::Error::new(
53-
variants.span(),
54-
"negative variants are not supported, please write manual impl",
55-
));
56-
}
57-
let max_bytes: u8 = bytes_needed(max as usize).try_into().expect("");
5839
if let Some((borsh_tag_width, span)) = maybe_borsh_tag_width {
5940
if borsh_tag_width < min_tag_width {
6041
return Err(syn::Error::new(
@@ -68,17 +49,17 @@ impl Discriminants {
6849
}
6950
}
7051

71-
let tag_with = maybe_borsh_tag_width
52+
let tag_width = maybe_borsh_tag_width
7253
.map(|(tag_width, _)| tag_width)
73-
.unwrap_or_else(|| (max_bytes).max(min_tag_width));
54+
.unwrap_or_else(|| (1).max(min_tag_width));
7455

75-
let tag_width_type = if tag_with <= 1 {
56+
let tag_width_type = if tag_width <= 1 {
7657
"u8"
77-
} else if tag_with <= 2 {
58+
} else if tag_width <= 2 {
7859
"u16"
79-
} else if tag_with <= 4 {
60+
} else if tag_width <= 4 {
8061
"u32"
81-
} else if tag_with <= 8 {
62+
} else if tag_width <= 8 {
8263
"u64"
8364
} else {
8465
unreachable!("we eliminated such error earlier")

borsh/tests/roundtrip/requires_derive_category/test_enum_discriminants.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub fn u16_discriminant() {
5454
data.serialize(&mut buf).unwrap();
5555
assert_eq!(buf[0], 154);
5656
assert_eq!(buf[1], 2);
57+
assert!(buf.len(), 2);
5758
let deserialized = U16Discriminant::deserialize(&mut buf.as_slice()).unwrap();
5859
assert_eq!(deserialized, data);
5960
}
@@ -63,16 +64,17 @@ pub fn u32_discriminant() {
6364
use borsh::{BorshDeserialize, BorshSerialize};
6465
#[derive(BorshSerialize, BorshDeserialize, Debug, Eq, PartialEq)]
6566
#[borsh(use_discriminant = true)]
67+
#[repr(u32)]
6668
enum U32Discriminant {
67-
U8 { a: u16 } = 42,
69+
U8 { a: u16 } = 42u32,
6870
U32 { b: u32 } = u32::MAX,
6971
}
7072
let mut buf = vec![];
71-
let data = U16Discriminant::U16 { b: 1234567 };
73+
let data = U32Discriminant::U32 { b: 1234567 };
7274
data.serialize(&mut buf).unwrap();
7375
assert_eq!(buf[0], 154);
7476
assert_eq!(buf[1], 2);
75-
let deserialized = U16Discriminant::deserialize(&mut buf.as_slice()).unwrap();
77+
let deserialized = U32Discriminant::deserialize(&mut buf.as_slice()).unwrap();
7678
assert_eq!(deserialized, data);
7779
}
7880

0 commit comments

Comments
 (0)