Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file json_repr.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180(* Representations of JSON documents *)(************************************************************************)(* ocplib-json-typed *)(* *)(* Copyright 2014 OCamlPro *)(* *)(* This file is distributed under the terms of the GNU Lesser General *)(* Public License as published by the Free Software Foundation; either *)(* version 2.1 of the License, or (at your option) any later version, *)(* with the OCaml static compilation exception. *)(* *)(* ocplib-json-typed is distributed in the hope that it will be useful,*)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU General Public License for more details. *)(* *)(************************************************************************)type'aview=[`Oof(string*'a)list|`Aof'alist|`Boolofbool|`Floatoffloat|`Stringofstring|`Null]type'arepr_uid='aoptionref(* This is used for limiting conversions. When a value is converted
from a representation to another, which mostly happens when using
the {!type:any} boxing, such as when writing custom encodings, the
original value is usually traversed using the [view] of the
original representation, and recreated using the [repr] of the
destination representation. When converting from a representation
to itself, we want to optimize out this transformation, that is a
deep copy, and just get the same value. For this, we have to prove
to OCaml that it is indeed a value from the same representation.
To do that, we use the following trick. Each representation has a
bucket, the uid below. When converting from the original
representation, we put the value in its bucket. Then, we check the
bucket of the destination, and if it happens to be occupied, we
find in it the original value, under the destination type. Voilà. *)letrepr_uid()=refNoneleteq_repr_uid:'a->'arepr_uid->'brepr_uid->'boption=funatatb->tb:=None;ta:=Somea;!tbmoduletypeRepr=sigtypevaluevalview:value->valueviewvalrepr:valueview->valuevalrepr_uid:valuerepr_uidendmoduleEzjsonm=structtypevalue=[`Oof(string*value)list|`Aofvaluelist|`Boolofbool|`Floatoffloat|`Stringofstring|`Null]letviewv=vletreprv=vletrepr_uid=repr_uid()endtypeezjsonm=Ezjsonm.valuemoduleYojson=structtypevalue=[`Boolofbool|`Assocof(string*value)list|`Floatoffloat|`Intofint|`Intlitofstring|`Listofvaluelist|`Null|`Stringofstring|`Tupleofvaluelist|`Variantofstring*valueoption]letview=function|`Intliti->`Stringi|`Tuplel->`Al|`Variant(label,Somex)->`A[`Stringlabel;x]|`Variant(label,None)->`Stringlabel|`Assocl->`Ol|`Listl->`Al|`Inti->`Float(floati)|`Floatf->`Floatf|`Strings->`Strings|`Null->`Null|`Boolb->`Boolbletrepr=function|`Ol->`Assocl|`Al->`Listl|`Boolb->`Boolb|`Floatf->`Floatf|`Strings->`Strings|`Null->`Nullletrepr_uid=repr_uid()endtypeyojson=Yojson.valueletconvert:typetttf.(moduleReprwithtypevalue=tf)->(moduleReprwithtypevalue=tt)->tf->tt=fun(moduleRepr_f)(moduleRepr_t)v->matcheq_repr_uidvRepr_f.repr_uidRepr_t.repr_uidwith|Somer->r|None->letrecconvv=matchRepr_f.viewvwith|`Float_|`Bool_|`String_|`Nullasv->Repr_t.reprv|`Avalues->Repr_t.repr(`A(List.mapconvvalues))|`Ovalues->Repr_t.repr(`O(List.map(fun(k,v)->(k,convv))values))inconvvletfrom_yojsonnon_basic=(* Delete `Variant, `Tuple and `Intlit *)letrecto_basicnon_basic=matchnon_basicwith|`Intliti->`Stringi|`Tuplel->`List(List.mapto_basicl)|`Variant(label,Somex)->`List[`Stringlabel;to_basicx]|`Variant(label,None)->`Stringlabel|`Assocl->`Assoc(List.map(fun(key,value)->(key,to_basicvalue))l)|`Listl->`List(List.mapto_basicl)|`Inti->`Inti|`Floatf->`Floatf|`Strings->`Strings|`Null->`Null|`Boolb->`Boolbin(* Rename `Assoc, `Int and `List *)letrecto_value:'a._->([>ezjsonm]as'a)=function|`Listl->`A(List.mapto_valuel)|`Assocl->`O(List.map(fun(key,value)->(key,to_valuevalue))l)|`Inti->`Float(float_of_inti)|`Floatf->`Floatf|`Null->`Null|`Strings->`Strings|`Boolb->`Boolbinto_basic(non_basic:>yojson)|>to_valueletrecto_yojsonjson=letrecaux:'a._->([>yojson]as'a)=function|`Avalues->`List(List.mapauxvalues)|`Ovalues->`Assoc(List.map(fun(k,v)->(k,auxv))values)|`Floatf->let(fract,intr)=modffinlet(min_intf,max_intf)=(min_int|>float_of_int,max_int|>float_of_int)iniffract=0.0thenifintr>=min_intf&&intr<=max_intfthen`Int(int_of_floatintr)else`Intlit(Printf.sprintf"%.0f"intr)else`Floatf|`Boolb->`Boolb|`Strings->`Strings|`Null->`Nullinaux(json:>ezjsonm)typeany=Value_with_repr:(moduleReprwithtypevalue='a)*'a->anyletany_to_repr:typett.(moduleReprwithtypevalue=tt)->any->tt=funrepr_t(Value_with_repr(repr_f,v))->convertrepr_frepr_tvletrepr_to_anyreprv=Value_with_repr(repr,v)letfrom_any:'a.any->([>ezjsonm]as'a)=funrepr->letres=any_to_repr(moduleEzjsonm)reprin(res:ezjsonm:>[>ezjsonm])letto_anyv=Value_with_repr((moduleEzjsonm),(v:>ezjsonm))