Skip to content

Commit b8c7911

Browse files
committed
mem_size_flat => mem_size(flat)
1 parent 63b8614 commit b8c7911

4 files changed

Lines changed: 102 additions & 32 deletions

File tree

Cargo.lock

Lines changed: 20 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 79 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,10 @@ assert_eq!(s, *t);
154154

155155
// This is a traditional deserialization instead
156156
let t: [usize; 1000] =
157-
unsafe { <[usize; 1000]>::deserialize_full(
158-
&mut std::fs::File::open(&file)?
159-
)? };
157+
unsafe { <[usize; 1000]>::deserialize_full(&mut std::fs::File::open(&file)?)? };
160158
assert_eq!(s, t);
161159

162160
// In this case we map the data structure into memory
163-
//
164-
// Note: requires the `mmap` feature.
165161
let u: MemCase<[usize; 1000]> =
166162
unsafe { <[usize; 1000]>::mmap(&file, Flags::empty())? };
167163

@@ -204,7 +200,7 @@ unsafe { s.serialize(&mut std::fs::File::create(&file)?)? };
204200
let b = std::fs::read(&file)?;
205201

206202
// The type of t will be inferred--it is shown here only for clarity
207-
let t: DeserType<'_, Vec<usize>> =
203+
let t: &[usize] =
208204
unsafe { <Vec<usize>>::deserialize_eps(b.as_ref())? };
209205

210206
assert_eq!(s, *t);
@@ -267,7 +263,7 @@ unsafe { s.serialize(&mut std::fs::File::create(&file)?)? };
267263
let b = std::fs::read(&file)?;
268264

269265
// The type of t will be inferred--it is shown here only for clarity
270-
let t: DeserType<'_, Vec<Data>> =
266+
let t: &[Data] =
271267
unsafe { <Vec<Data>>::deserialize_eps(b.as_ref())? };
272268

273269
assert_eq!(s, *t);
@@ -397,7 +393,7 @@ parameter that appears both as the type of a field and as a type parameter of
397393
another field. For example, the following code will not compile:
398394

399395
```compile_fail
400-
# # use epserde::prelude::*;
396+
# use epserde::prelude::*;
401397
# fn main() -> Result<(), Box<dyn std::error::Error>> {
402398
#[derive(Epserde, Debug, PartialEq)]
403399
struct MyStructParam<A> {
@@ -419,6 +415,28 @@ The result will be an error message similar to the following:
419415
| - found this type parameter
420416
```
421417

418+
Here are however workarounds for this issue. For example, you can wrap the field
419+
type in a newtype:
420+
421+
```rust
422+
# use epserde::prelude::*;
423+
# fn main() -> Result<(), Box<dyn std::error::Error>> {
424+
#[derive(Epserde, Debug, PartialEq)]
425+
struct NewType<T>(T);
426+
427+
#[derive(Epserde, Debug, PartialEq)]
428+
struct MyStructParam<A> {
429+
id: isize,
430+
data: NewType<A>,
431+
vec: Vec<A>
432+
}
433+
# Ok(())
434+
# }
435+
```
436+
437+
In some cases, you can simply add a bound to the type parameter: see the example
438+
below on pinning associated types.
439+
422440
## Example: User-defined deep-copy structures with internal parameters
423441

424442
Internal type parameters, that is, type parameters used by the types of your
@@ -607,6 +625,55 @@ type. This works because we expect `Mask` to be a primitive type, whose
607625
deserialization type is itself, but in general more complex bounds might be
608626
needed.
609627

