123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411open!ImportopenPpx_yojson_conv_lib.Yojson_conv.PrimitivesmoduleError=structtypemake=[`Invalid_qualifierofstring|`Invalid_account_idofstring][@@derivingyojson]endmoduleDefault=structletpartition="aws"endtyperesource_type=[`Slash_delimitedofstring|`Colon_delimitedofstring|`None][@@derivingyojson]typequalifier=[`Slash_delimitedofstring|`Colon_delimitedofstring|`None][@@derivingyojson]typet={partition:string;service:Service.t;region:Region.toption;account_id:stringoption;resource:string;resource_type:resource_type;qualifier:qualifier}[@@derivingyojson]letmake?(partition=Default.partition)?region?account_id?(resource_type=`None)?(qualifier=`None)~service~resource()=letmake_qualifierx=matchxwith|`None->`Ok`None|`Slash_delimiteds|`Colon_delimiteds->ifString.equals""then`Invalid_qualifierselse`Okxinletmake_account_idx=Option.value_mapx~default:(`OkNone)~f:(funx->ifString.equalx""then`Invalid_account_idxelse`Ok(Somex))inmatchmake_qualifierqualifierwith|`Invalid_qualifier_asx->x|`Okqualifier->(matchmake_account_idaccount_idwith|`Invalid_account_id_asx->x|`Okaccount_id->`Ok{partition;service;region;account_id;resource;resource_type;qualifier});;letmake_exn?partition?region?account_id?resource_type?qualifier~service~resource()=matchmake?partition?region?account_id?resource_type?qualifier~service~resource()with|`Okx->x|#Error.makease->failwith("Invalid ARN "^Yojson.Safe.to_string(Error.yojson_of_make(e:>Error.make)));;letof_strings=letbuildpartitionserviceregionaccount_idresource_typeresourcequalifier=letservice=Service.of_stringserviceinletregion=matchregionwith|""->None|_->Some(Region.of_stringregion)inletaccount_id=matchaccount_idwith|""->None|_->Someaccount_idinmake_exn~partition~service?region?account_id~resource~resource_type~qualifier()inletsplit=String.split~on:':'sinmatchsplitwith(* arn:partition:service:region:account-id:resourcetype:resource:qualifier *)|["arn";partition;service;region;account_id;resource_type;resource;qualifier]->buildpartitionserviceregionaccount_id(`Colon_delimitedresource_type)resource(`Colon_delimitedqualifier)|["arn";partition;service;region;account_id;resource_part;last_part]->ifString.containsresource_part'/'then((* arn:partition:service:region:account-id:resourcetype/resource:qualifier *)letqualifier=last_partinletresource_type,resource=String.lsplit2_exn~on:'/'resource_partinbuildpartitionserviceregionaccount_id(`Slash_delimitedresource_type)resource(`Colon_delimitedqualifier))else((* arn:partition:service:region:account-id:resourcetype:resource *)letresource=last_partinbuildpartitionserviceregionaccount_id(`Colon_delimitedresource_part)resource`None)(* arn:partition:service:region:account-id:resource
arn:partition:service:region:account-id:resourcetype/resource
arn:partition:service:region:account-id:resourcetype/resource/qualifier *)|["arn";partition;service;region;account_id;resource_type_slash_resource_slash_qualifier]->(matchString.split~on:'/'resource_type_slash_resource_slash_qualifierwith|[resource_type;resource;qualifier]->buildpartitionserviceregionaccount_id(`Slash_delimitedresource_type)resource(`Slash_delimitedqualifier)|[resource_type;resource]->buildpartitionserviceregionaccount_id(`Slash_delimitedresource_type)resource`None|[resource]->buildpartitionserviceregionaccount_id`Noneresource`None|_->failwithf"'%s' has an invalid number of '/' delimiters."s())|"arn"::_->failwithf"'%s' has an invalid number of ':' delimiters."s()|_->failwithf"'%s' is not an amazon resource name."s();;let%expect_test"of_string"=(* Strings expected to be valid ARNs. *)letgood=[(* Format arn:partition:service:region:account-id:resource *)["arn:partition:sqs:us-east-2:account-id:resource"];(* Format arn:partition:service:region:account-id:resourcetype/resource *)["arn:partition:sqs:us-east-2:account-id:resourcetype/resource"];(* Format
arn:partition:service:region:account-id:resourcetype/resource/qualifier *)["arn:partition:sqs:us-east-2:account-id:resourcetype/resource/qualifier"];(* Format
arn:partition:service:region:account-id:resourcetype/resource:qualifier *)["arn:partition:sqs:us-east-2:account-id:resourcetype/resource:qualifier"];(* Format arn:partition:service:region:account-id:resourcetype:resource *)[(* Full *)"arn:partition:sqs:us-east-2:account-id:resourcetype:resource";(* Empty region *)"arn:partition:sqs::account-id:resourcetype:resource";(* Empty account *)"arn:partition:sqs:us-east-2::resourcetype:resource"];(* Format
arn:partition:service:region:account-id:resourcetype:resource:qualifier *)["arn:partition:sqs:us-east-2:account-id:resourcetype:resource:qualifier"]]in(* Strings expected to be invalid ARNs. *)letbad=[(* Empty string. *)"";(* Invalid format. *)"x";(* Colon_delimited resource type with Slash_delimited qualifier. *)"arn:partition:sqs:us-east-2:account-id:resourcetype:resource/qualifier";(* Colon_delimited qualifier without resource type. *)"arn:partition:sqs:us-east-2:account-id::resource:qualifier";(* Slash_delimited qualifier without resource type. *)"arn:partition:sqs:us-east-2:account-id::resource/qualifier"]inlettest_badinput=matchof_stringinputwith|x->Test.fail"Input unexpected to parse as ARN but did."["input",input;"arn",Yojson.Safe.to_string(yojson_of_tx)]|exceptione->Test.pass"Correctly failed to parse input as an ARN."["input",input;"exception",Exn.to_stringe]inlettest_goodinput=matchof_stringinputwith|x->Test.pass"Input parsed as ARN."["input",input;"arn",Yojson.Safe.to_string(yojson_of_tx)]|exceptione->Test.fail"Input failed to parse as ARN."["input",input;"exception",Exn.to_stringe]inList.iter(List.concatgood)~f:(funx->test_goodx;printf"\n");List.iterbad~f:(funx->test_badx;printf"\n");[%expect{|
[OK] Input parsed as ARN.
input: arn:partition:sqs:us-east-2:account-id:resource
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource","resource_type":["None"],"qualifier":["None"]}
[OK] Input parsed as ARN.
input: arn:partition:sqs:us-east-2:account-id:resourcetype/resource
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource","resource_type":["Slash_delimited","resourcetype"],"qualifier":["None"]}
[OK] Input parsed as ARN.
input: arn:partition:sqs:us-east-2:account-id:resourcetype/resource/qualifier
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource","resource_type":["Slash_delimited","resourcetype"],"qualifier":["Slash_delimited","qualifier"]}
[OK] Input parsed as ARN.
input: arn:partition:sqs:us-east-2:account-id:resourcetype/resource:qualifier
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource","resource_type":["Slash_delimited","resourcetype"],"qualifier":["Colon_delimited","qualifier"]}
[OK] Input parsed as ARN.
input: arn:partition:sqs:us-east-2:account-id:resourcetype:resource
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource","resource_type":["Colon_delimited","resourcetype"],"qualifier":["None"]}
[OK] Input parsed as ARN.
input: arn:partition:sqs::account-id:resourcetype:resource
arn: {"partition":"partition","service":"sqs","region":null,"account_id":"account-id","resource":"resource","resource_type":["Colon_delimited","resourcetype"],"qualifier":["None"]}
[OK] Input parsed as ARN.
input: arn:partition:sqs:us-east-2::resourcetype:resource
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":null,"resource":"resource","resource_type":["Colon_delimited","resourcetype"],"qualifier":["None"]}
[OK] Input parsed as ARN.
input: arn:partition:sqs:us-east-2:account-id:resourcetype:resource:qualifier
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource","resource_type":["Colon_delimited","resourcetype"],"qualifier":["Colon_delimited","qualifier"]}
[OK] Correctly failed to parse input as an ARN.
input:
exception: (Failure "'' is not an amazon resource name.")
[OK] Correctly failed to parse input as an ARN.
input: x
exception: (Failure "'x' is not an amazon resource name.")
[FIXME] Input unexpected to parse as ARN but did.
input: arn:partition:sqs:us-east-2:account-id:resourcetype:resource/qualifier
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource/qualifier","resource_type":["Colon_delimited","resourcetype"],"qualifier":["None"]}
[FIXME] Input unexpected to parse as ARN but did.
input: arn:partition:sqs:us-east-2:account-id::resource:qualifier
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource","resource_type":["Colon_delimited",""],"qualifier":["Colon_delimited","qualifier"]}
[FIXME] Input unexpected to parse as ARN but did.
input: arn:partition:sqs:us-east-2:account-id::resource/qualifier
arn: {"partition":"partition","service":"sqs","region":"us-east-2","account_id":"account-id","resource":"resource/qualifier","resource_type":["Colon_delimited",""],"qualifier":["None"]}
|}];;letto_string{partition;service;region;account_id;resource;resource_type;qualifier}=letaccount_id=Option.value~default:""account_idinletregion=Option.value_map~default:""~f:Region.to_stringregioninmatchresource_type,qualifierwith(* arn:partition:service:region:account-id:resource *)|`None,`None->sprintf"arn:%s:%s:%s:%s:%s"partition(Service.to_stringservice)regionaccount_idresource(* arn:partition:service:region:account-id:resourcetype/resource *)|`Slash_delimitedresource_type,`None->sprintf"arn:%s:%s:%s:%s:%s/%s"partition(Service.to_stringservice)regionaccount_idresource_typeresource(* arn:partition:service:region:account-id:resourcetype/resource/qualifier *)|`Slash_delimitedresource_type,`Slash_delimitedqualifier->sprintf"arn:%s:%s:%s:%s:%s/%s/%s"partition(Service.to_stringservice)regionaccount_idresource_typeresourcequalifier(* arn:partition:service:region:account-id:resourcetype/resource:qualifier *)|`Slash_delimitedresource_type,`Colon_delimitedqualifier->sprintf"arn:%s:%s:%s:%s:%s/%s:%s"partition(Service.to_stringservice)regionaccount_idresource_typeresourcequalifier(* arn:partition:service:region:account-id:resourcetype:resource *)|`Colon_delimitedresource_type,`None->sprintf"arn:%s:%s:%s:%s:%s:%s"partition(Service.to_stringservice)regionaccount_idresource_typeresource(* arn:partition:service:region:account-id:resourcetype:resource:qualifier *)|`Colon_delimitedresource_type,`Colon_delimitedqualifier->sprintf"arn:%s:%s:%s:%s:%s:%s:%s"partition(Service.to_stringservice)regionaccount_idresource_typeresourcequalifier|`Colon_delimited_,`Slash_delimited_|`None,`Colon_delimited_|`None,`Slash_delimited_->failwith"cannot build such arn";;lets3?(partition=Default.partition)~bucket~key()=(* FIXME: Doing minimal validation at present. See #98 for information on what
we really need to do. *)ifString.equalbucket""then`Invalid_bucketbucketelseifString.equalkey""then`Invalid_keykeyelse`Ok{partition;service=Service.s3;region=None;account_id=None;resource=key;resource_type=`Slash_delimitedbucket;qualifier=`None};;lets3_exn?partition~bucket~key():t=matchs3?partition~bucket~key()with|`Okx->x|`Invalid_bucketb->failwithf"Invalid_bucket %s"b()|`Invalid_keyk->failwithf"Invalid_key %s"k();;moduleExn=structletmake=make_exnlets3=s3_exnend