Instance positive_Serializer : Serializer positive.
(* This is the first example of a "typical" serializer: it combines more primitive serializers (in this case, just for byte and positive) together in order to serialize a Z. *)
Definition Z_serialize (z : Z) : IOStreamWriter.t :=
match z with
| Z0 => serialize x00
| Zpos p => IOStreamWriter.append (fun _ => serialize x01)
(fun _ => serialize p)
| Zneg p => IOStreamWriter.append (fun _ => serialize x02)
(fun _ => serialize p)
end.
Definition Z_deserialize : ByteListReader.t Z :=
tag <- deserialize ;;
match tag with
| x02 => Zneg <$> deserialize
| x01 => Zpos <$> deserialize
| x00 => ByteListReader.ret Z0
| _ => ByteListReader.error
end.

(* This proof is typical for serializing an algebraic datatype. Unfold the serializer and deserializer, then do a case analysis and call serialize_deserialize_id_crush. *)
Lemma Z_serialize_deserialize_id :
serialize_deserialize_id_spec Z_serialize Z_deserialize.