123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881# 1 "src/lib/eliom_parameter_base.shared.ml"(* Ocsigen
* http://www.ocsigen.org
* Copyright (C) 2007 Vincent Balat
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)openEliom_libletsection=Lwt_log.Section.make"eliom:parameter"typeparams=(string*Eliommod_parameters.param)listtypeparams'=(string*string)listtype+'aparam_name=string(** Type of names in a form *)typeno_param_name(** empty type used when it is not possible to use the parameter in a form *)type('a,'b)binsum=Inj1of'a|Inj2of'btype'anlistnames={it:'el'a.('an->'el->'a->'a)->'ellist->'a->'a}typecoordinates={abscissa:int;ordinate:int}type'asetoneradio=[`Setof'a|`Oneof'a|`Radioof'a]type'aoneradio=[`Oneof'a|`Radioof'a]type'asetone=[`Setof'a|`Oneof'a]type'ato_and_of='aEliom_common.to_and_of={of_string:string->'a;to_string:'a->string}type_atom=|TFloat:floatatom|TInt:intatom|TInt32:int32atom|TInt64:int64atom|TNativeint:nativeintatom|TBool:boolatom|TString:stringatomletstring_of_atom(typea)(p:aatom):a->string=matchpwith|TFloat->string_of_float|TInt->string_of_int|TInt32->Int32.to_string|TInt64->Int64.to_string|TNativeint->Nativeint.to_string|TBool->string_of_bool|TString->funs->sletatom_of_string(typea)(p:aatom):string->a=matchpwith|TFloat->float_of_string|TInt->int_of_string|TInt32->Int32.of_string|TInt64->Int64.of_string|TNativeint->Nativeint.of_string|TBool->bool_of_string|TString->funs->sletto_from_of_atomx={to_string=string_of_atomx;of_string=atom_of_stringx}type'afilter=('a->unit)optiontyperaw=Eliom_request_info.raw_post_datatype'aocaml=string(* marshaled values of type 'a *)typesuff=[`WithoutSuffix|`WithSuffix|`Endsuffix]type(_,_)params_type_=|TProd:(('a,'an)params_type_*('b,'bn)params_type_)->('a*'b,'an*'bn)params_type_|TOption:(('a,'an)params_type_*bool)->('aoption,'an)params_type_|TList:(string*('a,'an)params_type_)->('alist,'anlistnames)params_type_|TSet:('a,[`Oneof'an]param_name)params_type_->('alist,[`Setof'an]param_name)params_type_|TSum:(('a,'an)params_type_*('b,'bn)params_type_)->(('a,'b)binsum,'an*'bn)params_type_|TAtom:(string*'aatom)->('a,[`Oneof'a]param_name)params_type_|TCoord:string->(coordinates,[`Oneofcoordinates]param_name)params_type_|TFile:string->(file_info,[`Oneoffile_info]param_name)params_type_|TUserType:(string*'aEliom_common.To_and_of_shared.t)->('a,[`Oneof'a]param_name)params_type_|TTypeFilter:(('a,'an)params_type_*'afilter)->('a,'an)params_type_(* remove TCoord *)|TESuffix:string->(stringlist,[`Oneofstringlist]param_name)params_type_|TESuffixs:string->(string,[`Oneofstring]param_name)params_type_|TESuffixu:(string*'aEliom_common.To_and_of_shared.t)->('a,[`Oneof'a]param_name)params_type_|TSuffix:(bool*('s,'sn)params_type_)->('s,'sn)params_type_(* bool = redirect the version without suffix to the suffix version *)|TUnit:(unit,unit)params_type_|TAny:((string*string)list,unit)params_type_|TConst:string->(unit,[`Oneofunit]param_name)params_type_|TNLParams:('a,'names)non_localized_params_->('a,'names)params_type_|TJson:(string*'aDeriving_Json.toption)->('a,[`Oneof'aocaml]param_name)params_type_(* custom *)|TRaw_post_data:(raw,no_param_name)params_type_and('a,'names)non_localized_params_={name:string;persistent:bool;get:'aoptionPolytables.key;post:'aoptionPolytables.key;param:('a,'names)params_type_}type('a,+'suff,'an)non_localized_params=('a,'an)non_localized_params_constraint'suff=[<suff]type('a,+'suff,'an)params_type=('a,'an)params_type_constraint'suff=[<suff]letint(n:string)=TAtom(n,TInt)letint32(n:string)=TAtom(n,TInt32)letint64(n:string)=TAtom(n,TInt64)letfloat(n:string)=TAtom(n,TFloat)letbool(n:string)=TAtom(n,TBool)letstring(n:string)=TAtom(n,TString)letfile(n:string)=TFilenletunit=TUnitletcoordinatesn=TCoordnlettype_checkercheckt=TTypeFilter(t,Somecheck)letsumt1t2=TSum(t1,t2)letprodt1t2=TProd(t1,t2)let(**)=prodletoptt=TOption(t,false)letneoptt=TOption(t,true)letradiof(n:string)=TOption(fn,false)letlist(n:string)t=TList(n,t)letsetf(n:string)=TSet(fn)letany=TAnyletsuffix_const(v:string)=TConstvletall_suffix(n:string)=TESuffixnletall_suffix_string(n:string)=TESuffixsnletsuffix?(redirect_if_not_suffix=true)s=TSuffix(redirect_if_not_suffix,s)letsuffix_prod?(redirect_if_not_suffix=true)(s:('s,[<`WithoutSuffix|`Endsuffix],'sn)params_type)(t:('a,[`WithoutSuffix],'an)params_type):('s*'a,[`WithSuffix],'sn*'an)params_type=TProd(TSuffix(redirect_if_not_suffix,s),t)letocaml(n:string)typ=TJson(n,Sometyp)letraw_post_data=TRaw_post_data(******************************************************************)letmake_list_suffixi="["^string_of_inti^"]"letrecmake_suffix:typeac.(a,'b,c)params_type->a->stringlist=funtypparams->matchtypwith|TNLParams{param;_}->make_suffixparamparams|TProd(t1,t2)->make_suffixt1(fstparams)@make_suffixt2(sndparams)|TAtom(_,a)->[string_of_atomaparams]|TCoord_->make_suffix(TAtom("",TInt))params.abscissa@make_suffix(TAtom("",TInt))params.ordinate|TUnit->[""]|TConstv->[v]|TOption(t,_)->(matchparamswithNone->[""]|Somev->make_suffixtv)|TList(_,t)->(matchparamswith|[]->[""]|a::l->make_suffixta@make_suffixtypl)|TSett->(matchparamswith|[]->[""]|a::l->make_suffixta@make_suffixtypl)|TUserType(_,tao)->[Eliom_common.To_and_of_shared.to_stringtaoparams]|TTypeFilter(t,_check)->make_suffixtparams|TSum(t1,t2)->(matchparamswithInj1p->make_suffixt1p|Inj2p->make_suffixt2p)|TESuffixs_->[params](* | TAny -> (match params with [] -> [""] | p -> p) *)|TESuffix_->(matchparamswith[]->[""]|p->p)|TESuffixu(_,tao)->[Eliom_common.To_and_of_shared.to_stringtaoparams]|TJson(_,typ)->(* server or client side *)[to_json?typparams]|_->raise(Eliom_Internal_Error"Bad parameter type in suffix")letrecaux:typeac.(a,'b,c)params_type->stringlistoption->'y->a->string->string->'z->'x*'y*(string*Eliommod_parameters.field)list=funtyppsuffnlpparamsprefsuffl->letopenEliommod_parametersinmatchtypwith|TNLParams{name;param=t;_}->letpsuff,nlp,nl=auxtpsuffnlpparamsprefsuff[]inpsuff,String.Table.addnamenlnlp,l|TProd(t1,t2)->letpsuff,nlp,l1=auxt1psuffnlp(fstparams)prefsufflinauxt2psuffnlp(sndparams)prefsuffl1|TOption(t,_)->(matchparamswith|None->psuff,nlp,l|Somev->auxtpsuffnlpvprefsuffl)|TList(list_name,t)->letpref2=pref^list_name^suff^"."infst(List.fold_left(fun((psuff,nlp,s),i)p->auxtpsuffnlpppref2(make_list_suffixi)s,i+1)((psuff,nlp,l),0)params)|TSett->List.fold_left(fun(psuff,nlp,l)v->auxtpsuffnlpvprefsuffl)(psuff,nlp,l)params|TAtom(name,TBool)->(psuff,nlp,ifparamsthen(pref^name^suff,insert_string"on")::lelsel)|TAtom(name,a)->(psuff,nlp,(pref^name^suff,insert_string(string_of_atomaparams))::l)|TCoordname->(psuff,nlp,letcoord=paramsin(pref^name^suff^".x",insert_string(string_of_intcoord.abscissa))::(pref^name^suff^".y",insert_string(string_of_intcoord.ordinate))::l)|TSum(t1,t2)->(matchparamswith|Inj1v->auxt1psuffnlpvprefsuffl|Inj2v->auxt2psuffnlpvprefsuffl)|TFilename->psuff,nlp,(pref^name^suff,insert_fileparams)::l|TUserType(name,tao)->(psuff,nlp,(pref^name^suff,insert_string(Eliom_common.To_and_of_shared.to_stringtaoparams))::l)|TTypeFilter(t,_check)->auxtpsuffnlpparamsprefsuffl|TUnit->psuff,nlp,l|TAny->psuff,nlp,l@List.map(fun(x,v)->x,insert_stringv)params|TConst_->psuff,nlp,l|TESuffix_->raise(Eliom_Internal_Error"Bad use of suffix")|TESuffixs_->raise(Eliom_Internal_Error"Bad use of suffix")|TESuffixu_->raise(Eliom_Internal_Error"Bad use of suffix")|TSuffix(_,s)->Some(make_suffixsparams),nlp,l|TJson(name,typ)->(* server or client side *)psuff,nlp,(pref^name^suff,insert_string(to_json?typparams))::l|TRaw_post_data->failwith"Constructing an URL with raw POST data not possible"(******************************************************************)(* The following function takes a 'a params_type and a 'a and
constructs the list of parameters (GET or POST)
(This is a marshalling function towards HTTP parameters format) *)letconstruct_params_list_rawnlptypparams=auxtypNonenlpparams""""[](** Given a parameter type, get the two functions
that converts from and to strings. You should
only use this function on
- options ;
- basic types : int, int32, int64, float, string
- marshal
- unit
- string
- bool
*)letrecget_to_and_of:typeac.(a,'b,c)params_type->ato_and_of=function|TOption(o,_)->let{to_string;of_string}=get_to_and_ofoin{of_string=(funs->trySome(of_strings)with_->None);to_string=(functionSomealpha->to_stringalpha|None->"")}|TUserType(_,tao)->Eliom_common.To_and_of_shared.to_and_oftao|TESuffixu(_,tao)->Eliom_common.To_and_of_shared.to_and_oftao|TAtom(_,a)->to_from_of_atoma|TJson(_,typ)->(* server or client side *){of_string=(funs->of_json?typs);to_string=(fund->to_json?typd)}|TUnit->{of_string=(fun_->());to_string=(fun()->"")}|_->failwith"get_to_and_of: not implemented"(** Walk the parameter tree to search for a parameter, given its name *)letrecwalk_parameter_tree:typeac.string->(a,'b,c)params_type->ato_and_ofoption=funnamex->letgetname'=ifname=name'thenSome(get_to_and_ofx)elseNoneinmatchxwith|TUserType(name',_)->getname'|TCoordname'->getname'|TAtom(name',_)->getname'|TFilename'->getname'|TConstname'->getname'|TESuffixname'->getname'|TESuffixsname'->getname'|TJson(name',_)->getname'|TESuffixu(name',_)->getname'|TTypeFilter(t,_)->walk_parameter_treenamet|TSuffix(_,o)->walk_parameter_treenameo|TAny->None|TNLParams_->None|TUnit->None|TOption(_,_)->failwith"walk_parameter_tree with option"|TSet_->failwith"walk_parameter_tree with set"|TList(_,_)->failwith"walk_parameter_tree with list"|TProd(_,_)->failwith"walk_parameter_tree with tuple"|TSum(_,_)->failwith"walk_parameter_tree with sum"|TRaw_post_data->failwith"walk_parameter_tree with raw post data"(* construct the string of parameters (& separated) for GET and POST *)letconstruct_params_stringl=Url.make_encoded_parameters(Eliommod_parameters.get_param_listl)letconstruct_params_listnonlocparamstypp=letsuff,nonlocparams,pl=construct_params_list_rawnonlocparamstyppinletnlp=String.Table.fold(fun_ls->l@s)nonlocparams[]inletpl=pl@nlpin(* pl at beginning *)suff,plletconstruct_paramsnonlocparamstypp=letsuff,pl=construct_params_listnonlocparamstyppinsuff,construct_params_stringplletmake_params_namesparams=letrecaux:typeac.bool->string->string->(a,'b,c)params_type->bool*c=funissuffixprefixsuffixx->matchxwith|TNLParams{param=t;_}->auxissuffixprefixsuffixt|TProd(t1,t2)->letissuffix,a=auxissuffixprefixsuffixt1inletissuffix,b=auxissuffixprefixsuffixt2inissuffix,(a,b)|TAtom(name,_)->issuffix,prefix^name^suffix|TCoordname->issuffix,prefix^name^suffix|TFilename->issuffix,prefix^name^suffix|TUserType(name,_)->issuffix,prefix^name^suffix|TJson(name,_)->issuffix,prefix^name^suffix|TUnit->issuffix,()|TAny->issuffix,()|TConst_->issuffix,""|TSett->auxissuffixprefixsuffixt|TESuffixn->issuffix,n|TESuffixsn->issuffix,n|TESuffixu(n,_)->issuffix,n|TSuffix(_,t)->auxtrueprefixsuffixt|TOption(t,_)->auxissuffixprefixsuffixt|TSum(t1,t2)->let_,a=auxissuffixprefixsuffixt1inlet_,b=auxissuffixprefixsuffixt2inissuffix,(a,b)(* TSuffix cannot be inside TSum *)|TList(name,t1)->(issuffix,{it=(funflinit->letlength=List.lengthlinsnd(List.fold_right(funel(i,l2)->leti'=i-1in(i',f(snd(auxissuffix(prefix^name^suffix^".")(make_list_suffixi')t1))ell2))l(length,init)))})(* TSuffix cannot be inside TList *)|TTypeFilter(t,_)->auxissuffixprefixsuffixt|TRaw_post_data->failwith"Not possible with raw post data"inauxfalse""""paramsletstring_of_param_name=id(* Add a prefix to parameters *)letrecadd_pref_params:typeac.string->(a,'b,c)params_type->(a,'b,c)params_type=funprefx->matchxwith|TNLParamst->TNLParams{twithparam=add_pref_paramspreft.param}|TProd(t1,t2)->TProd(add_pref_paramspreft1,add_pref_paramspreft2)|TOption(t,b)->TOption(add_pref_paramspreft,b)|TAtom(name,a)->TAtom(pref^name,a)|TList(list_name,t)->TList(pref^list_name,t)|TSett->TSet(add_pref_paramspreft)|TSum(t1,t2)->TSum(add_pref_paramspreft1,add_pref_paramspreft2)|TFilename->TFile(pref^name)|TUserType(name,to_of)->TUserType(pref^name,to_of)|TCoordname->TCoord(pref^name)|TUnit->TUnit|TAny->TAny|TConstv->TConstv(* ??? no recursive call ??? *)|TESuffixn->TESuffixn|TESuffixsn->TESuffixsn|TESuffixua->TESuffixua|TSuffixs->TSuffixs|TJson(name,typ)->TJson(pref^name,typ)|TTypeFiltera->TTypeFiltera(* ??? no recursive call ??? *)|TRaw_post_data->failwith"Eliom_parameters: add_pref_params not possible with raw post data"(*****************************************************************************)(* Non localized parameters *)letnl_prod(t:('a,'su,'an)params_type)(s:('s,[`WithoutSuffix],'sn)non_localized_params):('a*'s,'su,'an*'sn)params_type=TProd(t,TNLParamss)(* removes from nlp set the nlp parameters that are present in param
specification *)letrecremove_from_nlp:typeac.'s->(a,'b,c)params_type->'s=funnlpx->matchxwith|TNLParams{name=n;_}->String.Table.removennlp|TProd(t1,t2)->letnlp=remove_from_nlpnlpt1inremove_from_nlpnlpt2|_->nlptypenl_params_set=(string*Eliommod_parameters.param)listString.Table.tletempty_nl_params_set=String.Table.emptyletadd_nl_parameter(s:nl_params_set)tv=(fun(_,a,_)->a)(construct_params_list_raws(TNLParamst)v)lettable_of_nl_params_set=idletlist_of_nl_params_setnlp=snd(construct_params_listnlpunit())letstring_of_nl_params_setnlp=Url.make_encoded_parameters(Eliommod_parameters.get_param_list(list_of_nl_params_setnlp))letget_nl_params_namest=snd(make_params_names(TNLParamst))letmake_nlp_namepersistentprefixname=letpr=ifpersistentthen"p_"else"n_"inpr^prefix^"-"^nameletmake_non_localized_parameters~prefix~name?(persistent=false)(p:('a,[`WithoutSuffix],'b)params_type):('a,[`WithoutSuffix],'b)non_localized_params=letname=make_nlp_namepersistentprefixnameinifString.containsname'.'thenfailwith"Non localized parameters names cannot contain dots."else{name;persistent;get=Polytables.make_key();post=Polytables.make_key();param=add_pref_params(Eliom_common.nl_param_prefix^name^".")p}(*****************************************************************************)letreccontains_suffix:typeac.(a,'b,c)params_type->booloption=function|TProd(a,b)->(matchcontains_suffixawithNone->contains_suffixb|c->c)|TSuffix(b,_)->Someb|_->None(*****************************************************************************)letrecwrap_param_type:typeac.(a,'b,c)params_type->(a,'b,c)params_type=function|TNLParamst->TNLParams{twithparam=wrap_param_typet.param}|TProd(t1,t2)->TProd(wrap_param_typet1,wrap_param_typet2)|TOption(t,b)->TOption(wrap_param_typet,b)|TList(list_name,t)->TList(list_name,t)|TSett->TSet(wrap_param_typet)|TSum(t1,t2)->TSum(wrap_param_typet1,wrap_param_typet2)|TUserType(name,tao)->(* Eliom_common.To_and_of_shared.wrapper will take care of tao *)TUserType(name,tao)(* We remove the type information here: not possible to send a
closure. marshaling is just basic json marshaling on client
side. *)|TJson(name,_)->TJson(name,None)(* the filter is only on server side (at least for now) *)|TTypeFilter(t,_)->TTypeFilter(t,None)|t->ttype_is_unit=U_not:_is_unit|U_yes:unitis_unitletis_unit:typeac.(a,_,c)params_type->ais_unit=function|TUnit->U_yes|_->U_nottypeanon_params_type=intletanonymise_params_type(t:('a,'b,'c)params_type):anon_params_type=Hashtbl.hash_param10001000ttypefiles=(string*file_info)listtype+'ares_reconstr_param=|Res_of'a*params'*files|Errors_of((string*string*exn)list*params'*files)letend_of_listlppref=letf(a,_)=tryString.(suba0(lengthpref))=prefwithInvalid_argument_->falseinnot(List.existsflp)(* The following function reconstructs the value of parameters from
expected type and GET or POST parameters *)letreconstruct_params_typparamsfilesnosuffixversionurlsuffix:'a=letrecparse_suffix:typeac.(a,'b,c)params_type->stringlist->a*stringlist=funtypsuff->matchtyp,suffwith|TESuffix_,l->l,[](*VVV encode=false? *)|TESuffixs_,l->Url.string_of_url_path~encode:falsel,[]|TESuffixu(_,tao),l->(try(*VVV encode=false? *)(Eliom_common.To_and_of_shared.of_stringtao(Url.string_of_url_path~encode:falsel),[])withe->raise(Eliom_common.Eliom_Typing_Error["<suffix>",e]))|TOption(_,_),[]->None,[]|TOption(_,_),""::l->None,l|TOption(t,_),l->letr,ll=parse_suffixtlinSomer,ll|TList_,[]->[],[]|TList(_,t),l->(letb,l=parse_suffixtlinmatchlwith|[]->raiseEliom_common.Eliom_Wrong_parameter|[""]->[b],[]|_->letc,l=parse_suffixtyplinb::c,l)|TSet(TAtom(_,TBool)asy),l->letb,l=parse_suffixylin[b],l|TSett,l->(letb,l=parse_suffixtlinmatchlwith|[]->raiseEliom_common.Eliom_Wrong_parameter|[""]->[b],[]|_->letc,l=parse_suffixtyplinb::c,l)|TProd(TList_,_),_->failwith"Lists or sets in suffixes must be last parameters"|TProd(TSet_,_),_->failwith"Lists or sets in suffixes must be last parameters"|TProd(t1,t2),l->(matchparse_suffixt1lwith|_,[]->raiseEliom_common.Eliom_Wrong_parameter|r,l->letrr,ll=parse_suffixt2lin(r,rr),ll)|TAtom(_name,t),v::l->(tryatom_of_stringtv,lwithe->raise(Eliom_common.Eliom_Typing_Error["<suffix>",e]))|TUserType(_name,tao),v::l->(tryEliom_common.To_and_of_shared.of_stringtaov,lwithe->raise(Eliom_common.Eliom_Typing_Error["<suffix>",e]))|TTypeFilter(_,None),_->failwith"Type filter without filter"|TTypeFilter(t,Somecheck),l->let((v,_)asa)=parse_suffixtlincheckv;a|TConstvalue,v::l->ifv=valuethen(),lelseraiseEliom_common.Eliom_Wrong_parameter|TSum(t1,t2),l->(tryletx,l=parse_suffixt1linInj1x,lwithEliom_common.Eliom_Wrong_parameter->letx,l=parse_suffixt2linInj2x,l)|TCoord_,l->(matchparse_suffix(TAtom("",TInt))lwith|_,[]->raiseEliom_common.Eliom_Wrong_parameter|r,l->letrr,ll=parse_suffix(TAtom("",TInt))lin{abscissa=r;ordinate=rr},ll)|TNLParams_,_->failwith"It is not possible to have non localized parameters in suffix"|TJson(_,Sometyp),v::l->Deriving_Json.from_stringtypv,l|TJson(_,None),_::_->assertfalse(* client side only *)|TAny,_->failwith"It is not possible to use any in suffix. May be try with all_suffix ?"|TFile_,_->assertfalse|TRaw_post_data,_->assertfalse|TUnit,_->failwith"It is not possible to use TUnit in suffix."|TSuffix_,_->failwith"It is not possible to use TSuffix in suffix."|_,[]->raiseEliom_common.Eliom_Wrong_parameterinletrecaux_list:typeac.(a,'b,c)params_type->params'->files->string->string->string->alistres_reconstr_param=funtparamsfilesnameprefsuff->letrecloop_listilpflpref=ifmatchtwith|TFile_->end_of_listflpref|_->end_of_listlpprefthenRes_([],lp,fl)elsematchauxtlpflpref(make_list_suffixi)with|Res_(v,lp2,f)->(matchloop_list(i+1)lp2fprefwith|Res_(v2,lp3,f2)->Res_(v::v2,lp3,f2)|err->err)|Errors_errs->Errors_errsinloop_list0paramsfiles(pref^name^suff^".")andaux:typeac.(a,'b,c)params_type->params'->files->string->string->ares_reconstr_param=funtypparamsfilesprefsuff->matchtypwith|TNLParams{param=t;_}->auxtparamsfilesprefsuff|TProd(t1,t2)->(matchauxt1paramsfilesprefsuffwith|Res_(v1,l1,f)->(matchauxt2l1fprefsuffwith|Res_(v2,l2,f2)->Res_((v1,v2),l2,f2)|Errors_(err,params,files)->Errors_(err,params,files))|Errors_(errs,l,f)->(matchauxt2lfprefsuffwith|Res_(_,ll,ff)->Errors_(errs,ll,ff)|Errors_(errs2,ll,ff)->Errors_(errs2@errs,ll,ff)))|TOption((TAtom(_,TString)ast),b)->(trymatchauxtparamsfilesprefsuffwith|Res_(v,l,f)->ifb&&String.lengthv=0(* Is the value an empty string? *)thenRes_(None,l,f)elseRes_(Somev,l,f)|Errors_(errs,ll,ff)whenList.for_all(fun(_,s,_)->s="")errs->Res_(None,ll,ff)|Errors_err->Errors_errwithNot_found->Res_(None,params,files))|TOption(t,_)->(trymatchauxtparamsfilesprefsuffwith|Res_(v,l,f)->Res_(Somev,l,f)|Errors_(errs,ll,ff)whenList.for_all(fun(_,s,_)->s="")errs->Res_(None,ll,ff)|Errors_err->Errors_errwithNot_found->Res_(None,params,files))|TList(n,t)->aux_listtparamsfilesnprefsuff|TSet(TAtom(_,TBool)asy)->(matchauxyparamsfilesprefsuffwith|Res_(vv,ll,ff)->Res_([vv],ll,ff)|Errors_(err,ll,ff)->Errors_(err,ll,ff))|TSett->letrecaux_setparamsfiles=trymatchauxtparamsfilesprefsuffwith|Res_(vv,ll,ff)->(matchaux_setllffwith|Res_(vv2,ll2,ff2)->Res_(vv::vv2,ll2,ff2)|err->err)|Errors_(_errs,ll,ff)whenll=params&&ff=files->Res_([],params,files)|Errors_(errs,ll,ff)->(matchaux_setllffwith|Res_(_,ll2,ff2)->Errors_(errs,ll2,ff2)|Errors_(errs2,ll2,ff2)->Errors_(errs@errs2,ll2,ff2))withNot_found->Res_([],params,files)inaux_setparamsfiles|TSum(t1,t2)->((* We try to decode both cases, if both succeed,
we choose the one that consumes parameters
(or the 1st one if none consumes) *)trymatchauxt1paramsfilesprefsuffwith|Res_(v1,l1,files1)->ifl1=paramsthentrymatchauxt2paramsfilesprefsuffwith|Res_(v2,l2,files2)whenl2<>params->Res_(Inj2v2,l2,files2)|_->Res_(Inj1v1,l1,files1)withNot_found->Res_(Inj1v1,l1,files1)elseRes_(Inj1v1,l1,files1)|Errors_err->Errors_errwithNot_found->(matchauxt2paramsfilesprefsuffwith|Res_(v,l,files)->Res_(Inj2v,l,files)|Errors_err->Errors_err))|TAtom(name,TBool)->(trylet_,l=List.assoc_remove(pref^name^suff)paramsinRes_(true,l,files)withNot_found->Res_(false,params,files))|TAtom(name,a)->(letv,l=List.assoc_remove(pref^name^suff)paramsintryRes_(atom_of_stringav,l,files)withe->Errors_([pref^name^suff,v,e],l,files))|TFilename->(tryletv,f=List.assoc_remove(pref^name^suff)filesinRes_(v,params,f)withe->Errors_([pref^name^suff,"",e],[],files))|TCoordname->(letr1=letv,l=List.assoc_remove(pref^name^suff^".x")paramsintryRes_(int_of_stringv,l,files)withe->Errors_([pref^name^suff^".x",v,e],l,files)inmatchr1with|Res_(x1,l1,f)->(letv,l=List.assoc_remove(pref^name^suff^".y")l1intryRes_({abscissa=x1;ordinate=int_of_stringv},l,f)withe->Errors_([pref^name^suff^".y",v,e],l,f))|Errors_(errs,l1,f)->(letv,l=List.assoc_remove(pref^name^suff^".y")l1intryignore(int_of_stringv);Errors_(errs,l,f)withe->Errors_((pref^name^suff^".y",v,e)::errs,l,f)))|TUserType(name,tao)->(letv,l=List.assoc_remove(pref^name^suff)paramsintryRes_(Eliom_common.To_and_of_shared.of_stringtaov,l,files)withe->Errors_([pref^name^suff,v,e],l,files))|TTypeFilter(_,None)->failwith"Type filter without filter"|TTypeFilter(t,Somecheck)->(matchauxtparamsfilesprefsuffwith|Res_(v,l,files)asa->(trycheckv;awithe->Errors_(["<type_check>","<>",e],l,files))|a->a)|TUnit->Res_((),params,files)|TAny->Res_(params,[],files)|TConst_->Res_((),params,files)|TESuffixn->letv,l=List.assoc_removenparamsin(* cannot have prefix or suffix *)Res_(Eliom_lib.Url.split_pathv,l,files)|TESuffixsn->letv,l=List.assoc_removenparamsin(* cannot have prefix or suffix *)Res_(v,l,files)|TESuffixu(n,tao)->(letv,l=List.assoc_removenparamsin(* cannot have prefix or suffix *)tryRes_(Eliom_common.To_and_of_shared.of_stringtaov,l,files)withe->Errors_([pref^n^suff,v,e],l,files))|TSuffix(_,s)->(matchurlsuffixwith|None->ifnosuffixversion(* the special page name "nosuffix" is present *)thenauxsparamsfilesprefsuffelseraiseEliom_common.Eliom_Wrong_parameter|Someurlsuffix->(matchparse_suffixsurlsuffixwith|p,[]->Res_(p,params,files)|_->raiseEliom_common.Eliom_Wrong_parameter))|TJson(name,Sometyp)->letv,l=List.assoc_remove(pref^name^suff)paramsinRes_(of_json~typv,l,files)|TJson(_name,None)->assertfalse(* Never unmarshal server side without type! *)|TRaw_post_data->raiseEliom_common.Eliom_Wrong_parameterintrymatchauxtypparamsfiles""""with|Res_(v,l,files)->if(l,files)=([],[])thenvelse(ifl<>[]thenLwt_log.ign_debug_f~section"Eliom_Wrong_parameter: params non-empty (ERROR): %a"(fun()l->String.concat", "(List.map(fun(x,k)->x^"="^k)l))l;iffiles<>[]thenLwt_log.ign_debug_f~section"Eliom_Wrong_parameter: files non-empty (ERROR): %a"(fun()files->String.concat", "(List.map(fun(x,_)->x)files))files;raiseEliom_common.Eliom_Wrong_parameter)|Errors_(errs,l,files)->if(l,files)=([],[])thenraise(Eliom_common.Eliom_Typing_Error(List.map(fun(v,_,e)->v,e)errs))elseraiseEliom_common.Eliom_Wrong_parameterwithNot_found->raiseEliom_common.Eliom_Wrong_parameterletreconstruct_params~sp(typeac)(typ:(a,'b,c)params_type)paramsfilesnosuffixversionurlsuffix:aLwt.t=matchtyp,params,fileswith(* FIXME *)|TRaw_post_data,None,None->Eliom_request_info.raw_post_datasp|typ,None,None->(tryLwt.return(reconstruct_params_typ[][]nosuffixversionurlsuffix)withe->Lwt.faile)|typ,_,_->(let%lwtparams=matchparamswithSomeparams->params|None->Lwt.return_nilinlet%lwtfiles=matchfileswithSomefiles->files|None->Lwt.return_nilintryLwt.return(reconstruct_params_typparamsfilesnosuffixversionurlsuffix)withe->Lwt.faile)