mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-11-16 15:58:17 +00:00
fixed-bytes: add serde
, document feature flags (#226)
Some checks are pending
Audit / audit (push) Waiting to run
CI / fmt (push) Waiting to run
CI / typo (push) Waiting to run
CI / ci (macos-latest, stable, bash) (push) Waiting to run
CI / ci (ubuntu-latest, stable, bash) (push) Waiting to run
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Waiting to run
Deny / audit (push) Waiting to run
Doc / build (push) Waiting to run
Doc / deploy (push) Blocked by required conditions
Some checks are pending
Audit / audit (push) Waiting to run
CI / fmt (push) Waiting to run
CI / typo (push) Waiting to run
CI / ci (macos-latest, stable, bash) (push) Waiting to run
CI / ci (ubuntu-latest, stable, bash) (push) Waiting to run
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Waiting to run
Deny / audit (push) Waiting to run
Doc / build (push) Waiting to run
Doc / deploy (push) Blocked by required conditions
* fixed-bytes: add `serde`, document feature flags * manual impl `serde::Deserialize` * add serde tests
This commit is contained in:
parent
5aeb8af4b4
commit
824651c8cf
4 changed files with 116 additions and 2 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -274,6 +274,9 @@ name = "bytes"
|
|||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
|
@ -641,6 +644,8 @@ name = "cuprate-fixed-bytes"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
|
|
|
@ -6,9 +6,14 @@ license = "MIT"
|
|||
authors = ["Boog900"]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
default = ["std", "serde"]
|
||||
std = ["bytes/std", "dep:thiserror"]
|
||||
serde = ["bytes/serde", "dep:serde"]
|
||||
|
||||
[dependencies]
|
||||
thiserror = { workspace = true, optional = true }
|
||||
bytes = { workspace = true }
|
||||
serde = { workspace = true, features = ["derive"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = { workspace = true, features = ["std"] }
|
10
net/fixed-bytes/README.md
Normal file
10
net/fixed-bytes/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# `cuprate-fixed-bytes`
|
||||
TODO
|
||||
|
||||
# Feature flags
|
||||
| Feature flag | Does what |
|
||||
|--------------|-----------|
|
||||
| `std` | TODO
|
||||
| `serde` | Enables `serde` on applicable types
|
||||
|
||||
`serde` is enabled by default.
|
|
@ -1,3 +1,5 @@
|
|||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use core::{
|
||||
fmt::{Debug, Formatter},
|
||||
ops::{Deref, Index},
|
||||
|
@ -5,7 +7,11 @@ use core::{
|
|||
|
||||
use bytes::{BufMut, Bytes, BytesMut};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
pub enum FixedByteError {
|
||||
#[cfg_attr(
|
||||
feature = "std",
|
||||
|
@ -43,8 +49,30 @@ impl Debug for FixedByteError {
|
|||
/// Internally this is just a wrapper around [`Bytes`], with the constructors checking that the length is equal to `N`.
|
||||
/// This implements [`Deref`] with the target being `[u8; N]`.
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(transparent))]
|
||||
#[repr(transparent)]
|
||||
pub struct ByteArray<const N: usize>(Bytes);
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, const N: usize> Deserialize<'de> for ByteArray<N> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bytes = Bytes::deserialize(deserializer)?;
|
||||
let len = bytes.len();
|
||||
if len == N {
|
||||
Ok(Self(bytes))
|
||||
} else {
|
||||
Err(serde::de::Error::invalid_length(
|
||||
len,
|
||||
&N.to_string().as_str(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> ByteArray<N> {
|
||||
pub fn take_bytes(self) -> Bytes {
|
||||
self.0
|
||||
|
@ -88,8 +116,30 @@ impl<const N: usize> TryFrom<Vec<u8>> for ByteArray<N> {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(transparent))]
|
||||
#[repr(transparent)]
|
||||
pub struct ByteArrayVec<const N: usize>(Bytes);
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, const N: usize> Deserialize<'de> for ByteArrayVec<N> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let bytes = Bytes::deserialize(deserializer)?;
|
||||
let len = bytes.len();
|
||||
if len % N == 0 {
|
||||
Ok(Self(bytes))
|
||||
} else {
|
||||
Err(serde::de::Error::invalid_length(
|
||||
len,
|
||||
&N.to_string().as_str(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> ByteArrayVec<N> {
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len() / N
|
||||
|
@ -197,6 +247,8 @@ impl<const N: usize> Index<usize> for ByteArrayVec<N> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::{from_str, to_string};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -207,4 +259,46 @@ mod tests {
|
|||
assert_eq!(bytes.len(), 100);
|
||||
let _ = bytes[99];
|
||||
}
|
||||
|
||||
/// Tests that `serde` works on [`ByteArray`].
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
fn byte_array_serde() {
|
||||
let b = ByteArray::from([1, 0, 0, 0, 1]);
|
||||
let string = to_string(&b).unwrap();
|
||||
assert_eq!(string, "[1,0,0,0,1]");
|
||||
let b2 = from_str::<ByteArray<5>>(&string).unwrap();
|
||||
assert_eq!(b, b2);
|
||||
}
|
||||
|
||||
/// Tests that `serde` works on [`ByteArrayVec`].
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
fn byte_array_vec_serde() {
|
||||
let b = ByteArrayVec::from([1, 0, 0, 0, 1]);
|
||||
let string = to_string(&b).unwrap();
|
||||
assert_eq!(string, "[1,0,0,0,1]");
|
||||
let b2 = from_str::<ByteArrayVec<5>>(&string).unwrap();
|
||||
assert_eq!(b, b2);
|
||||
}
|
||||
|
||||
/// Tests that bad input `serde` fails on [`ByteArray`].
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
#[should_panic(
|
||||
expected = r#"called `Result::unwrap()` on an `Err` value: Error("invalid length 4, expected 5", line: 0, column: 0)"#
|
||||
)]
|
||||
fn byte_array_bad_deserialize() {
|
||||
from_str::<ByteArray<5>>("[1,0,0,0]").unwrap();
|
||||
}
|
||||
|
||||
/// Tests that bad input `serde` fails on [`ByteArrayVec`].
|
||||
#[test]
|
||||
#[cfg(feature = "serde")]
|
||||
#[should_panic(
|
||||
expected = r#"called `Result::unwrap()` on an `Err` value: Error("invalid length 4, expected 5", line: 0, column: 0)"#
|
||||
)]
|
||||
fn byte_array_vec_bad_deserialize() {
|
||||
from_str::<ByteArrayVec<5>>("[1,0,0,0]").unwrap();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue