Proof using.
intros.
destruct a;
unfold tag_serialize, tag_deserialize;
cheerios_crush;
unfold app;
cheerios_crush.
Qed.
Instance tag_Serializer : Serializer t.
(* json <-> tree tag conversion *)
Fixpoint json_treeify (j : json.t) : tree tag.t :=
let fix obj_list_to_tree_list (l : list (String.string * json.t)) :=
match l with
| [] => []
| (s, j) :: l => atom (tag.Str s)
:: json_treeify j
:: obj_list_to_tree_list l
end
in
match j with
| json.Null => atom tag.Null
| json.Bool b => atom (tag.Bool b)
| json.Num n => atom (tag.Num n)
| json.String s => atom (tag.Str s)
| json.Arr l => node (atom tag.Arr :: List.map json_treeify l)
| json.Obj l => node (atom tag.Obj :: obj_list_to_tree_list l)
end.
Definition obj_list_to_tree_list :=
fix obj_list_to_tree_list (l : list (String.string * json.t)) :
list (tree tag.t) :=
match l with
| [] => []
| (s, j) :: l => atom (tag.Str s) :: json_treeify j :: obj_list_to_tree_list l
end.
Fixpoint json_untreeify (t : tree tag.t) : option json.t :=
let fix untreeify_list (l : list (tree tag.t)) : option (list json.t) :=
match l with
| [] => Some []
| x :: l => match json_untreeify x with
| None => None
| Some y => match untreeify_list l with
| None => None
| Some l => Some (y :: l)
end
end
end in
let fix untreeify_obj_list (l : list (tree tag.t)) :
option (list (String.string * json.t)) :=
match l with
| [] => Some []
| atom (tag.Str s) :: t :: l =>
match json_untreeify t with
| None => None
| Some j => match untreeify_obj_list l with
| None => None
| Some l => Some ((s, j) :: l)
end
end
| _ => None
end in
match t with
| atom (tag.Num n) => Some (json.Num n)
| atom (tag.Bool b) => Some (json.Bool b)
| atom (tag.Str s) => Some (json.String s)
| node (atom tag.Arr :: l) => match untreeify_list l with
| None => None
| Some l => Some (json.Arr l)
end
| atom (tag.Null) => Some (json.Null)
| node (atom tag.Obj :: l) => match untreeify_obj_list l with
| None => None
| Some l => Some (json.Obj l)
end
| _ => None
end.
Definition untreeify_obj_list :=
fix untreeify_obj_list (l : list (tree tag.t)) :
option (list (String.string * json.t)) :=
match l with
| [] => Some []
| atom (tag.Str s) :: t :: l =>
match json_untreeify t with
| None => None
| Some j => match untreeify_obj_list l with
| None => None
| Some l => Some ((s, j) :: l)
end
end
| _ => None
end.
Definition untreeify_list :=
fix untreeify_list l : option (list json.t) :=
match l with
| [] => Some []
| x :: l => match json_untreeify x with
| None => None
| Some y => match untreeify_list l with
| None => None
| Some l => Some (y :: l)
end
end
end.
Definition treeify_untreeify_aux (j : json.t) :=
json_untreeify (json_treeify j) = Some j.

Lemma treeify_untreeify_id : forall j : json.t,
treeify_untreeify_aux j.