1 stable release
1.0.0 | Nov 6, 2023 |
---|
#1959 in Procedural macros
9KB
77 lines
fixed-size
fixed-size
- A struct attribute to set fixed sizes for certain fields which are normally dynamic
lib.rs
:
struct attribute to set fixed sizes for certain fields which are normally dynamic
This is useful when generating structs from protobufs using prost and also using those structs with a serde format that requires fixed length strings
Example
syntax = "proto3";
message Foo
{
string my_string = 1;
}
Prost will create use String
for the my_string field. If you have a binary format requiring
exactly 4 characters in a string this will be difficult to handle in a generic manner. If you add
the #[fixed(my_string=4)]
attribute then you'll end up with a ArrayString::<4>
instead.
By default, ArrayString will be used but this can be overridden with #[fixed(typ=MyString, thestring=4)]
The typical use is
use arrayvec::ArrayString;
struct MyString<const CAP: usize>(ArrayString<CAP>);
impl<const CAP: usize> AsRef<ArrayString<CAP>> for MyString<CAP> {
fn as_ref(&self) -> &ArrayString<CAP> {
&self.0
}
}
impl<const CAP: usize> serde::Serialize for MyString<CAP> {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where S: serde::Serializer
{
// specialized serialize to override ArrayString's conversion to &str
todo!()
}
}
// More impls, probably AsMut, etc.
use arrayvec::ArrayString;
use fixed_size::fixed;
#[fixed(my_string=4)]
#[derive(serde::Serialize, serde::Deserialize, PartialEq, Debug)]
struct Foo {
my_string: String,
}
let foo = Foo { my_string: ArrayString::<4>::from("abcd").unwrap() };
// bincode actually supports var length strings but it's just used as an example and test
let encoded = bincode::serialize(&foo).unwrap();
let decoded: Foo = bincode::deserialize(&encoded[..]).unwrap();
assert_eq!(foo, decoded);
Adding fewer than 4 characters to my_string will 0 pad the value. Adding more than 4 characters will result in an error.
Dependencies
~0.4–0.8MB
~19K SLoC