@@ -154,14 +154,10 @@ assert_eq!(s, *t);
154154
155155// This is a traditional deserialization instead
156156let 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 )? )? };
160158assert_eq! (s , t );
161159
162160// In this case we map the data structure into memory
163- //
164- // Note: requires the `mmap` feature.
165161let 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)?)? };
204200let 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
210206assert_eq! (s , * t );
@@ -267,7 +263,7 @@ unsafe { s.serialize(&mut std::fs::File::create(&file)?)? };
267263let 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
273269assert_eq! (s , * t );
@@ -397,7 +393,7 @@ parameter that appears both as the type of a field and as a type parameter of
397393another 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)]
403399struct 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
424442Internal 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
607625deserialization type is itself, but in general more complex bounds might be
608626needed.
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`)
852919and irreplaceable (it is a type parameter of the type of field ` vec ` ).
853920
854921The 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
857926The fundamental idea at the basis of ε-serde is that replaceable parameters make
858927it 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
0 commit comments