123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281moduleOt=Pb_codegen_ocaml_typemoduleF=Pb_codegen_formattingletsp=Pb_codegen_util.spletvalue_expression~r_name~rf_labelfield_type=letbasic_typehelper_fun=sp"Pbrt_bs.%s json \"%s\" \"%s\""helper_funr_namerf_labelinmatchfield_typewith|Ot.Ft_basic_typeOt.Bt_string->basic_type"string"|Ot.Ft_basic_typeOt.Bt_float->basic_type"float"|Ot.Ft_basic_typeOt.Bt_int->basic_type"int"|Ot.Ft_basic_typeOt.Bt_int32->basic_type"int32"|Ot.Ft_basic_typeOt.Bt_int64->basic_type"int64"|Ot.Ft_basic_typeOt.Bt_uint32->basic_type"[`unsigned of int32]"|Ot.Ft_basic_typeOt.Bt_uint64->basic_type"[`unsigned of int64]"|Ot.Ft_basic_typeOt.Bt_bool->basic_type"bool"|Ot.Ft_basic_typeOt.Bt_bytes->basic_type"bytes"|Ot.Ft_unit->"()"|Ot.Ft_user_defined_typeudt->let{Ot.udt_type;_}=udtinletf_name=letfunction_prefix="decode"inPb_codegen_util.function_name_of_user_defined~function_prefixudtin(matchudt_typewith|`Message->leto=sp"(Pbrt_bs.object_ json \"%s\" \"%s\")"r_namerf_labelin"("^f_name^" "^o^")"|`Enum->"("^f_name^" json)")|Ot.Ft_wrapper_type{Ot.wt_type=Ot.Bt_int32;_}->basic_type"int32_wrapped"|Ot.Ft_wrapper_type{Ot.wt_type=Ot.Bt_int64;_}->basic_type"int64_wrapped"|Ot.Ft_wrapper_type{Ot.wt_type=Ot.Bt_float;_}->basic_type"float_wrapped"|Ot.Ft_wrapper_type{Ot.wt_type=Ot.Bt_string;_}->basic_type"string_wrapped"|Ot.Ft_wrapper_type{Ot.wt_type=Ot.Bt_bool;_}->basic_type"bool_wrapped"|Ot.Ft_wrapper_type_->"None"(* | _ -> assert(false) *)(* Generate the pattern match for a record field *)letgen_rft_nolabelsc~r_name~rf_label(field_type,_,_)=letjson_label=Pb_codegen_util.camel_case_of_labelrf_labelinletvalue_expression=value_expression~r_name~rf_labelfield_typeinF.linepsc"| \"%s\" -> "json_label;F.linepsc" let json = Js.Dict.unsafeGet json \"%s\" in"json_label;F.linepsc" v.%s <- %s"rf_labelvalue_expression(* Generate all the pattern matches for a repeated field *)letgen_rft_repeatedsc~r_name~rf_labelrepeated_field=let_,field_type,_,_,_=repeated_fieldinletjson_label=Pb_codegen_util.camel_case_of_labelrf_labelinF.linepsc"| \"%s\" -> begin"json_label;F.sub_scopesc(funsc->F.linesc"let a = ";F.sub_scopesc(funsc->F.linepsc"let a = Js.Dict.unsafeGet json \"%s\" in "json_label;F.linepsc"Pbrt_bs.array_ a \"%s\" \"%s\""r_namerf_label);F.linesc"in";F.linepsc"v.%s <- Array.map (fun json -> "rf_label;letvalue_expression=value_expression~r_name~rf_labelfield_typeinF.linepsc" %s"value_expression;F.linesc") a |> Array.to_list;");F.linesc"end"letgen_rft_optionalsc~r_name~rf_labeloptional_field=letfield_type,_,_,_=optional_fieldinletjson_label=Pb_codegen_util.camel_case_of_labelrf_labelinletvalue_expression=value_expression~r_name~rf_labelfield_typeinF.linepsc"| \"%s\" -> "json_label;F.linepsc" let json = Js.Dict.unsafeGet json \"%s\" in"json_label;F.linepsc" v.%s <- Some (%s)"rf_labelvalue_expression(* Generate pattern match for a variant field *)letgen_rft_variantsc~r_name~rf_label{Ot.v_constructors;_}=List.iter(fun{Ot.vc_constructor;vc_field_type;_}->letjson_label=Pb_codegen_util.camel_case_of_constructorvc_constructorinmatchvc_field_typewith|Ot.Vct_nullary->F.linepsc"| \"%s\" -> v.%s <- %s"json_labelrf_labelvc_constructor|Ot.Vct_non_nullary_constructorfield_type->letvalue_expression=value_expression~r_name~rf_labelfield_typeinF.linepsc"| \"%s\" -> "json_label;F.linepsc" let json = Js.Dict.unsafeGet json \"%s\" in"json_label;F.linepsc" v.%s <- %s (%s)"rf_labelvc_constructorvalue_expression)v_constructors(* Generate decode function for a record *)letgen_record?and_{Ot.r_name;r_fields}sc=letmutable_record_name=Pb_codegen_util.mutable_record_namer_nameinF.linepsc"%s decode_%s json ="(Pb_codegen_util.let_decl_of_andand_)r_name;F.sub_scopesc(funsc->F.linepsc"let v = default_%s () in"mutable_record_name;F.linesc"let keys = Js.Dict.keys json in";F.linesc"let last_key_index = Array.length keys - 1 in";F.linesc"for i = 0 to last_key_index do";F.sub_scopesc(funsc->F.linesc"match Array.unsafe_get keys i with";(* Generate pattern match for all the possible message field *)List.iter(fun{Ot.rf_label;rf_field_type;_}->matchrf_field_typewith|Ot.Rft_nolabelnolabel_field->gen_rft_nolabelsc~r_name~rf_labelnolabel_field|Ot.Rft_optionaloptional_field->gen_rft_optionalsc~r_name~rf_labeloptional_field|Ot.Rft_repeatedrepeated_field->gen_rft_repeatedsc~r_name~rf_labelrepeated_field|Ot.Rft_variantvariant_field->gen_rft_variantsc~r_name~rf_labelvariant_field|Ot.Rft_required_->Printf.eprintf"Only proto3 syntax supported in JSON encoding";exit1|Ot.Rft_associative_->Printf.eprintf"Map field are not currently supported for JSON";exit1)r_fields;(* Unknown fields are simply ignored *)F.empty_linesc;F.linesc"| _ -> () (*Unknown fields are ignored*)");F.linesc"done;";(* Transform the mutable record in an immutable one *)F.linesc"({";F.sub_scopesc(funsc->List.iter(fun{Ot.rf_label;_}->F.linepsc"%s = v.%s;"rf_labelrf_label)r_fields);F.linepsc"} : %s)"r_name)(* Generate decode function for a variant type *)letgen_variant?and_{Ot.v_name;v_constructors}sc=(* helper function for each constructor case *)letprocess_v_constructorsc{Ot.vc_constructor;vc_field_type;_}=letjson_label=Pb_codegen_util.camel_case_of_constructorvc_constructorinmatchvc_field_typewith|Ot.Vct_nullary->F.linepsc"| \"%s\" -> (%s : %s)"json_labelvc_constructorv_name|Ot.Vct_non_nullary_constructorfield_type->letvalue_expression=letr_name=v_nameandrf_label=vc_constructorinvalue_expression~r_name~rf_labelfield_typeinF.linepsc"| \"%s\" -> "json_label;F.linepsc" let json = Js.Dict.unsafeGet json \"%s\" in"json_label;F.linepsc" (%s (%s) : %s)"vc_constructorvalue_expressionv_nameinF.linepsc"%s decode_%s json ="(Pb_codegen_util.let_decl_of_andand_)v_name;F.sub_scopesc(funsc->F.linesc"let keys = Js.Dict.keys json in";(* even though a variant should be an object with a single field,
* it is possible other fields are present in the JSON object. Therefore
* we still need a loop to iterate over the key/value, even if in 99.99%
* of the cases it will be a single iteration *)F.linesc"let rec loop = function ";F.sub_scopesc(funsc->F.linepsc"| -1 -> Pbrt_bs.E.malformed_variant \"%s\""v_name;F.linesc"| i -> ";F.sub_scopesc(funsc->F.linesc"begin match Array.unsafe_get keys i with";List.iter(process_v_constructorsc)v_constructors;F.empty_linesc;F.linesc"| _ -> loop (i - 1)";F.linesc"end"));F.linesc"in";F.linesc"loop (Array.length keys - 1)")letgen_const_variant?and_{Ot.cv_name;cv_constructors}sc=F.linepsc"%s decode_%s (json:Js.Json.t) ="(Pb_codegen_util.let_decl_of_andand_)cv_name;F.sub_scopesc(funsc->F.linepsc"match Pbrt_bs.string json \"%s\" \"value\" with"cv_name;List.iter(fun{Ot.cvc_name;cvc_string_value;_}->F.linepsc"| \"%s\" -> (%s : %s)"cvc_string_valuecvc_namecv_name)cv_constructors;F.linepsc"| \"\" -> %s"(let{Ot.cvc_name;_}=List.hdcv_constructorsincvc_name);F.linepsc"| _ -> Pbrt_bs.E.malformed_variant \"%s\""cv_name)(* Generate decode function for an empty record *)letgen_unit?and_{Ot.er_name}sc=F.linesc@@sp"%s decode_%s d ="(Pb_codegen_util.let_decl_of_andand_)er_name;F.linesc(sp"failwith \"support for empty messages not implemented\"")letgen_struct?and_tsc:bool=let{Ot.spec;_}=tinlethas_encoded=matchspecwith|Ot.Recordr->gen_record?and_rsc;true|Ot.Variantv->gen_variant?and_vsc;true|Ot.Const_variantv->gen_const_variant?and_vsc;true|Ot.Unitu->gen_unit?and_usc;trueinhas_encodedletgen_sig?and_tsc=let_=and_inlet{Ot.spec;_}=tinletftype_name=F.linepsc"val decode_%s : Js.Json.t Js.Dict.t -> %s"type_nametype_name;F.linepsc("(** [decode_%s decoder] decodes a "^^"[%s] value from [decoder] *)")type_nametype_nameinmatchspecwith|Ot.Record{Ot.r_name;_}->fr_name;true|Ot.Variant{Ot.v_name;_}->fv_name;true|Ot.Const_variant{Ot.cv_name;_}->F.linepsc"val decode_%s : Js.Json.t -> %s"cv_namecv_name;F.linepsc"(** [decode_%s value] decodes a [%s] from a Json value*)"cv_namecv_name;true|Ot.Unit{Ot.er_name;_}->fer_name;trueletocamldoc_title="BS Decoding"letrequires_mutable_records=trueletplugin:Pb_codegen_plugin.t=letmoduleP=structletgen_sig=gen_sigletgen_struct=gen_structletocamldoc_title=ocamldoc_titleletrequires_mutable_records=requires_mutable_recordsendin(moduleP)