Section serializer.
Variables A : Type.
Variable sA :Serializer A.
(* Now we're ready to serialize trees. First, we serialize their shape. *)
Fixpoint serialize_tree_shape (t : tree A) : IOStreamWriter.t :=
let fix serialize_list_tree_shape (l : list (tree A)) : IOStreamWriter.t :=
match l with
| [] => IOStreamWriter.empty
| x :: xs => IOStreamWriter.append (fun _ => serialize_tree_shape x)
(fun _ => serialize_list_tree_shape xs)
end in
match t with
| atom _ => serialize x00 (* ignore the data, since we're just focused on the shape *)
| node l => IOStreamWriter.append (fun _ => serialize x01)
(fun _ => (IOStreamWriter.append
(fun _ => serialize_list_tree_shape l)
(fun _ => serialize x02)))
end.
Definition serialize_list_tree_shape :=
fix serialize_list_tree_shape (l : list (tree A)) : IOStreamWriter.t :=
match l with
| [] => IOStreamWriter.empty
| x :: xs => IOStreamWriter.append (fun _ => serialize_tree_shape x)
(fun _ => serialize_list_tree_shape xs)
end.
Definition deserialize_tree_shape_step (b : byte) (s : list (list (tree unit))) :
fold_state (list (list (tree unit))) (tree unit) :=
match b with
| x00 => match s with
| [] => Done (atom tt)
| ts :: s => More ((atom tt :: ts) :: s)
end
| x01 => More ([] :: s)
| x02 => match s with
| [] => Error
| ts :: s => let t := node (rev' ts) in
match s with
| [] => Done t
| ts :: acc => More ((t :: ts) :: acc)
end
end
| _ => Error
end.
Proof using.
induction t using tree_rect with
(P_list := fun l =>
(* We need to extend the statement to a list of subtrees for the mutual induction hypothesis. It says that serializing and then deserializing a list of trees `l` is the same as `List.map (map (fun _ => tt) l)`. `deserialize_list_tree_shape'` is always called with at least one element on the accumulator, so there's no need for a match like there was above. *)
forall ts acc bytes,
ByteListReader.unwrap
(ByteListReader.fold deserialize_tree_shape_step (ts :: acc))
(IOStreamWriter.unwrap (serialize_list_tree_shape l) ++ bytes) =
ByteListReader.unwrap
(ByteListReader.fold
deserialize_tree_shape_step
((rev (List.map shape l) ++ ts) :: acc)) bytes);
intros;
try (unfold serialize_list_tree_shape;
rewrite IOStreamWriter.append_unwrap, app_ass, IHt, IHt0;
simpl;
now rewrite app_ass).
(cheerios_crush; simpl; cheerios_crush; simpl).
-  destruct acc;
repeat (cheerios_crush;
simpl).
- destruct acc;
simpl;
rewrite IOStreamWriter.append_unwrap,
ByteListReader.fold_unwrap,
IOStreamWriter.append_unwrap,
IOStreamWriter.putByte_unwrap;
simpl;
fold serialize_list_tree_shape;
rewrite app_ass, IHt, ByteListReader.fold_unwrap,
IOStreamWriter.putByte_unwrap;
simpl;
rewrite app_nil_r, rev'_spec, rev_involutive;
reflexivity.
Qed.
Definition deserialize_tree_shape : ByteListReader.t (tree unit) :=
ByteListReader.fold deserialize_tree_shape_step [].

(* This is the top level statement about serializing and deserializing tree shapes: it results in `shape` of the original tree. *)
Lemma serialize_deserialize_shape_id :
forall t bytes,
ByteListReader.unwrap deserialize_tree_shape
(IOStreamWriter.unwrap (serialize_tree_shape t) ++ bytes)
= Some (shape t, bytes).