Module tag.
Inductive t :=
| Null : t
| Bool : bool -> t
| Num : nat -> t
| Str : String.string -> t
| Arr : t
| Obj : t.
(* tag serializer *)
Definition tag_serialize (t : t) : IOStreamWriter.t :=
match t with
| Null => serialize x00
| Bool b => IOStreamWriter.append (fun _ => serialize x01)
(fun _ => serialize b)
| Num n => IOStreamWriter.append (fun _ => serialize x02)
(fun _ => serialize n)
| Str s => IOStreamWriter.append (fun _ => serialize x03)
(fun _ => serialize s)
| Arr => serialize x04
| Obj => serialize x05
end.
Definition tag_deserialize : ByteListReader.t t :=
tag <- deserialize ;;
match tag with
| x00 => ByteListReader.ret Null
| x01 => Bool <$> deserialize
| x02 => Num <$> deserialize
| x03 => Str <$> deserialize
| x04 => ByteListReader.ret Arr
| x05 => ByteListReader.ret Obj
| _ => ByteListReader.error
end.
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.
Proof using.
induction j using json.json_rect with
(P_list := fun l => untreeify_list (List.map json_treeify l) = Some l)
(P_list' := fun l => untreeify_obj_list (obj_list_to_tree_list l) = Some l);
unfold treeify_untreeify_aux;
auto;
simpl;
try (fold untreeify_list);
try (fold untreeify_obj_list);
try (fold obj_list_to_tree_list);
try (rewrite IHj);
try (rewrite IHj0);
auto.
Qed.
Definition json_serialize (j : json.t) : IOStreamWriter.t :=
serialize (json_treeify j).
Definition json_deserialize : ByteListReader.t json.t :=
j <- deserialize;;
match json_untreeify j with
| Some j => ByteListReader.ret j
| None => ByteListReader.error
end.

Lemma json_serialize_deserialize_id :
serialize_deserialize_id_spec json_serialize json_deserialize.