serbia 0.4.3

No-fuss big arrays for Serde
Documentation
# Serbia

[![docs.rs badge](https://img.shields.io/docsrs/serbia?style=flat-square)](https://docs.rs/serbia/)
[![crates.io badge](https://img.shields.io/crates/v/serbia.svg?style=flat-square&logo=rust)](https://crates.io/crates/serbia/)
[![Build Status](https://img.shields.io/github/workflow/status/uint/serbia/serbia%20CI?logo=Github&style=flat-square)](https://github.com/uint/serbia)

**Ser**de **bi**g **a**rrays. An attribute macro to make (de)serializing big arrays painless, roughly following a [design proposed by David Tolnay](https://github.com/dtolnay/request-for-implementation/issues/17).

## Why?
I saw the idea in [request-for-implementation](https://github.com/dtolnay/request-for-implementation). Then I came up with the name.

The name was too good. I had to do it. Don't judge me.

Also: Serbia has some tasty food.

## But what is it for?
Serde only implements `Serialize`/`Deserialize` for arrays of length up to 32. This is due to Rust's current limitation - we can't be generic over array length, so
an arbitrary upper limit was chosen and implementations were generated only up to it.

The crate provides a macro that generates all the code you need to (de)serialize arrays bigger than that.

## Status
Under development, but functional. Let me know what's missing or broken!

## Usage
Just slap `#[serbia]` on top of your type definition. Structs and enums both work!

```rust
use serbia::serbia;

#[serbia]
#[derive(Serialize, Deserialize)]
struct S {
    arr_big: [u8; 300],     // custom serialize/deserialize code generated here
    arr_small: [u8; 8],     // no custom code - this is handled by Serde fine
}

#[serbia]
#[derive(Serialize, Deserialize)]
enum E {
    ArrBig([u8; 300]),
    ArrSmall([u8; 22]),
    Mixed([u8; 8], [i32; 44], String),
}
```

If *Serbia* sees an array length given as a constant, it will generate custom
serialize/deserialize code by default, without inspecting whether the constant
is larger than 32 or not. This is a limitation of macros.

```rust
const BUFSIZE: usize = 22;

#[serbia]
#[derive(Serialize, Deserialize)]
struct S {
    arr: [i32; BUFSIZE],   // custom serialize/deserialize code generated here
    foo: String,
}
```

### Skipping fields

If for some reason you don't want *Serbia* to generate custom serialize/deserialize
code for a field that it would normally handle, you can skip it.

```rust
const BUFSIZE: usize = 24;

#[serbia]
#[derive(Serialize, Deserialize)]
struct S {
    #[serbia(skip)]
    arr_a: [u8; BUFSIZE],
    arr_b: [u8; 42],
    arr_small: [u8; 8],
}
```

It's possible to be more granular if needed for some reason.

```rust
const BUFSIZE: usize = 24;

#[serbia]
#[derive(Serialize, Deserialize)]
struct S {
    #[serbia(skip_serializing, skip_deserializing)]
    arr_a: [u8; BUFSIZE],
    arr_b: [u8; 42],
    arr_small: [u8; 8],
}
```

### Manual array length

You can use the `#[serbia(bufsize = ... )]` option to set an array length for
a field. This can be useful to make type aliases work. Constants work here!

```rust
type BigArray = [i32; 300];

#[serbia]
#[derive(Serialize, Deserialize)]
struct S {
    #[serbia(bufsize = 300)]
    arr_a: BigArray,
    foo: String,
}
```

```rust
const BUFSIZE: usize = 300;
type BigArray = [i32; BUFSIZE];

#[serbia]
#[derive(Serialize, Deserialize)]
struct S {
    #[serbia(bufsize = "BUFSIZE")]
    arr_a: BigArray,
    foo: String,
}
```

### Interaction with Serde field attributes
*Serbia* detects when certain *Serde* field attributes are used and avoids
generating code that would cause a conflict, instead yielding to *Serde*.

```rust
    #[serbia]
    #[derive(Debug, Serialize, Deserialize, PartialEq)]
    struct S {
        big_arr: [u8; 40],    // serbia generates code for this
        #[serde(serialize_with="ser", deserialize_with="de")]
        bigger_arr: [u8; 42], // serbia ignores this in favor of the (de)serializers you provided
    }
```

*Serbia* is intended to play nice with *Serde* field attributes.
If there are problems, please create an issue or submit a PR!

## What doesn't work
Nested types.

```rust
#[serbia]
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct S {
    big_arr: Option<[u8; 300]>,  // no code generated for this nested array
}
```

*Serbia* doesn't yet pick up on *Serde* variant attributes,
so there might be conflicts there. This can probably be worked around by using
`#[serbia(skip)]` on each field that *Serbia* would try to generate custom
(de)serialization code for.