123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155(*-------------------------------------------------------------------------
* Copyright (c) 2021 Bikal Gurung. All rights reserved.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
*-------------------------------------------------------------------------*)openPpxlibmoduleAst_builder=Ast_builder.Defaultlet(let*)rf=Result.bindrflet(>>=)=(let*)letrecdecode_wtr_expression~locwtr=(let*uri=decode_uriwtrinlet*query_components=decode_query_tokensuriinlet*path_components=decode_path_tokensuriinvalidate_tokens(path_components@query_components))|>function|Okwtr_tokens->wtr_expression~locwtr_tokens|Errormsg->Location.raise_errorf~loc"wtr: %s"msganddecode_uriwtr=letwtr=String.trimwtrinifString.lengthwtr>0thenOk(Uri.of_stringwtr)elseError"Empty uri path specification"anddecode_query_tokensuri=letexceptionEofstringintryUri.queryuri|>List.map(fun(k,v)->ifList.lengthv!=1thenraise(E(Printf.sprintf"Invalid query specification for key: %s"k))else[k;List.hdv])|>List.concat|>Result.okwith|Emsg->Errormsganddecode_path_tokensuri=Ok(Uri.pathuri|>String.split_on_char'/')andvalidate_tokenstokens=letvalidate_starttokens=matchList.hdtokenswith|""->Ok(List.tltokens)|_|(exception_)->Error"Uri path specification must start with '/'"inletvalidate_end_slashpath=let_,l2=split_on(funx->String.equal""x)pathinifList.lengthl2>0thenError"Invalid uri path specification. No tokens allowed after trailing '/' \
token"elseOkpathinletvalidate_full_splatpath=let_,l2=split_on(funx->String.equal"**"x)pathinifList.lengthl2>0thenError"Invalid uri path specification. No tokens allowed after full splat \
(**) token"elseOkpathinvalidate_starttokens>>=validate_end_slash>>=validate_full_splatandfindifl=letrecloopn=function|[]->None|x::t->iffxthenSomenelseloop(n+1)tinloop0landsplit_onfl=matchfindiflwith|Somen->(List.filteri(funi_->i<n)l,List.filteri(funi_->i>n)l)|None->(l,[])andwtr_expression~loc=function|[]->[%exprWtr.Private.nil]|[""]->[%exprWtr.Private.trailing_slash]|["**"]->[%exprWtr.Private.full_splat]|"*"::components->[%exprWtr.Private.decoderWtr.Private.string[%ewtr_expression~loccomponents]]|comp::componentswhenChar.equalcomp.[0]':'->(letcomp=String.subcomp1(String.lengthcomp-1)inmatchcompwith|"int"->[%exprWtr.Private.decoderWtr.Private.int[%ewtr_expression~loccomponents]]|"int32"->[%exprWtr.Private.decoderWtr.Private.int32[%ewtr_expression~loccomponents]]|"int64"->[%exprWtr.Private.decoderWtr.Private.int64[%ewtr_expression~loccomponents]]|"float"->[%exprWtr.Private.decoderWtr.Private.float[%ewtr_expression~loccomponents]]|"string"->[%exprWtr.Private.decoderWtr.Private.string[%ewtr_expression~loccomponents]]|"bool"->[%exprWtr.Private.decoderWtr.Private.bool[%ewtr_expression~loccomponents]]|custom_argwhencapitalizedcustom_arg->letlongident_loc={txt=Longident.parse(custom_arg^".t");loc}in[%exprWtr.Private.decoder[%eAst_builder.pexp_ident~loclongident_loc][%ewtr_expression~loccomponents]]|x->Location.raise_errorf~loc"wtr: Invalid custom argument name '%s'. Custom argument component \
name must be a valid module name."x)|comp::components->[%exprWtr.Private.lit[%eAst_builder.estring~loccomp][%ewtr_expression~loccomponents]]andcapitalizeds=Char.(uppercase_asciis.[0]|>equals.[0])letextend~loc~path:_wtr=decode_wtr_expression~locwtrletppx_name="wtr"letext=Extension.declareppx_nameExtension.Context.ExpressionAst_pattern.(single_expr_payload(estring__))extendlet()=Driver.register_transformationppx_name~extensions:[ext]