UNPKG

@randomorg/core

Version:

The official library to access the RANDOM.ORG JSON-RPC API

2 lines 239 kB
var RandomOrgCore=function(e){"use strict";function t(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var s={};s.RandomOrgBadHTTPResponseError=class extends Error{constructor(e){super(e)}},s.RandomOrgInsufficientBitsError=class extends Error{#e=-1;constructor(e,t){super(e),this.#e=t}getBitsLeft(){return this.#e}},s.RandomOrgInsufficientRequestsError=class extends Error{constructor(e){super(e)}},s.RandomOrgJSONRPCError=class extends Error{constructor(e){super(e)}},s.RandomOrgKeyNotRunningError=class extends Error{constructor(e){super(e)}},s.RandomOrgRANDOMORGError=class extends Error{#t=-1;constructor(e,t=-1){super(e),this.#t=t}getCode(){return this.#t}},s.RandomOrgSendTimeoutError=class extends Error{constructor(e){super(e)}},s.RandomOrgCacheEmptyError=class extends Error{#s=!1;constructor(e,t=!1){super(e),this.#s=t}wasPaused(){return this.#s}};const{RandomOrgInsufficientBitsError:r,RandomOrgCacheEmptyError:a}=s;var i=class{#r=null;#a=null;#i=0;#n=0;#u=-1;#c=[];#o=10;#s=!1;#l=0;#h=0;#d=!1;#E=null;constructor(e,t,s,r,a,i){this.#r=e,this.#a=t,this.#o=s,this.#i=r,this.#n=a,this.#u=i,this.#g()}#g=async()=>{if(!this.#d&&!this.#s){this.#d=!0;let e=null;for(;null==this.#E;)if(this.#i>0){if(!(this.#c.length<=this.#o-this.#i))break;try{e=await this.#r(this.#a),this.#R(e,!0)}catch(t){if(t instanceof r){let s=t.getBitsLeft();if(s>this.#u){let t=Math.floor(s/this.#u);this.#a.params.n=t*this.#n,e=await this.#r(this.#a),this.#R(e,!0),this.#a.params.n=this.#i*this.#n}else this.#E=t}else this.#E=t}}else{if(!(this.#c.length<this.#o))break;try{e=await this.#r(this.#a),this.#R(e,!1)}catch(e){this.#E=e}}this.#d=!1}};stop(){this.#s=!0}resume(){this.#s=!1,this.#m()}isPaused(){return this.#s}get(){if(null!=this.#E)throw this.#E;if(this.#c&&0==this.#c.length)throw this.#s?new a("The RandomOrgCache stack is empty and the cache is paused. Please call resume() to restart populating the cache.",!0):new a("The RandomOrgCache stack is empty, please wait for it to repopulate itself.");{let e=this.#c.pop();return this.#m(),e}}async getOrWait(){try{return this.get()}catch(e){if(e instanceof a){if(this.#s)throw e;return 0==await this.#g()&&await new Promise((e=>setTimeout(e,50))),this.getOrWait()}}}getCachedValues(){return this.#c.length}getBitsUsed(){return this.#l}getRequestsUsed(){return this.#h}#m=()=>{(this.#i>0&&this.#c.length<=this.#o-this.#i||this.#i<=0&&this.#c.length<this.#o)&&this.#g()};#R=(e,t)=>{if(this.#h++,this.#l+=e.result.bitsUsed,t){let t=e.result.random.data;for(let e=0;e<t.length;e+=this.#n)this.#c.push(t.slice(e,e+this.#n))}else this.#c.push(e.result.random.data)}},n=t(i);const{RandomOrgBadHTTPResponseError:u,RandomOrgInsufficientBitsError:c,RandomOrgInsufficientRequestsError:o,RandomOrgJSONRPCError:l,RandomOrgKeyNotRunningError:h,RandomOrgRANDOMORGError:d,RandomOrgSendTimeoutError:E}=s,g=i;var R=class e{static#T="generateIntegers";static#p="generateIntegerSequences";static#D="generateDecimalFractions";static#O="generateGaussians";static#_="generateStrings";static#f="generateUUIDs";static#S="generateBlobs";static#q="getUsage";static#I="generateSignedIntegers";static#y="generateSignedIntegerSequences";static#M="generateSignedDecimalFractions";static#b="generateSignedGaussians";static#A="generateSignedStrings";static#N="generateSignedUUIDs";static#U="generateSignedBlobs";static#x="getResult";static#L="createTickets";static#H="listTickets";static#k="revealTickets";static#C="getTicket";static#w="verifySignature";static BLOB_FORMAT_BASE64="base64";static BLOB_FORMAT_HEX="hex";static DEFAULT_REPLACEMENT=!0;static DEFAULT_BASE=10;static DEFAULT_USER_DATA=null;static DEFAULT_TICKET_ID=null;static DEFAULT_PREGENERATED_RANDOMIZATION=null;static DEFAULT_LICENSE_DATA=null;static UUID_SIZE=122;static DEFAULT_BLOCKING_TIMEOUT=864e5;static DEFAULT_HTTP_TIMEOUT=12e4;static MAX_URL_LENGTH=2046;static#G=1e3;static#B=36e5;#F=-1;#K=-1;#P=-1;#v="";#z="";#V=e.DEFAULT_BLOCKING_TIMEOUT;#j=e.DEFAULT_HTTP_TIMEOUT;#J=0;#Y=0;static#Z={};static#W=[100,101,200,201,202,203,204,300,301,302,303,304,305,306,307,400,401,402,403,404,405,420,421,422,423,424,425,426,500,32e3];constructor(t,s={}){if(e.#Z&&e.#Z[t])return e.#Z[t];this.#z=t,this.#V=s.blockingTimeout||864e5,this.#j=s.httpTimeout||12e4,e.#Z[t]=this}async generateIntegers(e,t,s,r={}){let a=this.#X(e,t,s,r);return this.#Q(this.#$(a))}async generateIntegerSequences(e,t,s,r,a={}){let i=this.#ee(e,t,s,r,a);return this.#Q(this.#$(i))}async generateDecimalFractions(e,t,s={}){let r=this.#te(e,t,s);return this.#Q(this.#$(r))}async generateGaussians(e,t,s,r,a={}){let i=this.#se(e,t,s,r,a);return this.#Q(this.#$(i))}async generateStrings(e,t,s,r={}){let a=this.#re(e,t,s,r);return this.#Q(this.#$(a))}async generateUUIDs(e,t={}){let s=this.#ae(e,t);return this.#Q(this.#$(s))}async generateBlobs(e,t,s={}){let r=this.#ie(e,t,s);return this.#Q(this.#$(r))}async generateSignedIntegers(e,t,s,r={}){let a=this.#X(e,t,s,r,!0);return this.#ne(this.#$(a))}async generateSignedIntegerSequences(e,t,s,r,a={}){let i=this.#ee(e,t,s,r,a,!0);return this.#ne(this.#$(i))}async generateSignedDecimalFractions(e,t,s={}){let r=this.#te(e,t,s,!0);return this.#ne(this.#$(r))}async generateSignedGaussians(e,t,s,r,a={}){let i=this.#se(e,t,s,r,a,!0);return this.#ne(this.#$(i))}async generateSignedStrings(e,t,s,r={}){let a=this.#re(e,t,s,r,!0);return this.#ne(this.#$(a))}async generateSignedUUIDs(e,t={}){let s=this.#ae(e,t,!0);return this.#ne(this.#$(s))}async generateSignedBlobs(e,t,s={}){let r=this.#ie(e,t,s,!0);return this.#ne(this.#$(r))}async verifySignature(t,s){let r={random:t,signature:s},a=this.#ue(e.#w,r);return this.#ce(this.#$(a))}async getBitsLeft(){let t=Date.now()>this.#Y+e.#B;return(this.#F<0||t)&&await this.#oe(),this.#F}async getRequestsLeft(){let t=Date.now()>this.#Y+e.#B;return(this.#K<0||t)&&await this.#oe(),this.#K}async getResult(t){let s={serialNumber:t},r=this.#le(e.#x,s);return this.#ne(this.#$(r))}async createTickets(t,s){let r={n:t,showResult:s},a=this.#le(e.#L,r);return this.#he(this.#$(a))}async revealTickets(t){let s={ticketId:t},r=this.#le(e.#k,s);return this.#he(this.#$(r))}async listTickets(t){let s={ticketType:t},r=this.#le(e.#H,s);return this.#he(this.#$(r))}async getTicket(t){let s={ticketId:t},r=this.#ue(e.#C,s);return this.#he(this.#$(r))}createUrl(t,s){let r="https://api.random.org/signatures/form?format=json";if(r+="&random="+this.#de(JSON.stringify(t)),r+="&signature="+this.#de(s),r.length>e.MAX_URL_LENGTH)throw new d("Error: URL exceeds maximum length("+e.MAX_URL_LENGTH+" characters).");return r}createHtml(e,t){let s="<form action='https://api.random.org/signatures/form' method='post'>\n";return s+=" "+this.#Ee("hidden","format","json")+"\n",s+=" "+this.#Ee("hidden","random",JSON.stringify(e))+"\n",s+=" "+this.#Ee("hidden","signature",t)+"\n",s+=" <input type='submit' value='Validate' />\n</form>",s}createIntegerCache(e,t,s,r={}){let a=r.cacheSize||20;a<2&&(a=2);let i=this.#X(e,t,s,r),n=Math.ceil(Math.log(s-t+1)/Math.log(2)*e),u=0;return"replacement"in r&&!0!==r.replacement||(u=a/2,i.params.n=e*u),new g(this.#$.bind(this),i,a,u,e,n)}createIntegerSequenceCache(e,t,s,r,a={}){let i=a.cacheSize||20;i<2&&(i=2);let n,u=Math.ceil(Math.log(this.#ge(r)-this.#Re(s),1)/Math.log(2)*e*this.#ge(t)),c=0;n=a.replacement&&Array.isArray(a.replacement)?a.replacement.every((e=>!0===e)):a.replacement||!0,n&&(c=i/2,Array.isArray(t)&&(t=this.#me(t,c)),Array.isArray(s)&&(s=this.#me(s,c)),Array.isArray(r)&&(r=this.#me(r,c)),a.replacement&&Array.isArray(a.replacement)&&(a.replacement=this.#me(a.replacement,c)),a.base&&Array.isArray(a.base)&&(a.base=this.#me(a.base,c)));let o=this.#ee(e,t,s,r,a);return n&&(o.params.n=c*e),new g(this.#$.bind(this),o,i,c,e,u)}createDecimalFractionCache(e,t,s={}){let r=s.cacheSize||20;r<2&&(r=2);let a=this.#te(e,t,s),i=0;"replacement"in s&&!0!==s.replacement||(i=r/2,a.params.n=e*i);let n=Math.ceil(Math.log(10)/Math.log(2)*t*e);return new g(this.#$.bind(this),a,r,i,e,n)}createGaussianCache(e,t,s,r,a={}){let i=a.cacheSize||20;i<2&&(i=2);let n=Math.ceil(Math.log(Math.pow(10,r))/Math.log(2)*e),u=i/2,c=this.#se(e*u,t,s,r);return new g(this.#$.bind(this),c,i,u,e,n)}createStringCache(e,t,s,r={}){let a=r.cacheSize||20;a<2&&(a=2);let i=this.#re(e,t,s,r),n=Math.ceil(Math.log(s.length)/Math.log(2)*t*e),u=0;return"replacement"in r&&!0!==r.replacement||(u=a/2,i.params.n=e*u),new g(this.#$.bind(this),i,a,u,e,n)}createUUIDCache(t,s={}){let r=s.cacheSize||10;r<2&&(r=2);let a=t*e.UUID_SIZE,i=r/2,n=this.#ae(t*i);return new g(this.#$.bind(this),n,r,i,t,a)}createBlobCache(e,t,s={}){let r=s.cacheSize||10;r<2&&(r=2);let a=e*t,i=r/2,n=this.#ie(e*i,t,s);return new g(this.#$.bind(this),n,r,i,e,a)}#$=async function(t){if(-1!=this.#P){if(Date.now()<this.#P)throw new o(this.#v);this.#P=-1,this.#v=null}let s=this.#J-(Date.now()-this.#Y);if(-1!=this.#V&&s>this.#V)throw new E("The server advisory delay of "+s+"millis is greater than the defined maximum allowed blocking time of "+this.#V+"millis.");s>0&&await new Promise((e=>setTimeout(e,s)));let r=this.#j;return new Promise((function(e){let s=new XMLHttpRequest;s.open("POST","https://api.random.org/json-rpc/4/invoke"),s.setRequestHeader("Content-Type","application/json"),s.ontimeout=function(){throw new E("The maximum allowed blocking time of "+r+"millis has been exceeded while waiting for the server to respond.")},s.onload=function(){if(!(this.status>=200&&this.status<300))throw new u("Error: "+s.status);e(s.responseText)},s.onerror=function(e){throw e instanceof Error?e:(console.info("** An error occurred during the transaction."),new Error(s.responseText))},s.timeout=r,s.send(JSON.stringify(t))})).then((s=>{if((s=JSON.parse(s)).error){let t=s.error.code,r=s.error.message,a=s.error.data;if(401==t)throw new h("Error "+t+": "+r);if(402==t){let e=(new Date).setUTCHours(0,0,0,0);throw this.#P=+e,this.#v="Error "+t+": "+r,this.#K=a[1],new o(this.#v)}throw 403==t?(this.#F=a[1],new c("Error"+t+": "+r,this.#F)):e.#W.includes(t)?new d("Error "+t+": "+r,t):new l("Error "+t+": "+r)}return[e.#w,e.#x,e.#L,e.#H,e.#C].includes(t.method)?this.#J=e.#G:(this.#K=s.result.requestsLeft,this.#F=s.result.bitsLeft,s.result.advisoryDelay?this.#J=s.result.advisoryDelay:this.#J=e.#G),this.#Y=Date.now(),s}))};#oe=async()=>{let t=this.#le(e.#q,{});return this.#he(this.#$(t))};#ue=(e,t)=>({jsonrpc:"2.0",method:e,params:t,id:this.#Te()});#le=(e,t)=>(t.apiKey=this.#z,this.#ue(e,t));#Q=async e=>e.then((e=>e.result.random.data));#ne=async e=>e.then((e=>({data:e.result.random.data,random:e.result.random,signature:e.result.signature})));#ce=async e=>e.then((e=>e.result.authenticity));#he=async e=>e.then((e=>e.result));#X=(t,s,r,{replacement:a=!0,base:i=10,pregeneratedRandomization:n=null,licenseData:u=null,userData:c=null,ticketId:o=null}={},l=!1)=>{let h={n:t,min:s,max:r,replacement:a,base:i};h=this.#pe(h,n,u,c,o,l);let d=l?e.#I:e.#T;return this.#le(d,h)};#ee=(t,s,r,a,{replacement:i=!0,base:n=10,pregeneratedRandomization:u=null,licenseData:c=null,userData:o=null,ticketId:l=null}={},h=!1)=>{let d={n:t,length:s,min:r,max:a,replacement:i,base:n};d=this.#pe(d,u,c,o,l,h);let E=h?e.#y:e.#p;return this.#le(E,d)};#te=(t,s,{replacement:r=!0,pregeneratedRandomization:a=null,licenseData:i=null,userData:n=null,ticketId:u=null}={},c=!1)=>{let o={n:t,decimalPlaces:s,replacement:r};o=this.#pe(o,a,i,n,u,c);let l=c?e.#M:e.#D;return this.#le(l,o)};#se=(t,s,r,a,{pregeneratedRandomization:i=null,licenseData:n=null,userData:u=null,ticketId:c=null}={},o=!1)=>{let l={n:t,mean:s,standardDeviation:r,significantDigits:a};l=this.#pe(l,i,n,u,c,o);let h=o?e.#b:e.#O;return this.#le(h,l)};#re=(t,s,r,{replacement:a=!0,pregeneratedRandomization:i=null,licenseData:n=null,userData:u=null,ticketId:c=null}={},o=!1)=>{let l={n:t,length:s,characters:r,replacement:a};l=this.#pe(l,i,n,u,c,o);let h=o?e.#A:e.#_;return this.#le(h,l)};#ae=(t,{pregeneratedRandomization:s=null,licenseData:r=null,userData:a=null,ticketId:i=null}={},n=!1)=>{let u={n:t};u=this.#pe(u,s,r,a,i,n);let c=n?e.#N:e.#f;return this.#le(c,u)};#ie=(t,s,{format:r=this.BASE64,pregeneratedRandomization:a=null,licenseData:i=null,userData:n=null,ticketId:u=null},c=!1)=>{let o={n:t,size:s,format:r};o=this.#pe(o,a,i,n,u,c);let l=c?e.#U:e.#S;return this.#le(l,o)};#pe=(e,t,s,r,a,i=!1)=>(e.pregeneratedRandomization=t,i&&(e.licenseData=s,e.userData=r,e.ticketId=a),e);#me=(e,t)=>Array.from({length:t},(()=>e)).flat();#ge=e=>Array.isArray(e)?e.reduce((function(e,t){return Math.max(e,t)})):e;#Re=e=>Array.isArray(e)?e.reduce((function(e,t){return Math.min(e,t)})):e;#de=e=>{if(!/^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/.test(e))try{window&&(e=btoa(e))}catch(t){t instanceof ReferenceError&&(e=Buffer.from(e).toString("base64"))}return e=(e=(e=e.replace(/=/g,"%3D")).replace(/\+/g,"%2B")).replace(/\//g,"%2F")};#Ee=(e,t,s)=>"<input type='"+e+"' name='"+t+"' value='"+s+"' />";#Te=()=>"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){var t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))},m=t(R);let T=s.RandomOrgRANDOMORGError,p=s.RandomOrgBadHTTPResponseError,D=s.RandomOrgInsufficientBitsError,O=s.RandomOrgInsufficientRequestsError,_=s.RandomOrgJSONRPCError,f=s.RandomOrgKeyNotRunningError,S=s.RandomOrgSendTimeoutError,q=s.RandomOrgCacheEmptyError;return e.RandomOrgBadHTTPResponseError=p,e.RandomOrgCache=n,e.RandomOrgCacheEmptyError=q,e.RandomOrgClient=m,e.RandomOrgInsufficientBitsError=D,e.RandomOrgInsufficientRequestsError=O,e.RandomOrgJSONRPCError=_,e.RandomOrgKeyNotRunningError=f,e.RandomOrgRANDOMORGError=T,e.RandomOrgSendTimeoutError=S,e.default=m,Object.defineProperty(e,"__esModule",{value:!0}),e}({}); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmRvY29yZS5paWZlLm1pbi5qcyIsInNvdXJjZXMiOlsiLi4vUmFuZG9tT3JnRXJyb3JzLmpzIiwiLi4vUmFuZG9tT3JnQ2FjaGUuanMiLCIuLi9SYW5kb21PcmdDbGllbnQuanMiLCIuLi9lc20vaW5kZXguanMiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xyXG5cclxuLyoqXHJcbiAqIEVycm9yIHRocm93biBieSB0aGUgUmFuZG9tT3JnQ2xpZW50IGNsYXNzIHdoZW4gdGhlIGNvbm5lY3Rpb24gZG9lc24ndCByZXR1cm5cclxuICogYSBIVFRQIDIwMCBPSyByZXNwb25zZS5cclxuICovXHJcbmV4cG9ydHMuUmFuZG9tT3JnQmFkSFRUUFJlc3BvbnNlRXJyb3IgPSBjbGFzcyBSYW5kb21PcmdCYWRIVFRQUmVzcG9uc2VFcnJvciBleHRlbmRzIEVycm9yXHJcbntcclxuICAgIC8qKlxyXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBleGNlcHRpb24gd2l0aCB0aGUgc3BlY2lmaWVkIGRldGFpbCBtZXNzYWdlLlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgVGhlIGRldGFpbCBtZXNzYWdlLlxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlKSB7XHJcbiAgICAgICAgc3VwZXIobWVzc2FnZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFcnJvciB0aHJvd24gYnkgdGhlIFJhbmRvbU9yZ0NsaWVudCBjbGFzcyB3aGVuIGl0cyBBUEkga2V5J3MgcmVxdWVzdCBoYXNcclxuICogZXhjZWVkZWQgaXRzIHJlbWFpbmluZyBzZXJ2ZXIgYml0cyBhbGxvd2FuY2UuXHJcbiAqIFxyXG4gKiBJZiB0aGUgY2xpZW50IGlzIGN1cnJlbnRseSBpc3N1aW5nIGxhcmdlIHJlcXVlc3RzIGl0IG1heSBiZSBwb3NzaWJsZSBzdWNjZWVkXHJcbiAqIHdpdGggc21hbGxlciByZXF1ZXN0cy4gVXNlIHRoZSBnZXRCaXRzTGVmdCgpIGNhbGwgaW4gdGhpcyBjbGFzcyB0byBoZWxwXHJcbiAqIGRldGVybWluZSBpZiBhbiBhbHRlcm5hdGl2ZSByZXF1ZXN0IHNpemUgaXMgYXBwcm9wcmlhdGUuXHJcbiAqL1xyXG4gZXhwb3J0cy5SYW5kb21PcmdJbnN1ZmZpY2llbnRCaXRzRXJyb3IgPSBjbGFzcyBSYW5kb21PcmdJbnN1ZmZpY2llbnRCaXRzRXJyb3IgZXh0ZW5kcyBFcnJvclxyXG57XHJcbiAgICAvLyBTdG9yZXMgdGhlIG51bWJlciBvZiBiaXRzIHJlbWFpbmluZ1xyXG4gICAgI2JpdHMgPSAtMTtcclxuICAgIFxyXG4gICAgLyoqXHJcbiAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IGV4Y2VwdGlvbiB3aXRoIHRoZSBzcGVjaWZpZWQgZGV0YWlsIG1lc3NhZ2UuXHJcbiAgICAgKiBAY29uc3RydWN0b3JcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIFRoZSBkZXRhaWwgbWVzc2FnZS5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiaXRzIEJpdHMgcmVtYWluaW5nIGp1c3QgYmVmb3JlIHRoZSBlcnJvciB3YXMgdGhyb3duLlxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlLCBiaXRzKSB7XHJcbiAgICAgICAgc3VwZXIobWVzc2FnZSk7XHJcbiAgICAgICAgdGhpcy4jYml0cyA9IGJpdHM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBudW1iZXIgb2YgYml0cyByZW1haW5pbmcuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIGJpdHMgbGVmdC5cclxuICAgICAqL1xyXG4gICAgZ2V0Qml0c0xlZnQoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuI2JpdHM7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFcnJvciB0aHJvd24gYnkgdGhlIFJhbmRvbU9yZ0NsaWVudCBjbGFzcyB3aGVuIGl0cyBBUEkga2V5J3Mgc2VydmVyIHJlcXVlc3RzXHJcbiAqIGFsbG93YW5jZSBoYXMgYmVlbiBleGNlZWRlZC5cclxuICogXHJcbiAqIFRoaXMgaW5kaWNhdGVzIHRoYXQgYSBiYWNrLW9mZiB1bnRpbCBtaWRuaWdodCBVVEMgaXMgaW4gZWZmZWN0LCBiZWZvcmUgd2hpY2hcclxuICogbm8gcmVxdWVzdHMgd2lsbCBiZSBzZW50IGJ5IHRoZSBjbGllbnQgYXMgbm8gbWVhbmluZ2Z1bCBzZXJ2ZXIgcmVzcG9uc2VzIHdpbGxcclxuICogYmUgcmV0dXJuZWQuXHJcbiAqL1xyXG5leHBvcnRzLlJhbmRvbU9yZ0luc3VmZmljaWVudFJlcXVlc3RzRXJyb3IgPSBjbGFzcyBSYW5kb21PcmdJbnN1ZmZpY2llbnRSZXF1ZXN0c0Vycm9yIGV4dGVuZHMgRXJyb3Jcclxue1xyXG4gICAgLyoqXHJcbiAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IGV4Y2VwdGlvbiB3aXRoIHRoZSBzcGVjaWZpZWQgZGV0YWlsIG1lc3NhZ2UuXHJcbiAgICAgKiBAY29uc3RydWN0b3JcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIFRoZSBkZXRhaWwgbWVzc2FnZS5cclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobWVzc2FnZSkge1xyXG4gICAgICAgIHN1cGVyKG1lc3NhZ2UpO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogRXJyb3IgdGhyb3duIGJ5IHRoZSBSYW5kb21PcmdDbGllbnQgY2xhc3Mgd2hlbiB0aGUgc2VydmVyIHJldHVybnMgYSBKU09OLVJQQ1xyXG4gKiBFcnJvci4gU2VlIGh0dHBzOi8vYXBpLnJhbmRvbS5vcmcvanNvbi1ycGMvNC9lcnJvci1jb2Rlc1xyXG4gKi9cclxuZXhwb3J0cy5SYW5kb21PcmdKU09OUlBDRXJyb3IgPSBjbGFzcyBSYW5kb21PcmdKU09OUlBDRXJyb3IgZXh0ZW5kcyBFcnJvclxyXG57XHJcbiAgICAvKipcclxuICAgICAqIENvbnN0cnVjdHMgYSBuZXcgZXhjZXB0aW9uIHdpdGggdGhlIHNwZWNpZmllZCBkZXRhaWwgbWVzc2FnZS5cclxuICAgICAqIEBjb25zdHJ1Y3RvclxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgVGhlIGRldGFpbCBtZXNzYWdlLlxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlKSB7XHJcbiAgICAgICAgc3VwZXIobWVzc2FnZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFcnJvciB0aHJvd24gYnkgdGhlIFJhbmRvbU9yZ0NsaWVudCBjbGFzcyB3aGVuIGl0cyBBUEkga2V5IGhhcyBiZWVuIHN0b3BwZWQuXHJcbiAqIFJlcXVlc3RzIHdpbGwgbm90IGNvbXBsZXRlIHdoaWxlIEFQSSBrZXkgaXMgaW4gdGhlIHN0b3BwZWQgc3RhdGUuXHJcbiAqL1xyXG5leHBvcnRzLlJhbmRvbU9yZ0tleU5vdFJ1bm5pbmdFcnJvciA9IGNsYXNzIFJhbmRvbU9yZ0tleU5vdFJ1bm5pbmdFcnJvciBleHRlbmRzIEVycm9yXHJcbntcclxuICAgIC8qKlxyXG4gICAgICogRXJyb3IgdGhyb3duIGJ5IHRoZSBSYW5kb21PcmdDbGllbnQgY2xhc3Mgd2hlbiBpdHMgQVBJIGtleSBoYXMgYmVlbiBzdG9wcGVkLlxyXG4gICAgICogUmVxdWVzdHMgd2lsbCBub3QgY29tcGxldGUgd2hpbGUgQVBJIGtleSBpcyBpbiB0aGUgc3RvcHBlZCBzdGF0ZS5cclxuICAgICAqIEBjb25zdHJ1Y3RvclxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgVGhlIGRldGFpbCBtZXNzYWdlLlxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlKSB7XHJcbiAgICAgICAgc3VwZXIobWVzc2FnZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFcnJvciB0aHJvd24gYnkgdGhlIFJhbmRvbU9yZ0NsaWVudCBjbGFzcyB3aGVuIHRoZSBzZXJ2ZXIgcmV0dXJucyBhXHJcbiAqIFJBTkRPTS5PUkcgRXJyb3IuIFNlZSBodHRwczovL2FwaS5yYW5kb20ub3JnL2pzb24tcnBjLzQvZXJyb3ItY29kZXNcclxuICovXHJcbmV4cG9ydHMuUmFuZG9tT3JnUkFORE9NT1JHRXJyb3IgPSBjbGFzcyBSYW5kb21PcmdSQU5ET01PUkdFcnJvciBleHRlbmRzIEVycm9yXHJcbntcclxuICAgIC8vIFN0b3JlcyB0aGUgY29kZSBvZiB0aGUgUkFORE9NLk9SRyBlcnJvclxyXG4gICAgI2NvZGUgPSAtMTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEVycm9yIHRocm93biBieSB0aGUgUmFuZG9tT3JnQ2xpZW50IGNsYXNzIHdoZW4gdGhlIHNlcnZlciByZXR1cm5zIGFcclxuICAgICAqIFJBTkRPTS5PUkcgRXJyb3IuIFNlZSBodHRwczovL2FwaS5yYW5kb20ub3JnL2pzb24tcnBjLzQvZXJyb3ItY29kZXNcclxuICAgICAqIEBjb25zdHJ1Y3RvclxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgVGhlIGRldGFpbCBtZXNzYWdlLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBbY29kZT0tMV0gVGhlIGVycm9yIGNvZGUuXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIGNvZGUgPSAtMSkge1xyXG4gICAgICAgIHN1cGVyKG1lc3NhZ2UpOyAgICBcclxuICAgICAgICB0aGlzLiNjb2RlID0gY29kZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgdGhlIFJBTkRPTS5PUkcgZXJyb3IgY29kZSwgc2VlXHJcbiAgICAgKiBodHRwczovL2FwaS5yYW5kb20ub3JnL2pzb24tcnBjLzQvZXJyb3ItY29kZXNcclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFRoZSBlcnJvciBjb2RlLlxyXG4gICAgICovXHJcbiAgICBnZXRDb2RlKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLiNjb2RlO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogRXJyb3IgdGhyb3duIGJ5IHRoZSBSYW5kb21PcmdDbGllbnQgY2xhc3Mgd2hlbiBpdHMgc2V0IGJsb2NraW5nIHRpbWVvdXQgaXNcclxuICogZXhjZWVkZWQgYmVmb3JlIHRoZSByZXF1ZXN0IGNhbiBiZSBzZW50LlxyXG4gKi9cclxuZXhwb3J0cy5SYW5kb21PcmdTZW5kVGltZW91dEVycm9yID0gY2xhc3MgUmFuZG9tT3JnU2VuZFRpbWVvdXRFcnJvciBleHRlbmRzIEVycm9yXHJcbntcclxuICAgIC8qKlxyXG4gICAgICogRXJyb3IgdGhyb3duIGJ5IHRoZSBSYW5kb21PcmdDbGllbnQgY2xhc3Mgd2hlbiBpdHMgc2V0IGJsb2NraW5nIHRpbWVvdXQgaXNcclxuICAgICAqIGV4Y2VlZGVkIGJlZm9yZSB0aGUgcmVxdWVzdCBjYW4gYmUgc2VudC5cclxuICAgICAqIEBjb25zdHJ1Y3RvclxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgVGhlIGRldGFpbCBtZXNzYWdlLlxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlKSB7XHJcbiAgICAgICAgc3VwZXIobWVzc2FnZSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFcnJvciB0aHJvd24gd2hlbiBkYXRhIHJldHJpZXZhbCBmcm9tIGFuIGVtdHB5IFJhbmRvbU9yZ0NhY2hlIGlzIGF0dGVtcHRlZC5cclxuICovXHJcbmV4cG9ydHMuUmFuZG9tT3JnQ2FjaGVFbXB0eUVycm9yID0gY2xhc3MgUmFuZG9tT3JnQ2FjaGVFbXB0eUVycm9yIGV4dGVuZHMgRXJyb3Jcclxue1xyXG4gICAgI3BhdXNlZCA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRXJyb3IgdGhyb3duIHdoZW4gZGF0YSByZXRyaWV2YWwgZnJvbSBhbiBlbXRweSBSYW5kb21PcmdDYWNoZSBpcyBhdHRlbXB0ZWQuXHJcbiAgICAgKiBAY29uc3RydWN0b3JcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIFRoZSBkZXRhaWwgbWVzc2FnZS5cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcGF1c2VkIFJlZmxlY3RzIHdoZXRoZXIgdGhlIFJhbmRvbU9yZ0NhY2hlIGluc3RhbmNlIHdhc1xyXG4gICAgICogICAgIHBhdXNlZCB3aGVuIHRoaXMgZXJyb3Igd2FzIHRocm93bi5cclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobWVzc2FnZSwgcGF1c2VkID0gZmFsc2UpIHtcclxuICAgICAgICBzdXBlcihtZXNzYWdlKTtcclxuICAgICAgICB0aGlzLiNwYXVzZWQgPSBwYXVzZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIGNhY2hlIHdhcyBwYXVzZWQgYXQgdGhlIHRpbWUgd2hlbiB0aGVcclxuICAgICAqIGVycm9yIHdhcyB0aHJvd24uXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gVHJ1ZSBpZiBwYXVzZWQsIGZhbHNlIG90aGVyd2lzZS5cclxuICAgICAqL1xyXG4gICAgd2FzUGF1c2VkKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLiNwYXVzZWQ7XHJcbiAgICB9XHJcbn0iLCIndXNlIHN0cmljdCc7XHJcbmNvbnN0IHtcclxuICAgIFJhbmRvbU9yZ0luc3VmZmljaWVudEJpdHNFcnJvcixcclxuICAgIFJhbmRvbU9yZ0NhY2hlRW1wdHlFcnJvclxyXG59ID0gcmVxdWlyZSgnLi9SYW5kb21PcmdFcnJvcnMuanMnKTtcclxuLyoqXHJcbiAqIFByZWNhY2hlIGNsYXNzIGZvciBmcmVxdWVudGx5IHVzZWQgcmVxdWVzdHMuXHJcbiAqL1xyXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzIFJhbmRvbU9yZ0NhY2hlIHtcclxuICAgIC8vIGZ1bmN0aW9uIHVzZWQgdG8gc2VuZCBhIHJlcXVlc3RcclxuICAgICNyZXF1ZXN0RnVuY3Rpb24gPSBudWxsO1xyXG5cclxuICAgIC8vIHJlcXVlc3QgdG8gYmUgc2VudFxyXG4gICAgI3JlcXVlc3QgPSBudWxsO1xyXG5cclxuICAgIC8vIG4gZm9yIGJ1bGsgcmVxdWVzdHNcclxuICAgICNidWxrUmVxdWVzdE51bWJlciA9IDA7XHJcbiAgICAvLyBuIGZvciBhIHNpbmdsZSByZXF1ZXN0XHJcbiAgICAjcmVxdWVzdE51bWJlciA9IDA7XHJcbiAgICAvLyBzaXplIG9mIGEgc2luZ2xlIHJlcXVlc3QgaW4gYml0c1xyXG4gICAgI3JlcXVlc3RTaXplID0gLTE7XHJcblxyXG4gICAgLy8gc3RvcmVzIGNhY2hlZCBhcnJheXMgb2YgdmFsdWVzXHJcbiAgICAjc3RhY2sgPSBbXTtcclxuICAgIC8vIG51bWJlciBvZiBhcnJheXMgdG8gdHJ5IHRvIG1haW50YWluIGluICNzdGFja1xyXG4gICAgI2NhY2hlU2l6ZSA9IDEwO1xyXG5cclxuICAgIC8vIHN0YXR1cyBvZiB0aGUgY2FjaGVcclxuICAgICNwYXVzZWQgPSBmYWxzZTtcclxuICAgIC8vIGJpdHMgdXNlZCBieSB0aGlzIGNhY2hlXHJcbiAgICAjYml0c1VzZWQgPSAwO1xyXG4gICAgLy8gcmVxdWVzdHMgdXNlZCBieSB0aGlzIGNhY2hlXHJcbiAgICAjcmVxdWVzdHNVc2VkID0gMDtcclxuICAgIC8vIGVuc3VyZXMgI3BvcHVsYXRlKCkgZG9lcyBub3QgaXNzdWUgcGFyYWxsZWwgcmVxdWVzdHNcclxuICAgICNjdXJyZW50bHlQb3B1bGF0aW5nID0gZmFsc2U7XHJcblxyXG4gICAgLy8gYW4gZXJyb3Igd2hpY2ggd2lsbCBiZSB0aHJvd24gb24gdGhlIG5leHQgY2FsbCB0byBnZXQoKSBvciBnZXRPcldhaXQoKVxyXG4gICAgI2Vycm9yID0gbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEluaXRpYWxpemUgY2xhc3MgYW5kIHN0YXJ0IHN0YWNrIHBvcHVsYXRpb25cclxuICAgICAqIFxyXG4gICAgICogKiogV0FSTklORyoqIFNob3VsZCBvbmx5IGJlIGNhbGxlZCBieSBSYW5kb21PcmdDbGllbnQncyBjcmVhdGVDYWNoZSgpXHJcbiAgICAgKiBtZXRob2RzLlxyXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbihPYmplY3QpIDogT2JqZWN0fSByZXF1ZXN0RnVuY3Rpb24gRnVuY3Rpb24gdXNlZCB0byBzZW5kXHJcbiAgICAgKiAgICAgc3VwcGxpZWQgcmVxdWVzdCB0byBzZXJ2ZXIuXHJcbiAgICAgKiBAcGFyYW0ge09iamVjdH0gcmVxdWVzdCBSZXF1ZXN0IHRvIHNlbmQgdG8gc2VydmVyIHZpYSByZXF1ZXN0RnVuY3Rpb24uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY2FjaGVTaXplIE51bWJlciBvZiByZXF1ZXN0IHJlc3BvbnNlcyB0byB0cnkgbWFpbnRhaW4uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gYnVsa1JlcXVlc3ROdW1iZXIgSWYgcmVxdWVzdCBpcyBzZXQgdG8gYmUgaXNzdWVkIGluIGJ1bGssXHJcbiAgICAgKiAgICAgbnVtYmVyIG9mIHJlc3VsdCBzZXRzIGluIGEgYnVsayByZXF1ZXN0LCBlbHNlIDAuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gcmVxdWVzdE51bWJlciBJZiByZXF1ZXN0IGlzIHNldCB0byBiZSBpc3N1ZWQgaW4gYnVsayxcclxuICAgICAqICAgICBudW1iZXIgb2YgcmVzdWx0cyBpbiBhIHNpbmdsZSByZXF1ZXN0LCBlbHNlIDAuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gc2luZ2xlUmVxdWVzdFNpemUgU2l6ZSBvZiBhIHNpbmdsZSByZXF1ZXN0IGluIGJpdHMgZm9yXHJcbiAgICAgKiAgICAgYWRqdXN0aW5nIGJ1bGsgcmVxdWVzdHMgaWYgYml0cyBhcmUgaW4gc2hvcnQgc3VwcGx5IG9uIHRoZSBzZXJ2ZXIuXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKHJlcXVlc3RGdW5jdGlvbiwgcmVxdWVzdCwgY2FjaGVTaXplLCBidWxrUmVxdWVzdE51bWJlciwgcmVxdWVzdE51bWJlciwgc2luZ2xlUmVxdWVzdFNpemUpIHtcclxuICAgICAgICB0aGlzLiNyZXF1ZXN0RnVuY3Rpb24gPSByZXF1ZXN0RnVuY3Rpb247XHJcblxyXG4gICAgICAgIHRoaXMuI3JlcXVlc3QgPSByZXF1ZXN0O1xyXG4gICAgICAgIFxyXG4gICAgICAgIHRoaXMuI2NhY2hlU2l6ZSA9IGNhY2hlU2l6ZTtcclxuXHJcbiAgICAgICAgdGhpcy4jYnVsa1JlcXVlc3ROdW1iZXIgPSBidWxrUmVxdWVzdE51bWJlcjtcclxuICAgICAgICB0aGlzLiNyZXF1ZXN0TnVtYmVyID0gcmVxdWVzdE51bWJlcjtcclxuICAgICAgICB0aGlzLiNyZXF1ZXN0U2l6ZSA9IHNpbmdsZVJlcXVlc3RTaXplO1xyXG5cclxuICAgICAgICB0aGlzLiNwb3B1bGF0ZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuY3Rpb24gdG8gY29udGludWUgaXNzdWluZyByZXF1ZXN0cyB1bnRpbCB0aGUgc3RhY2sgaXMgZnVsbC5cclxuICAgICAqIFxyXG4gICAgICogS2VlcCBpc3N1aW5nIHJlcXVlc3RzIHRvIHNlcnZlciB1bnRpbCBzdGFjayBpcyBmdWxsLiBXaGVuIHN0YWNrIGlzIGZ1bGxcclxuICAgICAqIGlmIHJlcXVlc3RzIGFyZSBiZWluZyBpc3N1ZWQgaW4gYnVsaywgd2FpdCB1bnRpbCBzdGFjayBoYXMgZW5vdWdoIHNwYWNlXHJcbiAgICAgKiB0byBhY2NvbW1vZGF0ZSBhbGwgb2YgYSBidWxrIHJlcXVlc3QgYmVmb3JlIGlzc3VpbmcgYSBuZXcgcmVxdWVzdCwgb3RoZXJ3aXNlXHJcbiAgICAgKiBpc3N1ZSBhIG5ldyByZXF1ZXN0IGV2ZXJ5IHRpbWUgYW4gaXRlbSBpbiB0aGUgc3RhY2sgaGFzIGJlZW4gY29uc3VtZWQuIE5vdGVcclxuICAgICAqIHRoYXQgcmVxdWVzdHMgYXJlIGJsb2NraW5nICgnYXdhaXQnIGlzIHVzZWQgd2hlbiBjYWxsaW5nIHRoZSByZXF1ZXN0RnVuY3Rpb24pLFxyXG4gICAgICogaS5lLiwgb25seSBvbmUgcmVxdWVzdCB3aWxsIGJlIGlzc3VlZCBieSB0aGUgY2FjaGUgYXQgYW55IGdpdmVuIHRpbWUuXHJcbiAgICAgKi9cclxuICAgICNwb3B1bGF0ZSA9IGFzeW5jICgpID0+IHtcclxuICAgICAgICBpZiAoIXRoaXMuI2N1cnJlbnRseVBvcHVsYXRpbmcgJiYgIXRoaXMuI3BhdXNlZCkge1xyXG4gICAgICAgICAgICB0aGlzLiNjdXJyZW50bHlQb3B1bGF0aW5nID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIGxldCByZXNwb25zZSA9IG51bGw7XHJcblxyXG4gICAgICAgICAgICB3aGlsZSAodHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuI2Vycm9yICE9IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLiNidWxrUmVxdWVzdE51bWJlciA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBJcyB0aGVyZSBzcGFjZSBmb3IgYSBidWxrIHJlc3BvbnNlIGluIHRoZSBzdGFjaz9cclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy4jc3RhY2subGVuZ3RoIDw9ICh0aGlzLiNjYWNoZVNpemUgLSB0aGlzLiNidWxrUmVxdWVzdE51bWJlcikpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gYXdhaXQgdGhpcy4jcmVxdWVzdEZ1bmN0aW9uKHRoaXMuI3JlcXVlc3QpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jYWRkUmVzcG9uc2UocmVzcG9uc2UsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub3QgZW5vdWdoIGJpdHMgcmVtYWluaW5nIGZvciBhIGJ1bGsgcmVxdWVzdFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGUgaW5zdGFuY2VvZiBSYW5kb21PcmdJbnN1ZmZpY2llbnRCaXRzRXJyb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYml0c0xlZnQgPSBlLmdldEJpdHNMZWZ0KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJpdHNMZWZ0ID4gdGhpcy4jcmVxdWVzdFNpemUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgcG9zc2libGUsIGFkanVzdCByZXF1ZXN0IGZvciB0aGUgbGFyZ2VzdCBwb3NzaWJsZSBzaXplXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhZGp1c3RlZEJ1bGsgPSBNYXRoLmZsb29yKGJpdHNMZWZ0L3RoaXMuI3JlcXVlc3RTaXplKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jcmVxdWVzdC5wYXJhbXMubiA9IGFkanVzdGVkQnVsayAqIHRoaXMuI3JlcXVlc3ROdW1iZXI7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IGF3YWl0IHRoaXMuI3JlcXVlc3RGdW5jdGlvbih0aGlzLiNyZXF1ZXN0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jYWRkUmVzcG9uc2UocmVzcG9uc2UsIHRydWUpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gcmVzZXQgdG8gb3JpZ2luYWwgYnVsayByZXF1ZXN0IHNpemVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy4jcmVxdWVzdC5wYXJhbXMubiA9IHRoaXMuI2J1bGtSZXF1ZXN0TnVtYmVyICogdGhpcy4jcmVxdWVzdE51bWJlcjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZXF1ZXN0IHNpemUgY2Fubm90IGJlIGFkanVzdGVkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI2Vycm9yID0gZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQW55IG90aGVyIGVycm9yIHRocm93biBkdXJpbmcgaW4gdGhlIHJlcXVlc3QgZnVuY3Rpb25cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLiNlcnJvciA9IGU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBubyBzcGFjZSBmb3IgYSBidWxrIHJlcXVlc3RcclxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLiNzdGFjay5sZW5ndGggPCB0aGlzLiNjYWNoZVNpemUpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBpbmRpdmlkdWFsIHJlcXVlc3RzXHJcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLiNyZXF1ZXN0RnVuY3Rpb24odGhpcy4jcmVxdWVzdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI2FkZFJlc3BvbnNlKHJlc3BvbnNlLCBmYWxzZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuI2Vycm9yID0gZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIHRoZSBzdGFjayBpcyBmdWxsXHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gICAgICAgICAgICAgICBcclxuXHJcbiAgICAgICAgICAgIHRoaXMuI2N1cnJlbnRseVBvcHVsYXRpbmcgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgY2FjaGUgd2lsbCBubyBsb25nZXIgY29udGludWUgdG8gcG9wdWxhdGUgaXRzZWxmLlxyXG4gICAgICovXHJcbiAgICBzdG9wKCkge1xyXG4gICAgICAgIHRoaXMuI3BhdXNlZCA9IHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgY2FjaGUgd2lsbCByZXN1bWUgcG9wdWxhdGluZyBpdHNlbGYgaWYgc3RvcHBlZC5cclxuICAgICAqL1xyXG4gICAgcmVzdW1lKCkge1xyXG4gICAgICAgIHRoaXMuI3BhdXNlZCA9IGZhbHNlO1xyXG5cclxuICAgICAgICAvLyBjaGVjayBpZiBpdCBuZWVkcyB0byBiZSByZXBvcHVsYXRlZFxyXG4gICAgICAgIHRoaXMuI3JlZnJlc2goKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoZWNrcyBpZiB0aGUgY2FjaGUgaXMgY3VycmVudGx5IG5vdCByZS1wb3B1bGF0aW5nIGl0c2VsZi5cclxuICAgICAqIFxyXG4gICAgICogVmFsdWVzIGN1cnJlbnRseSBjYWNoZWQgbWF5IHN0aWxsIGJlIHJldHJpZXZlZCB3aXRoIGdldCgpIGJ1dCBubyBuZXdcclxuICAgICAqIHZhbHVlcyBhcmUgYmVpbmcgZmV0Y2hlZCBmcm9tIHRoZSBzZXJ2ZXIuIFRoaXMgc3RhdGUgY2FuIGJlIGNoYW5nZWQgd2l0aFxyXG4gICAgICogc3RvcCgpIGFuZCByZXN1bWUoKS5cclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBUcnVlIGlmIGNhY2hlIGlzIGN1cnJlbnRseSBub3QgcmUtcG9wdWxhdGluZyBpdHNlbGYsXHJcbiAgICAgKiAgICAgZmFsc2Ugb3RoZXJ3aXNlLlxyXG4gICAgICovXHJcbiAgICBpc1BhdXNlZCgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy4jcGF1c2VkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgbmV4dCByZXNwb25zZS5cclxuICAgICAqIE5vdGUgdGhhdCBpZiB0aGUgY2FjaGUgaXMgZW1wdHksIGlmIHdhcyBjb25zdHJ1Y3RlZCB3aXRoIHVuc3VpdGFibGUgcGFyYW1ldGVyXHJcbiAgICAgKiB2YWx1ZXMgb3IgaWYgdGhlIGRhaWx5IGFsbG93YW5jZSBvZiBiaXRzL3JlcXVlc3RzIGhhcyBiZWVuIHJlYWNoZWQsIHRoZSBhcHByb3ByaWF0ZVxyXG4gICAgICogZXJyb3Igd2lsbCBiZSB0aHJvd24uXHJcbiAgICAgKiBAcmV0dXJucyB7YW55W119IFRoZSBuZXh0IGFwcHJvcHJpYXRlIHJlc3BvbnNlIGZvciB0aGUgcmVxdWVzdCB0aGlzIFJhbmRvbU9yZ0NhY2hlXHJcbiAgICAgKiAgICAgcmVwcmVzZW50cyBvciwgaWYgc3RhY2sgaXMgZW1wdHkgdGhyb3dzIGFuIGVycm9yLlxyXG4gICAgICogQHRocm93cyBSYW5kb21PcmdDYWNoZUVtcHR5RXJyb3IgaWYgdGhlIGNhY2hlIGlzIGVtcHR5LlxyXG4gICAgICovXHJcbiAgICBnZXQoKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuI2Vycm9yICE9IG51bGwpIHtcclxuICAgICAgICAgICAgdGhyb3cgdGhpcy4jZXJyb3I7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0aGlzLiNzdGFjayAmJiB0aGlzLiNzdGFjay5sZW5ndGggPT0gMCkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy4jcGF1c2VkKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmFuZG9tT3JnQ2FjaGVFbXB0eUVycm9yKCdUaGUgUmFuZG9tT3JnQ2FjaGUgc3RhY2sgJ1xyXG4gICAgICAgICAgICAgICAgICAgICsgJ2lzIGVtcHR5IGFuZCB0aGUgY2FjaGUgaXMgcGF1c2VkLiBQbGVhc2UgY2FsbCByZXN1bWUoKSB0byAnXHJcbiAgICAgICAgICAgICAgICAgICAgKyAncmVzdGFydCBwb3B1bGF0aW5nIHRoZSBjYWNoZS4nLCB0cnVlKTsgICAgICAgICAgICBcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBSYW5kb21PcmdDYWNoZUVtcHR5RXJyb3IoJ1RoZSBSYW5kb21PcmdDYWNoZSBzdGFjayAnXHJcbiAgICAgICAgICAgICAgICAgICAgKyAnaXMgZW1wdHksIHBsZWFzZSB3YWl0IGZvciBpdCB0byByZXBvcHVsYXRlIGl0c2VsZi4nKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGxldCBkYXRhID0gdGhpcy4jc3RhY2sucG9wKCk7XHJcblxyXG4gICAgICAgICAgICAvLyBjaGVjayBpZiBpdCBuZWVkcyB0byBiZSByZXBvcHVsYXRlZFxyXG4gICAgICAgICAgICB0aGlzLiNyZWZyZXNoKCk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXQgbmV4dCByZXNwb25zZSBvciB3YWl0IHVudGlsIHRoZSBuZXh0IHZhbHVlIGlzIGF2YWlsYWJsZS4gVGhpcyBtZXRob2RcclxuICAgICAqIHdpbGwgYmxvY2sgdW50aWwgYSB2YWx1ZSBpcyBhdmFpbGFibGUuIE5vdGU6IHRoaXMgbWV0aG9kIHdpbGwgdGhyb3cgYW4gZXJyb3JcclxuICAgICAqIGlmIHRoZSBjYWNoZSBpcyBlbXB0eSBhbmQgaGFzIGJlZW4gcGF1c2VkLCBpLmUuIGlzIG5vdCBiZWluZyBwb3B1bGF0ZWQuIElmXHJcbiAgICAgKiB0aGUgY2FjaGUgd2FzIGNvbnN0cnVjdGVkIHdpdGggdW5zdWl0YWJsZSBwYXJhbWV0ZXIgdmFsdWVzIG9yIHRoZSBkYWlseSBhbGxvd2FuY2VcclxuICAgICAqIG9mIGJpdHMvcmVxdWVzdHMgaGFzIGJlZW4gcmVhY2hlZCwgdGhlIGFwcHJvcHJpYXRlIGVycm9yIHdpbGwgYWxzbyBiZSB0aHJvd24uXHJcbiAgICAgKiBAcmV0dXJucyB7UHJvbWlzZTxhbnlbXT59IFRoZSBuZXh0IGFwcHJvcHJpYXRlIHJlc3BvbnNlIGZvciB0aGUgcmVxdWVzdCB0aGlzXHJcbiAgICAgKiBSYW5kb21PcmdDYWNoZSByZXByZXNlbnRzLlxyXG4gICAgICogQHRocm93cyBSYW5kb21PcmdDYWNoZUVtcHR5RXJyb3IgaWYgdGhlIGNhY2hlIGlzIGVtcHR5IGFuZCBpcyBwYXVzZWQuXHJcbiAgICAgKi9cclxuICAgIGFzeW5jIGdldE9yV2FpdCgpIHtcclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICBsZXQgdmFsdWVzID0gdGhpcy5nZXQoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlcztcclxuICAgICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgICAgIGlmIChlIGluc3RhbmNlb2YgUmFuZG9tT3JnQ2FjaGVFbXB0eUVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy4jcGF1c2VkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIGNhY2hlIGlzIHBhdXNlZCBhbmQgd2lsbCBub3QgcmV0dXJuIGFueSB2YWx1ZXNcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgbGV0IGNhY2hlZFZhbHVlcyA9IGF3YWl0IHRoaXMuI3BvcHVsYXRlKCk7XHJcbiAgICAgICAgICAgICAgICBpZiAoY2FjaGVkVmFsdWVzID09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgY2FjaGUgaGFzIG5vdCB5ZXQgcmVwb3B1bGF0ZWQuXHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UociA9PiBzZXRUaW1lb3V0KHIsIDUwKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRPcldhaXQoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgdGhlIG51bWJlciBvZiByZXN1bHQgc2V0cyByZW1haW5pbmcgaW4gdGhlIGNhY2hlLlxyXG4gICAgICogXHJcbiAgICAgKiBUaGlzIGVzc2VudGlhbGx5IHJldHVybnMgaG93IG9mdGVuIGdldCgpIG1heSBiZSBjYWxsZWQgd2l0aG91dFxyXG4gICAgICogYSBjYWNoZSByZWZpbGwuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBDdXJyZW50IG51bWJlciBvZiBjYWNoZWQgcmVzdWx0cy5cclxuICAgICAqL1xyXG4gICAgZ2V0Q2FjaGVkVmFsdWVzKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLiNzdGFjay5sZW5ndGg7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBudW1iZXIgb2YgYml0cyB1c2VkIGJ5IHRoaXMgY2FjaGUuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1iZXIgb2YgYml0cyB1c2VkLlxyXG4gICAgICovXHJcbiAgICBnZXRCaXRzVXNlZCgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy4jYml0c1VzZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIG51bWJlciBvZiByZXF1ZXN0cyB1c2VkIGJ5IHRoaXMgY2FjaGUuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1iZXIgb2YgcmVxdWVzdHMgdXNlZC5cclxuICAgICAqL1xyXG4gICAgZ2V0UmVxdWVzdHNVc2VkKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLiNyZXF1ZXN0c1VzZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIZWxwZXIgZnVuY3Rpb24gdG8gY2hlY2sgaWYgdGhlIGNhY2hlIG5lZWRzIHRvIGJlIHJlcG9wdWxhdGVkLlxyXG4gICAgICovXHJcbiAgICAjcmVmcmVzaCA9ICgpID0+IHtcclxuICAgICAgICBpZiAodGhpcy4jYnVsa1JlcXVlc3ROdW1iZXIgPiAwICYmIHRoaXMuI3N0YWNrLmxlbmd0aCA8PSAodGhpcy4jY2FjaGVTaXplIC0gdGhpcy4jYnVsa1JlcXVlc3ROdW1iZXIpKSB7XHJcbiAgICAgICAgICAgIC8vIGJ1bGsgcmVxdWVzdHNcclxuICAgICAgICAgICAgdGhpcy4jcG9wdWxhdGUoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAodGhpcy4jYnVsa1JlcXVlc3ROdW1iZXIgPD0gMCAmJiB0aGlzLiNzdGFjay5sZW5ndGggPCB0aGlzLiNjYWNoZVNpemUpIHtcclxuICAgICAgICAgICAgLy8gaW5kaXZpZHVhbCByZXF1ZXN0c1xyXG4gICAgICAgICAgICB0aGlzLiNwb3B1bGF0ZSgpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEhlbHBlciBmdW5jdGlvbiB0byBhZGQgYSByZXNwb25zZSB0byB0aGUgc3RhY2suXHJcbiAgICAgKiBAcGFyYW0ge2FueVtdfSByZXNwb25zZSBUaGUgcmVzcG9uc2UgcmVjZWl2ZWQgZnJvbSB0aGUgc2VydmVyLlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBidWxrIFRydWUgaWYgdGhlIGNhY2hlIGlzc3VlcyBidWxrIHJlcXVlc3RzLCBmYWxzZSBvdGhlcndpc2UuXHJcbiAgICAgKi9cclxuICAgICNhZGRSZXNwb25zZSA9IChyZXNwb25zZSwgYnVsaykgPT4ge1xyXG4gICAgICAgIHRoaXMuI3JlcXVlc3RzVXNlZCsrO1xyXG4gICAgICAgIHRoaXMuI2JpdHNVc2VkICs9IHJlc3BvbnNlLnJlc3VsdC5iaXRzVXNlZDtcclxuXHJcbiAgICAgICAgaWYgKGJ1bGspIHtcclxuICAgICAgICAgICAgbGV0IGRhdGEgPSByZXNwb25zZS5yZXN1bHQucmFuZG9tLmRhdGE7XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YS5sZW5ndGg7IGkgKz0gdGhpcy4jcmVxdWVzdE51bWJlcikge1xyXG4gICAgICAgICAgICAgICAgdGhpcy4jc3RhY2sucHVzaChkYXRhLnNsaWNlKGksIGkgKyB0aGlzLiNyZXF1ZXN0TnVtYmVyKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLiNzdGFjay5wdXNoKHJlc3BvbnNlLnJlc3VsdC5yYW5kb20uZGF0YSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59IiwiJ3VzZSBzdHJpY3QnO1xyXG5cclxuY29uc3Qge1xyXG4gICAgUmFuZG9tT3JnQmFkSFRUUFJlc3BvbnNlRXJyb3IsXHJcbiAgICBSYW5kb21PcmdJbnN1ZmZpY2llbnRCaXRzRXJyb3IsXHJcbiAgICBSYW5kb21PcmdJbnN1ZmZpY2llbnRSZXF1ZXN0c0Vycm9yLFxyXG4gICAgUmFuZG9tT3JnSlNPTlJQQ0Vycm9yLFxyXG4gICAgUmFuZG9tT3JnS2V5Tm90UnVubmluZ0Vycm9yLFxyXG4gICAgUmFuZG9tT3JnUkFORE9NT1JHRXJyb3IsXHJcbiAgICBSYW5kb21PcmdTZW5kVGltZW91dEVycm9yXHJcbn0gPSByZXF1aXJlKCcuL1JhbmRvbU9yZ0Vycm9ycy5qcycpO1xyXG5jb25zdCBSYW5kb21PcmdDYWNoZSA9IHJlcXVpcmUoJy4vUmFuZG9tT3JnQ2FjaGUuanMnKTtcclxuLyogbm9kZS1pbXBvcnQgKi9cclxuY29uc3QgWE1MSHR0cFJlcXVlc3QgPSByZXF1aXJlKCd4bWxodHRwcmVxdWVzdCcpLlhNTEh0dHBSZXF1ZXN0O1xyXG4vKiBlbmQtbm9kZS1pbXBvcnQgKi9cclxuXHJcbi8qKlxyXG4gKiBSYW5kb21PcmdDbGllbnQgbWFpbiBjbGFzcyB0aHJvdWdoIHdoaWNoIEFQSSBmdW5jdGlvbnMgYXJlIGFjY2Vzc2VkLlxyXG4gKiBcclxuICogVGhpcyBjbGFzcyBwcm92aWRlcyBhY2Nlc3MgdG8gYm90aCB0aGUgc2lnbmVkIGFuZCB1bnNpZ25lZCBtZXRob2RzIG9mIHRoZVxyXG4gKiBSQU5ET00uT1JHIEFQSS5cclxuICogXHJcbiAqIFRoZSBjbGFzcyBhbHNvIHByb3ZpZGVzIGFjY2VzcyB0byB0aGUgY3JlYXRpb24gb2YgYSBjb252ZW5pZW5jZSBjbGFzcywgUmFuZG9tT3JnQ2FjaGUsXHJcbiAqIGZvciBwcmVjYWNoaW5nIEFQSSByZXNwb25zZXMgd2hlbiB0aGUgcmVxdWVzdCBpcyBrbm93biBpbiBhZHZhbmNlLlxyXG4gKiBcclxuICogVGhpcyBjbGFzcyB3aWxsIG9ubHkgYWxsb3cgdGhlIGNyZWF0aW9uIG9mIG9uZSBpbnN0YW5jZSBwZXIgQVBJIGtleS4gSWYgYW5cclxuICogaW5zdGFuY2Ugb2YgdGhpcyBjbGFzcyBhbHJlYWR5IGV4aXN0cyBmb3IgYSBnaXZlbiBrZXksIHRoYXQgaW5zdGFuY2Ugd2lsbCBiZVxyXG4gKiByZXR1cm5lZCBpbnN0ZWFkIG9mIGEgbmV3IGluc3RhbmNlLlxyXG4gKiBcclxuICogVGhpcyBjbGFzcyBvYmV5cyBtb3N0IG9mIHRoZSBndWlkZWxpbmVzIHNldCBmb3J0aCBpbiBodHRwczovL2FwaS5yYW5kb20ub3JnL2pzb24tcnBjLzRcclxuICogQWxsIHJlcXVlc3RzIHJlc3BlY3QgdGhlIHNlcnZlcidzIGFkdmlzb3J5RGVsYXkgcmV0dXJuZWQgaW4gYW55IHJlc3BvbnNlcywgb3IgdXNlXHJcbiAqIERFRkFVTFRfREVMQVkgaWYgbm8gYWR2aXNvcnlEZWxheSBpcyByZXR1cm5lZC4gSWYgdGhlIHN1cHBsaWVkIEFQSSBrZXkgaXMgcGF1c2VkLCBpLmUuLFxyXG4gKiBoYXMgZXhjZWVkZWQgaXRzIGRhaWx5IGJpdC9yZXF1ZXN0IGFsbG93YW5jZSwgdGhpcyBpbXBsZW1lbnRhdGlvbiB3aWxsIGJhY2sgb2ZmIHVudGlsXHJcbiAqIG1pZG5pZ2h0IFVUQy5cclxuICovXHJcbm1vZHVsZS5leHBvcnRzID0gY2xhc3MgUmFuZG9tT3JnQ2xpZW50IHtcclxuICAgIC8vIEJhc2ljIEFQSVxyXG4gICAgc3RhdGljICNJTlRFR0VSX01FVEhPRCA9ICdnZW5lcmF0ZUludGVnZXJzJztcclxuICAgIHN0YXRpYyAjSU5URUdFUl9TRVFVRU5DRV9NRVRIT0QgPSAnZ2VuZXJhdGVJbnRlZ2VyU2VxdWVuY2VzJztcclxuICAgIHN0YXRpYyAjREVDSU1BTF9GUkFDVElPTl9NRVRIT0QgPSAnZ2VuZXJhdGVEZWNpbWFsRnJhY3Rpb25zJztcclxuICAgIHN0YXRpYyAjR0FVU1NJQU5fTUVUSE9EID0gJ2dlbmVyYXRlR2F1c3NpYW5zJztcclxuICAgIHN0YXRpYyAjU1RSSU5HX01FVEhPRCA9ICdnZW5lcmF0ZVN0cmluZ3MnO1xyXG4gICAgc3RhdGljICNVVUlEX01FVEhPRCA9ICdnZW5lcmF0ZVVVSURzJztcclxuICAgIHN0YXRpYyAjQkxPQl9NRVRIT0QgPSAnZ2VuZXJhdGVCbG9icyc7XHJcbiAgICBzdGF0aWMgI0dFVF9VU0FHRV9NRVRIT0QgPSAnZ2V0VXNhZ2UnO1xyXG5cclxuICAgIC8vIFNpZ25lZCBBUElcclxuICAgIHN0YXRpYyAjU0lHTkVEX0lOVEVHRVJfTUVUSE9EID0gJ2dlbmVyYXRlU2lnbmVkSW50ZWdlcnMnO1xyXG4gICAgc3RhdGljICNTSUdORURfSU5URUdFUl9TRVFVRU5DRV9NRVRIT0QgPSAnZ2VuZXJhdGVTaWduZWRJbnRlZ2VyU2VxdWVuY2VzJztcclxuICAgIHN0YXRpYyAjU0lHTkVEX0RFQ0lNQUxfRlJBQ1RJT05fTUVUSE9EID0gJ2dlbmVyYXRlU2lnbmVkRGVjaW1hbEZyYWN0aW9ucyc7XHJcbiAgICBzdGF0aWMgI1NJR05FRF9HQVVTU0lBTl9NRVRIT0QgPSAnZ2VuZXJhdGVTaWduZWRHYXVzc2lhbnMnO1xyXG4gICAgc3RhdGljICNTSUdORURfU1RSSU5HX01FVEhPRCA9ICdnZW5lcmF0ZVNpZ25lZFN0cmluZ3MnO1xyXG4gICAgc3RhdGljICNTSUdORURfVVVJRF9NRVRIT0QgPSAnZ2VuZXJhdGVTaWduZWRVVUlEcyc7XHJcbiAgICBzdGF0aWMgI1NJR05FRF9CTE9CX01FVEhPRCA9ICdnZW5lcmF0ZVNpZ25lZEJsb2JzJztcclxuICAgIHN0YXRpYyAjR0VUX1JFU1VMVF9NRVRIT0QgPSAnZ2V0UmVzdWx0JztcclxuICAgIHN0YXRpYyAjQ1JFQVRFX1RJQ0tFVF9NRVRIT0QgPSAnY3JlYXRlVGlja2V0cyc7XHJcbiAgICBzdGF0aWMgI0xJU1RfVElDS0VUX01FVEhPRCA9ICdsaXN0VGlja2V0cyc7XHJcbiAgICBzdGF0aWMgI1JFVkVBTF9USUNLRVRfTUVUSE9EID0gJ3JldmVhbFRpY2tldHMnO1xyXG4gICAgc3RhdGljICNHRVRfVElDS0VUX01FVEhPRCA9ICdnZXRUaWNrZXQnO1xyXG4gICAgc3RhdGljICNWRVJJRllfU0lHTkFUVVJFX01FVEhPRCA9ICd2ZXJpZnlTaWduYXR1cmUnO1xyXG5cclxuICAgIC8vIEJsb2IgZm9ybWF0IGxpdGVyYWxzXHJcbiAgICAvKiogQmxvYiBmb3JtYXQgbGl0ZXJhbCwgYmFzZTY0IGVuY29kaW5nIChkZWZhdWx0KS4gKi9cclxuICAgIHN0YXRpYyBCTE9CX0ZPUk1BVF9CQVNFNjQgPSAnYmFzZTY0JztcclxuICAgIC8qKiBCbG9iIGZvcm1hdCBsaXRlcmFsLCBoZXggZW5jb2RpbmcuICovXHJcbiAgICBzdGF0aWMgQkxPQl9GT1JNQVRfSEVYID0gJ2hleCc7XHJcblxyXG4gICAgLy8gRGVmYXVsdCB2YWx1ZXNcclxuICAgIC8qKiBEZWZhdWx0IHZhbHVlIGZvciB0aGUgcmVwbGFjZW1lbnQgcGFyYW1ldGVyICh0cnVlKS4gKi9cclxuICAgIHN0YXRpYyBERUZBVUxUX1JFUExBQ0VNRU5UID0gdHJ1ZTtcclxuICAgIC8qKiBEZWZhdWx0IHZhbHVlIGZvciB0aGUgYmFzZSBwYXJhbWV0ZXIgKDEwKS4gKi9cclxuICAgIHN0YXRpYyBERUZBVUxUX0JBU0UgPSAxMDtcclxuICAgIC8qKiBEZWZhdWx0IHZhbHVlIGZvciB0aGUgdXNlckRhdGEgcGFyYW1ldGVyIChudWxsKS4gKi9cclxuICAgIHN0YXRpYyBERUZBVUxUX1VTRVJfREFUQSA9IG51bGw7XHJcbiAgICAvKiogRGVmYXVsdCB2YWx1ZSBmb3IgdGhlIHRpY2tldElkIHBhcmFtZXRlciAobnVsbCkuICovXHJcbiAgICBzdGF0aWMgREVGQVVMVF9USUNLRVRfSUQgPSBudWxsO1xyXG4gICAgLyoqIERlZmF1bHQgdmFsdWUgZm9yIHRoZSBwcmVnZW5lcmF0ZWRSYW5kb21pemF0aW9uIHBhcmFtZXRlciAobnVsbCkuICovXHJcbiAgICBzdGF0aWMgREVGQVVMVF9QUkVHRU5FUkFURURfUkFORE9NSVpBVElPTiA9IG51bGw7XHJcbiAgICAvKiogRGVmYXVsdCB2YWx1ZSBmb3IgdGhlIGxpY2Vuc2VEYXRhIHBhcmFtZXRlciAobnVsbCkuICovXHJcbiAgICBzdGF0aWMgREVGQVVMVF9MSUNFTlNFX0RBVEEgPSBudWxsO1xyXG5cclxuICAgIC8qKiBTaXplIG9mIGEgc2luZ2xlIFVVSUQgaW4gYml0cy4gKi9cclxuICAgIHN0YXRpYyBVVUlEX1NJWkUgPSAxMjI7XHJcbiAgICAvKiogRGVmYXVsdCB2YWx1ZSBmb3IgdGhlIGJsb2NraW5nVGltZW91dCBwYXJhbWV0ZXIgKDEgZGF5KS4gKi9cclxuICAgIHN0YXRpYyBERUZBVUxUX0JMT0NLSU5HX1RJTUVPVVQgPSAyNCAqIDYwICogNjAgKiAxMDAwO1xyXG4gICAgLyoqIERlZmF1bHQgdmFsdWUgZm9yIHRoZSBodHRwVGltZW91dCBwYXJhbWV0ZXIgKDIgbWludXRlcykuICovXHJcbiAgICBzdGF0aWMgREVGQVVMVF9IVFRQX1RJTUVPVVQgPSAxMjAgKiAxMDAwO1xyXG4gICAgLyoqIE1heGltdW0gbnVtYmVyIG9mIGNoYXJhY3RlcnMgYWxsb3dlZCBpbiBhIHNpZ25hdHVyZSB2ZXJmaWNpYXRpb24gVVJMLiAqL1xyXG4gICAgc3RhdGljIE1BWF9VUkxfTEVOR1RIID0gMjA0NjtcclxuXHJcbiAgICAvLyBEZWZhdWx0IGJhY2stb2ZmIHRvIHVzZSBpZiBubyBhZHZpc29yeURlbGF5IGJhY2stb2ZmIHN1cHBsaWVkIGJ5IHNlcnZlciAoMSBzZWNvbmQpXHJcbiAgICBzdGF0aWMgI0RFRkFVTFRfREVMQVkgPSAxKjEwMDA7XHJcblxyXG4gICAgLy8gT24gcmVxdWVzdCBmZXRjaCBmcmVzaCBhbGxvd2FuY2Ugc3RhdGUgaWYgY3VycmVudCBzdGF0ZSBkYXRhIGlzIG9sZGVyIHRoYW5cclxuICAgIC8vIHRoaXMgdmFsdWUgKDEgaG91cikuXHJcbiAgICBzdGF0aWMgI0FMTE9XQU5DRV9TVEFURV9SRUZSRVNIX1NFQ09ORFMgPSAzNjAwICogMTAwMDtcclxuXHJcbiAgICAvLyBNYWludGFpbnMgdXNhZ2Ugc3RhdGlzdGljcyBmcm9tIHNlcnZlci5cclxuICAgICNiaXRzTGVmdCA9IC0xO1xyXG4gICAgI3JlcXVlc3RzTGVmdCA9IC0xO1xyXG5cclxuICAgIC8vIEJhY2stb2ZmIGluZm8gZm9yIHdoZW4gdGhlIEFQSSBrZXkgaXMgZGV0ZWN0ZWQgYXMgbm90IHJ1bm5pbmcsIHByb2JhYmx5XHJcbiAgICAvLyBiZWNhdXNlIHRoZSBrZXkgaGFzIGV4Y2VlZGVkIGl0cyBkYWlseSB1c2FnZSBsaW1pdC4gQmFjay1vZmYgcnVucyB1bnRpbFxyXG4gICAgLy8gbWlkbmlnaHQgVVRDLlxyXG4gICAgI2JhY2tvZmYgPSAtMTtcclxuICAgICNiYWNrb2ZmRXJyb3IgPSAnJztcclxuXHJcbiAgICAjYXBpS2V5ID0gJyc7XHJcbiAgICAjYmxvY2tpbmdUaW1lb3V0ID0gUmFuZG9tT3JnQ2xpZW50LkRFRkFVTFRfQkxPQ0tJTkdfVElNRU9VVDtcclxuICAgICNodHRwVGltZW91dCA9IFJhbmRvbU9yZ0NsaWVudC5ERUZBVUxUX0hUVFBfVElNRU9VVDtcclxuXHJcbiAgICAvLyBNYWludGFpbiBpbmZvIHRvIG9iZXkgc2VydmVyIGFkdmlzb3J5IGRlbGF5XHJcbiAgICAjYWR2aXNvcnlEZWxheSA9IDA7XHJcbiAgICAjbGFzdFJlc3BvbnNlUmVjZWl2ZWRUaW1lID0gMDtcclxuXHJcbiAgICAvLyBNYWludGFpbnMgYSBkaWN0aW9uYXJ5IG9mIEFQSSBrZXlzIGFuZCB0aGVpciBpbnN0YW5jZXMuXHJcbiAgICBzdGF0aWMgI2tleUluZGV4ZWRJbnN0YW5jZXMgPSB7fTtcclxuXHJcbiAgICBzdGF0aWMgI0VSUk9SX0NPREVTID0gWyAxMDAsIDEwMSwgMjAwLCAyMDEsIDIwMiwgMjAzLCAyMDQsIDMwMCxcclxuICAgICAgICAzMDEsIDMwMiwgMzAzLCAzMDQsIDMwNSwgMzA2LCAzMDcsIDQwMCwgNDAxLCA0MDIsIDQwMywgNDA0LFxyXG4gICAgICAgIDQwNSwgNDIwLCA0MjEsIDQyMiwgNDIzLCA0MjQsIDQyNSwgNDI2LCA1MDAsIDMyMDAwIF07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb25zdHJ1Y3Rvci4gRW5zdXJlcyBvbmx5IG9uZSBpbnN0YW5jZSBvZiBSYW5kb21PcmdDbGllbnQgZXhpc3RzIHBlciBBUElcclxuICAgICAqIGtleS4gQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZSBpZiB0aGUgc3VwcGxpZWQga2V5IGlzbid0IGFscmVhZHkga25vd24sXHJcbiAgICAgKiBvdGhlcndpc2UgcmV0dXJucyB0aGUgcHJldmlvdXNseSBpbnN0YW50aWF0ZWQgb25lLlxyXG4gICAgICogQGNvbnN0cnVjdG9yXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gYXBpS2V5IEFQSSBrZXkgb2YgaW5zdGFuY2UgdG8gY3JlYXRlL2ZpbmQsIG9idGFpbmVkIGZyb21cclxuICAgICAqICAgICBSQU5ET00uT1JHLCBzZWUgaHR0cHM6Ly9hcGkucmFuZG9tLm9yZy9hcGkta2V5c1xyXG4gICAgICogQHBhcmFtIHt7YmxvY2tpbmdUaW1lb3V0PzogbnVtYmVyLCBodHRwVGltZW91dD86IG51bWJlcn19IG9wdGlvbnMgQW4gb2JqZWN0XHJcbiAgICAgKiAgICAgd2hpY2ggbWF5IGNvbnRhaW5zIGFueSBvZiB0aGUgZm9sbG93aW5nIG9wdGlvbmFsIHBhcmFtZXRlcnM6XHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW29wdGlvbnMuYmxvY2tpbmdUaW1lb3V0ID0gMjQgKiA2MCAqIDYwICogMTAwMF0gTWF4aW11bVxyXG4gICAgICogICAgIHRpbWUgaW4gbWlsbGlzZWNvbmRzIHRvIHdhaXQgYmVmb3JlIGJlaW5nIGFsbG93ZWQgdG8gc2VuZCBhIHJlcXVlc3QuXHJcbiAgICAgKiAgICAgTm90ZSB0aGlzIGlzIGEgaGludCBub3QgYSBndWFyYW50ZWUuIFRoZSBhZHZpc29yeSBkZWxheSBmcm9tIHNlcnZlclxyXG4gICAgICogICAgIG11c3QgYWx3YXlzIGJlIG9iZXllZC4gU3VwcGx5IGEgdmFsdWUgb2YgLTEgdG8gYWxsb3cgYmxvY2tpbmcgZm9yZXZlclxyXG4gICAgICogICAgIChkZWZhdWx0IDI0ICogNjAgKiA2MCAqIDEwMDAsIGkuZS4sIDEgZGF5KS5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5odHRwVGltZW91dCA9IDEyMCAqIDEwMDBdIE1heGltdW0gdGltZSBpblxyXG4gICAgICogICAgIG1pbGxpc2Vjb25kcyB0byB3YWl0IGZvciB0aGUgc2VydmVyIHJlc3BvbnNlIHRvIGEgcmVxdWVzdCAoZGVmYXVsdFxyXG4gICAgICogICAgIDEyMCoxMDAwKS5cclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IoYXBpS2V5LCBvcHRpb25zID0ge30pIHtcclxuICAgICAgICBpZiAoUmFuZG9tT3JnQ2xpZW50LiNrZXlJbmRleGVkSW5zdGFuY2VzICYmIFJhbmRvbU9yZ0NsaWVudC4ja2V5SW5kZXhlZEluc3RhbmNlc1thcGlLZXldKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBSYW5kb21PcmdDbGllbnQuI2tleUluZGV4ZWRJbnN0YW5jZXNbYXBpS2V5XTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLiNhcGlLZXkgPSBhcGlLZXk7XHJcbiAgICAgICAgICAgIHRoaXMuI2Jsb2NraW5nVGltZW91dCA9IG9wdGlvbnMuYmxvY2tpbmdUaW1lb3V0IHx8IDI0ICogNjAgKiA2MCAqIDEwMDA7XHJcbiAgICAgICAgICAgIHRoaXMuI2h0dHBUaW1lb3V0ID0gb3B0aW9ucy5odHRwVGltZW91dCB8fCAxMjAgKiAxMDAwO1xyXG5cclxuICAgICAgICAgICAgUmFuZG9tT3JnQ2xpZW50LiNrZXlJbmRleGVkSW5zdGFuY2VzW2FwaUtleV0gPSB0aGlzO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBCYXNpYyBBUElcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlcXVlc3RzIGFuZCByZXR1cm5zIGFuIGFycmF5IG9mIHRydWUgcmFuZG9tIGludGVnZXJzIHdpdGhpbiBhIHVzZXItZGVmaW5lZFxyXG4gICAgICogcmFuZ2UgZnJvbSB0aGUgc2VydmVyLlxyXG4gICAgICogXHJcbiAgICAgKiBTZWU6IGh0dHBzOi8vYXBpLnJhbmRvbS5vcmcvanNvbi1ycGMvNC9iYXNpYyNnZW5lcmF0ZUludGVnZXJzXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBUaGUgbnVtYmVyIG9mIHJhbmRvbSBpbnRlZ2VycyB5b3UgbmVlZC4gTXVzdCBiZSB3aXRoaW5cclxuICAgICAqICAgICB0aGUgWzEsMWU0XSByYW5nZS5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaW4gVGhlIGxvd2VyIGJvdW5kYXJ5IGZvciB0aGUgcmFuZ2UgZnJvbSB3aGljaCB0aGUgcmFuZG9tXHJcbiAgICAgKiAgICAgbnVtYmVycyB3aWxsIGJlIHBpY2tlZC4gTXVzdCBiZSB3aXRoaW4gdGhlIFstMWU5LDFlOV0gcmFuZ2UuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbWF4IFRoZSB1cHBlciBib3VuZGFyeSBmb3IgdGhlIHJhbmdlIGZyb20gd2hpY2ggdGhlIHJhbmRvbVxyXG4gICAgICogICAgIG51bWJlcnMgd2lsbCBiZSBwaWNrZWQuIE11c3QgYmUgd2l0aGluIHRoZSBbLTFlOSwxZTldIHJhbmdlLlxyXG4gICAgICogQHBhcmFtIHt7cmVwbGFjZW1lbnQ/OiBib29sZWFuLCBiYXNlPzogbnVtYmVyLCBwcmVnZW5lcmF0ZWRSYW5kb21pemF0aW9uPzpcclxuICAgICAqICAgICBPYmplY3R9fSBvcHRpb25zIEFuIG9iamVjdCB3aGljaCBtYXkgY29udGFpbnMgYW55IG9mIHRoZSBmb2xsb3dpbmdcclxuICAgICAqICAgICBvcHRpb25hbCBwYXJhbWV0ZXJzOlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5yZXBsYWNlbWVudD10cnVlXSBTcGVjaWZpZXMgd2hldGhlciB0aGUgcmFuZG9tXHJcbiAgICAgKiAgICAgbnVtYmVycyBzaG91bGQgYmUgcGlja2VkIHdpdGggcmVwbGFjZW1lbnQuIElmIHRydWUsIHRoZSByZXN1bHRpbmcgbnVtYmVyc1xyXG4gICAgICogICAgIG1heSBjb250YWluIGR1cGxpY2F0ZSB2YWx1ZXMsIG90aGVyd2lzZSB0aGUgbnVtYmVycyB3aWxsIGFsbCBiZSB1bmlxdWVcclxuICAgICAqICAgICAoZGVmYXVsdCB0cnVlKS5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbb3B0aW9ucy5iYXNlPTEwXSBUaGUgYmFzZSB0aGF0IHdpbGwgYmUgdXNlZCB0byBkaXNwbGF5XHJcbiAgICAgKiAgICAgdGhlIG51bWJlcnMuIFZhbHVlcyBhbGxvd2VkIGFyZSAyLCA4LCAxMCBhbmQgMTYgKGRlZmF1bHQgMTApLlxyXG4gICAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLnByZWdlbmVyYXRlZFJhbmRvbWl6YXRpb249bnVsbF0gQSBkaWN0aW9uYXJ5IG9iamVjdFxyXG4gICAgICogICAgIHdoaWNoIGFsbG93cyB0aGUgY2xpZW50IHRvIHNwZWNpZnkgdGhhdCB0aGUgcmFuZG9tIHZhbHVlcyBzaG91bGQgYmVcclxuICAgICAqICAgICBnZW5lcmF0ZWQgZnJvbSBhIHByZWdlbmVyYXRlZCwgaGlzdG9yaWNhbCByYW5kb21pemF0aW9uIGluc3RlYWQgb2YgYVxyXG4gICAgICogICAgIG9uZS10aW1lIG9uLXRoZS1mbHkgcmFuZG9taXphdGlvbi4gVGhlcmUgYXJlIHRocmVlIHBvc3NpYmxlIGNhc2VzOlxyXG4gICAgICogKiAqKm51bGwqKjogVGhlIHN0YW5kYXJkIHdheSBvZiBjYWxsaW5nIGZvciByYW5kb20gdmFsdWVzLCBpLmUudHJ1ZVxyXG4gICAgICogICAgICAgcmFuZG9tbmVzcyBpcyBnZW5lcmF0ZWQgYW5kIGRpc2NhcmRlZCBhZnRlcndhcmRzLlxyXG4gICAgICogKiAqKmRhdGUqKjogUkFORE9NLk9SRyB1c2VzIGhpc3RvcmljYWwgdHJ1ZSByYW5kb21uZXNzIGdlbmVyYXRlZCBvbiB0aGVcclxuICAgICAqICAgICAgIGNvcnJlc3BvbmRpbmcgZGF0ZSAocGFzdCBvciBwcmVzZW50LCBmb3JtYXQ6IHsgJ2RhdGUnLCAnWVlZWS1NTS1ERCcgfSkuXHJcbiAgICAgKiAqICoqaWQqKjogUkFORE9NLk9SRyB1c2VzIGhpc3RvcmljYWwgdHJ1ZSByYW5kb21uZXNzIGRlcml2ZWQgZnJvbSB0aGVcclxuICAgICAqICAgICAgIGNvcnJlc3BvbmRpbmcgaWRlbnRpZmllciBpbiBhIGRldGVybWluaXN0aWMgbWFubmVyLiBGb3JtYXQ6IHsgJ2lkJyxcclxuICAgICAqICAgICAgICdQRVJTSVNURU5ULUlERU5USUZJRVInIH0gd2hlcmUgJ1BFUlNJU1RFTlQtSURFTlRJRklFUicgaXMgYSBzdHJpbmdcclxuICAgICAqICAgICAgIHdpdGggbGVuZ3RoIGluIHRoZSBbMSwgNjRdIHJhbmdlLlxyXG4gICAgICogQHJldHVybnMgeyhQcm9taXNlPG51bWJlcltdPnxQcm9taXNlPHN0cmluZ1tdPil9IEEgUHJvbWlzZSB3aGljaCwgaWZcclxuICAgICAqICAgICByZXNvbHZlZCBzdWNjZXNzZnVsbHksIHJlcHJlc2VudHMgYW4gYXJyYXkgb2YgdHJ1ZSByYW5kb20gaW50ZWdlcnMuXHJcbiAgICAgKiBAdGhyb3dzIHtSYW5kb21PcmdTZW5kVGltZW91dEVycm9yfSBUaHJvd24gd2hlbiBibG9ja2luZyB0aW1lb3V0IGlzIGV4Y2VlZGVkXHJcbiAgICAgKiAgICAgYmVmb3JlIHRoZSByZXF1ZXN0IGNhbiBiZSBzZW50LlxyXG4g