ProtoBuf.js.html 212 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>JSDoc: Source: protobuf.js</title>
  6. <script src="scripts/prettify/prettify.js"> </script>
  7. <script src="scripts/prettify/lang-css.js"> </script>
  8. <!--[if lt IE 9]>
  9. <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  10. <![endif]-->
  11. <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
  12. <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
  13. </head>
  14. <body>
  15. <div id="main">
  16. <h1 class="page-title">Source: protobuf.js</h1>
  17. <section>
  18. <article>
  19. <pre class="prettyprint source linenums"><code>/*
  20. Copyright 2013 Daniel Wirtz &lt;dcode@dcode.io>
  21. Licensed under the Apache License, Version 2.0 (the "License");
  22. you may not use this file except in compliance with the License.
  23. You may obtain a copy of the License at
  24. http://www.apache.org/licenses/LICENSE-2.0
  25. Unless required by applicable law or agreed to in writing, software
  26. distributed under the License is distributed on an "AS IS" BASIS,
  27. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  28. See the License for the specific language governing permissions and
  29. limitations under the License.
  30. */
  31. /**
  32. * @license protobuf.js (c) 2013 Daniel Wirtz &lt;dcode@dcode.io>
  33. * Released under the Apache License, Version 2.0
  34. * see: https://github.com/dcodeIO/protobuf.js for details
  35. */
  36. (function(global, factory) {
  37. /* AMD */ if (typeof define === 'function' &amp;&amp; define["amd"])
  38. define(["bytebuffer"], factory);
  39. /* CommonJS */ else if (typeof require === "function" &amp;&amp; typeof module === "object" &amp;&amp; module &amp;&amp; module["exports"])
  40. module["exports"] = factory(require("bytebuffer"), true);
  41. /* Global */ else
  42. (global["dcodeIO"] = global["dcodeIO"] || {})["ProtoBuf"] = factory(global["dcodeIO"]["ByteBuffer"]);
  43. })(this, function(ByteBuffer, isCommonJS) {
  44. "use strict";
  45. /**
  46. * The ProtoBuf namespace.
  47. * @exports ProtoBuf
  48. * @namespace
  49. * @expose
  50. */
  51. var ProtoBuf = {};
  52. /**
  53. * @type {!function(new: ByteBuffer, ...[*])}
  54. * @expose
  55. */
  56. ProtoBuf.ByteBuffer = ByteBuffer;
  57. /**
  58. * @type {?function(new: Long, ...[*])}
  59. * @expose
  60. */
  61. ProtoBuf.Long = ByteBuffer.Long || null;
  62. /**
  63. * ProtoBuf.js version.
  64. * @type {string}
  65. * @const
  66. * @expose
  67. */
  68. ProtoBuf.VERSION = "5.0.2";
  69. /**
  70. * Wire types.
  71. * @type {Object.&lt;string,number>}
  72. * @const
  73. * @expose
  74. */
  75. ProtoBuf.WIRE_TYPES = {};
  76. /**
  77. * Varint wire type.
  78. * @type {number}
  79. * @expose
  80. */
  81. ProtoBuf.WIRE_TYPES.VARINT = 0;
  82. /**
  83. * Fixed 64 bits wire type.
  84. * @type {number}
  85. * @const
  86. * @expose
  87. */
  88. ProtoBuf.WIRE_TYPES.BITS64 = 1;
  89. /**
  90. * Length delimited wire type.
  91. * @type {number}
  92. * @const
  93. * @expose
  94. */
  95. ProtoBuf.WIRE_TYPES.LDELIM = 2;
  96. /**
  97. * Start group wire type.
  98. * @type {number}
  99. * @const
  100. * @expose
  101. */
  102. ProtoBuf.WIRE_TYPES.STARTGROUP = 3;
  103. /**
  104. * End group wire type.
  105. * @type {number}
  106. * @const
  107. * @expose
  108. */
  109. ProtoBuf.WIRE_TYPES.ENDGROUP = 4;
  110. /**
  111. * Fixed 32 bits wire type.
  112. * @type {number}
  113. * @const
  114. * @expose
  115. */
  116. ProtoBuf.WIRE_TYPES.BITS32 = 5;
  117. /**
  118. * Packable wire types.
  119. * @type {!Array.&lt;number>}
  120. * @const
  121. * @expose
  122. */
  123. ProtoBuf.PACKABLE_WIRE_TYPES = [
  124. ProtoBuf.WIRE_TYPES.VARINT,
  125. ProtoBuf.WIRE_TYPES.BITS64,
  126. ProtoBuf.WIRE_TYPES.BITS32
  127. ];
  128. /**
  129. * Types.
  130. * @dict
  131. * @type {!Object.&lt;string,{name: string, wireType: number, defaultValue: *}>}
  132. * @const
  133. * @expose
  134. */
  135. ProtoBuf.TYPES = {
  136. // According to the protobuf spec.
  137. "int32": {
  138. name: "int32",
  139. wireType: ProtoBuf.WIRE_TYPES.VARINT,
  140. defaultValue: 0
  141. },
  142. "uint32": {
  143. name: "uint32",
  144. wireType: ProtoBuf.WIRE_TYPES.VARINT,
  145. defaultValue: 0
  146. },
  147. "sint32": {
  148. name: "sint32",
  149. wireType: ProtoBuf.WIRE_TYPES.VARINT,
  150. defaultValue: 0
  151. },
  152. "int64": {
  153. name: "int64",
  154. wireType: ProtoBuf.WIRE_TYPES.VARINT,
  155. defaultValue: ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
  156. },
  157. "uint64": {
  158. name: "uint64",
  159. wireType: ProtoBuf.WIRE_TYPES.VARINT,
  160. defaultValue: ProtoBuf.Long ? ProtoBuf.Long.UZERO : undefined
  161. },
  162. "sint64": {
  163. name: "sint64",
  164. wireType: ProtoBuf.WIRE_TYPES.VARINT,
  165. defaultValue: ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
  166. },
  167. "bool": {
  168. name: "bool",
  169. wireType: ProtoBuf.WIRE_TYPES.VARINT,
  170. defaultValue: false
  171. },
  172. "double": {
  173. name: "double",
  174. wireType: ProtoBuf.WIRE_TYPES.BITS64,
  175. defaultValue: 0
  176. },
  177. "string": {
  178. name: "string",
  179. wireType: ProtoBuf.WIRE_TYPES.LDELIM,
  180. defaultValue: ""
  181. },
  182. "bytes": {
  183. name: "bytes",
  184. wireType: ProtoBuf.WIRE_TYPES.LDELIM,
  185. defaultValue: null // overridden in the code, must be a unique instance
  186. },
  187. "fixed32": {
  188. name: "fixed32",
  189. wireType: ProtoBuf.WIRE_TYPES.BITS32,
  190. defaultValue: 0
  191. },
  192. "sfixed32": {
  193. name: "sfixed32",
  194. wireType: ProtoBuf.WIRE_TYPES.BITS32,
  195. defaultValue: 0
  196. },
  197. "fixed64": {
  198. name: "fixed64",
  199. wireType: ProtoBuf.WIRE_TYPES.BITS64,
  200. defaultValue: ProtoBuf.Long ? ProtoBuf.Long.UZERO : undefined
  201. },
  202. "sfixed64": {
  203. name: "sfixed64",
  204. wireType: ProtoBuf.WIRE_TYPES.BITS64,
  205. defaultValue: ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
  206. },
  207. "float": {
  208. name: "float",
  209. wireType: ProtoBuf.WIRE_TYPES.BITS32,
  210. defaultValue: 0
  211. },
  212. "enum": {
  213. name: "enum",
  214. wireType: ProtoBuf.WIRE_TYPES.VARINT,
  215. defaultValue: 0
  216. },
  217. "message": {
  218. name: "message",
  219. wireType: ProtoBuf.WIRE_TYPES.LDELIM,
  220. defaultValue: null
  221. },
  222. "group": {
  223. name: "group",
  224. wireType: ProtoBuf.WIRE_TYPES.STARTGROUP,
  225. defaultValue: null
  226. }
  227. };
  228. /**
  229. * Valid map key types.
  230. * @type {!Array.&lt;!Object.&lt;string,{name: string, wireType: number, defaultValue: *}>>}
  231. * @const
  232. * @expose
  233. */
  234. ProtoBuf.MAP_KEY_TYPES = [
  235. ProtoBuf.TYPES["int32"],
  236. ProtoBuf.TYPES["sint32"],
  237. ProtoBuf.TYPES["sfixed32"],
  238. ProtoBuf.TYPES["uint32"],
  239. ProtoBuf.TYPES["fixed32"],
  240. ProtoBuf.TYPES["int64"],
  241. ProtoBuf.TYPES["sint64"],
  242. ProtoBuf.TYPES["sfixed64"],
  243. ProtoBuf.TYPES["uint64"],
  244. ProtoBuf.TYPES["fixed64"],
  245. ProtoBuf.TYPES["bool"],
  246. ProtoBuf.TYPES["string"],
  247. ProtoBuf.TYPES["bytes"]
  248. ];
  249. /**
  250. * Minimum field id.
  251. * @type {number}
  252. * @const
  253. * @expose
  254. */
  255. ProtoBuf.ID_MIN = 1;
  256. /**
  257. * Maximum field id.
  258. * @type {number}
  259. * @const
  260. * @expose
  261. */
  262. ProtoBuf.ID_MAX = 0x1FFFFFFF;
  263. /**
  264. * If set to `true`, field names will be converted from underscore notation to camel case. Defaults to `false`.
  265. * Must be set prior to parsing.
  266. * @type {boolean}
  267. * @expose
  268. */
  269. ProtoBuf.convertFieldsToCamelCase = false;
  270. /**
  271. * By default, messages are populated with (setX, set_x) accessors for each field. This can be disabled by
  272. * setting this to `false` prior to building messages.
  273. * @type {boolean}
  274. * @expose
  275. */
  276. ProtoBuf.populateAccessors = true;
  277. /**
  278. * By default, messages are populated with default values if a field is not present on the wire. To disable
  279. * this behavior, set this setting to `false`.
  280. * @type {boolean}
  281. * @expose
  282. */
  283. ProtoBuf.populateDefaults = true;
  284. /**
  285. * @alias ProtoBuf.Util
  286. * @expose
  287. */
  288. ProtoBuf.Util = (function() {
  289. "use strict";
  290. /**
  291. * ProtoBuf utilities.
  292. * @exports ProtoBuf.Util
  293. * @namespace
  294. */
  295. var Util = {};
  296. /**
  297. * Flag if running in node or not.
  298. * @type {boolean}
  299. * @const
  300. * @expose
  301. */
  302. Util.IS_NODE = !!(
  303. typeof process === 'object' &amp;&amp; process+'' === '[object process]' &amp;&amp; !process['browser']
  304. );
  305. /**
  306. * Constructs a XMLHttpRequest object.
  307. * @return {XMLHttpRequest}
  308. * @throws {Error} If XMLHttpRequest is not supported
  309. * @expose
  310. */
  311. Util.XHR = function() {
  312. // No dependencies please, ref: http://www.quirksmode.org/js/xmlhttp.html
  313. var XMLHttpFactories = [
  314. function () {return new XMLHttpRequest()},
  315. function () {return new ActiveXObject("Msxml2.XMLHTTP")},
  316. function () {return new ActiveXObject("Msxml3.XMLHTTP")},
  317. function () {return new ActiveXObject("Microsoft.XMLHTTP")}
  318. ];
  319. /** @type {?XMLHttpRequest} */
  320. var xhr = null;
  321. for (var i=0;i&lt;XMLHttpFactories.length;i++) {
  322. try { xhr = XMLHttpFactories[i](); }
  323. catch (e) { continue; }
  324. break;
  325. }
  326. if (!xhr)
  327. throw Error("XMLHttpRequest is not supported");
  328. return xhr;
  329. };
  330. /**
  331. * Fetches a resource.
  332. * @param {string} path Resource path
  333. * @param {function(?string)=} callback Callback receiving the resource's contents. If omitted the resource will
  334. * be fetched synchronously. If the request failed, contents will be null.
  335. * @return {?string|undefined} Resource contents if callback is omitted (null if the request failed), else undefined.
  336. * @expose
  337. */
  338. Util.fetch = function(path, callback) {
  339. if (callback &amp;&amp; typeof callback != 'function')
  340. callback = null;
  341. if (Util.IS_NODE) {
  342. var fs = require("fs");
  343. if (callback) {
  344. fs.readFile(path, function(err, data) {
  345. if (err)
  346. callback(null);
  347. else
  348. callback(""+data);
  349. });
  350. } else
  351. try {
  352. return fs.readFileSync(path);
  353. } catch (e) {
  354. return null;
  355. }
  356. } else {
  357. var xhr = Util.XHR();
  358. xhr.open('GET', path, callback ? true : false);
  359. // xhr.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
  360. xhr.setRequestHeader('Accept', 'text/plain');
  361. if (typeof xhr.overrideMimeType === 'function') xhr.overrideMimeType('text/plain');
  362. if (callback) {
  363. xhr.onreadystatechange = function() {
  364. if (xhr.readyState != 4) return;
  365. if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 &amp;&amp; typeof xhr.responseText === 'string'))
  366. callback(xhr.responseText);
  367. else
  368. callback(null);
  369. };
  370. if (xhr.readyState == 4)
  371. return;
  372. xhr.send(null);
  373. } else {
  374. xhr.send(null);
  375. if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 &amp;&amp; typeof xhr.responseText === 'string'))
  376. return xhr.responseText;
  377. return null;
  378. }
  379. }
  380. };
  381. /**
  382. * Converts a string to camel case.
  383. * @param {string} str
  384. * @returns {string}
  385. * @expose
  386. */
  387. Util.toCamelCase = function(str) {
  388. return str.replace(/_([a-zA-Z])/g, function ($0, $1) {
  389. return $1.toUpperCase();
  390. });
  391. };
  392. return Util;
  393. })();
  394. /**
  395. * Language expressions.
  396. * @type {!Object.&lt;string,!RegExp>}
  397. * @expose
  398. */
  399. ProtoBuf.Lang = {
  400. // Characters always ending a statement
  401. DELIM: /[\s\{\}=;:\[\],'"\(\)&lt;>]/g,
  402. // Field rules
  403. RULE: /^(?:required|optional|repeated|map)$/,
  404. // Field types
  405. TYPE: /^(?:double|float|int32|uint32|sint32|int64|uint64|sint64|fixed32|sfixed32|fixed64|sfixed64|bool|string|bytes)$/,
  406. // Names
  407. NAME: /^[a-zA-Z_][a-zA-Z_0-9]*$/,
  408. // Type definitions
  409. TYPEDEF: /^[a-zA-Z][a-zA-Z_0-9]*$/,
  410. // Type references
  411. TYPEREF: /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)+$/,
  412. // Fully qualified type references
  413. FQTYPEREF: /^(?:\.[a-zA-Z][a-zA-Z_0-9]*)+$/,
  414. // All numbers
  415. NUMBER: /^-?(?:[1-9][0-9]*|0|0[xX][0-9a-fA-F]+|0[0-7]+|([0-9]*(\.[0-9]*)?([Ee][+-]?[0-9]+)?)|inf|nan)$/,
  416. // Decimal numbers
  417. NUMBER_DEC: /^(?:[1-9][0-9]*|0)$/,
  418. // Hexadecimal numbers
  419. NUMBER_HEX: /^0[xX][0-9a-fA-F]+$/,
  420. // Octal numbers
  421. NUMBER_OCT: /^0[0-7]+$/,
  422. // Floating point numbers
  423. NUMBER_FLT: /^([0-9]*(\.[0-9]*)?([Ee][+-]?[0-9]+)?|inf|nan)$/,
  424. // Booleans
  425. BOOL: /^(?:true|false)$/i,
  426. // Id numbers
  427. ID: /^(?:[1-9][0-9]*|0|0[xX][0-9a-fA-F]+|0[0-7]+)$/,
  428. // Negative id numbers (enum values)
  429. NEGID: /^\-?(?:[1-9][0-9]*|0|0[xX][0-9a-fA-F]+|0[0-7]+)$/,
  430. // Whitespaces
  431. WHITESPACE: /\s/,
  432. // All strings
  433. STRING: /(?:"([^"\\]*(?:\\.[^"\\]*)*)")|(?:'([^'\\]*(?:\\.[^'\\]*)*)')/g,
  434. // Double quoted strings
  435. STRING_DQ: /(?:"([^"\\]*(?:\\.[^"\\]*)*)")/g,
  436. // Single quoted strings
  437. STRING_SQ: /(?:'([^'\\]*(?:\\.[^'\\]*)*)')/g
  438. };
  439. /**
  440. * @alias ProtoBuf.DotProto
  441. * @expose
  442. */
  443. ProtoBuf.DotProto = (function(ProtoBuf, Lang) {
  444. "use strict";
  445. /**
  446. * Utilities to parse .proto files.
  447. * @exports ProtoBuf.DotProto
  448. * @namespace
  449. */
  450. var DotProto = {};
  451. /**
  452. * Constructs a new Tokenizer.
  453. * @exports ProtoBuf.DotProto.Tokenizer
  454. * @class prototype tokenizer
  455. * @param {string} proto Proto to tokenize
  456. * @constructor
  457. */
  458. var Tokenizer = function(proto) {
  459. /**
  460. * Source to parse.
  461. * @type {string}
  462. * @expose
  463. */
  464. this.source = proto+"";
  465. /**
  466. * Current index.
  467. * @type {number}
  468. * @expose
  469. */
  470. this.index = 0;
  471. /**
  472. * Current line.
  473. * @type {number}
  474. * @expose
  475. */
  476. this.line = 1;
  477. /**
  478. * Token stack.
  479. * @type {!Array.&lt;string>}
  480. * @expose
  481. */
  482. this.stack = [];
  483. /**
  484. * Opening character of the current string read, if any.
  485. * @type {?string}
  486. * @private
  487. */
  488. this._stringOpen = null;
  489. };
  490. /**
  491. * @alias ProtoBuf.DotProto.Tokenizer.prototype
  492. * @inner
  493. */
  494. var TokenizerPrototype = Tokenizer.prototype;
  495. /**
  496. * Reads a string beginning at the current index.
  497. * @return {string}
  498. * @private
  499. */
  500. TokenizerPrototype._readString = function() {
  501. var re = this._stringOpen === '"'
  502. ? Lang.STRING_DQ
  503. : Lang.STRING_SQ;
  504. re.lastIndex = this.index - 1; // Include the open quote
  505. var match = re.exec(this.source);
  506. if (!match)
  507. throw Error("unterminated string");
  508. this.index = re.lastIndex;
  509. this.stack.push(this._stringOpen);
  510. this._stringOpen = null;
  511. return match[1];
  512. };
  513. /**
  514. * Gets the next token and advances by one.
  515. * @return {?string} Token or `null` on EOF
  516. * @expose
  517. */
  518. TokenizerPrototype.next = function() {
  519. if (this.stack.length > 0)
  520. return this.stack.shift();
  521. if (this.index >= this.source.length)
  522. return null;
  523. if (this._stringOpen !== null)
  524. return this._readString();
  525. var repeat,
  526. prev,
  527. next;
  528. do {
  529. repeat = false;
  530. // Strip white spaces
  531. while (Lang.WHITESPACE.test(next = this.source.charAt(this.index))) {
  532. if (next === '\n')
  533. ++this.line;
  534. if (++this.index === this.source.length)
  535. return null;
  536. }
  537. // Strip comments
  538. if (this.source.charAt(this.index) === '/') {
  539. ++this.index;
  540. if (this.source.charAt(this.index) === '/') { // Line
  541. while (this.source.charAt(++this.index) !== '\n')
  542. if (this.index == this.source.length)
  543. return null;
  544. ++this.index;
  545. ++this.line;
  546. repeat = true;
  547. } else if ((next = this.source.charAt(this.index)) === '*') { /* Block */
  548. do {
  549. if (next === '\n')
  550. ++this.line;
  551. if (++this.index === this.source.length)
  552. return null;
  553. prev = next;
  554. next = this.source.charAt(this.index);
  555. } while (prev !== '*' || next !== '/');
  556. ++this.index;
  557. repeat = true;
  558. } else
  559. return '/';
  560. }
  561. } while (repeat);
  562. if (this.index === this.source.length)
  563. return null;
  564. // Read the next token
  565. var end = this.index;
  566. Lang.DELIM.lastIndex = 0;
  567. var delim = Lang.DELIM.test(this.source.charAt(end++));
  568. if (!delim)
  569. while(end &lt; this.source.length &amp;&amp; !Lang.DELIM.test(this.source.charAt(end)))
  570. ++end;
  571. var token = this.source.substring(this.index, this.index = end);
  572. if (token === '"' || token === "'")
  573. this._stringOpen = token;
  574. return token;
  575. };
  576. /**
  577. * Peeks for the next token.
  578. * @return {?string} Token or `null` on EOF
  579. * @expose
  580. */
  581. TokenizerPrototype.peek = function() {
  582. if (this.stack.length === 0) {
  583. var token = this.next();
  584. if (token === null)
  585. return null;
  586. this.stack.push(token);
  587. }
  588. return this.stack[0];
  589. };
  590. /**
  591. * Skips a specific token and throws if it differs.
  592. * @param {string} expected Expected token
  593. * @throws {Error} If the actual token differs
  594. */
  595. TokenizerPrototype.skip = function(expected) {
  596. var actual = this.next();
  597. if (actual !== expected)
  598. throw Error("illegal '"+actual+"', '"+expected+"' expected");
  599. };
  600. /**
  601. * Omits an optional token.
  602. * @param {string} expected Expected optional token
  603. * @returns {boolean} `true` if the token exists
  604. */
  605. TokenizerPrototype.omit = function(expected) {
  606. if (this.peek() === expected) {
  607. this.next();
  608. return true;
  609. }
  610. return false;
  611. };
  612. /**
  613. * Returns a string representation of this object.
  614. * @return {string} String representation as of "Tokenizer(index/length)"
  615. * @expose
  616. */
  617. TokenizerPrototype.toString = function() {
  618. return "Tokenizer ("+this.index+"/"+this.source.length+" at line "+this.line+")";
  619. };
  620. /**
  621. * @alias ProtoBuf.DotProto.Tokenizer
  622. * @expose
  623. */
  624. DotProto.Tokenizer = Tokenizer;
  625. /**
  626. * Constructs a new Parser.
  627. * @exports ProtoBuf.DotProto.Parser
  628. * @class prototype parser
  629. * @param {string} source Source
  630. * @constructor
  631. */
  632. var Parser = function(source) {
  633. /**
  634. * Tokenizer.
  635. * @type {!ProtoBuf.DotProto.Tokenizer}
  636. * @expose
  637. */
  638. this.tn = new Tokenizer(source);
  639. /**
  640. * Whether parsing proto3 or not.
  641. * @type {boolean}
  642. */
  643. this.proto3 = false;
  644. };
  645. /**
  646. * @alias ProtoBuf.DotProto.Parser.prototype
  647. * @inner
  648. */
  649. var ParserPrototype = Parser.prototype;
  650. /**
  651. * Parses the source.
  652. * @returns {!Object}
  653. * @throws {Error} If the source cannot be parsed
  654. * @expose
  655. */
  656. ParserPrototype.parse = function() {
  657. var topLevel = {
  658. "name": "[ROOT]", // temporary
  659. "package": null,
  660. "messages": [],
  661. "enums": [],
  662. "imports": [],
  663. "options": {},
  664. "services": []
  665. // "syntax": undefined
  666. };
  667. var token,
  668. head = true,
  669. weak;
  670. try {
  671. while (token = this.tn.next()) {
  672. switch (token) {
  673. case 'package':
  674. if (!head || topLevel["package"] !== null)
  675. throw Error("unexpected 'package'");
  676. token = this.tn.next();
  677. if (!Lang.TYPEREF.test(token))
  678. throw Error("illegal package name: " + token);
  679. this.tn.skip(";");
  680. topLevel["package"] = token;
  681. break;
  682. case 'import':
  683. if (!head)
  684. throw Error("unexpected 'import'");
  685. token = this.tn.peek();
  686. if (token === "public" || (weak = token === "weak")) // token ignored
  687. this.tn.next();
  688. token = this._readString();
  689. this.tn.skip(";");
  690. if (!weak) // import ignored
  691. topLevel["imports"].push(token);
  692. break;
  693. case 'syntax':
  694. if (!head)
  695. throw Error("unexpected 'syntax'");
  696. this.tn.skip("=");
  697. if ((topLevel["syntax"] = this._readString()) === "proto3")
  698. this.proto3 = true;
  699. this.tn.skip(";");
  700. break;
  701. case 'message':
  702. this._parseMessage(topLevel, null);
  703. head = false;
  704. break;
  705. case 'enum':
  706. this._parseEnum(topLevel);
  707. head = false;
  708. break;
  709. case 'option':
  710. this._parseOption(topLevel);
  711. break;
  712. case 'service':
  713. this._parseService(topLevel);
  714. break;
  715. case 'extend':
  716. this._parseExtend(topLevel);
  717. break;
  718. default:
  719. throw Error("unexpected '" + token + "'");
  720. }
  721. }
  722. } catch (e) {
  723. e.message = "Parse error at line "+this.tn.line+": " + e.message;
  724. throw e;
  725. }
  726. delete topLevel["name"];
  727. return topLevel;
  728. };
  729. /**
  730. * Parses the specified source.
  731. * @returns {!Object}
  732. * @throws {Error} If the source cannot be parsed
  733. * @expose
  734. */
  735. Parser.parse = function(source) {
  736. return new Parser(source).parse();
  737. };
  738. // ----- Conversion ------
  739. /**
  740. * Converts a numerical string to an id.
  741. * @param {string} value
  742. * @param {boolean=} mayBeNegative
  743. * @returns {number}
  744. * @inner
  745. */
  746. function mkId(value, mayBeNegative) {
  747. var id = -1,
  748. sign = 1;
  749. if (value.charAt(0) == '-') {
  750. sign = -1;
  751. value = value.substring(1);
  752. }
  753. if (Lang.NUMBER_DEC.test(value))
  754. id = parseInt(value);
  755. else if (Lang.NUMBER_HEX.test(value))
  756. id = parseInt(value.substring(2), 16);
  757. else if (Lang.NUMBER_OCT.test(value))
  758. id = parseInt(value.substring(1), 8);
  759. else
  760. throw Error("illegal id value: " + (sign &lt; 0 ? '-' : '') + value);
  761. id = (sign*id)|0; // Force to 32bit
  762. if (!mayBeNegative &amp;&amp; id &lt; 0)
  763. throw Error("illegal id value: " + (sign &lt; 0 ? '-' : '') + value);
  764. return id;
  765. }
  766. /**
  767. * Converts a numerical string to a number.
  768. * @param {string} val
  769. * @returns {number}
  770. * @inner
  771. */
  772. function mkNumber(val) {
  773. var sign = 1;
  774. if (val.charAt(0) == '-') {
  775. sign = -1;
  776. val = val.substring(1);
  777. }
  778. if (Lang.NUMBER_DEC.test(val))
  779. return sign * parseInt(val, 10);
  780. else if (Lang.NUMBER_HEX.test(val))
  781. return sign * parseInt(val.substring(2), 16);
  782. else if (Lang.NUMBER_OCT.test(val))
  783. return sign * parseInt(val.substring(1), 8);
  784. else if (val === 'inf')
  785. return sign * Infinity;
  786. else if (val === 'nan')
  787. return NaN;
  788. else if (Lang.NUMBER_FLT.test(val))
  789. return sign * parseFloat(val);
  790. throw Error("illegal number value: " + (sign &lt; 0 ? '-' : '') + val);
  791. }
  792. // ----- Reading ------
  793. /**
  794. * Reads a string.
  795. * @returns {string}
  796. * @private
  797. */
  798. ParserPrototype._readString = function() {
  799. var value = "",
  800. token,
  801. delim;
  802. do {
  803. delim = this.tn.next();
  804. if (delim !== "'" &amp;&amp; delim !== '"')
  805. throw Error("illegal string delimiter: "+delim);
  806. value += this.tn.next();
  807. this.tn.skip(delim);
  808. token = this.tn.peek();
  809. } while (token === '"' || token === '"'); // multi line?
  810. return value;
  811. };
  812. /**
  813. * Reads a value.
  814. * @param {boolean=} mayBeTypeRef
  815. * @returns {number|boolean|string}
  816. * @private
  817. */
  818. ParserPrototype._readValue = function(mayBeTypeRef) {
  819. var token = this.tn.peek(),
  820. value;
  821. if (token === '"' || token === "'")
  822. return this._readString();
  823. this.tn.next();
  824. if (Lang.NUMBER.test(token))
  825. return mkNumber(token);
  826. if (Lang.BOOL.test(token))
  827. return (token.toLowerCase() === 'true');
  828. if (mayBeTypeRef &amp;&amp; Lang.TYPEREF.test(token))
  829. return token;
  830. throw Error("illegal value: "+token);
  831. };
  832. // ----- Parsing constructs -----
  833. /**
  834. * Parses a namespace option.
  835. * @param {!Object} parent Parent definition
  836. * @param {boolean=} isList
  837. * @private
  838. */
  839. ParserPrototype._parseOption = function(parent, isList) {
  840. var token = this.tn.next(),
  841. custom = false;
  842. if (token === '(') {
  843. custom = true;
  844. token = this.tn.next();
  845. }
  846. if (!Lang.TYPEREF.test(token))
  847. // we can allow options of the form google.protobuf.* since they will just get ignored anyways
  848. // if (!/google\.protobuf\./.test(token)) // FIXME: Why should that not be a valid typeref?
  849. throw Error("illegal option name: "+token);
  850. var name = token;
  851. if (custom) { // (my_method_option).foo, (my_method_option), some_method_option, (foo.my_option).bar
  852. this.tn.skip(')');
  853. name = '('+name+')';
  854. token = this.tn.peek();
  855. if (Lang.FQTYPEREF.test(token)) {
  856. name += token;
  857. this.tn.next();
  858. }
  859. }
  860. this.tn.skip('=');
  861. this._parseOptionValue(parent, name);
  862. if (!isList)
  863. this.tn.skip(";");
  864. };
  865. /**
  866. * Sets an option on the specified options object.
  867. * @param {!Object.&lt;string,*>} options
  868. * @param {string} name
  869. * @param {string|number|boolean} value
  870. * @inner
  871. */
  872. function setOption(options, name, value) {
  873. if (typeof options[name] === 'undefined')
  874. options[name] = value;
  875. else {
  876. if (!Array.isArray(options[name]))
  877. options[name] = [ options[name] ];
  878. options[name].push(value);
  879. }
  880. }
  881. /**
  882. * Parses an option value.
  883. * @param {!Object} parent
  884. * @param {string} name
  885. * @private
  886. */
  887. ParserPrototype._parseOptionValue = function(parent, name) {
  888. var token = this.tn.peek();
  889. if (token !== '{') { // Plain value
  890. setOption(parent["options"], name, this._readValue(true));
  891. } else { // Aggregate options
  892. this.tn.skip("{");
  893. while ((token = this.tn.next()) !== '}') {
  894. if (!Lang.NAME.test(token))
  895. throw Error("illegal option name: " + name + "." + token);
  896. if (this.tn.omit(":"))
  897. setOption(parent["options"], name + "." + token, this._readValue(true));
  898. else
  899. this._parseOptionValue(parent, name + "." + token);
  900. }
  901. }
  902. };
  903. /**
  904. * Parses a service definition.
  905. * @param {!Object} parent Parent definition
  906. * @private
  907. */
  908. ParserPrototype._parseService = function(parent) {
  909. var token = this.tn.next();
  910. if (!Lang.NAME.test(token))
  911. throw Error("illegal service name at line "+this.tn.line+": "+token);
  912. var name = token;
  913. var svc = {
  914. "name": name,
  915. "rpc": {},
  916. "options": {}
  917. };
  918. this.tn.skip("{");
  919. while ((token = this.tn.next()) !== '}') {
  920. if (token === "option")
  921. this._parseOption(svc);
  922. else if (token === 'rpc')
  923. this._parseServiceRPC(svc);
  924. else
  925. throw Error("illegal service token: "+token);
  926. }
  927. this.tn.omit(";");
  928. parent["services"].push(svc);
  929. };
  930. /**
  931. * Parses a RPC service definition of the form ['rpc', name, (request), 'returns', (response)].
  932. * @param {!Object} svc Service definition
  933. * @private
  934. */
  935. ParserPrototype._parseServiceRPC = function(svc) {
  936. var type = "rpc",
  937. token = this.tn.next();
  938. if (!Lang.NAME.test(token))
  939. throw Error("illegal rpc service method name: "+token);
  940. var name = token;
  941. var method = {
  942. "request": null,
  943. "response": null,
  944. "request_stream": false,
  945. "response_stream": false,
  946. "options": {}
  947. };
  948. this.tn.skip("(");
  949. token = this.tn.next();
  950. if (token.toLowerCase() === "stream") {
  951. method["request_stream"] = true;
  952. token = this.tn.next();
  953. }
  954. if (!Lang.TYPEREF.test(token))
  955. throw Error("illegal rpc service request type: "+token);
  956. method["request"] = token;
  957. this.tn.skip(")");
  958. token = this.tn.next();
  959. if (token.toLowerCase() !== "returns")
  960. throw Error("illegal rpc service request type delimiter: "+token);
  961. this.tn.skip("(");
  962. token = this.tn.next();
  963. if (token.toLowerCase() === "stream") {
  964. method["response_stream"] = true;
  965. token = this.tn.next();
  966. }
  967. method["response"] = token;
  968. this.tn.skip(")");
  969. token = this.tn.peek();
  970. if (token === '{') {
  971. this.tn.next();
  972. while ((token = this.tn.next()) !== '}') {
  973. if (token === 'option')
  974. this._parseOption(method);
  975. else
  976. throw Error("illegal rpc service token: " + token);
  977. }
  978. this.tn.omit(";");
  979. } else
  980. this.tn.skip(";");
  981. if (typeof svc[type] === 'undefined')
  982. svc[type] = {};
  983. svc[type][name] = method;
  984. };
  985. /**
  986. * Parses a message definition.
  987. * @param {!Object} parent Parent definition
  988. * @param {!Object=} fld Field definition if this is a group
  989. * @returns {!Object}
  990. * @private
  991. */
  992. ParserPrototype._parseMessage = function(parent, fld) {
  993. var isGroup = !!fld,
  994. token = this.tn.next();
  995. var msg = {
  996. "name": "",
  997. "fields": [],
  998. "enums": [],
  999. "messages": [],
  1000. "options": {},
  1001. "services": [],
  1002. "oneofs": {}
  1003. // "extensions": undefined
  1004. };
  1005. if (!Lang.NAME.test(token))
  1006. throw Error("illegal "+(isGroup ? "group" : "message")+" name: "+token);
  1007. msg["name"] = token;
  1008. if (isGroup) {
  1009. this.tn.skip("=");
  1010. fld["id"] = mkId(this.tn.next());
  1011. msg["isGroup"] = true;
  1012. }
  1013. token = this.tn.peek();
  1014. if (token === '[' &amp;&amp; fld)
  1015. this._parseFieldOptions(fld);
  1016. this.tn.skip("{");
  1017. while ((token = this.tn.next()) !== '}') {
  1018. if (Lang.RULE.test(token))
  1019. this._parseMessageField(msg, token);
  1020. else if (token === "oneof")
  1021. this._parseMessageOneOf(msg);
  1022. else if (token === "enum")
  1023. this._parseEnum(msg);
  1024. else if (token === "message")
  1025. this._parseMessage(msg);
  1026. else if (token === "option")
  1027. this._parseOption(msg);
  1028. else if (token === "service")
  1029. this._parseService(msg);
  1030. else if (token === "extensions")
  1031. if (msg.hasOwnProperty("extensions")) {
  1032. msg["extensions"] = msg["extensions"].concat(this._parseExtensionRanges())
  1033. } else {
  1034. msg["extensions"] = this._parseExtensionRanges();
  1035. }
  1036. else if (token === "reserved")
  1037. this._parseIgnored(); // TODO
  1038. else if (token === "extend")
  1039. this._parseExtend(msg);
  1040. else if (Lang.TYPEREF.test(token)) {
  1041. if (!this.proto3)
  1042. throw Error("illegal field rule: "+token);
  1043. this._parseMessageField(msg, "optional", token);
  1044. } else
  1045. throw Error("illegal message token: "+token);
  1046. }
  1047. this.tn.omit(";");
  1048. parent["messages"].push(msg);
  1049. return msg;
  1050. };
  1051. /**
  1052. * Parses an ignored statement.
  1053. * @private
  1054. */
  1055. ParserPrototype._parseIgnored = function() {
  1056. while (this.tn.peek() !== ';')
  1057. this.tn.next();
  1058. this.tn.skip(";");
  1059. };
  1060. /**
  1061. * Parses a message field.
  1062. * @param {!Object} msg Message definition
  1063. * @param {string} rule Field rule
  1064. * @param {string=} type Field type if already known (never known for maps)
  1065. * @returns {!Object} Field descriptor
  1066. * @private
  1067. */
  1068. ParserPrototype._parseMessageField = function(msg, rule, type) {
  1069. if (!Lang.RULE.test(rule))
  1070. throw Error("illegal message field rule: "+rule);
  1071. var fld = {
  1072. "rule": rule,
  1073. "type": "",
  1074. "name": "",
  1075. "options": {},
  1076. "id": 0
  1077. };
  1078. var token;
  1079. if (rule === "map") {
  1080. if (type)
  1081. throw Error("illegal type: " + type);
  1082. this.tn.skip('&lt;');
  1083. token = this.tn.next();
  1084. if (!Lang.TYPE.test(token) &amp;&amp; !Lang.TYPEREF.test(token))
  1085. throw Error("illegal message field type: " + token);
  1086. fld["keytype"] = token;
  1087. this.tn.skip(',');
  1088. token = this.tn.next();
  1089. if (!Lang.TYPE.test(token) &amp;&amp; !Lang.TYPEREF.test(token))
  1090. throw Error("illegal message field: " + token);
  1091. fld["type"] = token;
  1092. this.tn.skip('>');
  1093. token = this.tn.next();
  1094. if (!Lang.NAME.test(token))
  1095. throw Error("illegal message field name: " + token);
  1096. fld["name"] = token;
  1097. this.tn.skip("=");
  1098. fld["id"] = mkId(this.tn.next());
  1099. token = this.tn.peek();
  1100. if (token === '[')
  1101. this._parseFieldOptions(fld);
  1102. this.tn.skip(";");
  1103. } else {
  1104. type = typeof type !== 'undefined' ? type : this.tn.next();
  1105. if (type === "group") {
  1106. // "A [legacy] group simply combines a nested message type and a field into a single declaration. In your
  1107. // code, you can treat this message just as if it had a Result type field called result (the latter name is
  1108. // converted to lower-case so that it does not conflict with the former)."
  1109. var grp = this._parseMessage(msg, fld);
  1110. if (!/^[A-Z]/.test(grp["name"]))
  1111. throw Error('illegal group name: '+grp["name"]);
  1112. fld["type"] = grp["name"];
  1113. fld["name"] = grp["name"].toLowerCase();
  1114. this.tn.omit(";");
  1115. } else {
  1116. if (!Lang.TYPE.test(type) &amp;&amp; !Lang.TYPEREF.test(type))
  1117. throw Error("illegal message field type: " + type);
  1118. fld["type"] = type;
  1119. token = this.tn.next();
  1120. if (!Lang.NAME.test(token))
  1121. throw Error("illegal message field name: " + token);
  1122. fld["name"] = token;
  1123. this.tn.skip("=");
  1124. fld["id"] = mkId(this.tn.next());
  1125. token = this.tn.peek();
  1126. if (token === "[")
  1127. this._parseFieldOptions(fld);
  1128. this.tn.skip(";");
  1129. }
  1130. }
  1131. msg["fields"].push(fld);
  1132. return fld;
  1133. };
  1134. /**
  1135. * Parses a message oneof.
  1136. * @param {!Object} msg Message definition
  1137. * @private
  1138. */
  1139. ParserPrototype._parseMessageOneOf = function(msg) {
  1140. var token = this.tn.next();
  1141. if (!Lang.NAME.test(token))
  1142. throw Error("illegal oneof name: "+token);
  1143. var name = token,
  1144. fld;
  1145. var fields = [];
  1146. this.tn.skip("{");
  1147. while ((token = this.tn.next()) !== "}") {
  1148. fld = this._parseMessageField(msg, "optional", token);
  1149. fld["oneof"] = name;
  1150. fields.push(fld["id"]);
  1151. }
  1152. this.tn.omit(";");
  1153. msg["oneofs"][name] = fields;
  1154. };
  1155. /**
  1156. * Parses a set of field option definitions.
  1157. * @param {!Object} fld Field definition
  1158. * @private
  1159. */
  1160. ParserPrototype._parseFieldOptions = function(fld) {
  1161. this.tn.skip("[");
  1162. var token,
  1163. first = true;
  1164. while ((token = this.tn.peek()) !== ']') {
  1165. if (!first)
  1166. this.tn.skip(",");
  1167. this._parseOption(fld, true);
  1168. first = false;
  1169. }
  1170. this.tn.next();
  1171. };
  1172. /**
  1173. * Parses an enum.
  1174. * @param {!Object} msg Message definition
  1175. * @private
  1176. */
  1177. ParserPrototype._parseEnum = function(msg) {
  1178. var enm = {
  1179. "name": "",
  1180. "values": [],
  1181. "options": {}
  1182. };
  1183. var token = this.tn.next();
  1184. if (!Lang.NAME.test(token))
  1185. throw Error("illegal name: "+token);
  1186. enm["name"] = token;
  1187. this.tn.skip("{");
  1188. while ((token = this.tn.next()) !== '}') {
  1189. if (token === "option")
  1190. this._parseOption(enm);
  1191. else {
  1192. if (!Lang.NAME.test(token))
  1193. throw Error("illegal name: "+token);
  1194. this.tn.skip("=");
  1195. var val = {
  1196. "name": token,
  1197. "id": mkId(this.tn.next(), true)
  1198. };
  1199. token = this.tn.peek();
  1200. if (token === "[")
  1201. this._parseFieldOptions({ "options": {} });
  1202. this.tn.skip(";");
  1203. enm["values"].push(val);
  1204. }
  1205. }
  1206. this.tn.omit(";");
  1207. msg["enums"].push(enm);
  1208. };
  1209. /**
  1210. * Parses extension / reserved ranges.
  1211. * @returns {!Array.&lt;!Array.&lt;number>>}
  1212. * @private
  1213. */
  1214. ParserPrototype._parseExtensionRanges = function() {
  1215. var ranges = [];
  1216. var token,
  1217. range,
  1218. value;
  1219. do {
  1220. range = [];
  1221. while (true) {
  1222. token = this.tn.next();
  1223. switch (token) {
  1224. case "min":
  1225. value = ProtoBuf.ID_MIN;
  1226. break;
  1227. case "max":
  1228. value = ProtoBuf.ID_MAX;
  1229. break;
  1230. default:
  1231. value = mkNumber(token);
  1232. break;
  1233. }
  1234. range.push(value);
  1235. if (range.length === 2)
  1236. break;
  1237. if (this.tn.peek() !== "to") {
  1238. range.push(value);
  1239. break;
  1240. }
  1241. this.tn.next();
  1242. }
  1243. ranges.push(range);
  1244. } while (this.tn.omit(","));
  1245. this.tn.skip(";");
  1246. return ranges;
  1247. };
  1248. /**
  1249. * Parses an extend block.
  1250. * @param {!Object} parent Parent object
  1251. * @private
  1252. */
  1253. ParserPrototype._parseExtend = function(parent) {
  1254. var token = this.tn.next();
  1255. if (!Lang.TYPEREF.test(token))
  1256. throw Error("illegal extend reference: "+token);
  1257. var ext = {
  1258. "ref": token,
  1259. "fields": []
  1260. };
  1261. this.tn.skip("{");
  1262. while ((token = this.tn.next()) !== '}') {
  1263. if (Lang.RULE.test(token))
  1264. this._parseMessageField(ext, token);
  1265. else if (Lang.TYPEREF.test(token)) {
  1266. if (!this.proto3)
  1267. throw Error("illegal field rule: "+token);
  1268. this._parseMessageField(ext, "optional", token);
  1269. } else
  1270. throw Error("illegal extend token: "+token);
  1271. }
  1272. this.tn.omit(";");
  1273. parent["messages"].push(ext);
  1274. return ext;
  1275. };
  1276. // ----- General -----
  1277. /**
  1278. * Returns a string representation of this parser.
  1279. * @returns {string}
  1280. */
  1281. ParserPrototype.toString = function() {
  1282. return "Parser at line "+this.tn.line;
  1283. };
  1284. /**
  1285. * @alias ProtoBuf.DotProto.Parser
  1286. * @expose
  1287. */
  1288. DotProto.Parser = Parser;
  1289. return DotProto;
  1290. })(ProtoBuf, ProtoBuf.Lang);
  1291. /**
  1292. * @alias ProtoBuf.Reflect
  1293. * @expose
  1294. */
  1295. ProtoBuf.Reflect = (function(ProtoBuf) {
  1296. "use strict";
  1297. /**
  1298. * Reflection types.
  1299. * @exports ProtoBuf.Reflect
  1300. * @namespace
  1301. */
  1302. var Reflect = {};
  1303. /**
  1304. * Constructs a Reflect base class.
  1305. * @exports ProtoBuf.Reflect.T
  1306. * @constructor
  1307. * @abstract
  1308. * @param {!ProtoBuf.Builder} builder Builder reference
  1309. * @param {?ProtoBuf.Reflect.T} parent Parent object
  1310. * @param {string} name Object name
  1311. */
  1312. var T = function(builder, parent, name) {
  1313. /**
  1314. * Builder reference.
  1315. * @type {!ProtoBuf.Builder}
  1316. * @expose
  1317. */
  1318. this.builder = builder;
  1319. /**
  1320. * Parent object.
  1321. * @type {?ProtoBuf.Reflect.T}
  1322. * @expose
  1323. */
  1324. this.parent = parent;
  1325. /**
  1326. * Object name in namespace.
  1327. * @type {string}
  1328. * @expose
  1329. */
  1330. this.name = name;
  1331. /**
  1332. * Fully qualified class name
  1333. * @type {string}
  1334. * @expose
  1335. */
  1336. this.className;
  1337. };
  1338. /**
  1339. * @alias ProtoBuf.Reflect.T.prototype
  1340. * @inner
  1341. */
  1342. var TPrototype = T.prototype;
  1343. /**
  1344. * Returns the fully qualified name of this object.
  1345. * @returns {string} Fully qualified name as of ".PATH.TO.THIS"
  1346. * @expose
  1347. */
  1348. TPrototype.fqn = function() {
  1349. var name = this.name,
  1350. ptr = this;
  1351. do {
  1352. ptr = ptr.parent;
  1353. if (ptr == null)
  1354. break;
  1355. name = ptr.name+"."+name;
  1356. } while (true);
  1357. return name;
  1358. };
  1359. /**
  1360. * Returns a string representation of this Reflect object (its fully qualified name).
  1361. * @param {boolean=} includeClass Set to true to include the class name. Defaults to false.
  1362. * @return String representation
  1363. * @expose
  1364. */
  1365. TPrototype.toString = function(includeClass) {
  1366. return (includeClass ? this.className + " " : "") + this.fqn();
  1367. };
  1368. /**
  1369. * Builds this type.
  1370. * @throws {Error} If this type cannot be built directly
  1371. * @expose
  1372. */
  1373. TPrototype.build = function() {
  1374. throw Error(this.toString(true)+" cannot be built directly");
  1375. };
  1376. /**
  1377. * @alias ProtoBuf.Reflect.T
  1378. * @expose
  1379. */
  1380. Reflect.T = T;
  1381. /**
  1382. * Constructs a new Namespace.
  1383. * @exports ProtoBuf.Reflect.Namespace
  1384. * @param {!ProtoBuf.Builder} builder Builder reference
  1385. * @param {?ProtoBuf.Reflect.Namespace} parent Namespace parent
  1386. * @param {string} name Namespace name
  1387. * @param {Object.&lt;string,*>=} options Namespace options
  1388. * @param {string?} syntax The syntax level of this definition (e.g., proto3)
  1389. * @constructor
  1390. * @extends ProtoBuf.Reflect.T
  1391. */
  1392. var Namespace = function(builder, parent, name, options, syntax) {
  1393. T.call(this, builder, parent, name);
  1394. /**
  1395. * @override
  1396. */
  1397. this.className = "Namespace";
  1398. /**
  1399. * Children inside the namespace.
  1400. * @type {!Array.&lt;ProtoBuf.Reflect.T>}
  1401. */
  1402. this.children = [];
  1403. /**
  1404. * Options.
  1405. * @type {!Object.&lt;string, *>}
  1406. */
  1407. this.options = options || {};
  1408. /**
  1409. * Syntax level (e.g., proto2 or proto3).
  1410. * @type {!string}
  1411. */
  1412. this.syntax = syntax || "proto2";
  1413. };
  1414. /**
  1415. * @alias ProtoBuf.Reflect.Namespace.prototype
  1416. * @inner
  1417. */
  1418. var NamespacePrototype = Namespace.prototype = Object.create(T.prototype);
  1419. /**
  1420. * Returns an array of the namespace's children.
  1421. * @param {ProtoBuf.Reflect.T=} type Filter type (returns instances of this type only). Defaults to null (all children).
  1422. * @return {Array.&lt;ProtoBuf.Reflect.T>}
  1423. * @expose
  1424. */
  1425. NamespacePrototype.getChildren = function(type) {
  1426. type = type || null;
  1427. if (type == null)
  1428. return this.children.slice();
  1429. var children = [];
  1430. for (var i=0, k=this.children.length; i&lt;k; ++i)
  1431. if (this.children[i] instanceof type)
  1432. children.push(this.children[i]);
  1433. return children;
  1434. };
  1435. /**
  1436. * Adds a child to the namespace.
  1437. * @param {ProtoBuf.Reflect.T} child Child
  1438. * @throws {Error} If the child cannot be added (duplicate)
  1439. * @expose
  1440. */
  1441. NamespacePrototype.addChild = function(child) {
  1442. var other;
  1443. if (other = this.getChild(child.name)) {
  1444. // Try to revert camelcase transformation on collision
  1445. if (other instanceof Message.Field &amp;&amp; other.name !== other.originalName &amp;&amp; this.getChild(other.originalName) === null)
  1446. other.name = other.originalName; // Revert previous first (effectively keeps both originals)
  1447. else if (child instanceof Message.Field &amp;&amp; child.name !== child.originalName &amp;&amp; this.getChild(child.originalName) === null)
  1448. child.name = child.originalName;
  1449. else
  1450. throw Error("Duplicate name in namespace "+this.toString(true)+": "+child.name);
  1451. }
  1452. this.children.push(child);
  1453. };
  1454. /**
  1455. * Gets a child by its name or id.
  1456. * @param {string|number} nameOrId Child name or id
  1457. * @return {?ProtoBuf.Reflect.T} The child or null if not found
  1458. * @expose
  1459. */
  1460. NamespacePrototype.getChild = function(nameOrId) {
  1461. var key = typeof nameOrId === 'number' ? 'id' : 'name';
  1462. for (var i=0, k=this.children.length; i&lt;k; ++i)
  1463. if (this.children[i][key] === nameOrId)
  1464. return this.children[i];
  1465. return null;
  1466. };
  1467. /**
  1468. * Resolves a reflect object inside of this namespace.
  1469. * @param {string|!Array.&lt;string>} qn Qualified name to resolve
  1470. * @param {boolean=} excludeNonNamespace Excludes non-namespace types, defaults to `false`
  1471. * @return {?ProtoBuf.Reflect.Namespace} The resolved type or null if not found
  1472. * @expose
  1473. */
  1474. NamespacePrototype.resolve = function(qn, excludeNonNamespace) {
  1475. var part = typeof qn === 'string' ? qn.split(".") : qn,
  1476. ptr = this,
  1477. i = 0;
  1478. if (part[i] === "") { // Fully qualified name, e.g. ".My.Message'
  1479. while (ptr.parent !== null)
  1480. ptr = ptr.parent;
  1481. i++;
  1482. }
  1483. var child;
  1484. do {
  1485. do {
  1486. if (!(ptr instanceof Reflect.Namespace)) {
  1487. ptr = null;
  1488. break;
  1489. }
  1490. child = ptr.getChild(part[i]);
  1491. if (!child || !(child instanceof Reflect.T) || (excludeNonNamespace &amp;&amp; !(child instanceof Reflect.Namespace))) {
  1492. ptr = null;
  1493. break;
  1494. }
  1495. ptr = child; i++;
  1496. } while (i &lt; part.length);
  1497. if (ptr != null)
  1498. break; // Found
  1499. // Else search the parent
  1500. if (this.parent !== null)
  1501. return this.parent.resolve(qn, excludeNonNamespace);
  1502. } while (ptr != null);
  1503. return ptr;
  1504. };
  1505. /**
  1506. * Determines the shortest qualified name of the specified type, if any, relative to this namespace.
  1507. * @param {!ProtoBuf.Reflect.T} t Reflection type
  1508. * @returns {string} The shortest qualified name or, if there is none, the fqn
  1509. * @expose
  1510. */
  1511. NamespacePrototype.qn = function(t) {
  1512. var part = [], ptr = t;
  1513. do {
  1514. part.unshift(ptr.name);
  1515. ptr = ptr.parent;
  1516. } while (ptr !== null);
  1517. for (var len=1; len &lt;= part.length; len++) {
  1518. var qn = part.slice(part.length-len);
  1519. if (t === this.resolve(qn, t instanceof Reflect.Namespace))
  1520. return qn.join(".");
  1521. }
  1522. return t.fqn();
  1523. };
  1524. /**
  1525. * Builds the namespace and returns the runtime counterpart.
  1526. * @return {Object.&lt;string,Function|Object>} Runtime namespace
  1527. * @expose
  1528. */
  1529. NamespacePrototype.build = function() {
  1530. /** @dict */
  1531. var ns = {};
  1532. var children = this.children;
  1533. for (var i=0, k=children.length, child; i&lt;k; ++i) {
  1534. child = children[i];
  1535. if (child instanceof Namespace)
  1536. ns[child.name] = child.build();
  1537. }
  1538. if (Object.defineProperty)
  1539. Object.defineProperty(ns, "$options", { "value": this.buildOpt() });
  1540. return ns;
  1541. };
  1542. /**
  1543. * Builds the namespace's '$options' property.
  1544. * @return {Object.&lt;string,*>}
  1545. */
  1546. NamespacePrototype.buildOpt = function() {
  1547. var opt = {},
  1548. keys = Object.keys(this.options);
  1549. for (var i=0, k=keys.length; i&lt;k; ++i) {
  1550. var key = keys[i],
  1551. val = this.options[keys[i]];
  1552. // TODO: Options are not resolved, yet.
  1553. // if (val instanceof Namespace) {
  1554. // opt[key] = val.build();
  1555. // } else {
  1556. opt[key] = val;
  1557. // }
  1558. }
  1559. return opt;
  1560. };
  1561. /**
  1562. * Gets the value assigned to the option with the specified name.
  1563. * @param {string=} name Returns the option value if specified, otherwise all options are returned.
  1564. * @return {*|Object.&lt;string,*>}null} Option value or NULL if there is no such option
  1565. */
  1566. NamespacePrototype.getOption = function(name) {
  1567. if (typeof name === 'undefined')
  1568. return this.options;
  1569. return typeof this.options[name] !== 'undefined' ? this.options[name] : null;
  1570. };
  1571. /**
  1572. * @alias ProtoBuf.Reflect.Namespace
  1573. * @expose
  1574. */
  1575. Reflect.Namespace = Namespace;
  1576. /**
  1577. * Constructs a new Element implementation that checks and converts values for a
  1578. * particular field type, as appropriate.
  1579. *
  1580. * An Element represents a single value: either the value of a singular field,
  1581. * or a value contained in one entry of a repeated field or map field. This
  1582. * class does not implement these higher-level concepts; it only encapsulates
  1583. * the low-level typechecking and conversion.
  1584. *
  1585. * @exports ProtoBuf.Reflect.Element
  1586. * @param {{name: string, wireType: number}} type Resolved data type
  1587. * @param {ProtoBuf.Reflect.T|null} resolvedType Resolved type, if relevant
  1588. * (e.g. submessage field).
  1589. * @param {boolean} isMapKey Is this element a Map key? The value will be
  1590. * converted to string form if so.
  1591. * @param {string} syntax Syntax level of defining message type, e.g.,
  1592. * proto2 or proto3.
  1593. * @param {string} name Name of the field containing this element (for error
  1594. * messages)
  1595. * @constructor
  1596. */
  1597. var Element = function(type, resolvedType, isMapKey, syntax, name) {
  1598. /**
  1599. * Element type, as a string (e.g., int32).
  1600. * @type {{name: string, wireType: number}}
  1601. */
  1602. this.type = type;
  1603. /**
  1604. * Element type reference to submessage or enum definition, if needed.
  1605. * @type {ProtoBuf.Reflect.T|null}
  1606. */
  1607. this.resolvedType = resolvedType;
  1608. /**
  1609. * Element is a map key.
  1610. * @type {boolean}
  1611. */
  1612. this.isMapKey = isMapKey;
  1613. /**
  1614. * Syntax level of defining message type, e.g., proto2 or proto3.
  1615. * @type {string}
  1616. */
  1617. this.syntax = syntax;
  1618. /**
  1619. * Name of the field containing this element (for error messages)
  1620. * @type {string}
  1621. */
  1622. this.name = name;
  1623. if (isMapKey &amp;&amp; ProtoBuf.MAP_KEY_TYPES.indexOf(type) &lt; 0)
  1624. throw Error("Invalid map key type: " + type.name);
  1625. };
  1626. var ElementPrototype = Element.prototype;
  1627. /**
  1628. * Obtains a (new) default value for the specified type.
  1629. * @param type {string|{name: string, wireType: number}} Field type
  1630. * @returns {*} Default value
  1631. * @inner
  1632. */
  1633. function mkDefault(type) {
  1634. if (typeof type === 'string')
  1635. type = ProtoBuf.TYPES[type];
  1636. if (typeof type.defaultValue === 'undefined')
  1637. throw Error("default value for type "+type.name+" is not supported");
  1638. if (type == ProtoBuf.TYPES["bytes"])
  1639. return new ByteBuffer(0);
  1640. return type.defaultValue;
  1641. }
  1642. /**
  1643. * Returns the default value for this field in proto3.
  1644. * @function
  1645. * @param type {string|{name: string, wireType: number}} the field type
  1646. * @returns {*} Default value
  1647. */
  1648. Element.defaultFieldValue = mkDefault;
  1649. /**
  1650. * Makes a Long from a value.
  1651. * @param {{low: number, high: number, unsigned: boolean}|string|number} value Value
  1652. * @param {boolean=} unsigned Whether unsigned or not, defaults to reuse it from Long-like objects or to signed for
  1653. * strings and numbers
  1654. * @returns {!Long}
  1655. * @throws {Error} If the value cannot be converted to a Long
  1656. * @inner
  1657. */
  1658. function mkLong(value, unsigned) {
  1659. if (value &amp;&amp; typeof value.low === 'number' &amp;&amp; typeof value.high === 'number' &amp;&amp; typeof value.unsigned === 'boolean'
  1660. &amp;&amp; value.low === value.low &amp;&amp; value.high === value.high)
  1661. return new ProtoBuf.Long(value.low, value.high, typeof unsigned === 'undefined' ? value.unsigned : unsigned);
  1662. if (typeof value === 'string')
  1663. return ProtoBuf.Long.fromString(value, unsigned || false, 10);
  1664. if (typeof value === 'number')
  1665. return ProtoBuf.Long.fromNumber(value, unsigned || false);
  1666. throw Error("not convertible to Long");
  1667. }
  1668. ElementPrototype.toString = function() {
  1669. return (this.name || '') + (this.isMapKey ? 'map' : 'value') + ' element';
  1670. }
  1671. /**
  1672. * Checks if the given value can be set for an element of this type (singular
  1673. * field or one element of a repeated field or map).
  1674. * @param {*} value Value to check
  1675. * @return {*} Verified, maybe adjusted, value
  1676. * @throws {Error} If the value cannot be verified for this element slot
  1677. * @expose
  1678. */
  1679. ElementPrototype.verifyValue = function(value) {
  1680. var self = this;
  1681. function fail(val, msg) {
  1682. throw Error("Illegal value for "+self.toString(true)+" of type "+self.type.name+": "+val+" ("+msg+")");
  1683. }
  1684. switch (this.type) {
  1685. // Signed 32bit
  1686. case ProtoBuf.TYPES["int32"]:
  1687. case ProtoBuf.TYPES["sint32"]:
  1688. case ProtoBuf.TYPES["sfixed32"]:
  1689. // Account for !NaN: value === value
  1690. if (typeof value !== 'number' || (value === value &amp;&amp; value % 1 !== 0))
  1691. fail(typeof value, "not an integer");
  1692. return value > 4294967295 ? value | 0 : value;
  1693. // Unsigned 32bit
  1694. case ProtoBuf.TYPES["uint32"]:
  1695. case ProtoBuf.TYPES["fixed32"]:
  1696. if (typeof value !== 'number' || (value === value &amp;&amp; value % 1 !== 0))
  1697. fail(typeof value, "not an integer");
  1698. return value &lt; 0 ? value >>> 0 : value;
  1699. // Signed 64bit
  1700. case ProtoBuf.TYPES["int64"]:
  1701. case ProtoBuf.TYPES["sint64"]:
  1702. case ProtoBuf.TYPES["sfixed64"]: {
  1703. if (ProtoBuf.Long)
  1704. try {
  1705. return mkLong(value, false);
  1706. } catch (e) {
  1707. fail(typeof value, e.message);
  1708. }
  1709. else
  1710. fail(typeof value, "requires Long.js");
  1711. }
  1712. // Unsigned 64bit
  1713. case ProtoBuf.TYPES["uint64"]:
  1714. case ProtoBuf.TYPES["fixed64"]: {
  1715. if (ProtoBuf.Long)
  1716. try {
  1717. return mkLong(value, true);
  1718. } catch (e) {
  1719. fail(typeof value, e.message);
  1720. }
  1721. else
  1722. fail(typeof value, "requires Long.js");
  1723. }
  1724. // Bool
  1725. case ProtoBuf.TYPES["bool"]:
  1726. if (typeof value !== 'boolean')
  1727. fail(typeof value, "not a boolean");
  1728. return value;
  1729. // Float
  1730. case ProtoBuf.TYPES["float"]:
  1731. case ProtoBuf.TYPES["double"]:
  1732. if (typeof value !== 'number')
  1733. fail(typeof value, "not a number");
  1734. return value;
  1735. // Length-delimited string
  1736. case ProtoBuf.TYPES["string"]:
  1737. if (typeof value !== 'string' &amp;&amp; !(value &amp;&amp; value instanceof String))
  1738. fail(typeof value, "not a string");
  1739. return ""+value; // Convert String object to string
  1740. // Length-delimited bytes
  1741. case ProtoBuf.TYPES["bytes"]:
  1742. if (ByteBuffer.isByteBuffer(value))
  1743. return value;
  1744. return ByteBuffer.wrap(value, "base64");
  1745. // Constant enum value
  1746. case ProtoBuf.TYPES["enum"]: {
  1747. var values = this.resolvedType.getChildren(ProtoBuf.Reflect.Enum.Value);
  1748. for (i=0; i&lt;values.length; i++)
  1749. if (values[i].name == value)
  1750. return values[i].id;
  1751. else if (values[i].id == value)
  1752. return values[i].id;
  1753. if (this.syntax === 'proto3') {
  1754. // proto3: just make sure it's an integer.
  1755. if (typeof value !== 'number' || (value === value &amp;&amp; value % 1 !== 0))
  1756. fail(typeof value, "not an integer");
  1757. if (value > 4294967295 || value &lt; 0)
  1758. fail(typeof value, "not in range for uint32")
  1759. return value;
  1760. } else {
  1761. // proto2 requires enum values to be valid.
  1762. fail(value, "not a valid enum value");
  1763. }
  1764. }
  1765. // Embedded message
  1766. case ProtoBuf.TYPES["group"]:
  1767. case ProtoBuf.TYPES["message"]: {
  1768. if (!value || typeof value !== 'object')
  1769. fail(typeof value, "object expected");
  1770. if (value instanceof this.resolvedType.clazz)
  1771. return value;
  1772. if (value instanceof ProtoBuf.Builder.Message) {
  1773. // Mismatched type: Convert to object (see: https://github.com/dcodeIO/ProtoBuf.js/issues/180)
  1774. var obj = {};
  1775. for (var i in value)
  1776. if (value.hasOwnProperty(i))
  1777. obj[i] = value[i];
  1778. value = obj;
  1779. }
  1780. // Else let's try to construct one from a key-value object
  1781. return new (this.resolvedType.clazz)(value); // May throw for a hundred of reasons
  1782. }
  1783. }
  1784. // We should never end here
  1785. throw Error("[INTERNAL] Illegal value for "+this.toString(true)+": "+value+" (undefined type "+this.type+")");
  1786. };
  1787. /**
  1788. * Calculates the byte length of an element on the wire.
  1789. * @param {number} id Field number
  1790. * @param {*} value Field value
  1791. * @returns {number} Byte length
  1792. * @throws {Error} If the value cannot be calculated
  1793. * @expose
  1794. */
  1795. ElementPrototype.calculateLength = function(id, value) {
  1796. if (value === null) return 0; // Nothing to encode
  1797. // Tag has already been written
  1798. var n;
  1799. switch (this.type) {
  1800. case ProtoBuf.TYPES["int32"]:
  1801. return value &lt; 0 ? ByteBuffer.calculateVarint64(value) : ByteBuffer.calculateVarint32(value);
  1802. case ProtoBuf.TYPES["uint32"]:
  1803. return ByteBuffer.calculateVarint32(value);
  1804. case ProtoBuf.TYPES["sint32"]:
  1805. return ByteBuffer.calculateVarint32(ByteBuffer.zigZagEncode32(value));
  1806. case ProtoBuf.TYPES["fixed32"]:
  1807. case ProtoBuf.TYPES["sfixed32"]:
  1808. case ProtoBuf.TYPES["float"]:
  1809. return 4;
  1810. case ProtoBuf.TYPES["int64"]:
  1811. case ProtoBuf.TYPES["uint64"]:
  1812. return ByteBuffer.calculateVarint64(value);
  1813. case ProtoBuf.TYPES["sint64"]:
  1814. return ByteBuffer.calculateVarint64(ByteBuffer.zigZagEncode64(value));
  1815. case ProtoBuf.TYPES["fixed64"]:
  1816. case ProtoBuf.TYPES["sfixed64"]:
  1817. return 8;
  1818. case ProtoBuf.TYPES["bool"]:
  1819. return 1;
  1820. case ProtoBuf.TYPES["enum"]:
  1821. return ByteBuffer.calculateVarint32(value);
  1822. case ProtoBuf.TYPES["double"]:
  1823. return 8;
  1824. case ProtoBuf.TYPES["string"]:
  1825. n = ByteBuffer.calculateUTF8Bytes(value);
  1826. return ByteBuffer.calculateVarint32(n) + n;
  1827. case ProtoBuf.TYPES["bytes"]:
  1828. if (value.remaining() &lt; 0)
  1829. throw Error("Illegal value for "+this.toString(true)+": "+value.remaining()+" bytes remaining");
  1830. return ByteBuffer.calculateVarint32(value.remaining()) + value.remaining();
  1831. case ProtoBuf.TYPES["message"]:
  1832. n = this.resolvedType.calculate(value);
  1833. return ByteBuffer.calculateVarint32(n) + n;
  1834. case ProtoBuf.TYPES["group"]:
  1835. n = this.resolvedType.calculate(value);
  1836. return n + ByteBuffer.calculateVarint32((id &lt;&lt; 3) | ProtoBuf.WIRE_TYPES.ENDGROUP);
  1837. }
  1838. // We should never end here
  1839. throw Error("[INTERNAL] Illegal value to encode in "+this.toString(true)+": "+value+" (unknown type)");
  1840. };
  1841. /**
  1842. * Encodes a value to the specified buffer. Does not encode the key.
  1843. * @param {number} id Field number
  1844. * @param {*} value Field value
  1845. * @param {ByteBuffer} buffer ByteBuffer to encode to
  1846. * @return {ByteBuffer} The ByteBuffer for chaining
  1847. * @throws {Error} If the value cannot be encoded
  1848. * @expose
  1849. */
  1850. ElementPrototype.encodeValue = function(id, value, buffer) {
  1851. if (value === null) return buffer; // Nothing to encode
  1852. // Tag has already been written
  1853. switch (this.type) {
  1854. // 32bit signed varint
  1855. case ProtoBuf.TYPES["int32"]:
  1856. // "If you use int32 or int64 as the type for a negative number, the resulting varint is always ten bytes
  1857. // long – it is, effectively, treated like a very large unsigned integer." (see #122)
  1858. if (value &lt; 0)
  1859. buffer.writeVarint64(value);
  1860. else
  1861. buffer.writeVarint32(value);
  1862. break;
  1863. // 32bit unsigned varint
  1864. case ProtoBuf.TYPES["uint32"]:
  1865. buffer.writeVarint32(value);
  1866. break;
  1867. // 32bit varint zig-zag
  1868. case ProtoBuf.TYPES["sint32"]:
  1869. buffer.writeVarint32ZigZag(value);
  1870. break;
  1871. // Fixed unsigned 32bit
  1872. case ProtoBuf.TYPES["fixed32"]:
  1873. buffer.writeUint32(value);
  1874. break;
  1875. // Fixed signed 32bit
  1876. case ProtoBuf.TYPES["sfixed32"]:
  1877. buffer.writeInt32(value);
  1878. break;
  1879. // 64bit varint as-is
  1880. case ProtoBuf.TYPES["int64"]:
  1881. case ProtoBuf.TYPES["uint64"]:
  1882. buffer.writeVarint64(value); // throws
  1883. break;
  1884. // 64bit varint zig-zag
  1885. case ProtoBuf.TYPES["sint64"]:
  1886. buffer.writeVarint64ZigZag(value); // throws
  1887. break;
  1888. // Fixed unsigned 64bit
  1889. case ProtoBuf.TYPES["fixed64"]:
  1890. buffer.writeUint64(value); // throws
  1891. break;
  1892. // Fixed signed 64bit
  1893. case ProtoBuf.TYPES["sfixed64"]:
  1894. buffer.writeInt64(value); // throws
  1895. break;
  1896. // Bool
  1897. case ProtoBuf.TYPES["bool"]:
  1898. if (typeof value === 'string')
  1899. buffer.writeVarint32(value.toLowerCase() === 'false' ? 0 : !!value);
  1900. else
  1901. buffer.writeVarint32(value ? 1 : 0);
  1902. break;
  1903. // Constant enum value
  1904. case ProtoBuf.TYPES["enum"]:
  1905. buffer.writeVarint32(value);
  1906. break;
  1907. // 32bit float
  1908. case ProtoBuf.TYPES["float"]:
  1909. buffer.writeFloat32(value);
  1910. break;
  1911. // 64bit float
  1912. case ProtoBuf.TYPES["double"]:
  1913. buffer.writeFloat64(value);
  1914. break;
  1915. // Length-delimited string
  1916. case ProtoBuf.TYPES["string"]:
  1917. buffer.writeVString(value);
  1918. break;
  1919. // Length-delimited bytes
  1920. case ProtoBuf.TYPES["bytes"]:
  1921. if (value.remaining() &lt; 0)
  1922. throw Error("Illegal value for "+this.toString(true)+": "+value.remaining()+" bytes remaining");
  1923. var prevOffset = value.offset;
  1924. buffer.writeVarint32(value.remaining());
  1925. buffer.append(value);
  1926. value.offset = prevOffset;
  1927. break;
  1928. // Embedded message
  1929. case ProtoBuf.TYPES["message"]:
  1930. var bb = new ByteBuffer().LE();
  1931. this.resolvedType.encode(value, bb);
  1932. buffer.writeVarint32(bb.offset);
  1933. buffer.append(bb.flip());
  1934. break;
  1935. // Legacy group
  1936. case ProtoBuf.TYPES["group"]:
  1937. this.resolvedType.encode(value, buffer);
  1938. buffer.writeVarint32((id &lt;&lt; 3) | ProtoBuf.WIRE_TYPES.ENDGROUP);
  1939. break;
  1940. default:
  1941. // We should never end here
  1942. throw Error("[INTERNAL] Illegal value to encode in "+this.toString(true)+": "+value+" (unknown type)");
  1943. }
  1944. return buffer;
  1945. };
  1946. /**
  1947. * Decode one element value from the specified buffer.
  1948. * @param {ByteBuffer} buffer ByteBuffer to decode from
  1949. * @param {number} wireType The field wire type
  1950. * @param {number} id The field number
  1951. * @return {*} Decoded value
  1952. * @throws {Error} If the field cannot be decoded
  1953. * @expose
  1954. */
  1955. ElementPrototype.decode = function(buffer, wireType, id) {
  1956. if (wireType != this.type.wireType)
  1957. throw Error("Unexpected wire type for element");
  1958. var value, nBytes;
  1959. switch (this.type) {
  1960. // 32bit signed varint
  1961. case ProtoBuf.TYPES["int32"]:
  1962. return buffer.readVarint32() | 0;
  1963. // 32bit unsigned varint
  1964. case ProtoBuf.TYPES["uint32"]:
  1965. return buffer.readVarint32() >>> 0;
  1966. // 32bit signed varint zig-zag
  1967. case ProtoBuf.TYPES["sint32"]:
  1968. return buffer.readVarint32ZigZag() | 0;
  1969. // Fixed 32bit unsigned
  1970. case ProtoBuf.TYPES["fixed32"]:
  1971. return buffer.readUint32() >>> 0;
  1972. case ProtoBuf.TYPES["sfixed32"]:
  1973. return buffer.readInt32() | 0;
  1974. // 64bit signed varint
  1975. case ProtoBuf.TYPES["int64"]:
  1976. return buffer.readVarint64();
  1977. // 64bit unsigned varint
  1978. case ProtoBuf.TYPES["uint64"]:
  1979. return buffer.readVarint64().toUnsigned();
  1980. // 64bit signed varint zig-zag
  1981. case ProtoBuf.TYPES["sint64"]:
  1982. return buffer.readVarint64ZigZag();
  1983. // Fixed 64bit unsigned
  1984. case ProtoBuf.TYPES["fixed64"]:
  1985. return buffer.readUint64();
  1986. // Fixed 64bit signed
  1987. case ProtoBuf.TYPES["sfixed64"]:
  1988. return buffer.readInt64();
  1989. // Bool varint
  1990. case ProtoBuf.TYPES["bool"]:
  1991. return !!buffer.readVarint32();
  1992. // Constant enum value (varint)
  1993. case ProtoBuf.TYPES["enum"]:
  1994. // The following Builder.Message#set will already throw
  1995. return buffer.readVarint32();
  1996. // 32bit float
  1997. case ProtoBuf.TYPES["float"]:
  1998. return buffer.readFloat();
  1999. // 64bit float
  2000. case ProtoBuf.TYPES["double"]:
  2001. return buffer.readDouble();
  2002. // Length-delimited string
  2003. case ProtoBuf.TYPES["string"]:
  2004. return buffer.readVString();
  2005. // Length-delimited bytes
  2006. case ProtoBuf.TYPES["bytes"]: {
  2007. nBytes = buffer.readVarint32();
  2008. if (buffer.remaining() &lt; nBytes)
  2009. throw Error("Illegal number of bytes for "+this.toString(true)+": "+nBytes+" required but got only "+buffer.remaining());
  2010. value = buffer.clone(); // Offset already set
  2011. value.limit = value.offset+nBytes;
  2012. buffer.offset += nBytes;
  2013. return value;
  2014. }
  2015. // Length-delimited embedded message
  2016. case ProtoBuf.TYPES["message"]: {
  2017. nBytes = buffer.readVarint32();
  2018. return this.resolvedType.decode(buffer, nBytes);
  2019. }
  2020. // Legacy group
  2021. case ProtoBuf.TYPES["group"]:
  2022. return this.resolvedType.decode(buffer, -1, id);
  2023. }
  2024. // We should never end here
  2025. throw Error("[INTERNAL] Illegal decode type");
  2026. };
  2027. /**
  2028. * Converts a value from a string to the canonical element type.
  2029. *
  2030. * Legal only when isMapKey is true.
  2031. *
  2032. * @param {string} str The string value
  2033. * @returns {*} The value
  2034. */
  2035. ElementPrototype.valueFromString = function(str) {
  2036. if (!this.isMapKey) {
  2037. throw Error("valueFromString() called on non-map-key element");
  2038. }
  2039. switch (this.type) {
  2040. case ProtoBuf.TYPES["int32"]:
  2041. case ProtoBuf.TYPES["sint32"]:
  2042. case ProtoBuf.TYPES["sfixed32"]:
  2043. case ProtoBuf.TYPES["uint32"]:
  2044. case ProtoBuf.TYPES["fixed32"]:
  2045. return this.verifyValue(parseInt(str));
  2046. case ProtoBuf.TYPES["int64"]:
  2047. case ProtoBuf.TYPES["sint64"]:
  2048. case ProtoBuf.TYPES["sfixed64"]:
  2049. case ProtoBuf.TYPES["uint64"]:
  2050. case ProtoBuf.TYPES["fixed64"]:
  2051. // Long-based fields support conversions from string already.
  2052. return this.verifyValue(str);
  2053. case ProtoBuf.TYPES["bool"]:
  2054. return str === "true";
  2055. case ProtoBuf.TYPES["string"]:
  2056. return this.verifyValue(str);
  2057. case ProtoBuf.TYPES["bytes"]:
  2058. return ByteBuffer.fromBinary(str);
  2059. }
  2060. };
  2061. /**
  2062. * Converts a value from the canonical element type to a string.
  2063. *
  2064. * It should be the case that `valueFromString(valueToString(val))` returns
  2065. * a value equivalent to `verifyValue(val)` for every legal value of `val`
  2066. * according to this element type.
  2067. *
  2068. * This may be used when the element must be stored or used as a string,
  2069. * e.g., as a map key on an Object.
  2070. *
  2071. * Legal only when isMapKey is true.
  2072. *
  2073. * @param {*} val The value
  2074. * @returns {string} The string form of the value.
  2075. */
  2076. ElementPrototype.valueToString = function(value) {
  2077. if (!this.isMapKey) {
  2078. throw Error("valueToString() called on non-map-key element");
  2079. }
  2080. if (this.type === ProtoBuf.TYPES["bytes"]) {
  2081. return value.toString("binary");
  2082. } else {
  2083. return value.toString();
  2084. }
  2085. };
  2086. /**
  2087. * @alias ProtoBuf.Reflect.Element
  2088. * @expose
  2089. */
  2090. Reflect.Element = Element;
  2091. /**
  2092. * Constructs a new Message.
  2093. * @exports ProtoBuf.Reflect.Message
  2094. * @param {!ProtoBuf.Builder} builder Builder reference
  2095. * @param {!ProtoBuf.Reflect.Namespace} parent Parent message or namespace
  2096. * @param {string} name Message name
  2097. * @param {Object.&lt;string,*>=} options Message options
  2098. * @param {boolean=} isGroup `true` if this is a legacy group
  2099. * @param {string?} syntax The syntax level of this definition (e.g., proto3)
  2100. * @constructor
  2101. * @extends ProtoBuf.Reflect.Namespace
  2102. */
  2103. var Message = function(builder, parent, name, options, isGroup, syntax) {
  2104. Namespace.call(this, builder, parent, name, options, syntax);
  2105. /**
  2106. * @override
  2107. */
  2108. this.className = "Message";
  2109. /**
  2110. * Extensions range.
  2111. * @type {!Array.&lt;number>|undefined}
  2112. * @expose
  2113. */
  2114. this.extensions = undefined;
  2115. /**
  2116. * Runtime message class.
  2117. * @type {?function(new:ProtoBuf.Builder.Message)}
  2118. * @expose
  2119. */
  2120. this.clazz = null;
  2121. /**
  2122. * Whether this is a legacy group or not.
  2123. * @type {boolean}
  2124. * @expose
  2125. */
  2126. this.isGroup = !!isGroup;
  2127. // The following cached collections are used to efficiently iterate over or look up fields when decoding.
  2128. /**
  2129. * Cached fields.
  2130. * @type {?Array.&lt;!ProtoBuf.Reflect.Message.Field>}
  2131. * @private
  2132. */
  2133. this._fields = null;
  2134. /**
  2135. * Cached fields by id.
  2136. * @type {?Object.&lt;number,!ProtoBuf.Reflect.Message.Field>}
  2137. * @private
  2138. */
  2139. this._fieldsById = null;
  2140. /**
  2141. * Cached fields by name.
  2142. * @type {?Object.&lt;string,!ProtoBuf.Reflect.Message.Field>}
  2143. * @private
  2144. */
  2145. this._fieldsByName = null;
  2146. };
  2147. /**
  2148. * @alias ProtoBuf.Reflect.Message.prototype
  2149. * @inner
  2150. */
  2151. var MessagePrototype = Message.prototype = Object.create(Namespace.prototype);
  2152. /**
  2153. * Builds the message and returns the runtime counterpart, which is a fully functional class.
  2154. * @see ProtoBuf.Builder.Message
  2155. * @param {boolean=} rebuild Whether to rebuild or not, defaults to false
  2156. * @return {ProtoBuf.Reflect.Message} Message class
  2157. * @throws {Error} If the message cannot be built
  2158. * @expose
  2159. */
  2160. MessagePrototype.build = function(rebuild) {
  2161. if (this.clazz &amp;&amp; !rebuild)
  2162. return this.clazz;
  2163. // Create the runtime Message class in its own scope
  2164. var clazz = (function(ProtoBuf, T) {
  2165. var fields = T.getChildren(ProtoBuf.Reflect.Message.Field),
  2166. oneofs = T.getChildren(ProtoBuf.Reflect.Message.OneOf);
  2167. /**
  2168. * Constructs a new runtime Message.
  2169. * @name ProtoBuf.Builder.Message
  2170. * @class Barebone of all runtime messages.
  2171. * @param {!Object.&lt;string,*>|string} values Preset values
  2172. * @param {...string} var_args
  2173. * @constructor
  2174. * @throws {Error} If the message cannot be created
  2175. */
  2176. var Message = function(values, var_args) {
  2177. ProtoBuf.Builder.Message.call(this);
  2178. // Create virtual oneof properties
  2179. for (var i=0, k=oneofs.length; i&lt;k; ++i)
  2180. this[oneofs[i].name] = null;
  2181. // Create fields and set default values
  2182. for (i=0, k=fields.length; i&lt;k; ++i) {
  2183. var field = fields[i];
  2184. this[field.name] =
  2185. field.repeated ? [] :
  2186. (field.map ? new ProtoBuf.Map(field) : null);
  2187. if ((field.required || T.syntax === 'proto3') &amp;&amp;
  2188. field.defaultValue !== null)
  2189. this[field.name] = field.defaultValue;
  2190. }
  2191. if (arguments.length > 0) {
  2192. var value;
  2193. // Set field values from a values object
  2194. if (arguments.length === 1 &amp;&amp; values !== null &amp;&amp; typeof values === 'object' &amp;&amp;
  2195. /* not _another_ Message */ (typeof values.encode !== 'function' || values instanceof Message) &amp;&amp;
  2196. /* not a repeated field */ !Array.isArray(values) &amp;&amp;
  2197. /* not a Map */ !(values instanceof ProtoBuf.Map) &amp;&amp;
  2198. /* not a ByteBuffer */ !ByteBuffer.isByteBuffer(values) &amp;&amp;
  2199. /* not an ArrayBuffer */ !(values instanceof ArrayBuffer) &amp;&amp;
  2200. /* not a Long */ !(ProtoBuf.Long &amp;&amp; values instanceof ProtoBuf.Long)) {
  2201. this.$set(values);
  2202. } else // Set field values from arguments, in declaration order
  2203. for (i=0, k=arguments.length; i&lt;k; ++i)
  2204. if (typeof (value = arguments[i]) !== 'undefined')
  2205. this.$set(fields[i].name, value); // May throw
  2206. }
  2207. };
  2208. /**
  2209. * @alias ProtoBuf.Builder.Message.prototype
  2210. * @inner
  2211. */
  2212. var MessagePrototype = Message.prototype = Object.create(ProtoBuf.Builder.Message.prototype);
  2213. /**
  2214. * Adds a value to a repeated field.
  2215. * @name ProtoBuf.Builder.Message#add
  2216. * @function
  2217. * @param {string} key Field name
  2218. * @param {*} value Value to add
  2219. * @param {boolean=} noAssert Whether to assert the value or not (asserts by default)
  2220. * @returns {!ProtoBuf.Builder.Message} this
  2221. * @throws {Error} If the value cannot be added
  2222. * @expose
  2223. */
  2224. MessagePrototype.add = function(key, value, noAssert) {
  2225. var field = T._fieldsByName[key];
  2226. if (!noAssert) {
  2227. if (!field)
  2228. throw Error(this+"#"+key+" is undefined");
  2229. if (!(field instanceof ProtoBuf.Reflect.Message.Field))
  2230. throw Error(this+"#"+key+" is not a field: "+field.toString(true)); // May throw if it's an enum or embedded message
  2231. if (!field.repeated)
  2232. throw Error(this+"#"+key+" is not a repeated field");
  2233. value = field.verifyValue(value, true);
  2234. }
  2235. if (this[key] === null)
  2236. this[key] = [];
  2237. this[key].push(value);
  2238. return this;
  2239. };
  2240. /**
  2241. * Adds a value to a repeated field. This is an alias for {@link ProtoBuf.Builder.Message#add}.
  2242. * @name ProtoBuf.Builder.Message#$add
  2243. * @function
  2244. * @param {string} key Field name
  2245. * @param {*} value Value to add
  2246. * @param {boolean=} noAssert Whether to assert the value or not (asserts by default)
  2247. * @returns {!ProtoBuf.Builder.Message} this
  2248. * @throws {Error} If the value cannot be added
  2249. * @expose
  2250. */
  2251. MessagePrototype.$add = MessagePrototype.add;
  2252. /**
  2253. * Sets a field's value.
  2254. * @name ProtoBuf.Builder.Message#set
  2255. * @function
  2256. * @param {string|!Object.&lt;string,*>} keyOrObj String key or plain object holding multiple values
  2257. * @param {(*|boolean)=} value Value to set if key is a string, otherwise omitted
  2258. * @param {boolean=} noAssert Whether to not assert for an actual field / proper value type, defaults to `false`
  2259. * @returns {!ProtoBuf.Builder.Message} this
  2260. * @throws {Error} If the value cannot be set
  2261. * @expose
  2262. */
  2263. MessagePrototype.set = function(keyOrObj, value, noAssert) {
  2264. if (keyOrObj &amp;&amp; typeof keyOrObj === 'object') {
  2265. noAssert = value;
  2266. for (var ikey in keyOrObj) {
  2267. // Check if virtual oneof field - don't set these
  2268. if (keyOrObj.hasOwnProperty(ikey) &amp;&amp; typeof (value = keyOrObj[ikey]) !== 'undefined' &amp;&amp; T._oneofsByName[ikey] === undefined)
  2269. this.$set(ikey, value, noAssert);
  2270. }
  2271. return this;
  2272. }
  2273. var field = T._fieldsByName[keyOrObj];
  2274. if (!noAssert) {
  2275. if (!field)
  2276. throw Error(this+"#"+keyOrObj+" is not a field: undefined");
  2277. if (!(field instanceof ProtoBuf.Reflect.Message.Field))
  2278. throw Error(this+"#"+keyOrObj+" is not a field: "+field.toString(true));
  2279. this[field.name] = (value = field.verifyValue(value)); // May throw
  2280. } else
  2281. this[keyOrObj] = value;
  2282. if (field &amp;&amp; field.oneof) { // Field is part of an OneOf (not a virtual OneOf field)
  2283. var currentField = this[field.oneof.name]; // Virtual field references currently set field
  2284. if (value !== null) {
  2285. if (currentField !== null &amp;&amp; currentField !== field.name)
  2286. this[currentField] = null; // Clear currently set field
  2287. this[field.oneof.name] = field.name; // Point virtual field at this field
  2288. } else if (/* value === null &amp;&amp; */currentField === keyOrObj)
  2289. this[field.oneof.name] = null; // Clear virtual field (current field explicitly cleared)
  2290. }
  2291. return this;
  2292. };
  2293. /**
  2294. * Sets a field's value. This is an alias for [@link ProtoBuf.Builder.Message#set}.
  2295. * @name ProtoBuf.Builder.Message#$set
  2296. * @function
  2297. * @param {string|!Object.&lt;string,*>} keyOrObj String key or plain object holding multiple values
  2298. * @param {(*|boolean)=} value Value to set if key is a string, otherwise omitted
  2299. * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
  2300. * @throws {Error} If the value cannot be set
  2301. * @expose
  2302. */
  2303. MessagePrototype.$set = MessagePrototype.set;
  2304. /**
  2305. * Gets a field's value.
  2306. * @name ProtoBuf.Builder.Message#get
  2307. * @function
  2308. * @param {string} key Key
  2309. * @param {boolean=} noAssert Whether to not assert for an actual field, defaults to `false`
  2310. * @return {*} Value
  2311. * @throws {Error} If there is no such field
  2312. * @expose
  2313. */
  2314. MessagePrototype.get = function(key, noAssert) {
  2315. if (noAssert)
  2316. return this[key];
  2317. var field = T._fieldsByName[key];
  2318. if (!field || !(field instanceof ProtoBuf.Reflect.Message.Field))
  2319. throw Error(this+"#"+key+" is not a field: undefined");
  2320. if (!(field instanceof ProtoBuf.Reflect.Message.Field))
  2321. throw Error(this+"#"+key+" is not a field: "+field.toString(true));
  2322. return this[field.name];
  2323. };
  2324. /**
  2325. * Gets a field's value. This is an alias for {@link ProtoBuf.Builder.Message#$get}.
  2326. * @name ProtoBuf.Builder.Message#$get
  2327. * @function
  2328. * @param {string} key Key
  2329. * @return {*} Value
  2330. * @throws {Error} If there is no such field
  2331. * @expose
  2332. */
  2333. MessagePrototype.$get = MessagePrototype.get;
  2334. // Getters and setters
  2335. for (var i=0; i&lt;fields.length; i++) {
  2336. var field = fields[i];
  2337. // no setters for extension fields as these are named by their fqn
  2338. if (field instanceof ProtoBuf.Reflect.Message.ExtensionField)
  2339. continue;
  2340. if (T.builder.options['populateAccessors'])
  2341. (function(field) {
  2342. // set/get[SomeValue]
  2343. var Name = field.originalName.replace(/(_[a-zA-Z])/g, function(match) {
  2344. return match.toUpperCase().replace('_','');
  2345. });
  2346. Name = Name.substring(0,1).toUpperCase() + Name.substring(1);
  2347. // set/get_[some_value] FIXME: Do we really need these?
  2348. var name = field.originalName.replace(/([A-Z])/g, function(match) {
  2349. return "_"+match;
  2350. });
  2351. /**
  2352. * The current field's unbound setter function.
  2353. * @function
  2354. * @param {*} value
  2355. * @param {boolean=} noAssert
  2356. * @returns {!ProtoBuf.Builder.Message}
  2357. * @inner
  2358. */
  2359. var setter = function(value, noAssert) {
  2360. this[field.name] = noAssert ? value : field.verifyValue(value);
  2361. return this;
  2362. };
  2363. /**
  2364. * The current field's unbound getter function.
  2365. * @function
  2366. * @returns {*}
  2367. * @inner
  2368. */
  2369. var getter = function() {
  2370. return this[field.name];
  2371. };
  2372. if (T.getChild("set"+Name) === null)
  2373. /**
  2374. * Sets a value. This method is present for each field, but only if there is no name conflict with
  2375. * another field.
  2376. * @name ProtoBuf.Builder.Message#set[SomeField]
  2377. * @function
  2378. * @param {*} value Value to set
  2379. * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
  2380. * @returns {!ProtoBuf.Builder.Message} this
  2381. * @abstract
  2382. * @throws {Error} If the value cannot be set
  2383. */
  2384. MessagePrototype["set"+Name] = setter;
  2385. if (T.getChild("set_"+name) === null)
  2386. /**
  2387. * Sets a value. This method is present for each field, but only if there is no name conflict with
  2388. * another field.
  2389. * @name ProtoBuf.Builder.Message#set_[some_field]
  2390. * @function
  2391. * @param {*} value Value to set
  2392. * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
  2393. * @returns {!ProtoBuf.Builder.Message} this
  2394. * @abstract
  2395. * @throws {Error} If the value cannot be set
  2396. */
  2397. MessagePrototype["set_"+name] = setter;
  2398. if (T.getChild("get"+Name) === null)
  2399. /**
  2400. * Gets a value. This method is present for each field, but only if there is no name conflict with
  2401. * another field.
  2402. * @name ProtoBuf.Builder.Message#get[SomeField]
  2403. * @function
  2404. * @abstract
  2405. * @return {*} The value
  2406. */
  2407. MessagePrototype["get"+Name] = getter;
  2408. if (T.getChild("get_"+name) === null)
  2409. /**
  2410. * Gets a value. This method is present for each field, but only if there is no name conflict with
  2411. * another field.
  2412. * @name ProtoBuf.Builder.Message#get_[some_field]
  2413. * @function
  2414. * @return {*} The value
  2415. * @abstract
  2416. */
  2417. MessagePrototype["get_"+name] = getter;
  2418. })(field);
  2419. }
  2420. // En-/decoding
  2421. /**
  2422. * Encodes the message.
  2423. * @name ProtoBuf.Builder.Message#$encode
  2424. * @function
  2425. * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted.
  2426. * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
  2427. * @return {!ByteBuffer} Encoded message as a ByteBuffer
  2428. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  2429. * returns the encoded ByteBuffer in the `encoded` property on the error.
  2430. * @expose
  2431. * @see ProtoBuf.Builder.Message#encode64
  2432. * @see ProtoBuf.Builder.Message#encodeHex
  2433. * @see ProtoBuf.Builder.Message#encodeAB
  2434. */
  2435. MessagePrototype.encode = function(buffer, noVerify) {
  2436. if (typeof buffer === 'boolean')
  2437. noVerify = buffer,
  2438. buffer = undefined;
  2439. var isNew = false;
  2440. if (!buffer)
  2441. buffer = new ByteBuffer(),
  2442. isNew = true;
  2443. var le = buffer.littleEndian;
  2444. try {
  2445. T.encode(this, buffer.LE(), noVerify);
  2446. return (isNew ? buffer.flip() : buffer).LE(le);
  2447. } catch (e) {
  2448. buffer.LE(le);
  2449. throw(e);
  2450. }
  2451. };
  2452. /**
  2453. * Encodes a message using the specified data payload.
  2454. * @param {!Object.&lt;string,*>} data Data payload
  2455. * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted.
  2456. * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
  2457. * @return {!ByteBuffer} Encoded message as a ByteBuffer
  2458. * @expose
  2459. */
  2460. Message.encode = function(data, buffer, noVerify) {
  2461. return new Message(data).encode(buffer, noVerify);
  2462. };
  2463. /**
  2464. * Calculates the byte length of the message.
  2465. * @name ProtoBuf.Builder.Message#calculate
  2466. * @function
  2467. * @returns {number} Byte length
  2468. * @throws {Error} If the message cannot be calculated or if required fields are missing.
  2469. * @expose
  2470. */
  2471. MessagePrototype.calculate = function() {
  2472. return T.calculate(this);
  2473. };
  2474. /**
  2475. * Encodes the varint32 length-delimited message.
  2476. * @name ProtoBuf.Builder.Message#encodeDelimited
  2477. * @function
  2478. * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted.
  2479. * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
  2480. * @return {!ByteBuffer} Encoded message as a ByteBuffer
  2481. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  2482. * returns the encoded ByteBuffer in the `encoded` property on the error.
  2483. * @expose
  2484. */
  2485. MessagePrototype.encodeDelimited = function(buffer, noVerify) {
  2486. var isNew = false;
  2487. if (!buffer)
  2488. buffer = new ByteBuffer(),
  2489. isNew = true;
  2490. var enc = new ByteBuffer().LE();
  2491. T.encode(this, enc, noVerify).flip();
  2492. buffer.writeVarint32(enc.remaining());
  2493. buffer.append(enc);
  2494. return isNew ? buffer.flip() : buffer;
  2495. };
  2496. /**
  2497. * Directly encodes the message to an ArrayBuffer.
  2498. * @name ProtoBuf.Builder.Message#encodeAB
  2499. * @function
  2500. * @return {ArrayBuffer} Encoded message as ArrayBuffer
  2501. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  2502. * returns the encoded ArrayBuffer in the `encoded` property on the error.
  2503. * @expose
  2504. */
  2505. MessagePrototype.encodeAB = function() {
  2506. try {
  2507. return this.encode().toArrayBuffer();
  2508. } catch (e) {
  2509. if (e["encoded"]) e["encoded"] = e["encoded"].toArrayBuffer();
  2510. throw(e);
  2511. }
  2512. };
  2513. /**
  2514. * Returns the message as an ArrayBuffer. This is an alias for {@link ProtoBuf.Builder.Message#encodeAB}.
  2515. * @name ProtoBuf.Builder.Message#toArrayBuffer
  2516. * @function
  2517. * @return {ArrayBuffer} Encoded message as ArrayBuffer
  2518. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  2519. * returns the encoded ArrayBuffer in the `encoded` property on the error.
  2520. * @expose
  2521. */
  2522. MessagePrototype.toArrayBuffer = MessagePrototype.encodeAB;
  2523. /**
  2524. * Directly encodes the message to a node Buffer.
  2525. * @name ProtoBuf.Builder.Message#encodeNB
  2526. * @function
  2527. * @return {!Buffer}
  2528. * @throws {Error} If the message cannot be encoded, not running under node.js or if required fields are
  2529. * missing. The later still returns the encoded node Buffer in the `encoded` property on the error.
  2530. * @expose
  2531. */
  2532. MessagePrototype.encodeNB = function() {
  2533. try {
  2534. return this.encode().toBuffer();
  2535. } catch (e) {
  2536. if (e["encoded"]) e["encoded"] = e["encoded"].toBuffer();
  2537. throw(e);
  2538. }
  2539. };
  2540. /**
  2541. * Returns the message as a node Buffer. This is an alias for {@link ProtoBuf.Builder.Message#encodeNB}.
  2542. * @name ProtoBuf.Builder.Message#toBuffer
  2543. * @function
  2544. * @return {!Buffer}
  2545. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  2546. * returns the encoded node Buffer in the `encoded` property on the error.
  2547. * @expose
  2548. */
  2549. MessagePrototype.toBuffer = MessagePrototype.encodeNB;
  2550. /**
  2551. * Directly encodes the message to a base64 encoded string.
  2552. * @name ProtoBuf.Builder.Message#encode64
  2553. * @function
  2554. * @return {string} Base64 encoded string
  2555. * @throws {Error} If the underlying buffer cannot be encoded or if required fields are missing. The later
  2556. * still returns the encoded base64 string in the `encoded` property on the error.
  2557. * @expose
  2558. */
  2559. MessagePrototype.encode64 = function() {
  2560. try {
  2561. return this.encode().toBase64();
  2562. } catch (e) {
  2563. if (e["encoded"]) e["encoded"] = e["encoded"].toBase64();
  2564. throw(e);
  2565. }
  2566. };
  2567. /**
  2568. * Returns the message as a base64 encoded string. This is an alias for {@link ProtoBuf.Builder.Message#encode64}.
  2569. * @name ProtoBuf.Builder.Message#toBase64
  2570. * @function
  2571. * @return {string} Base64 encoded string
  2572. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  2573. * returns the encoded base64 string in the `encoded` property on the error.
  2574. * @expose
  2575. */
  2576. MessagePrototype.toBase64 = MessagePrototype.encode64;
  2577. /**
  2578. * Directly encodes the message to a hex encoded string.
  2579. * @name ProtoBuf.Builder.Message#encodeHex
  2580. * @function
  2581. * @return {string} Hex encoded string
  2582. * @throws {Error} If the underlying buffer cannot be encoded or if required fields are missing. The later
  2583. * still returns the encoded hex string in the `encoded` property on the error.
  2584. * @expose
  2585. */
  2586. MessagePrototype.encodeHex = function() {
  2587. try {
  2588. return this.encode().toHex();
  2589. } catch (e) {
  2590. if (e["encoded"]) e["encoded"] = e["encoded"].toHex();
  2591. throw(e);
  2592. }
  2593. };
  2594. /**
  2595. * Returns the message as a hex encoded string. This is an alias for {@link ProtoBuf.Builder.Message#encodeHex}.
  2596. * @name ProtoBuf.Builder.Message#toHex
  2597. * @function
  2598. * @return {string} Hex encoded string
  2599. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  2600. * returns the encoded hex string in the `encoded` property on the error.
  2601. * @expose
  2602. */
  2603. MessagePrototype.toHex = MessagePrototype.encodeHex;
  2604. /**
  2605. * Clones a message object or field value to a raw object.
  2606. * @param {*} obj Object to clone
  2607. * @param {boolean} binaryAsBase64 Whether to include binary data as base64 strings or as a buffer otherwise
  2608. * @param {boolean} longsAsStrings Whether to encode longs as strings
  2609. * @param {!ProtoBuf.Reflect.T=} resolvedType The resolved field type if a field
  2610. * @returns {*} Cloned object
  2611. * @inner
  2612. */
  2613. function cloneRaw(obj, binaryAsBase64, longsAsStrings, resolvedType) {
  2614. if (obj === null || typeof obj !== 'object') {
  2615. // Convert enum values to their respective names
  2616. if (resolvedType &amp;&amp; resolvedType instanceof ProtoBuf.Reflect.Enum) {
  2617. var name = ProtoBuf.Reflect.Enum.getName(resolvedType.object, obj);
  2618. if (name !== null)
  2619. return name;
  2620. }
  2621. // Pass-through string, number, boolean, null...
  2622. return obj;
  2623. }
  2624. // Convert ByteBuffers to raw buffer or strings
  2625. if (ByteBuffer.isByteBuffer(obj))
  2626. return binaryAsBase64 ? obj.toBase64() : obj.toBuffer();
  2627. // Convert Longs to proper objects or strings
  2628. if (ProtoBuf.Long.isLong(obj))
  2629. return longsAsStrings ? obj.toString() : ProtoBuf.Long.fromValue(obj);
  2630. var clone;
  2631. // Clone arrays
  2632. if (Array.isArray(obj)) {
  2633. clone = [];
  2634. obj.forEach(function(v, k) {
  2635. clone[k] = cloneRaw(v, binaryAsBase64, longsAsStrings, resolvedType);
  2636. });
  2637. return clone;
  2638. }
  2639. clone = {};
  2640. // Convert maps to objects
  2641. if (obj instanceof ProtoBuf.Map) {
  2642. var it = obj.entries();
  2643. for (var e = it.next(); !e.done; e = it.next())
  2644. clone[obj.keyElem.valueToString(e.value[0])] = cloneRaw(e.value[1], binaryAsBase64, longsAsStrings, obj.valueElem.resolvedType);
  2645. return clone;
  2646. }
  2647. // Everything else is a non-null object
  2648. var type = obj.$type,
  2649. field = undefined;
  2650. for (var i in obj)
  2651. if (obj.hasOwnProperty(i)) {
  2652. if (type &amp;&amp; (field = type.getChild(i)))
  2653. clone[i] = cloneRaw(obj[i], binaryAsBase64, longsAsStrings, field.resolvedType);
  2654. else
  2655. clone[i] = cloneRaw(obj[i], binaryAsBase64, longsAsStrings);
  2656. }
  2657. return clone;
  2658. }
  2659. /**
  2660. * Returns the message's raw payload.
  2661. * @param {boolean=} binaryAsBase64 Whether to include binary data as base64 strings instead of Buffers, defaults to `false`
  2662. * @param {boolean} longsAsStrings Whether to encode longs as strings
  2663. * @returns {Object.&lt;string,*>} Raw payload
  2664. * @expose
  2665. */
  2666. MessagePrototype.toRaw = function(binaryAsBase64, longsAsStrings) {
  2667. return cloneRaw(this, !!binaryAsBase64, !!longsAsStrings, this.$type);
  2668. };
  2669. /**
  2670. * Encodes a message to JSON.
  2671. * @returns {string} JSON string
  2672. * @expose
  2673. */
  2674. MessagePrototype.encodeJSON = function() {
  2675. return JSON.stringify(
  2676. cloneRaw(this,
  2677. /* binary-as-base64 */ true,
  2678. /* longs-as-strings */ true,
  2679. this.$type
  2680. )
  2681. );
  2682. };
  2683. /**
  2684. * Decodes a message from the specified buffer or string.
  2685. * @name ProtoBuf.Builder.Message.decode
  2686. * @function
  2687. * @param {!ByteBuffer|!ArrayBuffer|!Buffer|string} buffer Buffer to decode from
  2688. * @param {(number|string)=} length Message length. Defaults to decode all the remainig data.
  2689. * @param {string=} enc Encoding if buffer is a string: hex, utf8 (not recommended), defaults to base64
  2690. * @return {!ProtoBuf.Builder.Message} Decoded message
  2691. * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
  2692. * returns the decoded message with missing fields in the `decoded` property on the error.
  2693. * @expose
  2694. * @see ProtoBuf.Builder.Message.decode64
  2695. * @see ProtoBuf.Builder.Message.decodeHex
  2696. */
  2697. Message.decode = function(buffer, length, enc) {
  2698. if (typeof length === 'string')
  2699. enc = length,
  2700. length = -1;
  2701. if (typeof buffer === 'string')
  2702. buffer = ByteBuffer.wrap(buffer, enc ? enc : "base64");
  2703. else if (!ByteBuffer.isByteBuffer(buffer))
  2704. buffer = ByteBuffer.wrap(buffer); // May throw
  2705. var le = buffer.littleEndian;
  2706. try {
  2707. var msg = T.decode(buffer.LE(), length);
  2708. buffer.LE(le);
  2709. return msg;
  2710. } catch (e) {
  2711. buffer.LE(le);
  2712. throw(e);
  2713. }
  2714. };
  2715. /**
  2716. * Decodes a varint32 length-delimited message from the specified buffer or string.
  2717. * @name ProtoBuf.Builder.Message.decodeDelimited
  2718. * @function
  2719. * @param {!ByteBuffer|!ArrayBuffer|!Buffer|string} buffer Buffer to decode from
  2720. * @param {string=} enc Encoding if buffer is a string: hex, utf8 (not recommended), defaults to base64
  2721. * @return {ProtoBuf.Builder.Message} Decoded message or `null` if not enough bytes are available yet
  2722. * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
  2723. * returns the decoded message with missing fields in the `decoded` property on the error.
  2724. * @expose
  2725. */
  2726. Message.decodeDelimited = function(buffer, enc) {
  2727. if (typeof buffer === 'string')
  2728. buffer = ByteBuffer.wrap(buffer, enc ? enc : "base64");
  2729. else if (!ByteBuffer.isByteBuffer(buffer))
  2730. buffer = ByteBuffer.wrap(buffer); // May throw
  2731. if (buffer.remaining() &lt; 1)
  2732. return null;
  2733. var off = buffer.offset,
  2734. len = buffer.readVarint32();
  2735. if (buffer.remaining() &lt; len) {
  2736. buffer.offset = off;
  2737. return null;
  2738. }
  2739. try {
  2740. var msg = T.decode(buffer.slice(buffer.offset, buffer.offset + len).LE());
  2741. buffer.offset += len;
  2742. return msg;
  2743. } catch (err) {
  2744. buffer.offset += len;
  2745. throw err;
  2746. }
  2747. };
  2748. /**
  2749. * Decodes the message from the specified base64 encoded string.
  2750. * @name ProtoBuf.Builder.Message.decode64
  2751. * @function
  2752. * @param {string} str String to decode from
  2753. * @return {!ProtoBuf.Builder.Message} Decoded message
  2754. * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
  2755. * returns the decoded message with missing fields in the `decoded` property on the error.
  2756. * @expose
  2757. */
  2758. Message.decode64 = function(str) {
  2759. return Message.decode(str, "base64");
  2760. };
  2761. /**
  2762. * Decodes the message from the specified hex encoded string.
  2763. * @name ProtoBuf.Builder.Message.decodeHex
  2764. * @function
  2765. * @param {string} str String to decode from
  2766. * @return {!ProtoBuf.Builder.Message} Decoded message
  2767. * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
  2768. * returns the decoded message with missing fields in the `decoded` property on the error.
  2769. * @expose
  2770. */
  2771. Message.decodeHex = function(str) {
  2772. return Message.decode(str, "hex");
  2773. };
  2774. /**
  2775. * Decodes the message from a JSON string.
  2776. * @name ProtoBuf.Builder.Message.decodeJSON
  2777. * @function
  2778. * @param {string} str String to decode from
  2779. * @return {!ProtoBuf.Builder.Message} Decoded message
  2780. * @throws {Error} If the message cannot be decoded or if required fields are
  2781. * missing.
  2782. * @expose
  2783. */
  2784. Message.decodeJSON = function(str) {
  2785. return new Message(JSON.parse(str));
  2786. };
  2787. // Utility
  2788. /**
  2789. * Returns a string representation of this Message.
  2790. * @name ProtoBuf.Builder.Message#toString
  2791. * @function
  2792. * @return {string} String representation as of ".Fully.Qualified.MessageName"
  2793. * @expose
  2794. */
  2795. MessagePrototype.toString = function() {
  2796. return T.toString();
  2797. };
  2798. // Properties
  2799. /**
  2800. * Message options.
  2801. * @name ProtoBuf.Builder.Message.$options
  2802. * @type {Object.&lt;string,*>}
  2803. * @expose
  2804. */
  2805. var $optionsS; // cc needs this
  2806. /**
  2807. * Message options.
  2808. * @name ProtoBuf.Builder.Message#$options
  2809. * @type {Object.&lt;string,*>}
  2810. * @expose
  2811. */
  2812. var $options;
  2813. /**
  2814. * Reflection type.
  2815. * @name ProtoBuf.Builder.Message.$type
  2816. * @type {!ProtoBuf.Reflect.Message}
  2817. * @expose
  2818. */
  2819. var $typeS;
  2820. /**
  2821. * Reflection type.
  2822. * @name ProtoBuf.Builder.Message#$type
  2823. * @type {!ProtoBuf.Reflect.Message}
  2824. * @expose
  2825. */
  2826. var $type;
  2827. if (Object.defineProperty)
  2828. Object.defineProperty(Message, '$options', { "value": T.buildOpt() }),
  2829. Object.defineProperty(MessagePrototype, "$options", { "value": Message["$options"] }),
  2830. Object.defineProperty(Message, "$type", { "value": T }),
  2831. Object.defineProperty(MessagePrototype, "$type", { "value": T });
  2832. return Message;
  2833. })(ProtoBuf, this);
  2834. // Static enums and prototyped sub-messages / cached collections
  2835. this._fields = [];
  2836. this._fieldsById = {};
  2837. this._fieldsByName = {};
  2838. this._oneofsByName = {};
  2839. for (var i=0, k=this.children.length, child; i&lt;k; i++) {
  2840. child = this.children[i];
  2841. if (child instanceof Enum || child instanceof Message || child instanceof Service) {
  2842. if (clazz.hasOwnProperty(child.name))
  2843. throw Error("Illegal reflect child of "+this.toString(true)+": "+child.toString(true)+" cannot override static property '"+child.name+"'");
  2844. clazz[child.name] = child.build();
  2845. } else if (child instanceof Message.Field)
  2846. child.build(),
  2847. this._fields.push(child),
  2848. this._fieldsById[child.id] = child,
  2849. this._fieldsByName[child.name] = child;
  2850. else if (child instanceof Message.OneOf) {
  2851. this._oneofsByName[child.name] = child;
  2852. }
  2853. else if (!(child instanceof Message.OneOf) &amp;&amp; !(child instanceof Extension)) // Not built
  2854. throw Error("Illegal reflect child of "+this.toString(true)+": "+this.children[i].toString(true));
  2855. }
  2856. return this.clazz = clazz;
  2857. };
  2858. /**
  2859. * Encodes a runtime message's contents to the specified buffer.
  2860. * @param {!ProtoBuf.Builder.Message} message Runtime message to encode
  2861. * @param {ByteBuffer} buffer ByteBuffer to write to
  2862. * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
  2863. * @return {ByteBuffer} The ByteBuffer for chaining
  2864. * @throws {Error} If required fields are missing or the message cannot be encoded for another reason
  2865. * @expose
  2866. */
  2867. MessagePrototype.encode = function(message, buffer, noVerify) {
  2868. var fieldMissing = null,
  2869. field;
  2870. for (var i=0, k=this._fields.length, val; i&lt;k; ++i) {
  2871. field = this._fields[i];
  2872. val = message[field.name];
  2873. if (field.required &amp;&amp; val === null) {
  2874. if (fieldMissing === null)
  2875. fieldMissing = field;
  2876. } else
  2877. field.encode(noVerify ? val : field.verifyValue(val), buffer, message);
  2878. }
  2879. if (fieldMissing !== null) {
  2880. var err = Error("Missing at least one required field for "+this.toString(true)+": "+fieldMissing);
  2881. err["encoded"] = buffer; // Still expose what we got
  2882. throw(err);
  2883. }
  2884. return buffer;
  2885. };
  2886. /**
  2887. * Calculates a runtime message's byte length.
  2888. * @param {!ProtoBuf.Builder.Message} message Runtime message to encode
  2889. * @returns {number} Byte length
  2890. * @throws {Error} If required fields are missing or the message cannot be calculated for another reason
  2891. * @expose
  2892. */
  2893. MessagePrototype.calculate = function(message) {
  2894. for (var n=0, i=0, k=this._fields.length, field, val; i&lt;k; ++i) {
  2895. field = this._fields[i];
  2896. val = message[field.name];
  2897. if (field.required &amp;&amp; val === null)
  2898. throw Error("Missing at least one required field for "+this.toString(true)+": "+field);
  2899. else
  2900. n += field.calculate(val, message);
  2901. }
  2902. return n;
  2903. };
  2904. /**
  2905. * Skips all data until the end of the specified group has been reached.
  2906. * @param {number} expectedId Expected GROUPEND id
  2907. * @param {!ByteBuffer} buf ByteBuffer
  2908. * @returns {boolean} `true` if a value as been skipped, `false` if the end has been reached
  2909. * @throws {Error} If it wasn't possible to find the end of the group (buffer overrun or end tag mismatch)
  2910. * @inner
  2911. */
  2912. function skipTillGroupEnd(expectedId, buf) {
  2913. var tag = buf.readVarint32(), // Throws on OOB
  2914. wireType = tag &amp; 0x07,
  2915. id = tag >>> 3;
  2916. switch (wireType) {
  2917. case ProtoBuf.WIRE_TYPES.VARINT:
  2918. do tag = buf.readUint8();
  2919. while ((tag &amp; 0x80) === 0x80);
  2920. break;
  2921. case ProtoBuf.WIRE_TYPES.BITS64:
  2922. buf.offset += 8;
  2923. break;
  2924. case ProtoBuf.WIRE_TYPES.LDELIM:
  2925. tag = buf.readVarint32(); // reads the varint
  2926. buf.offset += tag; // skips n bytes
  2927. break;
  2928. case ProtoBuf.WIRE_TYPES.STARTGROUP:
  2929. skipTillGroupEnd(id, buf);
  2930. break;
  2931. case ProtoBuf.WIRE_TYPES.ENDGROUP:
  2932. if (id === expectedId)
  2933. return false;
  2934. else
  2935. throw Error("Illegal GROUPEND after unknown group: "+id+" ("+expectedId+" expected)");
  2936. case ProtoBuf.WIRE_TYPES.BITS32:
  2937. buf.offset += 4;
  2938. break;
  2939. default:
  2940. throw Error("Illegal wire type in unknown group "+expectedId+": "+wireType);
  2941. }
  2942. return true;
  2943. }
  2944. /**
  2945. * Decodes an encoded message and returns the decoded message.
  2946. * @param {ByteBuffer} buffer ByteBuffer to decode from
  2947. * @param {number=} length Message length. Defaults to decode all remaining data.
  2948. * @param {number=} expectedGroupEndId Expected GROUPEND id if this is a legacy group
  2949. * @return {ProtoBuf.Builder.Message} Decoded message
  2950. * @throws {Error} If the message cannot be decoded
  2951. * @expose
  2952. */
  2953. MessagePrototype.decode = function(buffer, length, expectedGroupEndId) {
  2954. if (typeof length !== 'number')
  2955. length = -1;
  2956. var start = buffer.offset,
  2957. msg = new (this.clazz)(),
  2958. tag, wireType, id, field;
  2959. while (buffer.offset &lt; start+length || (length === -1 &amp;&amp; buffer.remaining() > 0)) {
  2960. tag = buffer.readVarint32();
  2961. wireType = tag &amp; 0x07;
  2962. id = tag >>> 3;
  2963. if (wireType === ProtoBuf.WIRE_TYPES.ENDGROUP) {
  2964. if (id !== expectedGroupEndId)
  2965. throw Error("Illegal group end indicator for "+this.toString(true)+": "+id+" ("+(expectedGroupEndId ? expectedGroupEndId+" expected" : "not a group")+")");
  2966. break;
  2967. }
  2968. if (!(field = this._fieldsById[id])) {
  2969. // "messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing."
  2970. switch (wireType) {
  2971. case ProtoBuf.WIRE_TYPES.VARINT:
  2972. buffer.readVarint32();
  2973. break;
  2974. case ProtoBuf.WIRE_TYPES.BITS32:
  2975. buffer.offset += 4;
  2976. break;
  2977. case ProtoBuf.WIRE_TYPES.BITS64:
  2978. buffer.offset += 8;
  2979. break;
  2980. case ProtoBuf.WIRE_TYPES.LDELIM:
  2981. var len = buffer.readVarint32();
  2982. buffer.offset += len;
  2983. break;
  2984. case ProtoBuf.WIRE_TYPES.STARTGROUP:
  2985. while (skipTillGroupEnd(id, buffer)) {}
  2986. break;
  2987. default:
  2988. throw Error("Illegal wire type for unknown field "+id+" in "+this.toString(true)+"#decode: "+wireType);
  2989. }
  2990. continue;
  2991. }
  2992. if (field.repeated &amp;&amp; !field.options["packed"]) {
  2993. msg[field.name].push(field.decode(wireType, buffer));
  2994. } else if (field.map) {
  2995. var keyval = field.decode(wireType, buffer);
  2996. msg[field.name].set(keyval[0], keyval[1]);
  2997. } else {
  2998. msg[field.name] = field.decode(wireType, buffer);
  2999. if (field.oneof) { // Field is part of an OneOf (not a virtual OneOf field)
  3000. var currentField = msg[field.oneof.name]; // Virtual field references currently set field
  3001. if (currentField !== null &amp;&amp; currentField !== field.name)
  3002. msg[currentField] = null; // Clear currently set field
  3003. msg[field.oneof.name] = field.name; // Point virtual field at this field
  3004. }
  3005. }
  3006. }
  3007. // Check if all required fields are present and set default values for optional fields that are not
  3008. for (var i=0, k=this._fields.length; i&lt;k; ++i) {
  3009. field = this._fields[i];
  3010. if (msg[field.name] === null) {
  3011. if (this.syntax === "proto3") { // Proto3 sets default values by specification
  3012. msg[field.name] = field.defaultValue;
  3013. } else if (field.required) {
  3014. var err = Error("Missing at least one required field for " + this.toString(true) + ": " + field.name);
  3015. err["decoded"] = msg; // Still expose what we got
  3016. throw(err);
  3017. } else if (ProtoBuf.populateDefaults &amp;&amp; field.defaultValue !== null)
  3018. msg[field.name] = field.defaultValue;
  3019. }
  3020. }
  3021. return msg;
  3022. };
  3023. /**
  3024. * @alias ProtoBuf.Reflect.Message
  3025. * @expose
  3026. */
  3027. Reflect.Message = Message;
  3028. /**
  3029. * Constructs a new Message Field.
  3030. * @exports ProtoBuf.Reflect.Message.Field
  3031. * @param {!ProtoBuf.Builder} builder Builder reference
  3032. * @param {!ProtoBuf.Reflect.Message} message Message reference
  3033. * @param {string} rule Rule, one of requried, optional, repeated
  3034. * @param {string?} keytype Key data type, if any.
  3035. * @param {string} type Data type, e.g. int32
  3036. * @param {string} name Field name
  3037. * @param {number} id Unique field id
  3038. * @param {Object.&lt;string,*>=} options Options
  3039. * @param {!ProtoBuf.Reflect.Message.OneOf=} oneof Enclosing OneOf
  3040. * @param {string?} syntax The syntax level of this definition (e.g., proto3)
  3041. * @constructor
  3042. * @extends ProtoBuf.Reflect.T
  3043. */
  3044. var Field = function(builder, message, rule, keytype, type, name, id, options, oneof, syntax) {
  3045. T.call(this, builder, message, name);
  3046. /**
  3047. * @override
  3048. */
  3049. this.className = "Message.Field";
  3050. /**
  3051. * Message field required flag.
  3052. * @type {boolean}
  3053. * @expose
  3054. */
  3055. this.required = rule === "required";
  3056. /**
  3057. * Message field repeated flag.
  3058. * @type {boolean}
  3059. * @expose
  3060. */
  3061. this.repeated = rule === "repeated";
  3062. /**
  3063. * Message field map flag.
  3064. * @type {boolean}
  3065. * @expose
  3066. */
  3067. this.map = rule === "map";
  3068. /**
  3069. * Message field key type. Type reference string if unresolved, protobuf
  3070. * type if resolved. Valid only if this.map === true, null otherwise.
  3071. * @type {string|{name: string, wireType: number}|null}
  3072. * @expose
  3073. */
  3074. this.keyType = keytype || null;
  3075. /**
  3076. * Message field type. Type reference string if unresolved, protobuf type if
  3077. * resolved. In a map field, this is the value type.
  3078. * @type {string|{name: string, wireType: number}}
  3079. * @expose
  3080. */
  3081. this.type = type;
  3082. /**
  3083. * Resolved type reference inside the global namespace.
  3084. * @type {ProtoBuf.Reflect.T|null}
  3085. * @expose
  3086. */
  3087. this.resolvedType = null;
  3088. /**
  3089. * Unique message field id.
  3090. * @type {number}
  3091. * @expose
  3092. */
  3093. this.id = id;
  3094. /**
  3095. * Message field options.
  3096. * @type {!Object.&lt;string,*>}
  3097. * @dict
  3098. * @expose
  3099. */
  3100. this.options = options || {};
  3101. /**
  3102. * Default value.
  3103. * @type {*}
  3104. * @expose
  3105. */
  3106. this.defaultValue = null;
  3107. /**
  3108. * Enclosing OneOf.
  3109. * @type {?ProtoBuf.Reflect.Message.OneOf}
  3110. * @expose
  3111. */
  3112. this.oneof = oneof || null;
  3113. /**
  3114. * Syntax level of this definition (e.g., proto3).
  3115. * @type {string}
  3116. * @expose
  3117. */
  3118. this.syntax = syntax || 'proto2';
  3119. /**
  3120. * Original field name.
  3121. * @type {string}
  3122. * @expose
  3123. */
  3124. this.originalName = this.name; // Used to revert camelcase transformation on naming collisions
  3125. /**
  3126. * Element implementation. Created in build() after types are resolved.
  3127. * @type {ProtoBuf.Element}
  3128. * @expose
  3129. */
  3130. this.element = null;
  3131. /**
  3132. * Key element implementation, for map fields. Created in build() after
  3133. * types are resolved.
  3134. * @type {ProtoBuf.Element}
  3135. * @expose
  3136. */
  3137. this.keyElement = null;
  3138. // Convert field names to camel case notation if the override is set
  3139. if (this.builder.options['convertFieldsToCamelCase'] &amp;&amp; !(this instanceof Message.ExtensionField))
  3140. this.name = ProtoBuf.Util.toCamelCase(this.name);
  3141. };
  3142. /**
  3143. * @alias ProtoBuf.Reflect.Message.Field.prototype
  3144. * @inner
  3145. */
  3146. var FieldPrototype = Field.prototype = Object.create(T.prototype);
  3147. /**
  3148. * Builds the field.
  3149. * @override
  3150. * @expose
  3151. */
  3152. FieldPrototype.build = function() {
  3153. this.element = new Element(this.type, this.resolvedType, false, this.syntax, this.name);
  3154. if (this.map)
  3155. this.keyElement = new Element(this.keyType, undefined, true, this.syntax, this.name);
  3156. // In proto3, fields do not have field presence, and every field is set to
  3157. // its type's default value ("", 0, 0.0, or false).
  3158. if (this.syntax === 'proto3' &amp;&amp; !this.repeated &amp;&amp; !this.map)
  3159. this.defaultValue = Element.defaultFieldValue(this.type);
  3160. // Otherwise, default values are present when explicitly specified
  3161. else if (typeof this.options['default'] !== 'undefined')
  3162. this.defaultValue = this.verifyValue(this.options['default']);
  3163. };
  3164. /**
  3165. * Checks if the given value can be set for this field.
  3166. * @param {*} value Value to check
  3167. * @param {boolean=} skipRepeated Whether to skip the repeated value check or not. Defaults to false.
  3168. * @return {*} Verified, maybe adjusted, value
  3169. * @throws {Error} If the value cannot be set for this field
  3170. * @expose
  3171. */
  3172. FieldPrototype.verifyValue = function(value, skipRepeated) {
  3173. skipRepeated = skipRepeated || false;
  3174. var self = this;
  3175. function fail(val, msg) {
  3176. throw Error("Illegal value for "+self.toString(true)+" of type "+self.type.name+": "+val+" ("+msg+")");
  3177. }
  3178. if (value === null) { // NULL values for optional fields
  3179. if (this.required)
  3180. fail(typeof value, "required");
  3181. if (this.syntax === 'proto3' &amp;&amp; this.type !== ProtoBuf.TYPES["message"])
  3182. fail(typeof value, "proto3 field without field presence cannot be null");
  3183. return null;
  3184. }
  3185. var i;
  3186. if (this.repeated &amp;&amp; !skipRepeated) { // Repeated values as arrays
  3187. if (!Array.isArray(value))
  3188. value = [value];
  3189. var res = [];
  3190. for (i=0; i&lt;value.length; i++)
  3191. res.push(this.element.verifyValue(value[i]));
  3192. return res;
  3193. }
  3194. if (this.map &amp;&amp; !skipRepeated) { // Map values as objects
  3195. if (!(value instanceof ProtoBuf.Map)) {
  3196. // If not already a Map, attempt to convert.
  3197. if (!(value instanceof Object)) {
  3198. fail(typeof value,
  3199. "expected ProtoBuf.Map or raw object for map field");
  3200. }
  3201. return new ProtoBuf.Map(this, value);
  3202. } else {
  3203. return value;
  3204. }
  3205. }
  3206. // All non-repeated fields expect no array
  3207. if (!this.repeated &amp;&amp; Array.isArray(value))
  3208. fail(typeof value, "no array expected");
  3209. return this.element.verifyValue(value);
  3210. };
  3211. /**
  3212. * Determines whether the field will have a presence on the wire given its
  3213. * value.
  3214. * @param {*} value Verified field value
  3215. * @param {!ProtoBuf.Builder.Message} message Runtime message
  3216. * @return {boolean} Whether the field will be present on the wire
  3217. */
  3218. FieldPrototype.hasWirePresence = function(value, message) {
  3219. if (this.syntax !== 'proto3')
  3220. return (value !== null);
  3221. if (this.oneof &amp;&amp; message[this.oneof.name] === this.name)
  3222. return true;
  3223. switch (this.type) {
  3224. case ProtoBuf.TYPES["int32"]:
  3225. case ProtoBuf.TYPES["sint32"]:
  3226. case ProtoBuf.TYPES["sfixed32"]:
  3227. case ProtoBuf.TYPES["uint32"]:
  3228. case ProtoBuf.TYPES["fixed32"]:
  3229. return value !== 0;
  3230. case ProtoBuf.TYPES["int64"]:
  3231. case ProtoBuf.TYPES["sint64"]:
  3232. case ProtoBuf.TYPES["sfixed64"]:
  3233. case ProtoBuf.TYPES["uint64"]:
  3234. case ProtoBuf.TYPES["fixed64"]:
  3235. return value.low !== 0 || value.high !== 0;
  3236. case ProtoBuf.TYPES["bool"]:
  3237. return value;
  3238. case ProtoBuf.TYPES["float"]:
  3239. case ProtoBuf.TYPES["double"]:
  3240. return value !== 0.0;
  3241. case ProtoBuf.TYPES["string"]:
  3242. return value.length > 0;
  3243. case ProtoBuf.TYPES["bytes"]:
  3244. return value.remaining() > 0;
  3245. case ProtoBuf.TYPES["enum"]:
  3246. return value !== 0;
  3247. case ProtoBuf.TYPES["message"]:
  3248. return value !== null;
  3249. default:
  3250. return true;
  3251. }
  3252. };
  3253. /**
  3254. * Encodes the specified field value to the specified buffer.
  3255. * @param {*} value Verified field value
  3256. * @param {ByteBuffer} buffer ByteBuffer to encode to
  3257. * @param {!ProtoBuf.Builder.Message} message Runtime message
  3258. * @return {ByteBuffer} The ByteBuffer for chaining
  3259. * @throws {Error} If the field cannot be encoded
  3260. * @expose
  3261. */
  3262. FieldPrototype.encode = function(value, buffer, message) {
  3263. if (this.type === null || typeof this.type !== 'object')
  3264. throw Error("[INTERNAL] Unresolved type in "+this.toString(true)+": "+this.type);
  3265. if (value === null || (this.repeated &amp;&amp; value.length == 0))
  3266. return buffer; // Optional omitted
  3267. try {
  3268. if (this.repeated) {
  3269. var i;
  3270. // "Only repeated fields of primitive numeric types (types which use the varint, 32-bit, or 64-bit wire
  3271. // types) can be declared 'packed'."
  3272. if (this.options["packed"] &amp;&amp; ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
  3273. // "All of the elements of the field are packed into a single key-value pair with wire type 2
  3274. // (length-delimited). Each element is encoded the same way it would be normally, except without a
  3275. // tag preceding it."
  3276. buffer.writeVarint32((this.id &lt;&lt; 3) | ProtoBuf.WIRE_TYPES.LDELIM);
  3277. buffer.ensureCapacity(buffer.offset += 1); // We do not know the length yet, so let's assume a varint of length 1
  3278. var start = buffer.offset; // Remember where the contents begin
  3279. for (i=0; i&lt;value.length; i++)
  3280. this.element.encodeValue(this.id, value[i], buffer);
  3281. var len = buffer.offset-start,
  3282. varintLen = ByteBuffer.calculateVarint32(len);
  3283. if (varintLen > 1) { // We need to move the contents
  3284. var contents = buffer.slice(start, buffer.offset);
  3285. start += varintLen-1;
  3286. buffer.offset = start;
  3287. buffer.append(contents);
  3288. }
  3289. buffer.writeVarint32(len, start-varintLen);
  3290. } else {
  3291. // "If your message definition has repeated elements (without the [packed=true] option), the encoded
  3292. // message has zero or more key-value pairs with the same tag number"
  3293. for (i=0; i&lt;value.length; i++)
  3294. buffer.writeVarint32((this.id &lt;&lt; 3) | this.type.wireType),
  3295. this.element.encodeValue(this.id, value[i], buffer);
  3296. }
  3297. } else if (this.map) {
  3298. // Write out each map entry as a submessage.
  3299. value.forEach(function(val, key, m) {
  3300. // Compute the length of the submessage (key, val) pair.
  3301. var length =
  3302. ByteBuffer.calculateVarint32((1 &lt;&lt; 3) | this.keyType.wireType) +
  3303. this.keyElement.calculateLength(1, key) +
  3304. ByteBuffer.calculateVarint32((2 &lt;&lt; 3) | this.type.wireType) +
  3305. this.element.calculateLength(2, val);
  3306. // Submessage with wire type of length-delimited.
  3307. buffer.writeVarint32((this.id &lt;&lt; 3) | ProtoBuf.WIRE_TYPES.LDELIM);
  3308. buffer.writeVarint32(length);
  3309. // Write out the key and val.
  3310. buffer.writeVarint32((1 &lt;&lt; 3) | this.keyType.wireType);
  3311. this.keyElement.encodeValue(1, key, buffer);
  3312. buffer.writeVarint32((2 &lt;&lt; 3) | this.type.wireType);
  3313. this.element.encodeValue(2, val, buffer);
  3314. }, this);
  3315. } else {
  3316. if (this.hasWirePresence(value, message)) {
  3317. buffer.writeVarint32((this.id &lt;&lt; 3) | this.type.wireType);
  3318. this.element.encodeValue(this.id, value, buffer);
  3319. }
  3320. }
  3321. } catch (e) {
  3322. throw Error("Illegal value for "+this.toString(true)+": "+value+" ("+e+")");
  3323. }
  3324. return buffer;
  3325. };
  3326. /**
  3327. * Calculates the length of this field's value on the network level.
  3328. * @param {*} value Field value
  3329. * @param {!ProtoBuf.Builder.Message} message Runtime message
  3330. * @returns {number} Byte length
  3331. * @expose
  3332. */
  3333. FieldPrototype.calculate = function(value, message) {
  3334. value = this.verifyValue(value); // May throw
  3335. if (this.type === null || typeof this.type !== 'object')
  3336. throw Error("[INTERNAL] Unresolved type in "+this.toString(true)+": "+this.type);
  3337. if (value === null || (this.repeated &amp;&amp; value.length == 0))
  3338. return 0; // Optional omitted
  3339. var n = 0;
  3340. try {
  3341. if (this.repeated) {
  3342. var i, ni;
  3343. if (this.options["packed"] &amp;&amp; ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
  3344. n += ByteBuffer.calculateVarint32((this.id &lt;&lt; 3) | ProtoBuf.WIRE_TYPES.LDELIM);
  3345. ni = 0;
  3346. for (i=0; i&lt;value.length; i++)
  3347. ni += this.element.calculateLength(this.id, value[i]);
  3348. n += ByteBuffer.calculateVarint32(ni);
  3349. n += ni;
  3350. } else {
  3351. for (i=0; i&lt;value.length; i++)
  3352. n += ByteBuffer.calculateVarint32((this.id &lt;&lt; 3) | this.type.wireType),
  3353. n += this.element.calculateLength(this.id, value[i]);
  3354. }
  3355. } else if (this.map) {
  3356. // Each map entry becomes a submessage.
  3357. value.forEach(function(val, key, m) {
  3358. // Compute the length of the submessage (key, val) pair.
  3359. var length =
  3360. ByteBuffer.calculateVarint32((1 &lt;&lt; 3) | this.keyType.wireType) +
  3361. this.keyElement.calculateLength(1, key) +
  3362. ByteBuffer.calculateVarint32((2 &lt;&lt; 3) | this.type.wireType) +
  3363. this.element.calculateLength(2, val);
  3364. n += ByteBuffer.calculateVarint32((this.id &lt;&lt; 3) | ProtoBuf.WIRE_TYPES.LDELIM);
  3365. n += ByteBuffer.calculateVarint32(length);
  3366. n += length;
  3367. }, this);
  3368. } else {
  3369. if (this.hasWirePresence(value, message)) {
  3370. n += ByteBuffer.calculateVarint32((this.id &lt;&lt; 3) | this.type.wireType);
  3371. n += this.element.calculateLength(this.id, value);
  3372. }
  3373. }
  3374. } catch (e) {
  3375. throw Error("Illegal value for "+this.toString(true)+": "+value+" ("+e+")");
  3376. }
  3377. return n;
  3378. };
  3379. /**
  3380. * Decode the field value from the specified buffer.
  3381. * @param {number} wireType Leading wire type
  3382. * @param {ByteBuffer} buffer ByteBuffer to decode from
  3383. * @param {boolean=} skipRepeated Whether to skip the repeated check or not. Defaults to false.
  3384. * @return {*} Decoded value: array for packed repeated fields, [key, value] for
  3385. * map fields, or an individual value otherwise.
  3386. * @throws {Error} If the field cannot be decoded
  3387. * @expose
  3388. */
  3389. FieldPrototype.decode = function(wireType, buffer, skipRepeated) {
  3390. var value, nBytes;
  3391. // We expect wireType to match the underlying type's wireType unless we see
  3392. // a packed repeated field, or unless this is a map field.
  3393. var wireTypeOK =
  3394. (!this.map &amp;&amp; wireType == this.type.wireType) ||
  3395. (!skipRepeated &amp;&amp; this.repeated &amp;&amp; this.options["packed"] &amp;&amp;
  3396. wireType == ProtoBuf.WIRE_TYPES.LDELIM) ||
  3397. (this.map &amp;&amp; wireType == ProtoBuf.WIRE_TYPES.LDELIM);
  3398. if (!wireTypeOK)
  3399. throw Error("Illegal wire type for field "+this.toString(true)+": "+wireType+" ("+this.type.wireType+" expected)");
  3400. // Handle packed repeated fields.
  3401. if (wireType == ProtoBuf.WIRE_TYPES.LDELIM &amp;&amp; this.repeated &amp;&amp; this.options["packed"] &amp;&amp; ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
  3402. if (!skipRepeated) {
  3403. nBytes = buffer.readVarint32();
  3404. nBytes = buffer.offset + nBytes; // Limit
  3405. var values = [];
  3406. while (buffer.offset &lt; nBytes)
  3407. values.push(this.decode(this.type.wireType, buffer, true));
  3408. return values;
  3409. }
  3410. // Read the next value otherwise...
  3411. }
  3412. // Handle maps.
  3413. if (this.map) {
  3414. // Read one (key, value) submessage, and return [key, value]
  3415. var key = Element.defaultFieldValue(this.keyType);
  3416. value = Element.defaultFieldValue(this.type);
  3417. // Read the length
  3418. nBytes = buffer.readVarint32();
  3419. if (buffer.remaining() &lt; nBytes)
  3420. throw Error("Illegal number of bytes for "+this.toString(true)+": "+nBytes+" required but got only "+buffer.remaining());
  3421. // Get a sub-buffer of this key/value submessage
  3422. var msgbuf = buffer.clone();
  3423. msgbuf.limit = msgbuf.offset + nBytes;
  3424. buffer.offset += nBytes;
  3425. while (msgbuf.remaining() > 0) {
  3426. var tag = msgbuf.readVarint32();
  3427. wireType = tag &amp; 0x07;
  3428. var id = tag >>> 3;
  3429. if (id === 1) {
  3430. key = this.keyElement.decode(msgbuf, wireType, id);
  3431. } else if (id === 2) {
  3432. value = this.element.decode(msgbuf, wireType, id);
  3433. } else {
  3434. throw Error("Unexpected tag in map field key/value submessage");
  3435. }
  3436. }
  3437. return [key, value];
  3438. }
  3439. // Handle singular and non-packed repeated field values.
  3440. return this.element.decode(buffer, wireType, this.id);
  3441. };
  3442. /**
  3443. * @alias ProtoBuf.Reflect.Message.Field
  3444. * @expose
  3445. */
  3446. Reflect.Message.Field = Field;
  3447. /**
  3448. * Constructs a new Message ExtensionField.
  3449. * @exports ProtoBuf.Reflect.Message.ExtensionField
  3450. * @param {!ProtoBuf.Builder} builder Builder reference
  3451. * @param {!ProtoBuf.Reflect.Message} message Message reference
  3452. * @param {string} rule Rule, one of requried, optional, repeated
  3453. * @param {string} type Data type, e.g. int32
  3454. * @param {string} name Field name
  3455. * @param {number} id Unique field id
  3456. * @param {!Object.&lt;string,*>=} options Options
  3457. * @constructor
  3458. * @extends ProtoBuf.Reflect.Message.Field
  3459. */
  3460. var ExtensionField = function(builder, message, rule, type, name, id, options) {
  3461. Field.call(this, builder, message, rule, /* keytype = */ null, type, name, id, options);
  3462. /**
  3463. * Extension reference.
  3464. * @type {!ProtoBuf.Reflect.Extension}
  3465. * @expose
  3466. */
  3467. this.extension;
  3468. };
  3469. // Extends Field
  3470. ExtensionField.prototype = Object.create(Field.prototype);
  3471. /**
  3472. * @alias ProtoBuf.Reflect.Message.ExtensionField
  3473. * @expose
  3474. */
  3475. Reflect.Message.ExtensionField = ExtensionField;
  3476. /**
  3477. * Constructs a new Message OneOf.
  3478. * @exports ProtoBuf.Reflect.Message.OneOf
  3479. * @param {!ProtoBuf.Builder} builder Builder reference
  3480. * @param {!ProtoBuf.Reflect.Message} message Message reference
  3481. * @param {string} name OneOf name
  3482. * @constructor
  3483. * @extends ProtoBuf.Reflect.T
  3484. */
  3485. var OneOf = function(builder, message, name) {
  3486. T.call(this, builder, message, name);
  3487. /**
  3488. * Enclosed fields.
  3489. * @type {!Array.&lt;!ProtoBuf.Reflect.Message.Field>}
  3490. * @expose
  3491. */
  3492. this.fields = [];
  3493. };
  3494. /**
  3495. * @alias ProtoBuf.Reflect.Message.OneOf
  3496. * @expose
  3497. */
  3498. Reflect.Message.OneOf = OneOf;
  3499. /**
  3500. * Constructs a new Enum.
  3501. * @exports ProtoBuf.Reflect.Enum
  3502. * @param {!ProtoBuf.Builder} builder Builder reference
  3503. * @param {!ProtoBuf.Reflect.T} parent Parent Reflect object
  3504. * @param {string} name Enum name
  3505. * @param {Object.&lt;string,*>=} options Enum options
  3506. * @param {string?} syntax The syntax level (e.g., proto3)
  3507. * @constructor
  3508. * @extends ProtoBuf.Reflect.Namespace
  3509. */
  3510. var Enum = function(builder, parent, name, options, syntax) {
  3511. Namespace.call(this, builder, parent, name, options, syntax);
  3512. /**
  3513. * @override
  3514. */
  3515. this.className = "Enum";
  3516. /**
  3517. * Runtime enum object.
  3518. * @type {Object.&lt;string,number>|null}
  3519. * @expose
  3520. */
  3521. this.object = null;
  3522. };
  3523. /**
  3524. * Gets the string name of an enum value.
  3525. * @param {!ProtoBuf.Builder.Enum} enm Runtime enum
  3526. * @param {number} value Enum value
  3527. * @returns {?string} Name or `null` if not present
  3528. * @expose
  3529. */
  3530. Enum.getName = function(enm, value) {
  3531. var keys = Object.keys(enm);
  3532. for (var i=0, key; i&lt;keys.length; ++i)
  3533. if (enm[key = keys[i]] === value)
  3534. return key;
  3535. return null;
  3536. };
  3537. /**
  3538. * @alias ProtoBuf.Reflect.Enum.prototype
  3539. * @inner
  3540. */
  3541. var EnumPrototype = Enum.prototype = Object.create(Namespace.prototype);
  3542. /**
  3543. * Builds this enum and returns the runtime counterpart.
  3544. * @param {boolean} rebuild Whether to rebuild or not, defaults to false
  3545. * @returns {!Object.&lt;string,number>}
  3546. * @expose
  3547. */
  3548. EnumPrototype.build = function(rebuild) {
  3549. if (this.object &amp;&amp; !rebuild)
  3550. return this.object;
  3551. var enm = new ProtoBuf.Builder.Enum(),
  3552. values = this.getChildren(Enum.Value);
  3553. for (var i=0, k=values.length; i&lt;k; ++i)
  3554. enm[values[i]['name']] = values[i]['id'];
  3555. if (Object.defineProperty)
  3556. Object.defineProperty(enm, '$options', {
  3557. "value": this.buildOpt(),
  3558. "enumerable": false
  3559. });
  3560. return this.object = enm;
  3561. };
  3562. /**
  3563. * @alias ProtoBuf.Reflect.Enum
  3564. * @expose
  3565. */
  3566. Reflect.Enum = Enum;
  3567. /**
  3568. * Constructs a new Enum Value.
  3569. * @exports ProtoBuf.Reflect.Enum.Value
  3570. * @param {!ProtoBuf.Builder} builder Builder reference
  3571. * @param {!ProtoBuf.Reflect.Enum} enm Enum reference
  3572. * @param {string} name Field name
  3573. * @param {number} id Unique field id
  3574. * @constructor
  3575. * @extends ProtoBuf.Reflect.T
  3576. */
  3577. var Value = function(builder, enm, name, id) {
  3578. T.call(this, builder, enm, name);
  3579. /**
  3580. * @override
  3581. */
  3582. this.className = "Enum.Value";
  3583. /**
  3584. * Unique enum value id.
  3585. * @type {number}
  3586. * @expose
  3587. */
  3588. this.id = id;
  3589. };
  3590. // Extends T
  3591. Value.prototype = Object.create(T.prototype);
  3592. /**
  3593. * @alias ProtoBuf.Reflect.Enum.Value
  3594. * @expose
  3595. */
  3596. Reflect.Enum.Value = Value;
  3597. /**
  3598. * An extension (field).
  3599. * @exports ProtoBuf.Reflect.Extension
  3600. * @constructor
  3601. * @param {!ProtoBuf.Builder} builder Builder reference
  3602. * @param {!ProtoBuf.Reflect.T} parent Parent object
  3603. * @param {string} name Object name
  3604. * @param {!ProtoBuf.Reflect.Message.Field} field Extension field
  3605. */
  3606. var Extension = function(builder, parent, name, field) {
  3607. T.call(this, builder, parent, name);
  3608. /**
  3609. * Extended message field.
  3610. * @type {!ProtoBuf.Reflect.Message.Field}
  3611. * @expose
  3612. */
  3613. this.field = field;
  3614. };
  3615. // Extends T
  3616. Extension.prototype = Object.create(T.prototype);
  3617. /**
  3618. * @alias ProtoBuf.Reflect.Extension
  3619. * @expose
  3620. */
  3621. Reflect.Extension = Extension;
  3622. /**
  3623. * Constructs a new Service.
  3624. * @exports ProtoBuf.Reflect.Service
  3625. * @param {!ProtoBuf.Builder} builder Builder reference
  3626. * @param {!ProtoBuf.Reflect.Namespace} root Root
  3627. * @param {string} name Service name
  3628. * @param {Object.&lt;string,*>=} options Options
  3629. * @constructor
  3630. * @extends ProtoBuf.Reflect.Namespace
  3631. */
  3632. var Service = function(builder, root, name, options) {
  3633. Namespace.call(this, builder, root, name, options);
  3634. /**
  3635. * @override
  3636. */
  3637. this.className = "Service";
  3638. /**
  3639. * Built runtime service class.
  3640. * @type {?function(new:ProtoBuf.Builder.Service)}
  3641. */
  3642. this.clazz = null;
  3643. };
  3644. /**
  3645. * @alias ProtoBuf.Reflect.Service.prototype
  3646. * @inner
  3647. */
  3648. var ServicePrototype = Service.prototype = Object.create(Namespace.prototype);
  3649. /**
  3650. * Builds the service and returns the runtime counterpart, which is a fully functional class.
  3651. * @see ProtoBuf.Builder.Service
  3652. * @param {boolean=} rebuild Whether to rebuild or not
  3653. * @return {Function} Service class
  3654. * @throws {Error} If the message cannot be built
  3655. * @expose
  3656. */
  3657. ServicePrototype.build = function(rebuild) {
  3658. if (this.clazz &amp;&amp; !rebuild)
  3659. return this.clazz;
  3660. // Create the runtime Service class in its own scope
  3661. return this.clazz = (function(ProtoBuf, T) {
  3662. /**
  3663. * Constructs a new runtime Service.
  3664. * @name ProtoBuf.Builder.Service
  3665. * @param {function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))=} rpcImpl RPC implementation receiving the method name and the message
  3666. * @class Barebone of all runtime services.
  3667. * @constructor
  3668. * @throws {Error} If the service cannot be created
  3669. */
  3670. var Service = function(rpcImpl) {
  3671. ProtoBuf.Builder.Service.call(this);
  3672. /**
  3673. * Service implementation.
  3674. * @name ProtoBuf.Builder.Service#rpcImpl
  3675. * @type {!function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))}
  3676. * @expose
  3677. */
  3678. this.rpcImpl = rpcImpl || function(name, msg, callback) {
  3679. // This is what a user has to implement: A function receiving the method name, the actual message to
  3680. // send (type checked) and the callback that's either provided with the error as its first
  3681. // argument or null and the actual response message.
  3682. setTimeout(callback.bind(this, Error("Not implemented, see: https://github.com/dcodeIO/ProtoBuf.js/wiki/Services")), 0); // Must be async!
  3683. };
  3684. };
  3685. /**
  3686. * @alias ProtoBuf.Builder.Service.prototype
  3687. * @inner
  3688. */
  3689. var ServicePrototype = Service.prototype = Object.create(ProtoBuf.Builder.Service.prototype);
  3690. /**
  3691. * Asynchronously performs an RPC call using the given RPC implementation.
  3692. * @name ProtoBuf.Builder.Service.[Method]
  3693. * @function
  3694. * @param {!function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))} rpcImpl RPC implementation
  3695. * @param {ProtoBuf.Builder.Message} req Request
  3696. * @param {function(Error, (ProtoBuf.Builder.Message|ByteBuffer|Buffer|string)=)} callback Callback receiving
  3697. * the error if any and the response either as a pre-parsed message or as its raw bytes
  3698. * @abstract
  3699. */
  3700. /**
  3701. * Asynchronously performs an RPC call using the instance's RPC implementation.
  3702. * @name ProtoBuf.Builder.Service#[Method]
  3703. * @function
  3704. * @param {ProtoBuf.Builder.Message} req Request
  3705. * @param {function(Error, (ProtoBuf.Builder.Message|ByteBuffer|Buffer|string)=)} callback Callback receiving
  3706. * the error if any and the response either as a pre-parsed message or as its raw bytes
  3707. * @abstract
  3708. */
  3709. var rpc = T.getChildren(ProtoBuf.Reflect.Service.RPCMethod);
  3710. for (var i=0; i&lt;rpc.length; i++) {
  3711. (function(method) {
  3712. // service#Method(message, callback)
  3713. ServicePrototype[method.name] = function(req, callback) {
  3714. try {
  3715. try {
  3716. // If given as a buffer, decode the request. Will throw a TypeError if not a valid buffer.
  3717. req = method.resolvedRequestType.clazz.decode(ByteBuffer.wrap(req));
  3718. } catch (err) {
  3719. if (!(err instanceof TypeError))
  3720. throw err;
  3721. }
  3722. if (req === null || typeof req !== 'object')
  3723. throw Error("Illegal arguments");
  3724. if (!(req instanceof method.resolvedRequestType.clazz))
  3725. req = new method.resolvedRequestType.clazz(req);
  3726. this.rpcImpl(method.fqn(), req, function(err, res) { // Assumes that this is properly async
  3727. if (err) {
  3728. callback(err);
  3729. return;
  3730. }
  3731. // Coalesce to empty string when service response has empty content
  3732. if (res === null)
  3733. res = ''
  3734. try { res = method.resolvedResponseType.clazz.decode(res); } catch (notABuffer) {}
  3735. if (!res || !(res instanceof method.resolvedResponseType.clazz)) {
  3736. callback(Error("Illegal response type received in service method "+ T.name+"#"+method.name));
  3737. return;
  3738. }
  3739. callback(null, res);
  3740. });
  3741. } catch (err) {
  3742. setTimeout(callback.bind(this, err), 0);
  3743. }
  3744. };
  3745. // Service.Method(rpcImpl, message, callback)
  3746. Service[method.name] = function(rpcImpl, req, callback) {
  3747. new Service(rpcImpl)[method.name](req, callback);
  3748. };
  3749. if (Object.defineProperty)
  3750. Object.defineProperty(Service[method.name], "$options", { "value": method.buildOpt() }),
  3751. Object.defineProperty(ServicePrototype[method.name], "$options", { "value": Service[method.name]["$options"] });
  3752. })(rpc[i]);
  3753. }
  3754. // Properties
  3755. /**
  3756. * Service options.
  3757. * @name ProtoBuf.Builder.Service.$options
  3758. * @type {Object.&lt;string,*>}
  3759. * @expose
  3760. */
  3761. var $optionsS; // cc needs this
  3762. /**
  3763. * Service options.
  3764. * @name ProtoBuf.Builder.Service#$options
  3765. * @type {Object.&lt;string,*>}
  3766. * @expose
  3767. */
  3768. var $options;
  3769. /**
  3770. * Reflection type.
  3771. * @name ProtoBuf.Builder.Service.$type
  3772. * @type {!ProtoBuf.Reflect.Service}
  3773. * @expose
  3774. */
  3775. var $typeS;
  3776. /**
  3777. * Reflection type.
  3778. * @name ProtoBuf.Builder.Service#$type
  3779. * @type {!ProtoBuf.Reflect.Service}
  3780. * @expose
  3781. */
  3782. var $type;
  3783. if (Object.defineProperty)
  3784. Object.defineProperty(Service, "$options", { "value": T.buildOpt() }),
  3785. Object.defineProperty(ServicePrototype, "$options", { "value": Service["$options"] }),
  3786. Object.defineProperty(Service, "$type", { "value": T }),
  3787. Object.defineProperty(ServicePrototype, "$type", { "value": T });
  3788. return Service;
  3789. })(ProtoBuf, this);
  3790. };
  3791. /**
  3792. * @alias ProtoBuf.Reflect.Service
  3793. * @expose
  3794. */
  3795. Reflect.Service = Service;
  3796. /**
  3797. * Abstract service method.
  3798. * @exports ProtoBuf.Reflect.Service.Method
  3799. * @param {!ProtoBuf.Builder} builder Builder reference
  3800. * @param {!ProtoBuf.Reflect.Service} svc Service
  3801. * @param {string} name Method name
  3802. * @param {Object.&lt;string,*>=} options Options
  3803. * @constructor
  3804. * @extends ProtoBuf.Reflect.T
  3805. */
  3806. var Method = function(builder, svc, name, options) {
  3807. T.call(this, builder, svc, name);
  3808. /**
  3809. * @override
  3810. */
  3811. this.className = "Service.Method";
  3812. /**
  3813. * Options.
  3814. * @type {Object.&lt;string, *>}
  3815. * @expose
  3816. */
  3817. this.options = options || {};
  3818. };
  3819. /**
  3820. * @alias ProtoBuf.Reflect.Service.Method.prototype
  3821. * @inner
  3822. */
  3823. var MethodPrototype = Method.prototype = Object.create(T.prototype);
  3824. /**
  3825. * Builds the method's '$options' property.
  3826. * @name ProtoBuf.Reflect.Service.Method#buildOpt
  3827. * @function
  3828. * @return {Object.&lt;string,*>}
  3829. */
  3830. MethodPrototype.buildOpt = NamespacePrototype.buildOpt;
  3831. /**
  3832. * @alias ProtoBuf.Reflect.Service.Method
  3833. * @expose
  3834. */
  3835. Reflect.Service.Method = Method;
  3836. /**
  3837. * RPC service method.
  3838. * @exports ProtoBuf.Reflect.Service.RPCMethod
  3839. * @param {!ProtoBuf.Builder} builder Builder reference
  3840. * @param {!ProtoBuf.Reflect.Service} svc Service
  3841. * @param {string} name Method name
  3842. * @param {string} request Request message name
  3843. * @param {string} response Response message name
  3844. * @param {boolean} request_stream Whether requests are streamed
  3845. * @param {boolean} response_stream Whether responses are streamed
  3846. * @param {Object.&lt;string,*>=} options Options
  3847. * @constructor
  3848. * @extends ProtoBuf.Reflect.Service.Method
  3849. */
  3850. var RPCMethod = function(builder, svc, name, request, response, request_stream, response_stream, options) {
  3851. Method.call(this, builder, svc, name, options);
  3852. /**
  3853. * @override
  3854. */
  3855. this.className = "Service.RPCMethod";
  3856. /**
  3857. * Request message name.
  3858. * @type {string}
  3859. * @expose
  3860. */
  3861. this.requestName = request;
  3862. /**
  3863. * Response message name.
  3864. * @type {string}
  3865. * @expose
  3866. */
  3867. this.responseName = response;
  3868. /**
  3869. * Whether requests are streamed
  3870. * @type {bool}
  3871. * @expose
  3872. */
  3873. this.requestStream = request_stream;
  3874. /**
  3875. * Whether responses are streamed
  3876. * @type {bool}
  3877. * @expose
  3878. */
  3879. this.responseStream = response_stream;
  3880. /**
  3881. * Resolved request message type.
  3882. * @type {ProtoBuf.Reflect.Message}
  3883. * @expose
  3884. */
  3885. this.resolvedRequestType = null;
  3886. /**
  3887. * Resolved response message type.
  3888. * @type {ProtoBuf.Reflect.Message}
  3889. * @expose
  3890. */
  3891. this.resolvedResponseType = null;
  3892. };
  3893. // Extends Method
  3894. RPCMethod.prototype = Object.create(Method.prototype);
  3895. /**
  3896. * @alias ProtoBuf.Reflect.Service.RPCMethod
  3897. * @expose
  3898. */
  3899. Reflect.Service.RPCMethod = RPCMethod;
  3900. return Reflect;
  3901. })(ProtoBuf);
  3902. /**
  3903. * @alias ProtoBuf.Builder
  3904. * @expose
  3905. */
  3906. ProtoBuf.Builder = (function(ProtoBuf, Lang, Reflect) {
  3907. "use strict";
  3908. /**
  3909. * Constructs a new Builder.
  3910. * @exports ProtoBuf.Builder
  3911. * @class Provides the functionality to build protocol messages.
  3912. * @param {Object.&lt;string,*>=} options Options
  3913. * @constructor
  3914. */
  3915. var Builder = function(options) {
  3916. /**
  3917. * Namespace.
  3918. * @type {ProtoBuf.Reflect.Namespace}
  3919. * @expose
  3920. */
  3921. this.ns = new Reflect.Namespace(this, null, ""); // Global namespace
  3922. /**
  3923. * Namespace pointer.
  3924. * @type {ProtoBuf.Reflect.T}
  3925. * @expose
  3926. */
  3927. this.ptr = this.ns;
  3928. /**
  3929. * Resolved flag.
  3930. * @type {boolean}
  3931. * @expose
  3932. */
  3933. this.resolved = false;
  3934. /**
  3935. * The current building result.
  3936. * @type {Object.&lt;string,ProtoBuf.Builder.Message|Object>|null}
  3937. * @expose
  3938. */
  3939. this.result = null;
  3940. /**
  3941. * Imported files.
  3942. * @type {Array.&lt;string>}
  3943. * @expose
  3944. */
  3945. this.files = {};
  3946. /**
  3947. * Import root override.
  3948. * @type {?string}
  3949. * @expose
  3950. */
  3951. this.importRoot = null;
  3952. /**
  3953. * Options.
  3954. * @type {!Object.&lt;string, *>}
  3955. * @expose
  3956. */
  3957. this.options = options || {};
  3958. };
  3959. /**
  3960. * @alias ProtoBuf.Builder.prototype
  3961. * @inner
  3962. */
  3963. var BuilderPrototype = Builder.prototype;
  3964. // ----- Definition tests -----
  3965. /**
  3966. * Tests if a definition most likely describes a message.
  3967. * @param {!Object} def
  3968. * @returns {boolean}
  3969. * @expose
  3970. */
  3971. Builder.isMessage = function(def) {
  3972. // Messages require a string name
  3973. if (typeof def["name"] !== 'string')
  3974. return false;
  3975. // Messages do not contain values (enum) or rpc methods (service)
  3976. if (typeof def["values"] !== 'undefined' || typeof def["rpc"] !== 'undefined')
  3977. return false;
  3978. return true;
  3979. };
  3980. /**
  3981. * Tests if a definition most likely describes a message field.
  3982. * @param {!Object} def
  3983. * @returns {boolean}
  3984. * @expose
  3985. */
  3986. Builder.isMessageField = function(def) {
  3987. // Message fields require a string rule, name and type and an id
  3988. if (typeof def["rule"] !== 'string' || typeof def["name"] !== 'string' || typeof def["type"] !== 'string' || typeof def["id"] === 'undefined')
  3989. return false;
  3990. return true;
  3991. };
  3992. /**
  3993. * Tests if a definition most likely describes an enum.
  3994. * @param {!Object} def
  3995. * @returns {boolean}
  3996. * @expose
  3997. */
  3998. Builder.isEnum = function(def) {
  3999. // Enums require a string name
  4000. if (typeof def["name"] !== 'string')
  4001. return false;
  4002. // Enums require at least one value
  4003. if (typeof def["values"] === 'undefined' || !Array.isArray(def["values"]) || def["values"].length === 0)
  4004. return false;
  4005. return true;
  4006. };
  4007. /**
  4008. * Tests if a definition most likely describes a service.
  4009. * @param {!Object} def
  4010. * @returns {boolean}
  4011. * @expose
  4012. */
  4013. Builder.isService = function(def) {
  4014. // Services require a string name and an rpc object
  4015. if (typeof def["name"] !== 'string' || typeof def["rpc"] !== 'object' || !def["rpc"])
  4016. return false;
  4017. return true;
  4018. };
  4019. /**
  4020. * Tests if a definition most likely describes an extended message
  4021. * @param {!Object} def
  4022. * @returns {boolean}
  4023. * @expose
  4024. */
  4025. Builder.isExtend = function(def) {
  4026. // Extends rquire a string ref
  4027. if (typeof def["ref"] !== 'string')
  4028. return false;
  4029. return true;
  4030. };
  4031. // ----- Building -----
  4032. /**
  4033. * Resets the pointer to the root namespace.
  4034. * @returns {!ProtoBuf.Builder} this
  4035. * @expose
  4036. */
  4037. BuilderPrototype.reset = function() {
  4038. this.ptr = this.ns;
  4039. return this;
  4040. };
  4041. /**
  4042. * Defines a namespace on top of the current pointer position and places the pointer on it.
  4043. * @param {string} namespace
  4044. * @return {!ProtoBuf.Builder} this
  4045. * @expose
  4046. */
  4047. BuilderPrototype.define = function(namespace) {
  4048. if (typeof namespace !== 'string' || !Lang.TYPEREF.test(namespace))
  4049. throw Error("illegal namespace: "+namespace);
  4050. namespace.split(".").forEach(function(part) {
  4051. var ns = this.ptr.getChild(part);
  4052. if (ns === null) // Keep existing
  4053. this.ptr.addChild(ns = new Reflect.Namespace(this, this.ptr, part));
  4054. this.ptr = ns;
  4055. }, this);
  4056. return this;
  4057. };
  4058. /**
  4059. * Creates the specified definitions at the current pointer position.
  4060. * @param {!Array.&lt;!Object>} defs Messages, enums or services to create
  4061. * @returns {!ProtoBuf.Builder} this
  4062. * @throws {Error} If a message definition is invalid
  4063. * @expose
  4064. */
  4065. BuilderPrototype.create = function(defs) {
  4066. if (!defs)
  4067. return this; // Nothing to create
  4068. if (!Array.isArray(defs))
  4069. defs = [defs];
  4070. else {
  4071. if (defs.length === 0)
  4072. return this;
  4073. defs = defs.slice();
  4074. }
  4075. // It's quite hard to keep track of scopes and memory here, so let's do this iteratively.
  4076. var stack = [defs];
  4077. while (stack.length > 0) {
  4078. defs = stack.pop();
  4079. if (!Array.isArray(defs)) // Stack always contains entire namespaces
  4080. throw Error("not a valid namespace: "+JSON.stringify(defs));
  4081. while (defs.length > 0) {
  4082. var def = defs.shift(); // Namespaces always contain an array of messages, enums and services
  4083. if (Builder.isMessage(def)) {
  4084. var obj = new Reflect.Message(this, this.ptr, def["name"], def["options"], def["isGroup"], def["syntax"]);
  4085. // Create OneOfs
  4086. var oneofs = {};
  4087. if (def["oneofs"])
  4088. Object.keys(def["oneofs"]).forEach(function(name) {
  4089. obj.addChild(oneofs[name] = new Reflect.Message.OneOf(this, obj, name));
  4090. }, this);
  4091. // Create fields
  4092. if (def["fields"])
  4093. def["fields"].forEach(function(fld) {
  4094. if (obj.getChild(fld["id"]|0) !== null)
  4095. throw Error("duplicate or invalid field id in "+obj.name+": "+fld['id']);
  4096. if (fld["options"] &amp;&amp; typeof fld["options"] !== 'object')
  4097. throw Error("illegal field options in "+obj.name+"#"+fld["name"]);
  4098. var oneof = null;
  4099. if (typeof fld["oneof"] === 'string' &amp;&amp; !(oneof = oneofs[fld["oneof"]]))
  4100. throw Error("illegal oneof in "+obj.name+"#"+fld["name"]+": "+fld["oneof"]);
  4101. fld = new Reflect.Message.Field(this, obj, fld["rule"], fld["keytype"], fld["type"], fld["name"], fld["id"], fld["options"], oneof, def["syntax"]);
  4102. if (oneof)
  4103. oneof.fields.push(fld);
  4104. obj.addChild(fld);
  4105. }, this);
  4106. // Push children to stack
  4107. var subObj = [];
  4108. if (def["enums"])
  4109. def["enums"].forEach(function(enm) {
  4110. subObj.push(enm);
  4111. });
  4112. if (def["messages"])
  4113. def["messages"].forEach(function(msg) {
  4114. subObj.push(msg);
  4115. });
  4116. if (def["services"])
  4117. def["services"].forEach(function(svc) {
  4118. subObj.push(svc);
  4119. });
  4120. // Set extension ranges
  4121. if (def["extensions"]) {
  4122. if (typeof def["extensions"][0] === 'number') // pre 5.0.1
  4123. obj.extensions = [ def["extensions"] ];
  4124. else
  4125. obj.extensions = def["extensions"];
  4126. }
  4127. // Create on top of current namespace
  4128. this.ptr.addChild(obj);
  4129. if (subObj.length > 0) {
  4130. stack.push(defs); // Push the current level back
  4131. defs = subObj; // Continue processing sub level
  4132. subObj = null;
  4133. this.ptr = obj; // And move the pointer to this namespace
  4134. obj = null;
  4135. continue;
  4136. }
  4137. subObj = null;
  4138. } else if (Builder.isEnum(def)) {
  4139. obj = new Reflect.Enum(this, this.ptr, def["name"], def["options"], def["syntax"]);
  4140. def["values"].forEach(function(val) {
  4141. obj.addChild(new Reflect.Enum.Value(this, obj, val["name"], val["id"]));
  4142. }, this);
  4143. this.ptr.addChild(obj);
  4144. } else if (Builder.isService(def)) {
  4145. obj = new Reflect.Service(this, this.ptr, def["name"], def["options"]);
  4146. Object.keys(def["rpc"]).forEach(function(name) {
  4147. var mtd = def["rpc"][name];
  4148. obj.addChild(new Reflect.Service.RPCMethod(this, obj, name, mtd["request"], mtd["response"], !!mtd["request_stream"], !!mtd["response_stream"], mtd["options"]));
  4149. }, this);
  4150. this.ptr.addChild(obj);
  4151. } else if (Builder.isExtend(def)) {
  4152. obj = this.ptr.resolve(def["ref"], true);
  4153. if (obj) {
  4154. def["fields"].forEach(function(fld) {
  4155. if (obj.getChild(fld['id']|0) !== null)
  4156. throw Error("duplicate extended field id in "+obj.name+": "+fld['id']);
  4157. // Check if field id is allowed to be extended
  4158. if (obj.extensions) {
  4159. var valid = false;
  4160. obj.extensions.forEach(function(range) {
  4161. if (fld["id"] >= range[0] &amp;&amp; fld["id"] &lt;= range[1])
  4162. valid = true;
  4163. });
  4164. if (!valid)
  4165. throw Error("illegal extended field id in "+obj.name+": "+fld['id']+" (not within valid ranges)");
  4166. }
  4167. // Convert extension field names to camel case notation if the override is set
  4168. var name = fld["name"];
  4169. if (this.options['convertFieldsToCamelCase'])
  4170. name = ProtoBuf.Util.toCamelCase(name);
  4171. // see #161: Extensions use their fully qualified name as their runtime key and...
  4172. var field = new Reflect.Message.ExtensionField(this, obj, fld["rule"], fld["type"], this.ptr.fqn()+'.'+name, fld["id"], fld["options"]);
  4173. // ...are added on top of the current namespace as an extension which is used for
  4174. // resolving their type later on (the extension always keeps the original name to
  4175. // prevent naming collisions)
  4176. var ext = new Reflect.Extension(this, this.ptr, fld["name"], field);
  4177. field.extension = ext;
  4178. this.ptr.addChild(ext);
  4179. obj.addChild(field);
  4180. }, this);
  4181. } else if (!/\.?google\.protobuf\./.test(def["ref"])) // Silently skip internal extensions
  4182. throw Error("extended message "+def["ref"]+" is not defined");
  4183. } else
  4184. throw Error("not a valid definition: "+JSON.stringify(def));
  4185. def = null;
  4186. obj = null;
  4187. }
  4188. // Break goes here
  4189. defs = null;
  4190. this.ptr = this.ptr.parent; // Namespace done, continue at parent
  4191. }
  4192. this.resolved = false; // Require re-resolve
  4193. this.result = null; // Require re-build
  4194. return this;
  4195. };
  4196. /**
  4197. * Propagates syntax to all children.
  4198. * @param {!Object} parent
  4199. * @inner
  4200. */
  4201. function propagateSyntax(parent) {
  4202. if (parent['messages']) {
  4203. parent['messages'].forEach(function(child) {
  4204. child["syntax"] = parent["syntax"];
  4205. propagateSyntax(child);
  4206. });
  4207. }
  4208. if (parent['enums']) {
  4209. parent['enums'].forEach(function(child) {
  4210. child["syntax"] = parent["syntax"];
  4211. });
  4212. }
  4213. }
  4214. /**
  4215. * Imports another definition into this builder.
  4216. * @param {Object.&lt;string,*>} json Parsed import
  4217. * @param {(string|{root: string, file: string})=} filename Imported file name
  4218. * @returns {!ProtoBuf.Builder} this
  4219. * @throws {Error} If the definition or file cannot be imported
  4220. * @expose
  4221. */
  4222. BuilderPrototype["import"] = function(json, filename) {
  4223. var delim = '/';
  4224. // Make sure to skip duplicate imports
  4225. if (typeof filename === 'string') {
  4226. if (ProtoBuf.Util.IS_NODE)
  4227. filename = require("path")['resolve'](filename);
  4228. if (this.files[filename] === true)
  4229. return this.reset();
  4230. this.files[filename] = true;
  4231. } else if (typeof filename === 'object') { // Object with root, file.
  4232. var root = filename.root;
  4233. if (ProtoBuf.Util.IS_NODE)
  4234. root = require("path")['resolve'](root);
  4235. if (root.indexOf("\\") >= 0 || filename.file.indexOf("\\") >= 0)
  4236. delim = '\\';
  4237. var fname;
  4238. if (ProtoBuf.Util.IS_NODE)
  4239. fname = require("path")['join'](root, filename.file);
  4240. else
  4241. fname = root + delim + filename.file;
  4242. if (this.files[fname] === true)
  4243. return this.reset();
  4244. this.files[fname] = true;
  4245. }
  4246. // Import imports
  4247. if (json['imports'] &amp;&amp; json['imports'].length > 0) {
  4248. var importRoot,
  4249. resetRoot = false;
  4250. if (typeof filename === 'object') { // If an import root is specified, override
  4251. this.importRoot = filename["root"]; resetRoot = true; // ... and reset afterwards
  4252. importRoot = this.importRoot;
  4253. filename = filename["file"];
  4254. if (importRoot.indexOf("\\") >= 0 || filename.indexOf("\\") >= 0)
  4255. delim = '\\';
  4256. } else if (typeof filename === 'string') {
  4257. if (this.importRoot) // If import root is overridden, use it
  4258. importRoot = this.importRoot;
  4259. else { // Otherwise compute from filename
  4260. if (filename.indexOf("/") >= 0) { // Unix
  4261. importRoot = filename.replace(/\/[^\/]*$/, "");
  4262. if (/* /file.proto */ importRoot === "")
  4263. importRoot = "/";
  4264. } else if (filename.indexOf("\\") >= 0) { // Windows
  4265. importRoot = filename.replace(/\\[^\\]*$/, "");
  4266. delim = '\\';
  4267. } else
  4268. importRoot = ".";
  4269. }
  4270. } else
  4271. importRoot = null;
  4272. for (var i=0; i&lt;json['imports'].length; i++) {
  4273. if (typeof json['imports'][i] === 'string') { // Import file
  4274. if (!importRoot)
  4275. throw Error("cannot determine import root");
  4276. var importFilename = json['imports'][i];
  4277. if (importFilename === "google/protobuf/descriptor.proto")
  4278. continue; // Not needed and therefore not used
  4279. if (ProtoBuf.Util.IS_NODE)
  4280. importFilename = require("path")['join'](importRoot, importFilename);
  4281. else
  4282. importFilename = importRoot + delim + importFilename;
  4283. if (this.files[importFilename] === true)
  4284. continue; // Already imported
  4285. if (/\.proto$/i.test(importFilename) &amp;&amp; !ProtoBuf.DotProto) // If this is a light build
  4286. importFilename = importFilename.replace(/\.proto$/, ".json"); // always load the JSON file
  4287. var contents = ProtoBuf.Util.fetch(importFilename);
  4288. if (contents === null)
  4289. throw Error("failed to import '"+importFilename+"' in '"+filename+"': file not found");
  4290. if (/\.json$/i.test(importFilename)) // Always possible
  4291. this["import"](JSON.parse(contents+""), importFilename); // May throw
  4292. else
  4293. this["import"](ProtoBuf.DotProto.Parser.parse(contents), importFilename); // May throw
  4294. } else // Import structure
  4295. if (!filename)
  4296. this["import"](json['imports'][i]);
  4297. else if (/\.(\w+)$/.test(filename)) // With extension: Append _importN to the name portion to make it unique
  4298. this["import"](json['imports'][i], filename.replace(/^(.+)\.(\w+)$/, function($0, $1, $2) { return $1+"_import"+i+"."+$2; }));
  4299. else // Without extension: Append _importN to make it unique
  4300. this["import"](json['imports'][i], filename+"_import"+i);
  4301. }
  4302. if (resetRoot) // Reset import root override when all imports are done
  4303. this.importRoot = null;
  4304. }
  4305. // Import structures
  4306. if (json['package'])
  4307. this.define(json['package']);
  4308. if (json['syntax'])
  4309. propagateSyntax(json);
  4310. var base = this.ptr;
  4311. if (json['options'])
  4312. Object.keys(json['options']).forEach(function(key) {
  4313. base.options[key] = json['options'][key];
  4314. });
  4315. if (json['messages'])
  4316. this.create(json['messages']),
  4317. this.ptr = base;
  4318. if (json['enums'])
  4319. this.create(json['enums']),
  4320. this.ptr = base;
  4321. if (json['services'])
  4322. this.create(json['services']),
  4323. this.ptr = base;
  4324. if (json['extends'])
  4325. this.create(json['extends']);
  4326. return this.reset();
  4327. };
  4328. /**
  4329. * Resolves all namespace objects.
  4330. * @throws {Error} If a type cannot be resolved
  4331. * @returns {!ProtoBuf.Builder} this
  4332. * @expose
  4333. */
  4334. BuilderPrototype.resolveAll = function() {
  4335. // Resolve all reflected objects
  4336. var res;
  4337. if (this.ptr == null || typeof this.ptr.type === 'object')
  4338. return this; // Done (already resolved)
  4339. if (this.ptr instanceof Reflect.Namespace) { // Resolve children
  4340. this.ptr.children.forEach(function(child) {
  4341. this.ptr = child;
  4342. this.resolveAll();
  4343. }, this);
  4344. } else if (this.ptr instanceof Reflect.Message.Field) { // Resolve type
  4345. if (!Lang.TYPE.test(this.ptr.type)) {
  4346. if (!Lang.TYPEREF.test(this.ptr.type))
  4347. throw Error("illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.type);
  4348. res = (this.ptr instanceof Reflect.Message.ExtensionField ? this.ptr.extension.parent : this.ptr.parent).resolve(this.ptr.type, true);
  4349. if (!res)
  4350. throw Error("unresolvable type reference in "+this.ptr.toString(true)+": "+this.ptr.type);
  4351. this.ptr.resolvedType = res;
  4352. if (res instanceof Reflect.Enum) {
  4353. this.ptr.type = ProtoBuf.TYPES["enum"];
  4354. if (this.ptr.syntax === 'proto3' &amp;&amp; res.syntax !== 'proto3')
  4355. throw Error("proto3 message cannot reference proto2 enum");
  4356. }
  4357. else if (res instanceof Reflect.Message)
  4358. this.ptr.type = res.isGroup ? ProtoBuf.TYPES["group"] : ProtoBuf.TYPES["message"];
  4359. else
  4360. throw Error("illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.type);
  4361. } else
  4362. this.ptr.type = ProtoBuf.TYPES[this.ptr.type];
  4363. // If it's a map field, also resolve the key type. The key type can be only a numeric, string, or bool type
  4364. // (i.e., no enums or messages), so we don't need to resolve against the current namespace.
  4365. if (this.ptr.map) {
  4366. if (!Lang.TYPE.test(this.ptr.keyType))
  4367. throw Error("illegal key type for map field in "+this.ptr.toString(true)+": "+this.ptr.keyType);
  4368. this.ptr.keyType = ProtoBuf.TYPES[this.ptr.keyType];
  4369. }
  4370. // If it's a repeated and packable field then proto3 mandates it should be packed by
  4371. // default
  4372. if (
  4373. this.ptr.syntax === 'proto3' &amp;&amp;
  4374. this.ptr.repeated &amp;&amp; this.ptr.options.packed === undefined &amp;&amp;
  4375. ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.ptr.type.wireType) !== -1
  4376. ) {
  4377. this.ptr.options.packed = true;
  4378. }
  4379. } else if (this.ptr instanceof ProtoBuf.Reflect.Service.Method) {
  4380. if (this.ptr instanceof ProtoBuf.Reflect.Service.RPCMethod) {
  4381. res = this.ptr.parent.resolve(this.ptr.requestName, true);
  4382. if (!res || !(res instanceof ProtoBuf.Reflect.Message))
  4383. throw Error("Illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.requestName);
  4384. this.ptr.resolvedRequestType = res;
  4385. res = this.ptr.parent.resolve(this.ptr.responseName, true);
  4386. if (!res || !(res instanceof ProtoBuf.Reflect.Message))
  4387. throw Error("Illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.responseName);
  4388. this.ptr.resolvedResponseType = res;
  4389. } else // Should not happen as nothing else is implemented
  4390. throw Error("illegal service type in "+this.ptr.toString(true));
  4391. } else if (
  4392. !(this.ptr instanceof ProtoBuf.Reflect.Message.OneOf) &amp;&amp; // Not built
  4393. !(this.ptr instanceof ProtoBuf.Reflect.Extension) &amp;&amp; // Not built
  4394. !(this.ptr instanceof ProtoBuf.Reflect.Enum.Value) // Built in enum
  4395. )
  4396. throw Error("illegal object in namespace: "+typeof(this.ptr)+": "+this.ptr);
  4397. return this.reset();
  4398. };
  4399. /**
  4400. * Builds the protocol. This will first try to resolve all definitions and, if this has been successful,
  4401. * return the built package.
  4402. * @param {(string|Array.&lt;string>)=} path Specifies what to return. If omitted, the entire namespace will be returned.
  4403. * @returns {!ProtoBuf.Builder.Message|!Object.&lt;string,*>}
  4404. * @throws {Error} If a type could not be resolved
  4405. * @expose
  4406. */
  4407. BuilderPrototype.build = function(path) {
  4408. this.reset();
  4409. if (!this.resolved)
  4410. this.resolveAll(),
  4411. this.resolved = true,
  4412. this.result = null; // Require re-build
  4413. if (this.result === null) // (Re-)Build
  4414. this.result = this.ns.build();
  4415. if (!path)
  4416. return this.result;
  4417. var part = typeof path === 'string' ? path.split(".") : path,
  4418. ptr = this.result; // Build namespace pointer (no hasChild etc.)
  4419. for (var i=0; i&lt;part.length; i++)
  4420. if (ptr[part[i]])
  4421. ptr = ptr[part[i]];
  4422. else {
  4423. ptr = null;
  4424. break;
  4425. }
  4426. return ptr;
  4427. };
  4428. /**
  4429. * Similar to {@link ProtoBuf.Builder#build}, but looks up the internal reflection descriptor.
  4430. * @param {string=} path Specifies what to return. If omitted, the entire namespace wiil be returned.
  4431. * @param {boolean=} excludeNonNamespace Excludes non-namespace types like fields, defaults to `false`
  4432. * @returns {?ProtoBuf.Reflect.T} Reflection descriptor or `null` if not found
  4433. */
  4434. BuilderPrototype.lookup = function(path, excludeNonNamespace) {
  4435. return path ? this.ns.resolve(path, excludeNonNamespace) : this.ns;
  4436. };
  4437. /**
  4438. * Returns a string representation of this object.
  4439. * @return {string} String representation as of "Builder"
  4440. * @expose
  4441. */
  4442. BuilderPrototype.toString = function() {
  4443. return "Builder";
  4444. };
  4445. // ----- Base classes -----
  4446. // Exist for the sole purpose of being able to "... instanceof ProtoBuf.Builder.Message" etc.
  4447. /**
  4448. * @alias ProtoBuf.Builder.Message
  4449. */
  4450. Builder.Message = function() {};
  4451. /**
  4452. * @alias ProtoBuf.Builder.Enum
  4453. */
  4454. Builder.Enum = function() {};
  4455. /**
  4456. * @alias ProtoBuf.Builder.Message
  4457. */
  4458. Builder.Service = function() {};
  4459. return Builder;
  4460. })(ProtoBuf, ProtoBuf.Lang, ProtoBuf.Reflect);
  4461. /**
  4462. * @alias ProtoBuf.Map
  4463. * @expose
  4464. */
  4465. ProtoBuf.Map = (function(ProtoBuf, Reflect) {
  4466. "use strict";
  4467. /**
  4468. * Constructs a new Map. A Map is a container that is used to implement map
  4469. * fields on message objects. It closely follows the ES6 Map API; however,
  4470. * it is distinct because we do not want to depend on external polyfills or
  4471. * on ES6 itself.
  4472. *
  4473. * @exports ProtoBuf.Map
  4474. * @param {!ProtoBuf.Reflect.Field} field Map field
  4475. * @param {Object.&lt;string,*>=} contents Initial contents
  4476. * @constructor
  4477. */
  4478. var Map = function(field, contents) {
  4479. if (!field.map)
  4480. throw Error("field is not a map");
  4481. /**
  4482. * The field corresponding to this map.
  4483. * @type {!ProtoBuf.Reflect.Field}
  4484. */
  4485. this.field = field;
  4486. /**
  4487. * Element instance corresponding to key type.
  4488. * @type {!ProtoBuf.Reflect.Element}
  4489. */
  4490. this.keyElem = new Reflect.Element(field.keyType, null, true, field.syntax);
  4491. /**
  4492. * Element instance corresponding to value type.
  4493. * @type {!ProtoBuf.Reflect.Element}
  4494. */
  4495. this.valueElem = new Reflect.Element(field.type, field.resolvedType, false, field.syntax);
  4496. /**
  4497. * Internal map: stores mapping of (string form of key) -> (key, value)
  4498. * pair.
  4499. *
  4500. * We provide map semantics for arbitrary key types, but we build on top
  4501. * of an Object, which has only string keys. In order to avoid the need
  4502. * to convert a string key back to its native type in many situations,
  4503. * we store the native key value alongside the value. Thus, we only need
  4504. * a one-way mapping from a key type to its string form that guarantees
  4505. * uniqueness and equality (i.e., str(K1) === str(K2) if and only if K1
  4506. * === K2).
  4507. *
  4508. * @type {!Object&lt;string, {key: *, value: *}>}
  4509. */
  4510. this.map = {};
  4511. /**
  4512. * Returns the number of elements in the map.
  4513. */
  4514. Object.defineProperty(this, "size", {
  4515. get: function() { return Object.keys(this.map).length; }
  4516. });
  4517. // Fill initial contents from a raw object.
  4518. if (contents) {
  4519. var keys = Object.keys(contents);
  4520. for (var i = 0; i &lt; keys.length; i++) {
  4521. var key = this.keyElem.valueFromString(keys[i]);
  4522. var val = this.valueElem.verifyValue(contents[keys[i]]);
  4523. this.map[this.keyElem.valueToString(key)] =
  4524. { key: key, value: val };
  4525. }
  4526. }
  4527. };
  4528. var MapPrototype = Map.prototype;
  4529. /**
  4530. * Helper: return an iterator over an array.
  4531. * @param {!Array&lt;*>} arr the array
  4532. * @returns {!Object} an iterator
  4533. * @inner
  4534. */
  4535. function arrayIterator(arr) {
  4536. var idx = 0;
  4537. return {
  4538. next: function() {
  4539. if (idx &lt; arr.length)
  4540. return { done: false, value: arr[idx++] };
  4541. return { done: true };
  4542. }
  4543. }
  4544. }
  4545. /**
  4546. * Clears the map.
  4547. */
  4548. MapPrototype.clear = function() {
  4549. this.map = {};
  4550. };
  4551. /**
  4552. * Deletes a particular key from the map.
  4553. * @returns {boolean} Whether any entry with this key was deleted.
  4554. */
  4555. MapPrototype["delete"] = function(key) {
  4556. var keyValue = this.keyElem.valueToString(this.keyElem.verifyValue(key));
  4557. var hadKey = keyValue in this.map;
  4558. delete this.map[keyValue];
  4559. return hadKey;
  4560. };
  4561. /**
  4562. * Returns an iterator over [key, value] pairs in the map.
  4563. * @returns {Object} The iterator
  4564. */
  4565. MapPrototype.entries = function() {
  4566. var entries = [];
  4567. var strKeys = Object.keys(this.map);
  4568. for (var i = 0, entry; i &lt; strKeys.length; i++)
  4569. entries.push([(entry=this.map[strKeys[i]]).key, entry.value]);
  4570. return arrayIterator(entries);
  4571. };
  4572. /**
  4573. * Returns an iterator over keys in the map.
  4574. * @returns {Object} The iterator
  4575. */
  4576. MapPrototype.keys = function() {
  4577. var keys = [];
  4578. var strKeys = Object.keys(this.map);
  4579. for (var i = 0; i &lt; strKeys.length; i++)
  4580. keys.push(this.map[strKeys[i]].key);
  4581. return arrayIterator(keys);
  4582. };
  4583. /**
  4584. * Returns an iterator over values in the map.
  4585. * @returns {!Object} The iterator
  4586. */
  4587. MapPrototype.values = function() {
  4588. var values = [];
  4589. var strKeys = Object.keys(this.map);
  4590. for (var i = 0; i &lt; strKeys.length; i++)
  4591. values.push(this.map[strKeys[i]].value);
  4592. return arrayIterator(values);
  4593. };
  4594. /**
  4595. * Iterates over entries in the map, calling a function on each.
  4596. * @param {function(this:*, *, *, *)} cb The callback to invoke with value, key, and map arguments.
  4597. * @param {Object=} thisArg The `this` value for the callback
  4598. */
  4599. MapPrototype.forEach = function(cb, thisArg) {
  4600. var strKeys = Object.keys(this.map);
  4601. for (var i = 0, entry; i &lt; strKeys.length; i++)
  4602. cb.call(thisArg, (entry=this.map[strKeys[i]]).value, entry.key, this);
  4603. };
  4604. /**
  4605. * Sets a key in the map to the given value.
  4606. * @param {*} key The key
  4607. * @param {*} value The value
  4608. * @returns {!ProtoBuf.Map} The map instance
  4609. */
  4610. MapPrototype.set = function(key, value) {
  4611. var keyValue = this.keyElem.verifyValue(key);
  4612. var valValue = this.valueElem.verifyValue(value);
  4613. this.map[this.keyElem.valueToString(keyValue)] =
  4614. { key: keyValue, value: valValue };
  4615. return this;
  4616. };
  4617. /**
  4618. * Gets the value corresponding to a key in the map.
  4619. * @param {*} key The key
  4620. * @returns {*|undefined} The value, or `undefined` if key not present
  4621. */
  4622. MapPrototype.get = function(key) {
  4623. var keyValue = this.keyElem.valueToString(this.keyElem.verifyValue(key));
  4624. if (!(keyValue in this.map))
  4625. return undefined;
  4626. return this.map[keyValue].value;
  4627. };
  4628. /**
  4629. * Determines whether the given key is present in the map.
  4630. * @param {*} key The key
  4631. * @returns {boolean} `true` if the key is present
  4632. */
  4633. MapPrototype.has = function(key) {
  4634. var keyValue = this.keyElem.valueToString(this.keyElem.verifyValue(key));
  4635. return (keyValue in this.map);
  4636. };
  4637. return Map;
  4638. })(ProtoBuf, ProtoBuf.Reflect);
  4639. /**
  4640. * Loads a .proto string and returns the Builder.
  4641. * @param {string} proto .proto file contents
  4642. * @param {(ProtoBuf.Builder|string|{root: string, file: string})=} builder Builder to append to. Will create a new one if omitted.
  4643. * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
  4644. * @return {ProtoBuf.Builder} Builder to create new messages
  4645. * @throws {Error} If the definition cannot be parsed or built
  4646. * @expose
  4647. */
  4648. ProtoBuf.loadProto = function(proto, builder, filename) {
  4649. if (typeof builder === 'string' || (builder &amp;&amp; typeof builder["file"] === 'string' &amp;&amp; typeof builder["root"] === 'string'))
  4650. filename = builder,
  4651. builder = undefined;
  4652. return ProtoBuf.loadJson(ProtoBuf.DotProto.Parser.parse(proto), builder, filename);
  4653. };
  4654. /**
  4655. * Loads a .proto string and returns the Builder. This is an alias of {@link ProtoBuf.loadProto}.
  4656. * @function
  4657. * @param {string} proto .proto file contents
  4658. * @param {(ProtoBuf.Builder|string)=} builder Builder to append to. Will create a new one if omitted.
  4659. * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
  4660. * @return {ProtoBuf.Builder} Builder to create new messages
  4661. * @throws {Error} If the definition cannot be parsed or built
  4662. * @expose
  4663. */
  4664. ProtoBuf.protoFromString = ProtoBuf.loadProto; // Legacy
  4665. /**
  4666. * Loads a .proto file and returns the Builder.
  4667. * @param {string|{root: string, file: string}} filename Path to proto file or an object specifying 'file' with
  4668. * an overridden 'root' path for all imported files.
  4669. * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
  4670. * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
  4671. * file will be read synchronously and this function will return the Builder.
  4672. * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
  4673. * @return {?ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
  4674. * request has failed), else undefined
  4675. * @expose
  4676. */
  4677. ProtoBuf.loadProtoFile = function(filename, callback, builder) {
  4678. if (callback &amp;&amp; typeof callback === 'object')
  4679. builder = callback,
  4680. callback = null;
  4681. else if (!callback || typeof callback !== 'function')
  4682. callback = null;
  4683. if (callback)
  4684. return ProtoBuf.Util.fetch(typeof filename === 'string' ? filename : filename["root"]+"/"+filename["file"], function(contents) {
  4685. if (contents === null) {
  4686. callback(Error("Failed to fetch file"));
  4687. return;
  4688. }
  4689. try {
  4690. callback(null, ProtoBuf.loadProto(contents, builder, filename));
  4691. } catch (e) {
  4692. callback(e);
  4693. }
  4694. });
  4695. var contents = ProtoBuf.Util.fetch(typeof filename === 'object' ? filename["root"]+"/"+filename["file"] : filename);
  4696. return contents === null ? null : ProtoBuf.loadProto(contents, builder, filename);
  4697. };
  4698. /**
  4699. * Loads a .proto file and returns the Builder. This is an alias of {@link ProtoBuf.loadProtoFile}.
  4700. * @function
  4701. * @param {string|{root: string, file: string}} filename Path to proto file or an object specifying 'file' with
  4702. * an overridden 'root' path for all imported files.
  4703. * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
  4704. * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
  4705. * file will be read synchronously and this function will return the Builder.
  4706. * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
  4707. * @return {!ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
  4708. * request has failed), else undefined
  4709. * @expose
  4710. */
  4711. ProtoBuf.protoFromFile = ProtoBuf.loadProtoFile; // Legacy
  4712. /**
  4713. * Constructs a new empty Builder.
  4714. * @param {Object.&lt;string,*>=} options Builder options, defaults to global options set on ProtoBuf
  4715. * @return {!ProtoBuf.Builder} Builder
  4716. * @expose
  4717. */
  4718. ProtoBuf.newBuilder = function(options) {
  4719. options = options || {};
  4720. if (typeof options['convertFieldsToCamelCase'] === 'undefined')
  4721. options['convertFieldsToCamelCase'] = ProtoBuf.convertFieldsToCamelCase;
  4722. if (typeof options['populateAccessors'] === 'undefined')
  4723. options['populateAccessors'] = ProtoBuf.populateAccessors;
  4724. return new ProtoBuf.Builder(options);
  4725. };
  4726. /**
  4727. * Loads a .json definition and returns the Builder.
  4728. * @param {!*|string} json JSON definition
  4729. * @param {(ProtoBuf.Builder|string|{root: string, file: string})=} builder Builder to append to. Will create a new one if omitted.
  4730. * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
  4731. * @return {ProtoBuf.Builder} Builder to create new messages
  4732. * @throws {Error} If the definition cannot be parsed or built
  4733. * @expose
  4734. */
  4735. ProtoBuf.loadJson = function(json, builder, filename) {
  4736. if (typeof builder === 'string' || (builder &amp;&amp; typeof builder["file"] === 'string' &amp;&amp; typeof builder["root"] === 'string'))
  4737. filename = builder,
  4738. builder = null;
  4739. if (!builder || typeof builder !== 'object')
  4740. builder = ProtoBuf.newBuilder();
  4741. if (typeof json === 'string')
  4742. json = JSON.parse(json);
  4743. builder["import"](json, filename);
  4744. builder.resolveAll();
  4745. return builder;
  4746. };
  4747. /**
  4748. * Loads a .json file and returns the Builder.
  4749. * @param {string|!{root: string, file: string}} filename Path to json file or an object specifying 'file' with
  4750. * an overridden 'root' path for all imported files.
  4751. * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
  4752. * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
  4753. * file will be read synchronously and this function will return the Builder.
  4754. * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
  4755. * @return {?ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
  4756. * request has failed), else undefined
  4757. * @expose
  4758. */
  4759. ProtoBuf.loadJsonFile = function(filename, callback, builder) {
  4760. if (callback &amp;&amp; typeof callback === 'object')
  4761. builder = callback,
  4762. callback = null;
  4763. else if (!callback || typeof callback !== 'function')
  4764. callback = null;
  4765. if (callback)
  4766. return ProtoBuf.Util.fetch(typeof filename === 'string' ? filename : filename["root"]+"/"+filename["file"], function(contents) {
  4767. if (contents === null) {
  4768. callback(Error("Failed to fetch file"));
  4769. return;
  4770. }
  4771. try {
  4772. callback(null, ProtoBuf.loadJson(JSON.parse(contents), builder, filename));
  4773. } catch (e) {
  4774. callback(e);
  4775. }
  4776. });
  4777. var contents = ProtoBuf.Util.fetch(typeof filename === 'object' ? filename["root"]+"/"+filename["file"] : filename);
  4778. return contents === null ? null : ProtoBuf.loadJson(JSON.parse(contents), builder, filename);
  4779. };
  4780. return ProtoBuf;
  4781. });
  4782. </code></pre>
  4783. </article>
  4784. </section>
  4785. </div>
  4786. <nav>
  4787. <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="ProtoBuf.Builder.html">Builder</a></li><li><a href="ProtoBuf.Builder.Message.html">Message</a></li><li><a href="ProtoBuf.Builder.Service.html">Service</a></li><li><a href="ProtoBuf.DotProto.Parser.html">Parser</a></li><li><a href="ProtoBuf.DotProto.Tokenizer.html">Tokenizer</a></li><li><a href="ProtoBuf.Map.html">Map</a></li><li><a href="ProtoBuf.Reflect.Element.html">Element</a></li><li><a href="ProtoBuf.Reflect.Enum.html">Enum</a></li><li><a href="ProtoBuf.Reflect.Enum.Value.html">Value</a></li><li><a href="ProtoBuf.Reflect.Extension.html">Extension</a></li><li><a href="ProtoBuf.Reflect.Message.html">Message</a></li><li><a href="ProtoBuf.Reflect.Message.ExtensionField.html">ExtensionField</a></li><li><a href="ProtoBuf.Reflect.Message.Field.html">Field</a></li><li><a href="ProtoBuf.Reflect.Message.OneOf.html">OneOf</a></li><li><a href="ProtoBuf.Reflect.Namespace.html">Namespace</a></li><li><a href="ProtoBuf.Reflect.Service.html">Service</a></li><li><a href="ProtoBuf.Reflect.Service.Method.html">Method</a></li><li><a href="ProtoBuf.Reflect.Service.RPCMethod.html">RPCMethod</a></li><li><a href="ProtoBuf.Reflect.T.html">T</a></li></ul><h3>Namespaces</h3><ul><li><a href="ProtoBuf.html">ProtoBuf</a></li><li><a href="ProtoBuf.DotProto.html">DotProto</a></li><li><a href="ProtoBuf.Reflect.html">Reflect</a></li><li><a href="ProtoBuf.Util.html">Util</a></li></ul>
  4788. </nav>
  4789. <br class="clear">
  4790. <footer>
  4791. Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.3</a> on Fri Jan 27 2017 17:03:55 GMT+0100 (Mitteleuropäische Zeit)
  4792. </footer>
  4793. <script> prettyPrint(); </script>
  4794. <script src="scripts/linenumber.js"> </script>
  4795. </body>
  4796. </html>