serde-big-array-0.5.1/.cargo_vcs_info.json0000644000000001360000000000100140140ustar { "git": { "sha1": "a6f7cf86e3808773b763d04b06745e67f3d20daf" }, "path_in_vcs": "" }serde-big-array-0.5.1/.github/workflows/ci.yml000064400000000000000000000012441046102023000173200ustar 00000000000000name: ci on: [push, pull_request] jobs: build: strategy: matrix: os: [macOS-latest, ubuntu-latest] toolchain: [stable, beta, nightly, 1.56.0] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@master - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.toolchain }} override: true - name: Run cargo check --all env: RUSTFLAGS: -D warnings run: | cargo check --all - name: Run the tests env: RUSTFLAGS: -D warnings run: | cargo test --all - name: Run cargo doc run: | cargo doc --all serde-big-array-0.5.1/.gitignore000064400000000000000000000000431046102023000145710ustar 00000000000000/target **/*.rs.bk Cargo.lock *swp serde-big-array-0.5.1/Cargo.toml0000644000000017320000000000100120150ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "serde-big-array" version = "0.5.1" authors = [ "est31 ", "David Tolnay ", ] description = "Big array helper for serde." documentation = "https://docs.rs/serde-big-array" readme = "README.md" license = "MIT OR Apache-2.0" repository = "https://github.com/est31/serde-big-array" [dependencies.serde] version = "1.0" default-features = false [dev-dependencies.serde_derive] version = "1.0" [dev-dependencies.serde_json] version = "1.0" serde-big-array-0.5.1/Cargo.toml.orig000064400000000000000000000007401046102023000154740ustar 00000000000000[package] name = "serde-big-array" version = "0.5.1" authors = ["est31 ", "David Tolnay "] license = "MIT OR Apache-2.0" description = "Big array helper for serde." documentation = "https://docs.rs/serde-big-array" repository = "https://github.com/est31/serde-big-array" readme = "README.md" edition = "2021" [dependencies] serde = { version = "1.0", default-features = false } [dev-dependencies] serde_derive = "1.0" serde_json = "1.0" serde-big-array-0.5.1/LICENSE-APACHE000064400000000000000000000010341046102023000145260ustar 00000000000000Copyright 2018 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. serde-big-array-0.5.1/LICENSE-MIT000064400000000000000000000020521046102023000142370ustar 00000000000000The MIT License (MIT) Copyright (c) 2018 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. serde-big-array-0.5.1/README.md000064400000000000000000000042411046102023000140640ustar 00000000000000## serde-big-array [![docs](https://docs.rs/serde-big-array/badge.svg)](https://docs.rs/crate/serde-big-array) [![crates.io](https://img.shields.io/crates/v/serde-big-array.svg)](https://crates.io/crates/serde-big-array) [![dependency status](https://deps.rs/repo/github/est31/serde-big-array/status.svg)](https://deps.rs/repo/github/est31/serde-big-array) Big array helper for serde. The purpose of this crate is to make (de-)serializing arrays of sizes > 32 easy. This solution is needed until [serde adopts const generics support](https://github.com/serde-rs/serde/issues/1937). Bases on [this](https://github.com/serde-rs/serde/issues/631#issuecomment-322677033) snippet. ```Rust extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json; #[macro_use] extern crate serde_big_array; use serde_big_array::BigArray; #[derive(Serialize, Deserialize)] struct S { #[serde(with = "BigArray")] arr: [u8; 64], } #[test] fn test() { let s = S { arr: [1; 64] }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr[..] == &s_back.arr[..]); } ``` Important links: * Original serde issue [requesting large array support](https://github.com/serde-rs/serde/issues/631) * [Const generics support issue on serde](https://github.com/serde-rs/serde/issues/1937) * [serde PR](https://github.com/serde-rs/serde/pull/1860) to add const generics support * Rust [const generics tracking issue](https://github.com/rust-lang/rust/issues/44580) * Rust [complex generic constants tracking issue](https://github.com/rust-lang/rust/issues/76560) ### MSRV The minimum supported Rust version (MSRV) is Rust 1.56.0. ### License [license]: #license This crate is distributed under the terms of both the MIT license and the Apache License (Version 2.0), at your option. See [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) for details. #### License of your contributions Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. serde-big-array-0.5.1/src/array.rs000064400000000000000000000054201046102023000150600ustar 00000000000000use crate::const_generics::PartiallyInitialized; use crate::BigArray; use core::ops::{Deref, DerefMut, Index, IndexMut}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// An array newtype usable for nested structures /// /// In most cases, using the [`BigArray`] trait /// is more convenient, so you should use that one. /// /// In nesting scenarios however, the trick of using /// `#[serde(with = ...)]` comes to its limits. For /// these cases, we offer the `Array` struct. /// /// [`BigArray`]: crate::BigArray /// /// ```Rust /// # use serde_derive::{Serialize, Deserialize}; /// #[derive(Serialize, Deserialize)] /// struct S { /// arr: Box>, /// } /// ``` #[repr(transparent)] #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Clone, Debug)] pub struct Array(pub [T; N]); impl<'de, T: Deserialize<'de>, const N: usize> Deserialize<'de> for Array { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { Ok(Self(<[T; N] as BigArray>::deserialize(deserializer)?)) } } impl Default for Array { fn default() -> Self { // TODO use array::from_fn once the MSRV allows stuff from 1.63.0 let arr = { let mut arr = PartiallyInitialized::::new(); unsafe { { let p = arr.0.as_mut().unwrap(); for i in 0..N { let p = (p.as_mut_ptr() as *mut T).wrapping_add(i); core::ptr::write(p, Default::default()); arr.1 += 1; } } let initialized = arr.0.take().unwrap().assume_init(); initialized } }; Self(arr) } } impl Serialize for Array { fn serialize(&self, serializer: S) -> Result where S: Serializer, { <[T; N] as BigArray>::serialize(&self.0, serializer) } } impl Deref for Array { type Target = [T; N]; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for Array { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl Index for Array where [T]: Index, { type Output = <[T] as Index>::Output; #[inline] fn index(&self, index: I) -> &Self::Output { Index::index(&self.0 as &[T], index) } } impl IndexMut for Array where [T]: IndexMut, { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { IndexMut::index_mut(&mut self.0 as &mut [T], index) } } serde-big-array-0.5.1/src/const_generics.rs000064400000000000000000000071401046102023000167500ustar 00000000000000use core::fmt; use core::marker::PhantomData; use core::mem::MaybeUninit; use core::result; use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor}; use serde::ser::{Serialize, SerializeTuple, Serializer}; pub(crate) struct PartiallyInitialized( pub(crate) Option>, pub(crate) usize, ); impl PartiallyInitialized { #[inline] pub(crate) fn new() -> Self { PartiallyInitialized(Some(MaybeUninit::uninit()), 0) } } impl Drop for PartiallyInitialized { fn drop(&mut self) { if !core::mem::needs_drop::() { return; } if let Some(arr) = &mut self.0 { while self.1 > 0 { self.1 -= 1; let offs = self.1; let p = (arr.as_mut_ptr() as *mut T).wrapping_add(offs); unsafe { core::ptr::drop_in_place::(p); } } } } } /// The big array serialization helper trait /// /// ``` /// # use serde_derive::{Serialize, Deserialize}; /// # use serde_big_array::BigArray; /// #[derive(Serialize, Deserialize)] /// struct S { /// #[serde(with = "BigArray")] /// arr: [u8; 64], /// } /// ``` pub trait BigArray<'de, T>: Sized { fn serialize(&self, serializer: S) -> result::Result where S: Serializer, T: Serialize; fn deserialize(deserializer: D) -> result::Result where D: Deserializer<'de>, T: Deserialize<'de>; } impl<'de, T, const N: usize> BigArray<'de, T> for [T; N] { fn serialize(&self, serializer: S) -> result::Result where S: Serializer, T: Serialize, { let mut seq = serializer.serialize_tuple(self.len())?; for elem in &self[..] { seq.serialize_element(elem)?; } seq.end() } fn deserialize(deserializer: D) -> result::Result where D: Deserializer<'de>, T: Deserialize<'de>, { struct ArrayVisitor { element: PhantomData, } impl<'de, T, const N: usize> Visitor<'de> for ArrayVisitor<[T; N]> where T: Deserialize<'de>, { type Value = [T; N]; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "an array of length {}", N) } fn visit_seq(self, mut seq: A) -> result::Result<[T; N], A::Error> where A: SeqAccess<'de>, { unsafe { let mut arr = PartiallyInitialized::::new(); { let p = arr.0.as_mut().unwrap(); for i in 0..N { let p = (p.as_mut_ptr() as *mut T).wrapping_add(i); let val = seq .next_element()? .ok_or_else(|| Error::invalid_length(i, &self))?; core::ptr::write(p, val); arr.1 += 1; } } let initialized = arr.0.take().unwrap().assume_init(); Ok(initialized) } } } let visitor = ArrayVisitor { element: PhantomData, }; // The allow is needed to support (32 + 33) like expressions #[allow(unused_parens)] deserializer.deserialize_tuple(N, visitor) } } serde-big-array-0.5.1/src/lib.rs000064400000000000000000000027061046102023000145140ustar 00000000000000/*! Big array helper for serde. The purpose of this crate is to make (de-)serializing arrays of sizes > 32 easy. This solution is needed until [serde adopts const generics support](https://github.com/serde-rs/serde/issues/1937). This crates provides you with two tools to use big arrays in your crate: * The first tool is the [`BigArray`] trait. You can use it together with the `serde_derive` macro and an `#[serde(with = "BigArray")]` next to your data declaration. * The second tool is the [`Array`] struct. It requires you to change your datastructures, and some of the code accessing your array, but it allows for nested use cases, which [`BigArray`] struggles with. We recommended using the [`BigArray`] trait in most cases, and using the [`Array`] struct only if [`BigArray`] doesn't work. [`BigArray`]: self::BigArray [`Array`]: self::Array ## Example ``` extern crate serde; #[macro_use] extern crate serde_derive; extern crate serde_json; extern crate serde_big_array; use serde_big_array::BigArray; #[derive(Serialize, Deserialize)] struct S { #[serde(with = "BigArray")] arr: [u8; 64], } #[test] fn test() { let s = S { arr: [1; 64] }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr[..] == &s_back.arr[..]); assert!(false); } # fn main() {} ``` */ #![no_std] mod array; pub(crate) mod const_generics; pub use array::Array; pub use const_generics::BigArray; serde-big-array-0.5.1/tests/basic.rs000064400000000000000000000006061046102023000153770ustar 00000000000000#![no_std] use serde_big_array::BigArray; use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] struct S { #[serde(with = "BigArray")] arr: [u8; 64], } #[test] fn test() { let s = S { arr: [1; 64] }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr[..] == &s_back.arr[..]); } serde-big-array-0.5.1/tests/const.rs000064400000000000000000000006521046102023000154450ustar 00000000000000#![no_std] use serde_big_array::BigArray; use serde_derive::{Deserialize, Serialize}; const NUMBER: usize = 127; #[derive(Serialize, Deserialize)] struct S { #[serde(with = "BigArray")] arr: [u8; NUMBER], } #[test] fn test() { let s = S { arr: [1; NUMBER] }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr[..] == &s_back.arr[..]); } serde-big-array-0.5.1/tests/const_expr.rs000064400000000000000000000013351046102023000165020ustar 00000000000000#![no_std] use serde_big_array::BigArray; use serde_derive::{Deserialize, Serialize}; const NUMBER: usize = 137; #[derive(Serialize, Deserialize)] struct S { #[serde(with = "BigArray")] arr_1: [u8; NUMBER * NUMBER + 17], #[serde(with = "BigArray")] arr_2: [u8; NUMBER], #[serde(with = "BigArray")] arr_3: [u8; 42], } #[test] fn test() { let s = S { arr_1: [1; NUMBER * NUMBER + 17], arr_2: [2; NUMBER], arr_3: [3; 42], }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr_1[..] == &s_back.arr_1[..]); assert!(&s.arr_2[..] == &s_back.arr_2[..]); assert!(&s.arr_3[..] == &s_back.arr_3[..]); } serde-big-array-0.5.1/tests/const_generics.rs000064400000000000000000000067271046102023000173350ustar 00000000000000use serde_big_array::BigArray; use serde_derive::{Deserialize, Serialize}; use std::cell::RefCell; use std::collections::HashSet; #[derive(Serialize, Deserialize)] struct S { #[serde(with = "BigArray")] arr: [u8; 64], #[serde(with = "BigArray")] arr2: [u8; 65], } #[test] fn test() { let s = S { arr: [1; 64], arr2: [1; 65], }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr[..] == &s_back.arr[..]); } // test that drop is executed nicely if there is an error // during deserialization #[test] fn test_droppped_partial() { thread_local! { static DROPPED: RefCell> = RefCell::new(Vec::new()); } fn get_droppped_set() -> HashSet { DROPPED.with(|dropped| dropped.borrow().iter().copied().collect::>()) } fn clear_droppped_set() { DROPPED.with(|dropped| dropped.borrow_mut().clear()); assert_eq!(get_droppped_set().len(), 0); } #[derive(Serialize, Deserialize, PartialEq, Eq, Clone, Debug)] struct DroppableU32(u32); impl Drop for DroppableU32 { fn drop(&mut self) { DROPPED.with(|dropped| dropped.borrow_mut().push(self.0)); } } #[derive(Serialize, Deserialize, Debug)] struct Droppables { #[serde(with = "BigArray")] arr: [DroppableU32; CNT], } impl Droppables { fn test(val_idx: usize, val: u32) { let mut maybe_init_array = core::mem::MaybeUninit::<[DroppableU32; CNT]>::uninit(); for i in 0..CNT { unsafe { let p = (maybe_init_array.as_mut_ptr() as *mut DroppableU32).wrapping_add(i); core::ptr::write(p, DroppableU32(i as u32 * 3)); } } let mut ds = Self { arr: unsafe { maybe_init_array.assume_init() }, }; clear_droppped_set(); ds.arr[val_idx] = DroppableU32(val); assert_eq!( get_droppped_set(), vec![val_idx as u32 * 3].into_iter().collect::>() ); clear_droppped_set(); let j = serde_json::to_string(&ds).unwrap(); println!("{}", j); // Completely deserialize the string, // and ensure the entire array was dropped let val_starts = j.find(&val.to_string()).unwrap(); { let ds_back = serde_json::from_str::(&j).unwrap(); assert!(&ds.arr[..] == &ds_back.arr[..]); } let mut zero_to_cnt_set: HashSet = (0..CNT as u32).map(|v| v * 3).into_iter().collect(); zero_to_cnt_set.remove(&(val_idx as u32 * 3)); zero_to_cnt_set.insert(val); assert_eq!(get_droppped_set(), zero_to_cnt_set); clear_droppped_set(); // Now only partially deserialize the string, // and ensure the contents were dropped successfully let _ds_back_err = serde_json::from_str::(&j[0..val_starts]).unwrap_err(); let zero_to_val_idx_set: HashSet = (0..val_idx as u32).map(|v| v * 3).into_iter().collect(); assert_eq!(get_droppped_set(), zero_to_val_idx_set); clear_droppped_set(); } } Droppables::<4>::test(2, 20220325); Droppables::<77>::test(50, 20220325); } serde-big-array-0.5.1/tests/const_path.rs000064400000000000000000000007361046102023000164640ustar 00000000000000#![no_std] use serde_big_array::BigArray; use serde_derive::{Deserialize, Serialize}; mod module { pub const NUMBER: usize = 127; } #[derive(Serialize, Deserialize)] struct S { #[serde(with = "BigArray")] arr: [u8; module::NUMBER], } #[test] fn test() { let s = S { arr: [1; module::NUMBER], }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr[..] == &s_back.arr[..]); } serde-big-array-0.5.1/tests/nested.rs000064400000000000000000000006671046102023000156070ustar 00000000000000#![no_std] use serde_big_array::Array; use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] struct S { arr: Array, 65>, } #[test] fn test() { let s = S { arr: Array([Array([1; 234]); 65]), }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr[..] == &s_back.arr[..]); assert_eq!(s.arr.len(), 65); } serde-big-array-0.5.1/tests/nested_box.rs000064400000000000000000000006731046102023000164540ustar 00000000000000#![no_std] extern crate alloc; use alloc::boxed::Box; use serde_big_array::Array; use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] struct S { arr: Box>, } #[test] fn test() { let s = S { arr: Box::new(Array([1; 1234])), }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert!(&s.arr[..] == &s_back.arr[..]); } serde-big-array-0.5.1/tests/ser_xor_de.rs000064400000000000000000000013411046102023000164440ustar 00000000000000#![no_std] use serde_big_array::BigArray; use serde_derive::{Deserialize, Serialize}; #[derive(Serialize)] struct S { #[serde(with = "BigArray")] arr: [SerOnly; 64], } #[derive(Debug, Clone, Copy, Serialize)] struct SerOnly(u8); #[derive(Deserialize)] struct D { #[serde(with = "BigArray")] arr: [DeOnly; 64], } #[derive(Debug, Clone, Copy, Deserialize)] struct DeOnly(u8); impl PartialEq for SerOnly { fn eq(&self, other: &DeOnly) -> bool { self.0 == other.0 } } #[test] fn test() { let s = S { arr: [SerOnly(1); 64], }; let j = serde_json::to_string(&s).unwrap(); let s_back = serde_json::from_str::(&j).unwrap(); assert_eq!(&s.arr[..], &s_back.arr[..]); }