628+
## Example: `impl` blocks for nested types
629+
630+
When you write `impl` blocks that work both for the original type and for the
631+
deserialization type, for type parameters that are replaced by a reference you need
632+
to use a suitable trait bound, usually `AsRef<[T]>`. For example,
633+
634+
```rust
635+
# use epserde::prelude::*;
636+
// Intended usage: MyStruct<Vec<usize>> or MyStruct<Box<[usize]>>
637+
#[derive(Epserde)]
638+
struct MyStruct<A> {
639+
data: A,
640+
}
641+
642+
/// This method can be called on both an original and an ε-copied structure
643+
impl <A: AsRef<[usize]>> MyStruct<A> {
644+
fn sum(&self) -> usize {
645+
self.data.as_ref().iter().sum()
646+
}
647+
}
648+
```
649+
650+
However, if we start to nest opaque types, `impl` section needs to be written
651+
by unrolling the nested type, as we need to bound the inner type parameters:
652+
653+
```rust
654+
# use epserde::prelude::*;
655+
# #[derive(Epserde)]
656+
# struct MyStruct<A> {
657+
# data: A,
658+
# }
659+
# impl <A: AsRef<[usize]>> MyStruct<A> {
660+
# fn sum(&self) -> usize {
661+
# self.data.as_ref().iter().sum()
662+
# }
663+
# }
664+
#[derive(Epserde)]
665+
struct MyNestedStruct<B> {
666+
inner: B,
667+
}
668+
669+
/// Note how we had to unroll the nested type
670+
impl <A: AsRef<[usize]>> MyNestedStruct<MyStruct<A>> {
671+
fn sum(&self) -> usize {
672+
self.inner.sum()
673+
}
674+
}
675+
```
676+
610677
## Example: (Structures containing) iterators
611678

612679
ε-serde can serialize exact-size iterators. The resulting field can be
@@ -852,7 +919,9 @@ the type parameter `A` is both replaceable (it is the type of the field `data`)
852919
and irreplaceable (it is a type parameter of the type of field `vec`).
853920

854921
The only exception to this rule is for type parameters that appear inside a
855-
[`PhantomDeserData`], which must be replaceable.
922+
[`PhantomDeserData`], which must be replaceable. Moreover, you can use the
923+
`bound` attribute to solve some cases (e.g., when [`DeserType<'_, A>`] is equal
924+
to `A`—see the example above about pinning associated types).
856925

857926
The fundamental idea at the basis of ε-serde is that replaceable parameters make
858927
it possible for an instance of a deserialization type to refer to serialized
@@ -1100,6 +1169,7 @@ European Union nor the Italian MUR can be held responsible for them.
11001169
[`DeserType<'_>`]: https://docs.rs/epserde/latest/epserde/deser/type.DeserType.html
11011170
[`DeserType<'_,T>`]: https://docs.rs/epserde/latest/epserde/deser/type.DeserType.html
11021171
[`DeserType<'_,B>`]: https://docs.rs/epserde/latest/epserde/deser/type.DeserType.html
1172+
[`DeserType<'_,A>`]: https://docs.rs/epserde/latest/epserde/deser/type.DeserType.html
11031173
[`sux`]: http://crates.io/sux/
11041174
[serde]: https://serde.rs/
11051175
[Abomonation]: https://crates.io/crates/abomonation

epserde/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ categories = ["encoding", "no-std"]
1616
rust-version = "1.85"
1717

1818
[dependencies]
19-
mem_dbg = { version = "0.4.0", features = [ "derive", ], default-features = false, optional = true }
19+
mem_dbg = { version = ">=0.4.1", features = [ "derive", ], default-features = false, optional = true }
2020

2121
mmap-rs = { version = "0.7.0", optional = true }
2222
bitflags = { version = "2.9.4", default-features = false }

epserde/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub const MAGIC_REV: u64 = u64::from_le_bytes(MAGIC.to_be_bytes());
6767
/// instances with 128-bit alignment.
6868
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6969
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg, mem_dbg::MemSize))]
70-
#[cfg_attr(feature = "mem_dbg", mem_size_flat)]
70+
#[cfg_attr(feature = "mem_dbg", mem_size(flat))]
7171
#[repr(align(16))]
7272
#[derive(Default)]
7373
pub struct Aligned16(pub [u8; 16]);
@@ -79,7 +79,7 @@ pub struct Aligned16(pub [u8; 16]);
7979
/// instances with 64-bit alignment.
8080
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8181
#[cfg_attr(feature = "mem_dbg", derive(mem_dbg::MemDbg, mem_dbg::MemSize))]
82-
#[cfg_attr(feature = "mem_dbg", mem_size_flat)]
82+
#[cfg_attr(feature = "mem_dbg", mem_size(flat))]
8383
#[repr(align(64))]
8484
pub struct Aligned64(pub [u8; 64]);
8585

0 commit comments

Comments
 (0)