Crate fixed_size

source ·
Expand description

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.

Attribute Macros

  • Replace one or more variable length fields with a fixed length equivalent