123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356(*
Copyright 2009, 2010, 2011, 2012, 2013, 2014, 2017, 2018 Anton Lavrik
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)moduleC=Piqi_commonopenCopenPiqobj_commonmoduleW=Piqi_protobufletnext_count=Piqloc.next_icountletreference0fx=letcount=next_count()inletobj=fxinPiqloc.addrefretcountobjletreferenceftx=letcount=next_count()inletobj=ftxinPiqloc.addrefretcountobj(* XXX: move to Piqi_protobuf? *)letparse_int?wire_typex=letr0=reference0inletwire_type=W.get_wire_type`intwire_typeinmatchwire_typewith|`varint->`uint(r0Piqirun.int64_of_varintx)|`zigzag_varint->`int(r0Piqirun.int64_of_zigzag_varintx)|`fixed32->`uint(r0Piqirun.int64_of_fixed32x)|`fixed64->`uint(r0Piqirun.int64_of_fixed64x)|`signed_varint->`int(r0Piqirun.int64_of_signed_varintx)|`signed_fixed32->`int(r0Piqirun.int64_of_signed_fixed32x)|`signed_fixed64->`int(r0Piqirun.int64_of_signed_fixed64x)|`block->assertfalse(* XXX *)letparse_packed_int?wire_typex=letwire_type=W.get_wire_type`intwire_typeinmatchwire_typewith|`varint->`uint(Piqirun.int64_of_packed_varintx)|`zigzag_varint->`int(Piqirun.int64_of_packed_zigzag_varintx)|`fixed32->`uint(Piqirun.int64_of_packed_fixed32x)|`fixed64->`uint(Piqirun.int64_of_packed_fixed64x)|`signed_varint->`int(Piqirun.int64_of_packed_signed_varintx)|`signed_fixed32->`int(Piqirun.int64_of_packed_signed_fixed32x)|`signed_fixed64->`int(Piqirun.int64_of_packed_signed_fixed64x)|`block->assertfalse(* XXX *)letparse_float?wire_typex=letr0=reference0inletwire_type=W.get_wire_type`floatwire_typeinmatchwire_typewith|`fixed32->r0Piqirun.float_of_fixed32x|`fixed64->r0Piqirun.float_of_fixed64x|_->assertfalse(* XXX *)letparse_packed_float?wire_typex=letwire_type=W.get_wire_type`floatwire_typeinmatchwire_typewith|`fixed32->Piqirun.float_of_packed_fixed32x|`fixed64->Piqirun.float_of_packed_fixed64x|_->assertfalse(* XXX *)letrecparse_obj0(t:T.piqtype)x:Piqobj.obj=letr0=reference0inletr=referenceinmatchtwith(* built-in types *)|`int->parse_intx|`float->`float(parse_floatx)|`bool->`bool(r0Piqirun.parse_bool_fieldx)|`string->`string(r0Piqirun.parse_string_fieldx)|`binary->`binary(r0Piqirun.parse_binary_fieldx)|`any->`any(parse_anyx)(* custom types *)|`recordt->`record(rparse_recordtx)|`variantt->`variant(rparse_varianttx)|`enumt->`enum(rparse_enumtx)|`listt->`list(rparse_listtx)|`aliast->`alias(parse_alias0tx)andparse_packed_obj(t:T.piqtype)x:Piqobj.obj=matchtwith(* built-in types *)|`int->parse_packed_intx|`float->`float(parse_packed_floatx)|`bool->`bool(Piqirun.bool_of_packed_varintx)|`enumt->`enum(parse_packed_enumtx)|`aliast->`alias(parse_packed_aliastx)|_->assertfalse(* objects of other types can't be packed *)andparse_objtx=(* using the same count here as we will use for parsing the objects themselves
*)letcount=!Piqloc.icountinletres=parse_obj0txinPiqloc.addrefretcountresandparse_binobjpiqtypebinobj=Piqirun.parse_binobj(parse_objpiqtype)binobjandparse_anyx=letpiqi_any=T.parse_anyxinmatchpiqi_any.T.Any.refwith|Someref->(* recover internally passed Piqobj.any from an integer reference *)C.debug"Piqobj_of_protobuf.parse_any: recovering any from existing ref %d\n"ref;Piqobj.get_anyref|None->(* external mode *)letany=Any.({Piqobj.default_anywithtypename=piqi_any.Piqi_impl_piqi.Any.typename;pb=piqi_any.Piqi_impl_piqi.Any.protobuf;})in(* if there's no typed protobuf, look for untyped JSON or XML values *)ifany.Any.pb=Nonethen(letjson_string=piqi_any.T.Any.jsoninletxml_string=piqi_any.T.Any.xmlinletpiq_string=piqi_any.T.Any.piqinifjson_string<>Nonethen(letjson_ast=!Piqobj.json_of_string(some_ofjson_string)inany.Any.json_ast<-Somejson_ast;(* same as in Piqobj_of_piq.parse_any *)any.Any.json_string<-json_string)elseifxml_string<>Nonethen(letxml_list=!Piqobj.xml_of_string(some_ofxml_string)inany.Any.xml_ast<-Some("undefined",xml_list)(* same as in Piqobj_of_piq.parse_any *))elseifpiq_string<>Nonethen(letpiq_ast=!Piqobj.piq_of_string(some_ofpiq_string)inany.Any.piq_ast<-Somepiq_ast;(* same as in Piqobj_of_piq.parse_any *))else(* XXX: hmm... no protobuf, JSON, XML, Piq -- what are we
* dealing with here? *)assertfalse);anyandparse_recordtx=letl=Piqirun.parse_recordxin(* obtain the reference to unparsed piq fields if we are dealing with
* serialized Piqi object *)letunparsed_piq_fields_ref,l=if!C.is_inside_parse_piqithenparse_unparsed_piq_fields_reflelseNone,lin(* NOTE: fields are pre-order by wire code *)letfields_spec=t.T.Record.wire_fieldinletfields,rem=List.fold_leftparse_field([],l)fields_specinPiqirun.check_unparsed_fieldsrem;R.({t=t;field=List.revfields;unparsed_piq_fields_ref=unparsed_piq_fields_ref})andparse_unparsed_piq_fields_refl=letres=Piqirun.parse_optional_field1(funx->parse_int~wire_type:`varintx)linmatchreswith|Some(`uintx),rem->Some(Int64.to_intx),rem|None,l->None,l|_->assertfalseandparse_field(accu,rem)t=letfields,rem=do_parse_fieldtremin(List.rev_appendfieldsaccu,rem)anddo_parse_fieldtl=letopenT.Fieldinletcode=Int32.to_int(some_oft.code)inletfield_type=some_oft.piqtypeinletvalues,rem=matcht.modewith|`required->letx,rem=parse_required_fieldcodefield_typelin[x],rem|`optional->(* XXX: location reference for default? *)letx,rem=parse_optional_fieldcodefield_typet.defaultlinletres=(matchxwithSomex->[x]|None->[])inres,rem|`repeated->ifnott.protobuf_packedthenparse_repeated_fieldcodefield_typelelseparse_packed_repeated_fieldcodefield_typelinletfields=List.map(funx->letres=F.({t=t;obj=Somex})inPiqloc.addrefretxres)valuesinfields,remandparse_required_fieldcodefield_typel=Piqirun.parse_required_fieldcode(parse_objfield_type)landparse_optional_fieldcodefield_typedefaultl=letres=Piqirun.parse_optional_fieldcode(parse_objfield_type)linmatchreswith|Some_,_->res|None,rem->Piqobj_common.parse_defaultfield_typedefault,remandparse_repeated_fieldcodefield_typel=Piqirun.parse_repeated_fieldcode(parse_objfield_type)landparse_packed_repeated_fieldcodefield_typel=Piqirun.parse_packed_repeated_fieldcode(parse_packed_objfield_type)(parse_objfield_type)landparse_varianttx=letcode,obj=Piqirun.parse_variantxinletcode32=Int32.of_intcodeinletoptions=t.T.Variant.optioninletoption=tryleto=List.find(funo->some_ofo.T.Option.code=code32)optionsinparse_optionoobjwithNot_found->Piqirun.error_variantxcodeinV.({t=t;option=option})andparse_optiontx=letopenT.Optioninmatcht.piqtypewith|None->ifPiqirun.parse_bool_fieldx=truethenletres=O.({t=t;obj=None})in(* skip boolean used to encode empty option value *)letcount=next_count()inPiqloc.addrefretcountreselsepiqi_error"invalid representation of untyped option"|Someoption_type->letobj=parse_objoption_typexinletres=O.({t=t;obj=Someobj})inPiqloc.addrefretobjresandparse_enumtx=letcode32=Piqirun.int32_of_signed_varintxinletoption=tryparse_enum_optiontcode32withNot_found->Piqirun.error_enum_constxin(* add location reference which is equal to the enum location *)Piqloc.addref!Piqloc.icountoption;E.({t=t;option=option})andparse_packed_enumtx=letcode32=Piqirun.int32_of_packed_signed_varintxinletoption=tryparse_enum_optiontcode32withNot_found->Piqirun.error_enum_constxinE.({t=t;option=option})andparse_enum_optiontcode32=letoptions=t.T.Enum.optioninleto=List.find(funo->some_ofo.T.Option.code=code32)optionsinO.({t=o;obj=None})andparse_listtx=letobj_type=some_oft.T.Piqi_list.piqtypeinletcontents=ifnott.T.Piqi_list.protobuf_packedthenPiqirun.parse_list(parse_objobj_type)xelsePiqirun.parse_packed_list(parse_packed_objobj_type)(parse_objobj_type)xinL.({t=t;obj=contents})andparse_alias0tx=parse_aliastx(* XXX: roll-up multiple enclosed aliases into one? *)andparse_aliast?wire_typex=letopenT.Aliasinletwire_type=Piqobj_to_protobuf.resolve_wire_type?wire_typet.protobuf_wire_typeinletobj=matchsome_oft.piqtypewith|`int->parse_intx?wire_type|`float->`float(parse_floatx?wire_type)|`aliast->`alias(parse_aliastx?wire_type)|t->parse_objtxinA.({t=t;obj=obj})andparse_packed_aliast?wire_typex=letopenT.Aliasinletwire_type=Piqobj_to_protobuf.resolve_wire_type?wire_typet.protobuf_wire_typeinletobj=matchsome_oft.piqtypewith|`int->parse_packed_intx?wire_type|`float->`float(parse_packed_floatx?wire_type)|`aliast->`alias(parse_packed_aliastx?wire_type)|t->parse_packed_objtxinA.({t=t;obj=obj})let_=Piqobj.of_pb:=parse_binobj