components.js 371 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555
  1. /*
  2. Copyright 2013 Daniel Wirtz <dcode@dcode.io>
  3. Copyright 2009 The Closure Library Authors. All Rights Reserved.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS-IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. */
  14. /**
  15. * @license Long.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
  16. * Released under the Apache License, Version 2.0
  17. * see: https://github.com/dcodeIO/Long.js for details
  18. */
  19. (function(global) {
  20. "use strict";
  21. /**
  22. * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
  23. * See the from* functions below for more convenient ways of constructing Longs.
  24. * @exports Long
  25. * @class A Long class for representing a 64 bit two's-complement integer value.
  26. * @param {number} low The low (signed) 32 bits of the long
  27. * @param {number} high The high (signed) 32 bits of the long
  28. * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
  29. * @constructor
  30. */
  31. var Long = function(low, high, unsigned) {
  32. /**
  33. * The low 32 bits as a signed value.
  34. * @type {number}
  35. * @expose
  36. */
  37. this.low = low|0;
  38. /**
  39. * The high 32 bits as a signed value.
  40. * @type {number}
  41. * @expose
  42. */
  43. this.high = high|0;
  44. /**
  45. * Whether unsigned or not.
  46. * @type {boolean}
  47. * @expose
  48. */
  49. this.unsigned = !!unsigned;
  50. };
  51. // The internal representation of a long is the two given signed, 32-bit values.
  52. // We use 32-bit pieces because these are the size of integers on which
  53. // Javascript performs bit-operations. For operations like addition and
  54. // multiplication, we split each number into 16 bit pieces, which can easily be
  55. // multiplied within Javascript's floating-point representation without overflow
  56. // or change in sign.
  57. //
  58. // In the algorithms below, we frequently reduce the negative case to the
  59. // positive case by negating the input(s) and then post-processing the result.
  60. // Note that we must ALWAYS check specially whether those values are MIN_VALUE
  61. // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
  62. // a positive number, it overflows back into a negative). Not handling this
  63. // case would often result in infinite recursion.
  64. //
  65. // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
  66. // methods on which they depend.
  67. /**
  68. * Tests if the specified object is a Long.
  69. * @param {*} obj Object
  70. * @returns {boolean}
  71. * @expose
  72. */
  73. Long.isLong = function(obj) {
  74. return (obj && obj instanceof Long) === true;
  75. };
  76. /**
  77. * A cache of the Long representations of small integer values.
  78. * @type {!Object}
  79. * @inner
  80. */
  81. var INT_CACHE = {};
  82. /**
  83. * A cache of the Long representations of small unsigned integer values.
  84. * @type {!Object}
  85. * @inner
  86. */
  87. var UINT_CACHE = {};
  88. /**
  89. * Returns a Long representing the given 32 bit integer value.
  90. * @param {number} value The 32 bit integer in question
  91. * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
  92. * @returns {!Long} The corresponding Long value
  93. * @expose
  94. */
  95. Long.fromInt = function(value, unsigned) {
  96. var obj, cachedObj;
  97. if (!unsigned) {
  98. value = value | 0;
  99. if (-128 <= value && value < 128) {
  100. cachedObj = INT_CACHE[value];
  101. if (cachedObj)
  102. return cachedObj;
  103. }
  104. obj = new Long(value, value < 0 ? -1 : 0, false);
  105. if (-128 <= value && value < 128)
  106. INT_CACHE[value] = obj;
  107. return obj;
  108. } else {
  109. value = value >>> 0;
  110. if (0 <= value && value < 256) {
  111. cachedObj = UINT_CACHE[value];
  112. if (cachedObj)
  113. return cachedObj;
  114. }
  115. obj = new Long(value, (value | 0) < 0 ? -1 : 0, true);
  116. if (0 <= value && value < 256)
  117. UINT_CACHE[value] = obj;
  118. return obj;
  119. }
  120. };
  121. /**
  122. * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
  123. * @param {number} value The number in question
  124. * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
  125. * @returns {!Long} The corresponding Long value
  126. * @expose
  127. */
  128. Long.fromNumber = function(value, unsigned) {
  129. unsigned = !!unsigned;
  130. if (isNaN(value) || !isFinite(value))
  131. return Long.ZERO;
  132. if (!unsigned && value <= -TWO_PWR_63_DBL)
  133. return Long.MIN_VALUE;
  134. if (!unsigned && value + 1 >= TWO_PWR_63_DBL)
  135. return Long.MAX_VALUE;
  136. if (unsigned && value >= TWO_PWR_64_DBL)
  137. return Long.MAX_UNSIGNED_VALUE;
  138. if (value < 0)
  139. return Long.fromNumber(-value, unsigned).negate();
  140. return new Long((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
  141. };
  142. /**
  143. * Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
  144. * assumed to use 32 bits.
  145. * @param {number} lowBits The low 32 bits
  146. * @param {number} highBits The high 32 bits
  147. * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
  148. * @returns {!Long} The corresponding Long value
  149. * @expose
  150. */
  151. Long.fromBits = function(lowBits, highBits, unsigned) {
  152. return new Long(lowBits, highBits, unsigned);
  153. };
  154. /**
  155. * Returns a Long representation of the given string, written using the specified radix.
  156. * @param {string} str The textual representation of the Long
  157. * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed
  158. * @param {number=} radix The radix in which the text is written (2-36), defaults to 10
  159. * @returns {!Long} The corresponding Long value
  160. * @expose
  161. */
  162. Long.fromString = function(str, unsigned, radix) {
  163. if (str.length === 0)
  164. throw Error('number format error: empty string');
  165. if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
  166. return Long.ZERO;
  167. if (typeof unsigned === 'number') // For goog.math.long compatibility
  168. radix = unsigned,
  169. unsigned = false;
  170. radix = radix || 10;
  171. if (radix < 2 || 36 < radix)
  172. throw Error('radix out of range: ' + radix);
  173. var p;
  174. if ((p = str.indexOf('-')) > 0)
  175. throw Error('number format error: interior "-" character: ' + str);
  176. else if (p === 0)
  177. return Long.fromString(str.substring(1), unsigned, radix).negate();
  178. // Do several (8) digits each time through the loop, so as to
  179. // minimize the calls to the very expensive emulated div.
  180. var radixToPower = Long.fromNumber(Math.pow(radix, 8));
  181. var result = Long.ZERO;
  182. for (var i = 0; i < str.length; i += 8) {
  183. var size = Math.min(8, str.length - i);
  184. var value = parseInt(str.substring(i, i + size), radix);
  185. if (size < 8) {
  186. var power = Long.fromNumber(Math.pow(radix, size));
  187. result = result.multiply(power).add(Long.fromNumber(value));
  188. } else {
  189. result = result.multiply(radixToPower);
  190. result = result.add(Long.fromNumber(value));
  191. }
  192. }
  193. result.unsigned = unsigned;
  194. return result;
  195. };
  196. /**
  197. * Converts the specified value to a Long.
  198. * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val Value
  199. * @returns {!Long}
  200. * @expose
  201. */
  202. Long.fromValue = function(val) {
  203. if (typeof val === 'number')
  204. return Long.fromNumber(val);
  205. if (typeof val === 'string')
  206. return Long.fromString(val);
  207. if (Long.isLong(val))
  208. return val;
  209. // Throws for not an object (undefined, null):
  210. return new Long(val.low, val.high, val.unsigned);
  211. };
  212. // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
  213. // no runtime penalty for these.
  214. /**
  215. * @type {number}
  216. * @const
  217. * @inner
  218. */
  219. var TWO_PWR_16_DBL = 1 << 16;
  220. /**
  221. * @type {number}
  222. * @const
  223. * @inner
  224. */
  225. var TWO_PWR_24_DBL = 1 << 24;
  226. /**
  227. * @type {number}
  228. * @const
  229. * @inner
  230. */
  231. var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
  232. /**
  233. * @type {number}
  234. * @const
  235. * @inner
  236. */
  237. var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
  238. /**
  239. * @type {number}
  240. * @const
  241. * @inner
  242. */
  243. var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
  244. /**
  245. * @type {!Long}
  246. * @const
  247. * @inner
  248. */
  249. var TWO_PWR_24 = Long.fromInt(TWO_PWR_24_DBL);
  250. /**
  251. * Signed zero.
  252. * @type {!Long}
  253. * @expose
  254. */
  255. Long.ZERO = Long.fromInt(0);
  256. /**
  257. * Unsigned zero.
  258. * @type {!Long}
  259. * @expose
  260. */
  261. Long.UZERO = Long.fromInt(0, true);
  262. /**
  263. * Signed one.
  264. * @type {!Long}
  265. * @expose
  266. */
  267. Long.ONE = Long.fromInt(1);
  268. /**
  269. * Unsigned one.
  270. * @type {!Long}
  271. * @expose
  272. */
  273. Long.UONE = Long.fromInt(1, true);
  274. /**
  275. * Signed negative one.
  276. * @type {!Long}
  277. * @expose
  278. */
  279. Long.NEG_ONE = Long.fromInt(-1);
  280. /**
  281. * Maximum signed value.
  282. * @type {!Long}
  283. * @expose
  284. */
  285. Long.MAX_VALUE = Long.fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
  286. /**
  287. * Maximum unsigned value.
  288. * @type {!Long}
  289. * @expose
  290. */
  291. Long.MAX_UNSIGNED_VALUE = Long.fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
  292. /**
  293. * Minimum signed value.
  294. * @type {!Long}
  295. * @expose
  296. */
  297. Long.MIN_VALUE = Long.fromBits(0, 0x80000000|0, false);
  298. /**
  299. * Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
  300. * @returns {number}
  301. * @expose
  302. */
  303. Long.prototype.toInt = function() {
  304. return this.unsigned ? this.low >>> 0 : this.low;
  305. };
  306. /**
  307. * Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa).
  308. * @returns {number}
  309. * @expose
  310. */
  311. Long.prototype.toNumber = function() {
  312. if (this.unsigned) {
  313. return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0);
  314. }
  315. return this.high * TWO_PWR_32_DBL + (this.low >>> 0);
  316. };
  317. /**
  318. * Converts the Long to a string written in the specified radix.
  319. * @param {number=} radix Radix (2-36), defaults to 10
  320. * @returns {string}
  321. * @override
  322. * @throws {RangeError} If `radix` is out of range
  323. * @expose
  324. */
  325. Long.prototype.toString = function(radix) {
  326. radix = radix || 10;
  327. if (radix < 2 || 36 < radix)
  328. throw RangeError('radix out of range: ' + radix);
  329. if (this.isZero())
  330. return '0';
  331. var rem;
  332. if (this.isNegative()) { // Unsigned Longs are never negative
  333. if (this.equals(Long.MIN_VALUE)) {
  334. // We need to change the Long value before it can be negated, so we remove
  335. // the bottom-most digit in this base and then recurse to do the rest.
  336. var radixLong = Long.fromNumber(radix);
  337. var div = this.div(radixLong);
  338. rem = div.multiply(radixLong).subtract(this);
  339. return div.toString(radix) + rem.toInt().toString(radix);
  340. } else
  341. return '-' + this.negate().toString(radix);
  342. }
  343. // Do several (6) digits each time through the loop, so as to
  344. // minimize the calls to the very expensive emulated div.
  345. var radixToPower = Long.fromNumber(Math.pow(radix, 6), this.unsigned);
  346. rem = this;
  347. var result = '';
  348. while (true) {
  349. var remDiv = rem.div(radixToPower),
  350. intval = rem.subtract(remDiv.multiply(radixToPower)).toInt() >>> 0,
  351. digits = intval.toString(radix);
  352. rem = remDiv;
  353. if (rem.isZero())
  354. return digits + result;
  355. else {
  356. while (digits.length < 6)
  357. digits = '0' + digits;
  358. result = '' + digits + result;
  359. }
  360. }
  361. };
  362. /**
  363. * Gets the high 32 bits as a signed integer.
  364. * @returns {number} Signed high bits
  365. * @expose
  366. */
  367. Long.prototype.getHighBits = function() {
  368. return this.high;
  369. };
  370. /**
  371. * Gets the high 32 bits as an unsigned integer.
  372. * @returns {number} Unsigned high bits
  373. * @expose
  374. */
  375. Long.prototype.getHighBitsUnsigned = function() {
  376. return this.high >>> 0;
  377. };
  378. /**
  379. * Gets the low 32 bits as a signed integer.
  380. * @returns {number} Signed low bits
  381. * @expose
  382. */
  383. Long.prototype.getLowBits = function() {
  384. return this.low;
  385. };
  386. /**
  387. * Gets the low 32 bits as an unsigned integer.
  388. * @returns {number} Unsigned low bits
  389. * @expose
  390. */
  391. Long.prototype.getLowBitsUnsigned = function() {
  392. return this.low >>> 0;
  393. };
  394. /**
  395. * Gets the number of bits needed to represent the absolute value of this Long.
  396. * @returns {number}
  397. * @expose
  398. */
  399. Long.prototype.getNumBitsAbs = function() {
  400. if (this.isNegative()) // Unsigned Longs are never negative
  401. return this.equals(Long.MIN_VALUE) ? 64 : this.negate().getNumBitsAbs();
  402. var val = this.high != 0 ? this.high : this.low;
  403. for (var bit = 31; bit > 0; bit--)
  404. if ((val & (1 << bit)) != 0)
  405. break;
  406. return this.high != 0 ? bit + 33 : bit + 1;
  407. };
  408. /**
  409. * Tests if this Long's value equals zero.
  410. * @returns {boolean}
  411. * @expose
  412. */
  413. Long.prototype.isZero = function() {
  414. return this.high === 0 && this.low === 0;
  415. };
  416. /**
  417. * Tests if this Long's value is negative.
  418. * @returns {boolean}
  419. * @expose
  420. */
  421. Long.prototype.isNegative = function() {
  422. return !this.unsigned && this.high < 0;
  423. };
  424. /**
  425. * Tests if this Long's value is positive.
  426. * @returns {boolean}
  427. * @expose
  428. */
  429. Long.prototype.isPositive = function() {
  430. return this.unsigned || this.high >= 0;
  431. };
  432. /**
  433. * Tests if this Long's value is odd.
  434. * @returns {boolean}
  435. * @expose
  436. */
  437. Long.prototype.isOdd = function() {
  438. return (this.low & 1) === 1;
  439. };
  440. /**
  441. * Tests if this Long's value is even.
  442. * @returns {boolean}
  443. * @expose
  444. */
  445. Long.prototype.isEven = function() {
  446. return (this.low & 1) === 0;
  447. };
  448. /**
  449. * Tests if this Long's value equals the specified's.
  450. * @param {!Long|number|string} other Other value
  451. * @returns {boolean}
  452. * @expose
  453. */
  454. Long.prototype.equals = function(other) {
  455. if (!Long.isLong(other))
  456. other = Long.fromValue(other);
  457. if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1)
  458. return false;
  459. return this.high === other.high && this.low === other.low;
  460. };
  461. /**
  462. * Tests if this Long's value differs from the specified's.
  463. * @param {!Long|number|string} other Other value
  464. * @returns {boolean}
  465. * @expose
  466. */
  467. Long.prototype.notEquals = function(other) {
  468. if (!Long.isLong(other))
  469. other = Long.fromValue(other);
  470. return !this.equals(other);
  471. };
  472. /**
  473. * Tests if this Long's value is less than the specified's.
  474. * @param {!Long|number|string} other Other value
  475. * @returns {boolean}
  476. * @expose
  477. */
  478. Long.prototype.lessThan = function(other) {
  479. if (!Long.isLong(other))
  480. other = Long.fromValue(other);
  481. return this.compare(other) < 0;
  482. };
  483. /**
  484. * Tests if this Long's value is less than or equal the specified's.
  485. * @param {!Long|number|string} other Other value
  486. * @returns {boolean}
  487. * @expose
  488. */
  489. Long.prototype.lessThanOrEqual = function(other) {
  490. if (!Long.isLong(other))
  491. other = Long.fromValue(other);
  492. return this.compare(other) <= 0;
  493. };
  494. /**
  495. * Tests if this Long's value is greater than the specified's.
  496. * @param {!Long|number|string} other Other value
  497. * @returns {boolean}
  498. * @expose
  499. */
  500. Long.prototype.greaterThan = function(other) {
  501. if (!Long.isLong(other))
  502. other = Long.fromValue(other);
  503. return this.compare(other) > 0;
  504. };
  505. /**
  506. * Tests if this Long's value is greater than or equal the specified's.
  507. * @param {!Long|number|string} other Other value
  508. * @returns {boolean}
  509. * @expose
  510. */
  511. Long.prototype.greaterThanOrEqual = function(other) {
  512. return this.compare(other) >= 0;
  513. };
  514. /**
  515. * Compares this Long's value with the specified's.
  516. * @param {!Long|number|string} other Other value
  517. * @returns {number} 0 if they are the same, 1 if the this is greater and -1
  518. * if the given one is greater
  519. * @expose
  520. */
  521. Long.prototype.compare = function(other) {
  522. if (this.equals(other))
  523. return 0;
  524. var thisNeg = this.isNegative(),
  525. otherNeg = other.isNegative();
  526. if (thisNeg && !otherNeg)
  527. return -1;
  528. if (!thisNeg && otherNeg)
  529. return 1;
  530. // At this point the sign bits are the same
  531. if (!this.unsigned)
  532. return this.subtract(other).isNegative() ? -1 : 1;
  533. // Both are positive if at least one is unsigned
  534. return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
  535. };
  536. /**
  537. * Negates this Long's value.
  538. * @returns {!Long} Negated Long
  539. * @expose
  540. */
  541. Long.prototype.negate = function() {
  542. if (!this.unsigned && this.equals(Long.MIN_VALUE))
  543. return Long.MIN_VALUE;
  544. return this.not().add(Long.ONE);
  545. };
  546. /**
  547. * Returns the sum of this and the specified Long.
  548. * @param {!Long|number|string} addend Addend
  549. * @returns {!Long} Sum
  550. * @expose
  551. */
  552. Long.prototype.add = function(addend) {
  553. if (!Long.isLong(addend))
  554. addend = Long.fromValue(addend);
  555. // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
  556. var a48 = this.high >>> 16;
  557. var a32 = this.high & 0xFFFF;
  558. var a16 = this.low >>> 16;
  559. var a00 = this.low & 0xFFFF;
  560. var b48 = addend.high >>> 16;
  561. var b32 = addend.high & 0xFFFF;
  562. var b16 = addend.low >>> 16;
  563. var b00 = addend.low & 0xFFFF;
  564. var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
  565. c00 += a00 + b00;
  566. c16 += c00 >>> 16;
  567. c00 &= 0xFFFF;
  568. c16 += a16 + b16;
  569. c32 += c16 >>> 16;
  570. c16 &= 0xFFFF;
  571. c32 += a32 + b32;
  572. c48 += c32 >>> 16;
  573. c32 &= 0xFFFF;
  574. c48 += a48 + b48;
  575. c48 &= 0xFFFF;
  576. return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
  577. };
  578. /**
  579. * Returns the difference of this and the specified Long.
  580. * @param {!Long|number|string} subtrahend Subtrahend
  581. * @returns {!Long} Difference
  582. * @expose
  583. */
  584. Long.prototype.subtract = function(subtrahend) {
  585. if (!Long.isLong(subtrahend))
  586. subtrahend = Long.fromValue(subtrahend);
  587. return this.add(subtrahend.negate());
  588. };
  589. /**
  590. * Returns the product of this and the specified Long.
  591. * @param {!Long|number|string} multiplier Multiplier
  592. * @returns {!Long} Product
  593. * @expose
  594. */
  595. Long.prototype.multiply = function(multiplier) {
  596. if (this.isZero())
  597. return Long.ZERO;
  598. if (!Long.isLong(multiplier))
  599. multiplier = Long.fromValue(multiplier);
  600. if (multiplier.isZero())
  601. return Long.ZERO;
  602. if (this.equals(Long.MIN_VALUE))
  603. return multiplier.isOdd() ? Long.MIN_VALUE : Long.ZERO;
  604. if (multiplier.equals(Long.MIN_VALUE))
  605. return this.isOdd() ? Long.MIN_VALUE : Long.ZERO;
  606. if (this.isNegative()) {
  607. if (multiplier.isNegative())
  608. return this.negate().multiply(multiplier.negate());
  609. else
  610. return this.negate().multiply(multiplier).negate();
  611. } else if (multiplier.isNegative())
  612. return this.multiply(multiplier.negate()).negate();
  613. // If both longs are small, use float multiplication
  614. if (this.lessThan(TWO_PWR_24) && multiplier.lessThan(TWO_PWR_24))
  615. return Long.fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned);
  616. // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
  617. // We can skip products that would overflow.
  618. var a48 = this.high >>> 16;
  619. var a32 = this.high & 0xFFFF;
  620. var a16 = this.low >>> 16;
  621. var a00 = this.low & 0xFFFF;
  622. var b48 = multiplier.high >>> 16;
  623. var b32 = multiplier.high & 0xFFFF;
  624. var b16 = multiplier.low >>> 16;
  625. var b00 = multiplier.low & 0xFFFF;
  626. var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
  627. c00 += a00 * b00;
  628. c16 += c00 >>> 16;
  629. c00 &= 0xFFFF;
  630. c16 += a16 * b00;
  631. c32 += c16 >>> 16;
  632. c16 &= 0xFFFF;
  633. c16 += a00 * b16;
  634. c32 += c16 >>> 16;
  635. c16 &= 0xFFFF;
  636. c32 += a32 * b00;
  637. c48 += c32 >>> 16;
  638. c32 &= 0xFFFF;
  639. c32 += a16 * b16;
  640. c48 += c32 >>> 16;
  641. c32 &= 0xFFFF;
  642. c32 += a00 * b32;
  643. c48 += c32 >>> 16;
  644. c32 &= 0xFFFF;
  645. c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
  646. c48 &= 0xFFFF;
  647. return Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
  648. };
  649. /**
  650. * Returns this Long divided by the specified.
  651. * @param {!Long|number|string} divisor Divisor
  652. * @returns {!Long} Quotient
  653. * @expose
  654. */
  655. Long.prototype.div = function(divisor) {
  656. if (!Long.isLong(divisor))
  657. divisor = Long.fromValue(divisor);
  658. if (divisor.isZero())
  659. throw(new Error('division by zero'));
  660. if (this.isZero())
  661. return this.unsigned ? Long.UZERO : Long.ZERO;
  662. var approx, rem, res;
  663. if (this.equals(Long.MIN_VALUE)) {
  664. if (divisor.equals(Long.ONE) || divisor.equals(Long.NEG_ONE))
  665. return Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
  666. else if (divisor.equals(Long.MIN_VALUE))
  667. return Long.ONE;
  668. else {
  669. // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
  670. var halfThis = this.shiftRight(1);
  671. approx = halfThis.div(divisor).shiftLeft(1);
  672. if (approx.equals(Long.ZERO)) {
  673. return divisor.isNegative() ? Long.ONE : Long.NEG_ONE;
  674. } else {
  675. rem = this.subtract(divisor.multiply(approx));
  676. res = approx.add(rem.div(divisor));
  677. return res;
  678. }
  679. }
  680. } else if (divisor.equals(Long.MIN_VALUE))
  681. return this.unsigned ? Long.UZERO : Long.ZERO;
  682. if (this.isNegative()) {
  683. if (divisor.isNegative())
  684. return this.negate().div(divisor.negate());
  685. return this.negate().div(divisor).negate();
  686. } else if (divisor.isNegative())
  687. return this.div(divisor.negate()).negate();
  688. // Repeat the following until the remainder is less than other: find a
  689. // floating-point that approximates remainder / other *from below*, add this
  690. // into the result, and subtract it from the remainder. It is critical that
  691. // the approximate value is less than or equal to the real value so that the
  692. // remainder never becomes negative.
  693. res = Long.ZERO;
  694. rem = this;
  695. while (rem.greaterThanOrEqual(divisor)) {
  696. // Approximate the result of division. This may be a little greater or
  697. // smaller than the actual value.
  698. approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber()));
  699. // We will tweak the approximate result by changing it in the 48-th digit or
  700. // the smallest non-fractional digit, whichever is larger.
  701. var log2 = Math.ceil(Math.log(approx) / Math.LN2),
  702. delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48),
  703. // Decrease the approximation until it is smaller than the remainder. Note
  704. // that if it is too large, the product overflows and is negative.
  705. approxRes = Long.fromNumber(approx),
  706. approxRem = approxRes.multiply(divisor);
  707. while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
  708. approx -= delta;
  709. approxRes = Long.fromNumber(approx, this.unsigned);
  710. approxRem = approxRes.multiply(divisor);
  711. }
  712. // We know the answer can't be zero... and actually, zero would cause
  713. // infinite recursion since we would make no progress.
  714. if (approxRes.isZero())
  715. approxRes = Long.ONE;
  716. res = res.add(approxRes);
  717. rem = rem.subtract(approxRem);
  718. }
  719. return res;
  720. };
  721. /**
  722. * Returns this Long modulo the specified.
  723. * @param {!Long|number|string} divisor Divisor
  724. * @returns {!Long} Remainder
  725. * @expose
  726. */
  727. Long.prototype.modulo = function(divisor) {
  728. if (!Long.isLong(divisor))
  729. divisor = Long.fromValue(divisor);
  730. return this.subtract(this.div(divisor).multiply(divisor));
  731. };
  732. /**
  733. * Returns the bitwise NOT of this Long.
  734. * @returns {!Long}
  735. * @expose
  736. */
  737. Long.prototype.not = function() {
  738. return Long.fromBits(~this.low, ~this.high, this.unsigned);
  739. };
  740. /**
  741. * Returns the bitwise AND of this Long and the specified.
  742. * @param {!Long|number|string} other Other Long
  743. * @returns {!Long}
  744. * @expose
  745. */
  746. Long.prototype.and = function(other) {
  747. if (!Long.isLong(other))
  748. other = Long.fromValue(other);
  749. return Long.fromBits(this.low & other.low, this.high & other.high, this.unsigned);
  750. };
  751. /**
  752. * Returns the bitwise OR of this Long and the specified.
  753. * @param {!Long|number|string} other Other Long
  754. * @returns {!Long}
  755. * @expose
  756. */
  757. Long.prototype.or = function(other) {
  758. if (!Long.isLong(other))
  759. other = Long.fromValue(other);
  760. return Long.fromBits(this.low | other.low, this.high | other.high, this.unsigned);
  761. };
  762. /**
  763. * Returns the bitwise XOR of this Long and the given one.
  764. * @param {!Long|number|string} other Other Long
  765. * @returns {!Long}
  766. * @expose
  767. */
  768. Long.prototype.xor = function(other) {
  769. if (!Long.isLong(other))
  770. other = Long.fromValue(other);
  771. return Long.fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned);
  772. };
  773. /**
  774. * Returns this Long with bits shifted to the left by the given amount.
  775. * @param {number|!Long} numBits Number of bits
  776. * @returns {!Long} Shifted Long
  777. * @expose
  778. */
  779. Long.prototype.shiftLeft = function(numBits) {
  780. if (Long.isLong(numBits))
  781. numBits = numBits.toInt();
  782. if ((numBits &= 63) === 0)
  783. return this;
  784. else if (numBits < 32)
  785. return Long.fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned);
  786. else
  787. return Long.fromBits(0, this.low << (numBits - 32), this.unsigned);
  788. };
  789. /**
  790. * Returns this Long with bits arithmetically shifted to the right by the given amount.
  791. * @param {number|!Long} numBits Number of bits
  792. * @returns {!Long} Shifted Long
  793. * @expose
  794. */
  795. Long.prototype.shiftRight = function(numBits) {
  796. if (Long.isLong(numBits))
  797. numBits = numBits.toInt();
  798. if ((numBits &= 63) === 0)
  799. return this;
  800. else if (numBits < 32)
  801. return Long.fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned);
  802. else
  803. return Long.fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned);
  804. };
  805. /**
  806. * Returns this Long with bits logically shifted to the right by the given amount.
  807. * @param {number|!Long} numBits Number of bits
  808. * @returns {!Long} Shifted Long
  809. * @expose
  810. */
  811. Long.prototype.shiftRightUnsigned = function(numBits) {
  812. if (Long.isLong(numBits))
  813. numBits = numBits.toInt();
  814. numBits &= 63;
  815. if (numBits === 0)
  816. return this;
  817. else {
  818. var high = this.high;
  819. if (numBits < 32) {
  820. var low = this.low;
  821. return Long.fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned);
  822. } else if (numBits === 32)
  823. return Long.fromBits(high, 0, this.unsigned);
  824. else
  825. return Long.fromBits(high >>> (numBits - 32), 0, this.unsigned);
  826. }
  827. };
  828. /**
  829. * Converts this Long to signed.
  830. * @returns {!Long} Signed long
  831. * @expose
  832. */
  833. Long.prototype.toSigned = function() {
  834. if (!this.unsigned)
  835. return this;
  836. return new Long(this.low, this.high, false);
  837. };
  838. /**
  839. * Converts this Long to unsigned.
  840. * @returns {!Long} Unsigned long
  841. * @expose
  842. */
  843. Long.prototype.toUnsigned = function() {
  844. if (this.unsigned)
  845. return this;
  846. return new Long(this.low, this.high, true);
  847. };
  848. /* CommonJS */ if (typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports)
  849. module["exports"] = Long;
  850. /* AMD */ else if (typeof define === 'function' && define["amd"])
  851. define(function() { return Long; });
  852. /* Global */ else
  853. (global["dcodeIO"] = global["dcodeIO"] || {})["Long"] = Long;
  854. })(this);
  855. /*
  856. Copyright 2013-2014 Daniel Wirtz <dcode@dcode.io>
  857. Licensed under the Apache License, Version 2.0 (the "License");
  858. you may not use this file except in compliance with the License.
  859. You may obtain a copy of the License at
  860. http://www.apache.org/licenses/LICENSE-2.0
  861. Unless required by applicable law or agreed to in writing, software
  862. distributed under the License is distributed on an "AS IS" BASIS,
  863. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  864. See the License for the specific language governing permissions and
  865. limitations under the License.
  866. */
  867. /**
  868. * @license ByteBuffer.js (c) 2013-2014 Daniel Wirtz <dcode@dcode.io>
  869. * This version of ByteBuffer.js uses an ArrayBuffer (AB) as its backing buffer and is compatible with modern browsers.
  870. * Released under the Apache License, Version 2.0
  871. * see: https://github.com/dcodeIO/ByteBuffer.js for details
  872. */ //
  873. (function(global) {
  874. "use strict";
  875. /**
  876. * @param {function(new: Long, number, number, boolean=)=} Long
  877. * @returns {function(new: ByteBuffer, number=, boolean=, boolean=)}}
  878. * @inner
  879. */
  880. function loadByteBuffer(Long) {
  881. /**
  882. * Constructs a new ByteBuffer.
  883. * @class The swiss army knife for binary data in JavaScript.
  884. * @exports ByteBuffer
  885. * @constructor
  886. * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
  887. * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
  888. * {@link ByteBuffer.DEFAULT_ENDIAN}.
  889. * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
  890. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  891. * @expose
  892. */
  893. var ByteBuffer = function(capacity, littleEndian, noAssert) {
  894. if (typeof capacity === 'undefined') capacity = ByteBuffer.DEFAULT_CAPACITY;
  895. if (typeof littleEndian === 'undefined') littleEndian = ByteBuffer.DEFAULT_ENDIAN;
  896. if (typeof noAssert === 'undefined') noAssert = ByteBuffer.DEFAULT_NOASSERT;
  897. if (!noAssert) {
  898. capacity = capacity | 0;
  899. if (capacity < 0)
  900. throw RangeError("Illegal capacity");
  901. littleEndian = !!littleEndian;
  902. noAssert = !!noAssert;
  903. }
  904. /**
  905. * Backing buffer.
  906. * @type {!ArrayBuffer}
  907. * @expose
  908. */
  909. this.buffer = capacity === 0 ? EMPTY_BUFFER : new ArrayBuffer(capacity);
  910. /**
  911. * Data view to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`.
  912. * @type {?DataView}
  913. * @expose
  914. */
  915. this.view = capacity === 0 ? null : new DataView(this.buffer);
  916. /**
  917. * Absolute read/write offset.
  918. * @type {number}
  919. * @expose
  920. * @see ByteBuffer#flip
  921. * @see ByteBuffer#clear
  922. */
  923. this.offset = 0;
  924. /**
  925. * Marked offset.
  926. * @type {number}
  927. * @expose
  928. * @see ByteBuffer#mark
  929. * @see ByteBuffer#reset
  930. */
  931. this.markedOffset = -1;
  932. /**
  933. * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation.
  934. * @type {number}
  935. * @expose
  936. * @see ByteBuffer#flip
  937. * @see ByteBuffer#clear
  938. */
  939. this.limit = capacity;
  940. /**
  941. * Whether to use little endian byte order, defaults to `false` for big endian.
  942. * @type {boolean}
  943. * @expose
  944. */
  945. this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : false;
  946. /**
  947. * Whether to skip assertions of offsets and values, defaults to `false`.
  948. * @type {boolean}
  949. * @expose
  950. */
  951. this.noAssert = !!noAssert;
  952. };
  953. /**
  954. * ByteBuffer version.
  955. * @type {string}
  956. * @const
  957. * @expose
  958. */
  959. ByteBuffer.VERSION = "3.5.4";
  960. /**
  961. * Little endian constant that can be used instead of its boolean value. Evaluates to `true`.
  962. * @type {boolean}
  963. * @const
  964. * @expose
  965. */
  966. ByteBuffer.LITTLE_ENDIAN = true;
  967. /**
  968. * Big endian constant that can be used instead of its boolean value. Evaluates to `false`.
  969. * @type {boolean}
  970. * @const
  971. * @expose
  972. */
  973. ByteBuffer.BIG_ENDIAN = false;
  974. /**
  975. * Default initial capacity of `16`.
  976. * @type {number}
  977. * @expose
  978. */
  979. ByteBuffer.DEFAULT_CAPACITY = 16;
  980. /**
  981. * Default endianess of `false` for big endian.
  982. * @type {boolean}
  983. * @expose
  984. */
  985. ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN;
  986. /**
  987. * Default no assertions flag of `false`.
  988. * @type {boolean}
  989. * @expose
  990. */
  991. ByteBuffer.DEFAULT_NOASSERT = false;
  992. /**
  993. * A `Long` class for representing a 64-bit two's-complement integer value. May be `null` if Long.js has not been loaded
  994. * and int64 support is not available.
  995. * @type {?Long}
  996. * @const
  997. * @see https://github.com/dcodeIO/Long.js
  998. * @expose
  999. */
  1000. ByteBuffer.Long = Long || null;
  1001. /**
  1002. * @alias ByteBuffer.prototype
  1003. * @inner
  1004. */
  1005. var ByteBufferPrototype = ByteBuffer.prototype;
  1006. // helpers
  1007. /**
  1008. * @type {!ArrayBuffer}
  1009. * @inner
  1010. */
  1011. var EMPTY_BUFFER = new ArrayBuffer(0);
  1012. /**
  1013. * String.fromCharCode reference for compile-time renaming.
  1014. * @type {function(...number):string}
  1015. * @inner
  1016. */
  1017. var stringFromCharCode = String.fromCharCode;
  1018. /**
  1019. * Creates a source function for a string.
  1020. * @param {string} s String to read from
  1021. * @returns {function():number|null} Source function returning the next char code respectively `null` if there are
  1022. * no more characters left.
  1023. * @throws {TypeError} If the argument is invalid
  1024. * @inner
  1025. */
  1026. function stringSource(s) {
  1027. var i=0; return function() {
  1028. return i < s.length ? s.charCodeAt(i++) : null;
  1029. };
  1030. }
  1031. /**
  1032. * Creates a destination function for a string.
  1033. * @returns {function(number=):undefined|string} Destination function successively called with the next char code.
  1034. * Returns the final string when called without arguments.
  1035. * @inner
  1036. */
  1037. function stringDestination() {
  1038. var cs = [], ps = []; return function() {
  1039. if (arguments.length === 0)
  1040. return ps.join('')+stringFromCharCode.apply(String, cs);
  1041. if (cs.length + arguments.length > 1024)
  1042. ps.push(stringFromCharCode.apply(String, cs)),
  1043. cs.length = 0;
  1044. Array.prototype.push.apply(cs, arguments);
  1045. };
  1046. }
  1047. /**
  1048. * Allocates a new ByteBuffer backed by a buffer of the specified capacity.
  1049. * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
  1050. * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
  1051. * {@link ByteBuffer.DEFAULT_ENDIAN}.
  1052. * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
  1053. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  1054. * @returns {!ByteBuffer}
  1055. * @expose
  1056. */
  1057. ByteBuffer.allocate = function(capacity, littleEndian, noAssert) {
  1058. return new ByteBuffer(capacity, littleEndian, noAssert);
  1059. };
  1060. /**
  1061. * Concatenates multiple ByteBuffers into one.
  1062. * @param {!Array.<!ByteBuffer|!ArrayBuffer|!Uint8Array|string>} buffers Buffers to concatenate
  1063. * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary",
  1064. * defaults to "utf8")
  1065. * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults
  1066. * to {@link ByteBuffer.DEFAULT_ENDIAN}.
  1067. * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to
  1068. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  1069. * @returns {!ByteBuffer} Concatenated ByteBuffer
  1070. * @expose
  1071. */
  1072. ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) {
  1073. if (typeof encoding === 'boolean' || typeof encoding !== 'string') {
  1074. noAssert = littleEndian;
  1075. littleEndian = encoding;
  1076. encoding = undefined;
  1077. }
  1078. var capacity = 0;
  1079. for (var i=0, k=buffers.length, length; i<k; ++i) {
  1080. if (!ByteBuffer.isByteBuffer(buffers[i]))
  1081. buffers[i] = ByteBuffer.wrap(buffers[i], encoding);
  1082. length = buffers[i].limit - buffers[i].offset;
  1083. if (length > 0) capacity += length;
  1084. }
  1085. if (capacity === 0)
  1086. return new ByteBuffer(0, littleEndian, noAssert);
  1087. var bb = new ByteBuffer(capacity, littleEndian, noAssert),
  1088. bi;
  1089. var view = new Uint8Array(bb.buffer);
  1090. i=0; while (i<k) {
  1091. bi = buffers[i++];
  1092. length = bi.limit - bi.offset;
  1093. if (length <= 0) continue;
  1094. view.set(new Uint8Array(bi.buffer).subarray(bi.offset, bi.limit), bb.offset);
  1095. bb.offset += length;
  1096. }
  1097. bb.limit = bb.offset;
  1098. bb.offset = 0;
  1099. return bb;
  1100. };
  1101. /**
  1102. * Tests if the specified type is a ByteBuffer.
  1103. * @param {*} bb ByteBuffer to test
  1104. * @returns {boolean} `true` if it is a ByteBuffer, otherwise `false`
  1105. * @expose
  1106. */
  1107. ByteBuffer.isByteBuffer = function(bb) {
  1108. return (bb && bb instanceof ByteBuffer) === true;
  1109. };
  1110. /**
  1111. * Gets the backing buffer type.
  1112. * @returns {Function} `Buffer` for NB builds, `ArrayBuffer` for AB builds (classes)
  1113. * @expose
  1114. */
  1115. ByteBuffer.type = function() {
  1116. return ArrayBuffer;
  1117. };
  1118. /**
  1119. * Wraps a buffer or a string. Sets the allocated ByteBuffer's {@link ByteBuffer#offset} to `0` and its
  1120. * {@link ByteBuffer#limit} to the length of the wrapped data.
  1121. * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string|!Array.<number>} buffer Anything that can be wrapped
  1122. * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to
  1123. * "utf8")
  1124. * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
  1125. * {@link ByteBuffer.DEFAULT_ENDIAN}.
  1126. * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
  1127. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  1128. * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer`
  1129. * @expose
  1130. */
  1131. ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) {
  1132. if (typeof encoding !== 'string') {
  1133. noAssert = littleEndian;
  1134. littleEndian = encoding;
  1135. encoding = undefined;
  1136. }
  1137. if (typeof buffer === 'string') {
  1138. if (typeof encoding === 'undefined')
  1139. encoding = "utf8";
  1140. switch (encoding) {
  1141. case "base64":
  1142. return ByteBuffer.fromBase64(buffer, littleEndian);
  1143. case "hex":
  1144. return ByteBuffer.fromHex(buffer, littleEndian);
  1145. case "binary":
  1146. return ByteBuffer.fromBinary(buffer, littleEndian);
  1147. case "utf8":
  1148. return ByteBuffer.fromUTF8(buffer, littleEndian);
  1149. case "debug":
  1150. return ByteBuffer.fromDebug(buffer, littleEndian);
  1151. default:
  1152. throw Error("Unsupported encoding: "+encoding);
  1153. }
  1154. }
  1155. if (buffer === null || typeof buffer !== 'object')
  1156. throw TypeError("Illegal buffer");
  1157. var bb;
  1158. if (ByteBuffer.isByteBuffer(buffer)) {
  1159. bb = ByteBufferPrototype.clone.call(buffer);
  1160. bb.markedOffset = -1;
  1161. return bb;
  1162. }
  1163. if (buffer instanceof Uint8Array) { // Extract ArrayBuffer from Uint8Array
  1164. bb = new ByteBuffer(0, littleEndian, noAssert);
  1165. if (buffer.length > 0) { // Avoid references to more than one EMPTY_BUFFER
  1166. bb.buffer = buffer.buffer;
  1167. bb.offset = buffer.byteOffset;
  1168. bb.limit = buffer.byteOffset + buffer.length;
  1169. bb.view = buffer.length > 0 ? new DataView(buffer.buffer) : null;
  1170. }
  1171. } else if (buffer instanceof ArrayBuffer) { // Reuse ArrayBuffer
  1172. bb = new ByteBuffer(0, littleEndian, noAssert);
  1173. if (buffer.byteLength > 0) {
  1174. bb.buffer = buffer;
  1175. bb.offset = 0;
  1176. bb.limit = buffer.byteLength;
  1177. bb.view = buffer.byteLength > 0 ? new DataView(buffer) : null;
  1178. }
  1179. } else if (Object.prototype.toString.call(buffer) === "[object Array]") { // Create from octets
  1180. bb = new ByteBuffer(buffer.length, littleEndian, noAssert);
  1181. bb.limit = buffer.length;
  1182. for (i=0; i<buffer.length; ++i)
  1183. bb.view.setUint8(i, buffer[i]);
  1184. } else
  1185. throw TypeError("Illegal buffer"); // Otherwise fail
  1186. return bb;
  1187. };
  1188. // types/ints/int8
  1189. /**
  1190. * Writes an 8bit signed integer.
  1191. * @param {number} value Value to write
  1192. * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
  1193. * @returns {!ByteBuffer} this
  1194. * @expose
  1195. */
  1196. ByteBufferPrototype.writeInt8 = function(value, offset) {
  1197. var relative = typeof offset === 'undefined';
  1198. if (relative) offset = this.offset;
  1199. if (!this.noAssert) {
  1200. if (typeof value !== 'number' || value % 1 !== 0)
  1201. throw TypeError("Illegal value: "+value+" (not an integer)");
  1202. value |= 0;
  1203. if (typeof offset !== 'number' || offset % 1 !== 0)
  1204. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1205. offset >>>= 0;
  1206. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1207. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1208. }
  1209. offset += 1;
  1210. var capacity0 = this.buffer.byteLength;
  1211. if (offset > capacity0)
  1212. this.resize((capacity0 *= 2) > offset ? capacity0 : offset);
  1213. offset -= 1;
  1214. this.view.setInt8(offset, value);
  1215. if (relative) this.offset += 1;
  1216. return this;
  1217. };
  1218. /**
  1219. * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}.
  1220. * @function
  1221. * @param {number} value Value to write
  1222. * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
  1223. * @returns {!ByteBuffer} this
  1224. * @expose
  1225. */
  1226. ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8;
  1227. /**
  1228. * Reads an 8bit signed integer.
  1229. * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
  1230. * @returns {number} Value read
  1231. * @expose
  1232. */
  1233. ByteBufferPrototype.readInt8 = function(offset) {
  1234. var relative = typeof offset === 'undefined';
  1235. if (relative) offset = this.offset;
  1236. if (!this.noAssert) {
  1237. if (typeof offset !== 'number' || offset % 1 !== 0)
  1238. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1239. offset >>>= 0;
  1240. if (offset < 0 || offset + 1 > this.buffer.byteLength)
  1241. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
  1242. }
  1243. var value = this.view.getInt8(offset);
  1244. if (relative) this.offset += 1;
  1245. return value;
  1246. };
  1247. /**
  1248. * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}.
  1249. * @function
  1250. * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
  1251. * @returns {number} Value read
  1252. * @expose
  1253. */
  1254. ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8;
  1255. /**
  1256. * Writes an 8bit unsigned integer.
  1257. * @param {number} value Value to write
  1258. * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
  1259. * @returns {!ByteBuffer} this
  1260. * @expose
  1261. */
  1262. ByteBufferPrototype.writeUint8 = function(value, offset) {
  1263. var relative = typeof offset === 'undefined';
  1264. if (relative) offset = this.offset;
  1265. if (!this.noAssert) {
  1266. if (typeof value !== 'number' || value % 1 !== 0)
  1267. throw TypeError("Illegal value: "+value+" (not an integer)");
  1268. value >>>= 0;
  1269. if (typeof offset !== 'number' || offset % 1 !== 0)
  1270. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1271. offset >>>= 0;
  1272. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1273. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1274. }
  1275. offset += 1;
  1276. var capacity1 = this.buffer.byteLength;
  1277. if (offset > capacity1)
  1278. this.resize((capacity1 *= 2) > offset ? capacity1 : offset);
  1279. offset -= 1;
  1280. this.view.setUint8(offset, value);
  1281. if (relative) this.offset += 1;
  1282. return this;
  1283. };
  1284. /**
  1285. * Reads an 8bit unsigned integer.
  1286. * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
  1287. * @returns {number} Value read
  1288. * @expose
  1289. */
  1290. ByteBufferPrototype.readUint8 = function(offset) {
  1291. var relative = typeof offset === 'undefined';
  1292. if (relative) offset = this.offset;
  1293. if (!this.noAssert) {
  1294. if (typeof offset !== 'number' || offset % 1 !== 0)
  1295. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1296. offset >>>= 0;
  1297. if (offset < 0 || offset + 1 > this.buffer.byteLength)
  1298. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
  1299. }
  1300. var value = this.view.getUint8(offset);
  1301. if (relative) this.offset += 1;
  1302. return value;
  1303. };
  1304. // types/ints/int16
  1305. /**
  1306. * Writes a 16bit signed integer.
  1307. * @param {number} value Value to write
  1308. * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
  1309. * @throws {TypeError} If `offset` or `value` is not a valid number
  1310. * @throws {RangeError} If `offset` is out of bounds
  1311. * @expose
  1312. */
  1313. ByteBufferPrototype.writeInt16 = function(value, offset) {
  1314. var relative = typeof offset === 'undefined';
  1315. if (relative) offset = this.offset;
  1316. if (!this.noAssert) {
  1317. if (typeof value !== 'number' || value % 1 !== 0)
  1318. throw TypeError("Illegal value: "+value+" (not an integer)");
  1319. value |= 0;
  1320. if (typeof offset !== 'number' || offset % 1 !== 0)
  1321. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1322. offset >>>= 0;
  1323. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1324. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1325. }
  1326. offset += 2;
  1327. var capacity2 = this.buffer.byteLength;
  1328. if (offset > capacity2)
  1329. this.resize((capacity2 *= 2) > offset ? capacity2 : offset);
  1330. offset -= 2;
  1331. this.view.setInt16(offset, value, this.littleEndian);
  1332. if (relative) this.offset += 2;
  1333. return this;
  1334. };
  1335. /**
  1336. * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}.
  1337. * @function
  1338. * @param {number} value Value to write
  1339. * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
  1340. * @throws {TypeError} If `offset` or `value` is not a valid number
  1341. * @throws {RangeError} If `offset` is out of bounds
  1342. * @expose
  1343. */
  1344. ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16;
  1345. /**
  1346. * Reads a 16bit signed integer.
  1347. * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
  1348. * @returns {number} Value read
  1349. * @throws {TypeError} If `offset` is not a valid number
  1350. * @throws {RangeError} If `offset` is out of bounds
  1351. * @expose
  1352. */
  1353. ByteBufferPrototype.readInt16 = function(offset) {
  1354. var relative = typeof offset === 'undefined';
  1355. if (relative) offset = this.offset;
  1356. if (!this.noAssert) {
  1357. if (typeof offset !== 'number' || offset % 1 !== 0)
  1358. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1359. offset >>>= 0;
  1360. if (offset < 0 || offset + 2 > this.buffer.byteLength)
  1361. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength);
  1362. }
  1363. var value = this.view.getInt16(offset, this.littleEndian);
  1364. if (relative) this.offset += 2;
  1365. return value;
  1366. };
  1367. /**
  1368. * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}.
  1369. * @function
  1370. * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
  1371. * @returns {number} Value read
  1372. * @throws {TypeError} If `offset` is not a valid number
  1373. * @throws {RangeError} If `offset` is out of bounds
  1374. * @expose
  1375. */
  1376. ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16;
  1377. /**
  1378. * Writes a 16bit unsigned integer.
  1379. * @param {number} value Value to write
  1380. * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
  1381. * @throws {TypeError} If `offset` or `value` is not a valid number
  1382. * @throws {RangeError} If `offset` is out of bounds
  1383. * @expose
  1384. */
  1385. ByteBufferPrototype.writeUint16 = function(value, offset) {
  1386. var relative = typeof offset === 'undefined';
  1387. if (relative) offset = this.offset;
  1388. if (!this.noAssert) {
  1389. if (typeof value !== 'number' || value % 1 !== 0)
  1390. throw TypeError("Illegal value: "+value+" (not an integer)");
  1391. value >>>= 0;
  1392. if (typeof offset !== 'number' || offset % 1 !== 0)
  1393. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1394. offset >>>= 0;
  1395. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1396. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1397. }
  1398. offset += 2;
  1399. var capacity3 = this.buffer.byteLength;
  1400. if (offset > capacity3)
  1401. this.resize((capacity3 *= 2) > offset ? capacity3 : offset);
  1402. offset -= 2;
  1403. this.view.setUint16(offset, value, this.littleEndian);
  1404. if (relative) this.offset += 2;
  1405. return this;
  1406. };
  1407. /**
  1408. * Reads a 16bit unsigned integer.
  1409. * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
  1410. * @returns {number} Value read
  1411. * @throws {TypeError} If `offset` is not a valid number
  1412. * @throws {RangeError} If `offset` is out of bounds
  1413. * @expose
  1414. */
  1415. ByteBufferPrototype.readUint16 = function(offset) {
  1416. var relative = typeof offset === 'undefined';
  1417. if (relative) offset = this.offset;
  1418. if (!this.noAssert) {
  1419. if (typeof offset !== 'number' || offset % 1 !== 0)
  1420. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1421. offset >>>= 0;
  1422. if (offset < 0 || offset + 2 > this.buffer.byteLength)
  1423. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength);
  1424. }
  1425. var value = this.view.getUint16(offset, this.littleEndian);
  1426. if (relative) this.offset += 2;
  1427. return value;
  1428. };
  1429. // types/ints/int32
  1430. /**
  1431. * Writes a 32bit signed integer.
  1432. * @param {number} value Value to write
  1433. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1434. * @expose
  1435. */
  1436. ByteBufferPrototype.writeInt32 = function(value, offset) {
  1437. var relative = typeof offset === 'undefined';
  1438. if (relative) offset = this.offset;
  1439. if (!this.noAssert) {
  1440. if (typeof value !== 'number' || value % 1 !== 0)
  1441. throw TypeError("Illegal value: "+value+" (not an integer)");
  1442. value |= 0;
  1443. if (typeof offset !== 'number' || offset % 1 !== 0)
  1444. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1445. offset >>>= 0;
  1446. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1447. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1448. }
  1449. offset += 4;
  1450. var capacity4 = this.buffer.byteLength;
  1451. if (offset > capacity4)
  1452. this.resize((capacity4 *= 2) > offset ? capacity4 : offset);
  1453. offset -= 4;
  1454. this.view.setInt32(offset, value, this.littleEndian);
  1455. if (relative) this.offset += 4;
  1456. return this;
  1457. };
  1458. /**
  1459. * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}.
  1460. * @param {number} value Value to write
  1461. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1462. * @expose
  1463. */
  1464. ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32;
  1465. /**
  1466. * Reads a 32bit signed integer.
  1467. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1468. * @returns {number} Value read
  1469. * @expose
  1470. */
  1471. ByteBufferPrototype.readInt32 = function(offset) {
  1472. var relative = typeof offset === 'undefined';
  1473. if (relative) offset = this.offset;
  1474. if (!this.noAssert) {
  1475. if (typeof offset !== 'number' || offset % 1 !== 0)
  1476. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1477. offset >>>= 0;
  1478. if (offset < 0 || offset + 4 > this.buffer.byteLength)
  1479. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
  1480. }
  1481. var value = this.view.getInt32(offset, this.littleEndian);
  1482. if (relative) this.offset += 4;
  1483. return value;
  1484. };
  1485. /**
  1486. * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}.
  1487. * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted.
  1488. * @returns {number} Value read
  1489. * @expose
  1490. */
  1491. ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32;
  1492. /**
  1493. * Writes a 32bit unsigned integer.
  1494. * @param {number} value Value to write
  1495. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1496. * @expose
  1497. */
  1498. ByteBufferPrototype.writeUint32 = function(value, offset) {
  1499. var relative = typeof offset === 'undefined';
  1500. if (relative) offset = this.offset;
  1501. if (!this.noAssert) {
  1502. if (typeof value !== 'number' || value % 1 !== 0)
  1503. throw TypeError("Illegal value: "+value+" (not an integer)");
  1504. value >>>= 0;
  1505. if (typeof offset !== 'number' || offset % 1 !== 0)
  1506. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1507. offset >>>= 0;
  1508. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1509. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1510. }
  1511. offset += 4;
  1512. var capacity5 = this.buffer.byteLength;
  1513. if (offset > capacity5)
  1514. this.resize((capacity5 *= 2) > offset ? capacity5 : offset);
  1515. offset -= 4;
  1516. this.view.setUint32(offset, value, this.littleEndian);
  1517. if (relative) this.offset += 4;
  1518. return this;
  1519. };
  1520. /**
  1521. * Reads a 32bit unsigned integer.
  1522. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1523. * @returns {number} Value read
  1524. * @expose
  1525. */
  1526. ByteBufferPrototype.readUint32 = function(offset) {
  1527. var relative = typeof offset === 'undefined';
  1528. if (relative) offset = this.offset;
  1529. if (!this.noAssert) {
  1530. if (typeof offset !== 'number' || offset % 1 !== 0)
  1531. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1532. offset >>>= 0;
  1533. if (offset < 0 || offset + 4 > this.buffer.byteLength)
  1534. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
  1535. }
  1536. var value = this.view.getUint32(offset, this.littleEndian);
  1537. if (relative) this.offset += 4;
  1538. return value;
  1539. };
  1540. // types/ints/int64
  1541. if (Long) {
  1542. /**
  1543. * Writes a 64bit signed integer.
  1544. * @param {number|!Long} value Value to write
  1545. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1546. * @returns {!ByteBuffer} this
  1547. * @expose
  1548. */
  1549. ByteBufferPrototype.writeInt64 = function(value, offset) {
  1550. var relative = typeof offset === 'undefined';
  1551. if (relative) offset = this.offset;
  1552. if (!this.noAssert) {
  1553. if (typeof value === 'number')
  1554. value = Long.fromNumber(value);
  1555. else if (!(value && value instanceof Long))
  1556. throw TypeError("Illegal value: "+value+" (not an integer or Long)");
  1557. if (typeof offset !== 'number' || offset % 1 !== 0)
  1558. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1559. offset >>>= 0;
  1560. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1561. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1562. }
  1563. if (typeof value === 'number')
  1564. value = Long.fromNumber(value);
  1565. offset += 8;
  1566. var capacity6 = this.buffer.byteLength;
  1567. if (offset > capacity6)
  1568. this.resize((capacity6 *= 2) > offset ? capacity6 : offset);
  1569. offset -= 8;
  1570. if (this.littleEndian) {
  1571. this.view.setInt32(offset , value.low , true);
  1572. this.view.setInt32(offset+4, value.high, true);
  1573. } else {
  1574. this.view.setInt32(offset , value.high, false);
  1575. this.view.setInt32(offset+4, value.low , false);
  1576. }
  1577. if (relative) this.offset += 8;
  1578. return this;
  1579. };
  1580. /**
  1581. * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}.
  1582. * @param {number|!Long} value Value to write
  1583. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1584. * @returns {!ByteBuffer} this
  1585. * @expose
  1586. */
  1587. ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64;
  1588. /**
  1589. * Reads a 64bit signed integer.
  1590. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1591. * @returns {!Long}
  1592. * @expose
  1593. */
  1594. ByteBufferPrototype.readInt64 = function(offset) {
  1595. var relative = typeof offset === 'undefined';
  1596. if (relative) offset = this.offset;
  1597. if (!this.noAssert) {
  1598. if (typeof offset !== 'number' || offset % 1 !== 0)
  1599. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1600. offset >>>= 0;
  1601. if (offset < 0 || offset + 8 > this.buffer.byteLength)
  1602. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
  1603. }
  1604. var value = this.littleEndian
  1605. ? new Long(this.view.getInt32(offset , true ), this.view.getInt32(offset+4, true ), false)
  1606. : new Long(this.view.getInt32(offset+4, false), this.view.getInt32(offset , false), false);
  1607. if (relative) this.offset += 8;
  1608. return value;
  1609. };
  1610. /**
  1611. * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}.
  1612. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1613. * @returns {!Long}
  1614. * @expose
  1615. */
  1616. ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64;
  1617. /**
  1618. * Writes a 64bit unsigned integer.
  1619. * @param {number|!Long} value Value to write
  1620. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1621. * @returns {!ByteBuffer} this
  1622. * @expose
  1623. */
  1624. ByteBufferPrototype.writeUint64 = function(value, offset) {
  1625. var relative = typeof offset === 'undefined';
  1626. if (relative) offset = this.offset;
  1627. if (!this.noAssert) {
  1628. if (typeof value === 'number')
  1629. value = Long.fromNumber(value);
  1630. else if (!(value && value instanceof Long))
  1631. throw TypeError("Illegal value: "+value+" (not an integer or Long)");
  1632. if (typeof offset !== 'number' || offset % 1 !== 0)
  1633. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1634. offset >>>= 0;
  1635. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1636. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1637. }
  1638. if (typeof value === 'number')
  1639. value = Long.fromNumber(value);
  1640. offset += 8;
  1641. var capacity7 = this.buffer.byteLength;
  1642. if (offset > capacity7)
  1643. this.resize((capacity7 *= 2) > offset ? capacity7 : offset);
  1644. offset -= 8;
  1645. if (this.littleEndian) {
  1646. this.view.setInt32(offset , value.low , true);
  1647. this.view.setInt32(offset+4, value.high, true);
  1648. } else {
  1649. this.view.setInt32(offset , value.high, false);
  1650. this.view.setInt32(offset+4, value.low , false);
  1651. }
  1652. if (relative) this.offset += 8;
  1653. return this;
  1654. };
  1655. /**
  1656. * Reads a 64bit unsigned integer.
  1657. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1658. * @returns {!Long}
  1659. * @expose
  1660. */
  1661. ByteBufferPrototype.readUint64 = function(offset) {
  1662. var relative = typeof offset === 'undefined';
  1663. if (relative) offset = this.offset;
  1664. if (!this.noAssert) {
  1665. if (typeof offset !== 'number' || offset % 1 !== 0)
  1666. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1667. offset >>>= 0;
  1668. if (offset < 0 || offset + 8 > this.buffer.byteLength)
  1669. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
  1670. }
  1671. var value = this.littleEndian
  1672. ? new Long(this.view.getInt32(offset , true ), this.view.getInt32(offset+4, true ), true)
  1673. : new Long(this.view.getInt32(offset+4, false), this.view.getInt32(offset , false), true);
  1674. if (relative) this.offset += 8;
  1675. return value;
  1676. };
  1677. } // Long
  1678. // types/floats/float32
  1679. /**
  1680. * Writes a 32bit float.
  1681. * @param {number} value Value to write
  1682. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1683. * @returns {!ByteBuffer} this
  1684. * @expose
  1685. */
  1686. ByteBufferPrototype.writeFloat32 = function(value, offset) {
  1687. var relative = typeof offset === 'undefined';
  1688. if (relative) offset = this.offset;
  1689. if (!this.noAssert) {
  1690. if (typeof value !== 'number')
  1691. throw TypeError("Illegal value: "+value+" (not a number)");
  1692. if (typeof offset !== 'number' || offset % 1 !== 0)
  1693. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1694. offset >>>= 0;
  1695. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1696. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1697. }
  1698. offset += 4;
  1699. var capacity8 = this.buffer.byteLength;
  1700. if (offset > capacity8)
  1701. this.resize((capacity8 *= 2) > offset ? capacity8 : offset);
  1702. offset -= 4;
  1703. this.view.setFloat32(offset, value, this.littleEndian);
  1704. if (relative) this.offset += 4;
  1705. return this;
  1706. };
  1707. /**
  1708. * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}.
  1709. * @function
  1710. * @param {number} value Value to write
  1711. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1712. * @returns {!ByteBuffer} this
  1713. * @expose
  1714. */
  1715. ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32;
  1716. /**
  1717. * Reads a 32bit float.
  1718. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1719. * @returns {number}
  1720. * @expose
  1721. */
  1722. ByteBufferPrototype.readFloat32 = function(offset) {
  1723. var relative = typeof offset === 'undefined';
  1724. if (relative) offset = this.offset;
  1725. if (!this.noAssert) {
  1726. if (typeof offset !== 'number' || offset % 1 !== 0)
  1727. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1728. offset >>>= 0;
  1729. if (offset < 0 || offset + 4 > this.buffer.byteLength)
  1730. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
  1731. }
  1732. var value = this.view.getFloat32(offset, this.littleEndian);
  1733. if (relative) this.offset += 4;
  1734. return value;
  1735. };
  1736. /**
  1737. * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}.
  1738. * @function
  1739. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
  1740. * @returns {number}
  1741. * @expose
  1742. */
  1743. ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32;
  1744. // types/floats/float64
  1745. /**
  1746. * Writes a 64bit float.
  1747. * @param {number} value Value to write
  1748. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1749. * @returns {!ByteBuffer} this
  1750. * @expose
  1751. */
  1752. ByteBufferPrototype.writeFloat64 = function(value, offset) {
  1753. var relative = typeof offset === 'undefined';
  1754. if (relative) offset = this.offset;
  1755. if (!this.noAssert) {
  1756. if (typeof value !== 'number')
  1757. throw TypeError("Illegal value: "+value+" (not a number)");
  1758. if (typeof offset !== 'number' || offset % 1 !== 0)
  1759. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1760. offset >>>= 0;
  1761. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1762. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1763. }
  1764. offset += 8;
  1765. var capacity9 = this.buffer.byteLength;
  1766. if (offset > capacity9)
  1767. this.resize((capacity9 *= 2) > offset ? capacity9 : offset);
  1768. offset -= 8;
  1769. this.view.setFloat64(offset, value, this.littleEndian);
  1770. if (relative) this.offset += 8;
  1771. return this;
  1772. };
  1773. /**
  1774. * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}.
  1775. * @function
  1776. * @param {number} value Value to write
  1777. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1778. * @returns {!ByteBuffer} this
  1779. * @expose
  1780. */
  1781. ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64;
  1782. /**
  1783. * Reads a 64bit float.
  1784. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1785. * @returns {number}
  1786. * @expose
  1787. */
  1788. ByteBufferPrototype.readFloat64 = function(offset) {
  1789. var relative = typeof offset === 'undefined';
  1790. if (relative) offset = this.offset;
  1791. if (!this.noAssert) {
  1792. if (typeof offset !== 'number' || offset % 1 !== 0)
  1793. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1794. offset >>>= 0;
  1795. if (offset < 0 || offset + 8 > this.buffer.byteLength)
  1796. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
  1797. }
  1798. var value = this.view.getFloat64(offset, this.littleEndian);
  1799. if (relative) this.offset += 8;
  1800. return value;
  1801. };
  1802. /**
  1803. * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}.
  1804. * @function
  1805. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
  1806. * @returns {number}
  1807. * @expose
  1808. */
  1809. ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64;
  1810. // types/varints/varint32
  1811. /**
  1812. * Maximum number of bytes required to store a 32bit base 128 variable-length integer.
  1813. * @type {number}
  1814. * @const
  1815. * @expose
  1816. */
  1817. ByteBuffer.MAX_VARINT32_BYTES = 5;
  1818. /**
  1819. * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer.
  1820. * @param {number} value Value to encode
  1821. * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES}
  1822. * @expose
  1823. */
  1824. ByteBuffer.calculateVarint32 = function(value) {
  1825. // ref: src/google/protobuf/io/coded_stream.cc
  1826. value = value >>> 0;
  1827. if (value < 1 << 7 ) return 1;
  1828. else if (value < 1 << 14) return 2;
  1829. else if (value < 1 << 21) return 3;
  1830. else if (value < 1 << 28) return 4;
  1831. else return 5;
  1832. };
  1833. /**
  1834. * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding.
  1835. * @param {number} n Signed 32bit integer
  1836. * @returns {number} Unsigned zigzag encoded 32bit integer
  1837. * @expose
  1838. */
  1839. ByteBuffer.zigZagEncode32 = function(n) {
  1840. return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h
  1841. };
  1842. /**
  1843. * Decodes a zigzag encoded signed 32bit integer.
  1844. * @param {number} n Unsigned zigzag encoded 32bit integer
  1845. * @returns {number} Signed 32bit integer
  1846. * @expose
  1847. */
  1848. ByteBuffer.zigZagDecode32 = function(n) {
  1849. return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h
  1850. };
  1851. /**
  1852. * Writes a 32bit base 128 variable-length integer.
  1853. * @param {number} value Value to write
  1854. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  1855. * written if omitted.
  1856. * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written
  1857. * @expose
  1858. */
  1859. ByteBufferPrototype.writeVarint32 = function(value, offset) {
  1860. var relative = typeof offset === 'undefined';
  1861. if (relative) offset = this.offset;
  1862. if (!this.noAssert) {
  1863. if (typeof value !== 'number' || value % 1 !== 0)
  1864. throw TypeError("Illegal value: "+value+" (not an integer)");
  1865. value |= 0;
  1866. if (typeof offset !== 'number' || offset % 1 !== 0)
  1867. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1868. offset >>>= 0;
  1869. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  1870. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  1871. }
  1872. var size = ByteBuffer.calculateVarint32(value),
  1873. b;
  1874. offset += size;
  1875. var capacity10 = this.buffer.byteLength;
  1876. if (offset > capacity10)
  1877. this.resize((capacity10 *= 2) > offset ? capacity10 : offset);
  1878. offset -= size;
  1879. // ref: http://code.google.com/searchframe#WTeibokF6gE/trunk/src/google/protobuf/io/coded_stream.cc
  1880. this.view.setUint8(offset, b = value | 0x80);
  1881. value >>>= 0;
  1882. if (value >= 1 << 7) {
  1883. b = (value >> 7) | 0x80;
  1884. this.view.setUint8(offset+1, b);
  1885. if (value >= 1 << 14) {
  1886. b = (value >> 14) | 0x80;
  1887. this.view.setUint8(offset+2, b);
  1888. if (value >= 1 << 21) {
  1889. b = (value >> 21) | 0x80;
  1890. this.view.setUint8(offset+3, b);
  1891. if (value >= 1 << 28) {
  1892. this.view.setUint8(offset+4, (value >> 28) & 0x0F);
  1893. size = 5;
  1894. } else {
  1895. this.view.setUint8(offset+3, b & 0x7F);
  1896. size = 4;
  1897. }
  1898. } else {
  1899. this.view.setUint8(offset+2, b & 0x7F);
  1900. size = 3;
  1901. }
  1902. } else {
  1903. this.view.setUint8(offset+1, b & 0x7F);
  1904. size = 2;
  1905. }
  1906. } else {
  1907. this.view.setUint8(offset, b & 0x7F);
  1908. size = 1;
  1909. }
  1910. if (relative) {
  1911. this.offset += size;
  1912. return this;
  1913. }
  1914. return size;
  1915. };
  1916. /**
  1917. * Writes a zig-zag encoded 32bit base 128 variable-length integer.
  1918. * @param {number} value Value to write
  1919. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  1920. * written if omitted.
  1921. * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written
  1922. * @expose
  1923. */
  1924. ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) {
  1925. return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset);
  1926. };
  1927. /**
  1928. * Reads a 32bit base 128 variable-length integer.
  1929. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  1930. * written if omitted.
  1931. * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read
  1932. * and the actual number of bytes read.
  1933. * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available
  1934. * to fully decode the varint.
  1935. * @expose
  1936. */
  1937. ByteBufferPrototype.readVarint32 = function(offset) {
  1938. var relative = typeof offset === 'undefined';
  1939. if (relative) offset = this.offset;
  1940. if (!this.noAssert) {
  1941. if (typeof offset !== 'number' || offset % 1 !== 0)
  1942. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  1943. offset >>>= 0;
  1944. if (offset < 0 || offset + 1 > this.buffer.byteLength)
  1945. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
  1946. }
  1947. // ref: src/google/protobuf/io/coded_stream.cc
  1948. var size = 0,
  1949. value = 0 >>> 0,
  1950. temp,
  1951. ioffset;
  1952. do {
  1953. ioffset = offset+size;
  1954. if (!this.noAssert && ioffset > this.limit) {
  1955. var err = Error("Truncated");
  1956. err['truncated'] = true;
  1957. throw err;
  1958. }
  1959. temp = this.view.getUint8(ioffset);
  1960. if (size < 5)
  1961. value |= ((temp&0x7F)<<(7*size)) >>> 0;
  1962. ++size;
  1963. } while ((temp & 0x80) === 0x80);
  1964. value = value | 0; // Make sure to discard the higher order bits
  1965. if (relative) {
  1966. this.offset += size;
  1967. return value;
  1968. }
  1969. return {
  1970. "value": value,
  1971. "length": size
  1972. };
  1973. };
  1974. /**
  1975. * Reads a zig-zag encoded 32bit base 128 variable-length integer.
  1976. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  1977. * written if omitted.
  1978. * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read
  1979. * and the actual number of bytes read.
  1980. * @throws {Error} If it's not a valid varint
  1981. * @expose
  1982. */
  1983. ByteBufferPrototype.readVarint32ZigZag = function(offset) {
  1984. var val = this.readVarint32(offset);
  1985. if (typeof val === 'object')
  1986. val["value"] = ByteBuffer.zigZagDecode32(val["value"]);
  1987. else
  1988. val = ByteBuffer.zigZagDecode32(val);
  1989. return val;
  1990. };
  1991. // types/varints/varint64
  1992. if (Long) {
  1993. /**
  1994. * Maximum number of bytes required to store a 64bit base 128 variable-length integer.
  1995. * @type {number}
  1996. * @const
  1997. * @expose
  1998. */
  1999. ByteBuffer.MAX_VARINT64_BYTES = 10;
  2000. /**
  2001. * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer.
  2002. * @param {number|!Long} value Value to encode
  2003. * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES}
  2004. * @expose
  2005. */
  2006. ByteBuffer.calculateVarint64 = function(value) {
  2007. if (typeof value === 'number')
  2008. value = Long.fromNumber(value);
  2009. // ref: src/google/protobuf/io/coded_stream.cc
  2010. var part0 = value.toInt() >>> 0,
  2011. part1 = value.shiftRightUnsigned(28).toInt() >>> 0,
  2012. part2 = value.shiftRightUnsigned(56).toInt() >>> 0;
  2013. if (part2 == 0) {
  2014. if (part1 == 0) {
  2015. if (part0 < 1 << 14)
  2016. return part0 < 1 << 7 ? 1 : 2;
  2017. else
  2018. return part0 < 1 << 21 ? 3 : 4;
  2019. } else {
  2020. if (part1 < 1 << 14)
  2021. return part1 < 1 << 7 ? 5 : 6;
  2022. else
  2023. return part1 < 1 << 21 ? 7 : 8;
  2024. }
  2025. } else
  2026. return part2 < 1 << 7 ? 9 : 10;
  2027. };
  2028. /**
  2029. * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding.
  2030. * @param {number|!Long} value Signed long
  2031. * @returns {!Long} Unsigned zigzag encoded long
  2032. * @expose
  2033. */
  2034. ByteBuffer.zigZagEncode64 = function(value) {
  2035. if (typeof value === 'number')
  2036. value = Long.fromNumber(value, false);
  2037. else if (value.unsigned !== false) value = value.toSigned();
  2038. // ref: src/google/protobuf/wire_format_lite.h
  2039. return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned();
  2040. };
  2041. /**
  2042. * Decodes a zigzag encoded signed 64bit integer.
  2043. * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number
  2044. * @returns {!Long} Signed long
  2045. * @expose
  2046. */
  2047. ByteBuffer.zigZagDecode64 = function(value) {
  2048. if (typeof value === 'number')
  2049. value = Long.fromNumber(value, false);
  2050. else if (value.unsigned !== false) value = value.toSigned();
  2051. // ref: src/google/protobuf/wire_format_lite.h
  2052. return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned();
  2053. };
  2054. /**
  2055. * Writes a 64bit base 128 variable-length integer.
  2056. * @param {number|Long} value Value to write
  2057. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2058. * written if omitted.
  2059. * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written.
  2060. * @expose
  2061. */
  2062. ByteBufferPrototype.writeVarint64 = function(value, offset) {
  2063. var relative = typeof offset === 'undefined';
  2064. if (relative) offset = this.offset;
  2065. if (!this.noAssert) {
  2066. if (typeof value === 'number')
  2067. value = Long.fromNumber(value);
  2068. else if (!(value && value instanceof Long))
  2069. throw TypeError("Illegal value: "+value+" (not an integer or Long)");
  2070. if (typeof offset !== 'number' || offset % 1 !== 0)
  2071. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2072. offset >>>= 0;
  2073. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2074. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2075. }
  2076. if (typeof value === 'number')
  2077. value = Long.fromNumber(value, false);
  2078. else if (value.unsigned !== false) value = value.toSigned();
  2079. var size = ByteBuffer.calculateVarint64(value),
  2080. part0 = value.toInt() >>> 0,
  2081. part1 = value.shiftRightUnsigned(28).toInt() >>> 0,
  2082. part2 = value.shiftRightUnsigned(56).toInt() >>> 0;
  2083. offset += size;
  2084. var capacity11 = this.buffer.byteLength;
  2085. if (offset > capacity11)
  2086. this.resize((capacity11 *= 2) > offset ? capacity11 : offset);
  2087. offset -= size;
  2088. switch (size) {
  2089. case 10: this.view.setUint8(offset+9, (part2 >>> 7) & 0x01);
  2090. case 9 : this.view.setUint8(offset+8, size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F);
  2091. case 8 : this.view.setUint8(offset+7, size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F);
  2092. case 7 : this.view.setUint8(offset+6, size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F);
  2093. case 6 : this.view.setUint8(offset+5, size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F);
  2094. case 5 : this.view.setUint8(offset+4, size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F);
  2095. case 4 : this.view.setUint8(offset+3, size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F);
  2096. case 3 : this.view.setUint8(offset+2, size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F);
  2097. case 2 : this.view.setUint8(offset+1, size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F);
  2098. case 1 : this.view.setUint8(offset , size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F);
  2099. }
  2100. if (relative) {
  2101. this.offset += size;
  2102. return this;
  2103. } else {
  2104. return size;
  2105. }
  2106. };
  2107. /**
  2108. * Writes a zig-zag encoded 64bit base 128 variable-length integer.
  2109. * @param {number|Long} value Value to write
  2110. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2111. * written if omitted.
  2112. * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written.
  2113. * @expose
  2114. */
  2115. ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) {
  2116. return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset);
  2117. };
  2118. /**
  2119. * Reads a 64bit base 128 variable-length integer. Requires Long.js.
  2120. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2121. * read if omitted.
  2122. * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and
  2123. * the actual number of bytes read.
  2124. * @throws {Error} If it's not a valid varint
  2125. * @expose
  2126. */
  2127. ByteBufferPrototype.readVarint64 = function(offset) {
  2128. var relative = typeof offset === 'undefined';
  2129. if (relative) offset = this.offset;
  2130. if (!this.noAssert) {
  2131. if (typeof offset !== 'number' || offset % 1 !== 0)
  2132. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2133. offset >>>= 0;
  2134. if (offset < 0 || offset + 1 > this.buffer.byteLength)
  2135. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
  2136. }
  2137. // ref: src/google/protobuf/io/coded_stream.cc
  2138. var start = offset,
  2139. part0 = 0,
  2140. part1 = 0,
  2141. part2 = 0,
  2142. b = 0;
  2143. b = this.view.getUint8(offset++); part0 = (b & 0x7F) ; if (b & 0x80) {
  2144. b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 7; if (b & 0x80) {
  2145. b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 14; if (b & 0x80) {
  2146. b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 21; if (b & 0x80) {
  2147. b = this.view.getUint8(offset++); part1 = (b & 0x7F) ; if (b & 0x80) {
  2148. b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 7; if (b & 0x80) {
  2149. b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 14; if (b & 0x80) {
  2150. b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 21; if (b & 0x80) {
  2151. b = this.view.getUint8(offset++); part2 = (b & 0x7F) ; if (b & 0x80) {
  2152. b = this.view.getUint8(offset++); part2 |= (b & 0x7F) << 7; if (b & 0x80) {
  2153. throw Error("Buffer overrun"); }}}}}}}}}}
  2154. var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false);
  2155. if (relative) {
  2156. this.offset = offset;
  2157. return value;
  2158. } else {
  2159. return {
  2160. 'value': value,
  2161. 'length': offset-start
  2162. };
  2163. }
  2164. };
  2165. /**
  2166. * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js.
  2167. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2168. * read if omitted.
  2169. * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and
  2170. * the actual number of bytes read.
  2171. * @throws {Error} If it's not a valid varint
  2172. * @expose
  2173. */
  2174. ByteBufferPrototype.readVarint64ZigZag = function(offset) {
  2175. var val = this.readVarint64(offset);
  2176. if (val && val['value'] instanceof Long)
  2177. val["value"] = ByteBuffer.zigZagDecode64(val["value"]);
  2178. else
  2179. val = ByteBuffer.zigZagDecode64(val);
  2180. return val;
  2181. };
  2182. } // Long
  2183. // types/strings/cstring
  2184. /**
  2185. * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL
  2186. * characters itself.
  2187. * @param {string} str String to write
  2188. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2189. * contained in `str` + 1 if omitted.
  2190. * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written
  2191. * @expose
  2192. */
  2193. ByteBufferPrototype.writeCString = function(str, offset) {
  2194. var relative = typeof offset === 'undefined';
  2195. if (relative) offset = this.offset;
  2196. var i,
  2197. k = str.length;
  2198. if (!this.noAssert) {
  2199. if (typeof str !== 'string')
  2200. throw TypeError("Illegal str: Not a string");
  2201. for (i=0; i<k; ++i) {
  2202. if (str.charCodeAt(i) === 0)
  2203. throw RangeError("Illegal str: Contains NULL-characters");
  2204. }
  2205. if (typeof offset !== 'number' || offset % 1 !== 0)
  2206. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2207. offset >>>= 0;
  2208. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2209. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2210. }
  2211. var start = offset;
  2212. // UTF8 strings do not contain zero bytes in between except for the zero character, so:
  2213. k = utfx.calculateUTF16asUTF8(stringSource(str))[1];
  2214. offset += k+1;
  2215. var capacity12 = this.buffer.byteLength;
  2216. if (offset > capacity12)
  2217. this.resize((capacity12 *= 2) > offset ? capacity12 : offset);
  2218. offset -= k+1;
  2219. utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
  2220. this.view.setUint8(offset++, b);
  2221. }.bind(this));
  2222. this.view.setUint8(offset++, 0);
  2223. if (relative) {
  2224. this.offset = offset - start;
  2225. return this;
  2226. }
  2227. return k;
  2228. };
  2229. /**
  2230. * Reads a NULL-terminated UTF8 encoded string. For this to work the string read must not contain any NULL characters
  2231. * itself.
  2232. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2233. * read if omitted.
  2234. * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
  2235. * read and the actual number of bytes read.
  2236. * @expose
  2237. */
  2238. ByteBufferPrototype.readCString = function(offset) {
  2239. var relative = typeof offset === 'undefined';
  2240. if (relative) offset = this.offset;
  2241. if (!this.noAssert) {
  2242. if (typeof offset !== 'number' || offset % 1 !== 0)
  2243. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2244. offset >>>= 0;
  2245. if (offset < 0 || offset + 1 > this.buffer.byteLength)
  2246. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
  2247. }
  2248. var start = offset,
  2249. temp;
  2250. // UTF8 strings do not contain zero bytes in between except for the zero character itself, so:
  2251. var sd, b = -1;
  2252. utfx.decodeUTF8toUTF16(function() {
  2253. if (b === 0) return null;
  2254. if (offset >= this.limit)
  2255. throw RangeError("Illegal range: Truncated data, "+offset+" < "+this.limit);
  2256. return (b = this.view.getUint8(offset++)) === 0 ? null : b;
  2257. }.bind(this), sd = stringDestination(), true);
  2258. if (relative) {
  2259. this.offset = offset;
  2260. return sd();
  2261. } else {
  2262. return {
  2263. "string": sd(),
  2264. "length": offset - start
  2265. };
  2266. }
  2267. };
  2268. // types/strings/istring
  2269. /**
  2270. * Writes a length as uint32 prefixed UTF8 encoded string.
  2271. * @param {string} str String to write
  2272. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2273. * written if omitted.
  2274. * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written
  2275. * @expose
  2276. * @see ByteBuffer#writeVarint32
  2277. */
  2278. ByteBufferPrototype.writeIString = function(str, offset) {
  2279. var relative = typeof offset === 'undefined';
  2280. if (relative) offset = this.offset;
  2281. if (!this.noAssert) {
  2282. if (typeof str !== 'string')
  2283. throw TypeError("Illegal str: Not a string");
  2284. if (typeof offset !== 'number' || offset % 1 !== 0)
  2285. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2286. offset >>>= 0;
  2287. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2288. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2289. }
  2290. var start = offset,
  2291. k;
  2292. k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1];
  2293. offset += 4+k;
  2294. var capacity13 = this.buffer.byteLength;
  2295. if (offset > capacity13)
  2296. this.resize((capacity13 *= 2) > offset ? capacity13 : offset);
  2297. offset -= 4+k;
  2298. this.view.setUint32(offset, k, this.littleEndian);
  2299. offset += 4;
  2300. utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
  2301. this.view.setUint8(offset++, b);
  2302. }.bind(this));
  2303. if (offset !== start + 4 + k)
  2304. throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+4+k));
  2305. if (relative) {
  2306. this.offset = offset;
  2307. return this;
  2308. }
  2309. return offset - start;
  2310. };
  2311. /**
  2312. * Reads a length as uint32 prefixed UTF8 encoded string.
  2313. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2314. * read if omitted.
  2315. * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
  2316. * read and the actual number of bytes read.
  2317. * @expose
  2318. * @see ByteBuffer#readVarint32
  2319. */
  2320. ByteBufferPrototype.readIString = function(offset) {
  2321. var relative = typeof offset === 'undefined';
  2322. if (relative) offset = this.offset;
  2323. if (!this.noAssert) {
  2324. if (typeof offset !== 'number' || offset % 1 !== 0)
  2325. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2326. offset >>>= 0;
  2327. if (offset < 0 || offset + 4 > this.buffer.byteLength)
  2328. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
  2329. }
  2330. var temp = 0,
  2331. start = offset,
  2332. str;
  2333. temp = this.view.getUint32(offset, this.littleEndian);
  2334. offset += 4;
  2335. var k = offset + temp,
  2336. sd;
  2337. utfx.decodeUTF8toUTF16(function() {
  2338. return offset < k ? this.view.getUint8(offset++) : null;
  2339. }.bind(this), sd = stringDestination(), this.noAssert);
  2340. str = sd();
  2341. if (relative) {
  2342. this.offset = offset;
  2343. return str;
  2344. } else {
  2345. return {
  2346. 'string': str,
  2347. 'length': offset - start
  2348. };
  2349. }
  2350. };
  2351. // types/strings/utf8string
  2352. /**
  2353. * Metrics representing number of UTF8 characters. Evaluates to `c`.
  2354. * @type {string}
  2355. * @const
  2356. * @expose
  2357. */
  2358. ByteBuffer.METRICS_CHARS = 'c';
  2359. /**
  2360. * Metrics representing number of bytes. Evaluates to `b`.
  2361. * @type {string}
  2362. * @const
  2363. * @expose
  2364. */
  2365. ByteBuffer.METRICS_BYTES = 'b';
  2366. /**
  2367. * Writes an UTF8 encoded string.
  2368. * @param {string} str String to write
  2369. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted.
  2370. * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
  2371. * @expose
  2372. */
  2373. ByteBufferPrototype.writeUTF8String = function(str, offset) {
  2374. var relative = typeof offset === 'undefined';
  2375. if (relative) offset = this.offset;
  2376. if (!this.noAssert) {
  2377. if (typeof offset !== 'number' || offset % 1 !== 0)
  2378. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2379. offset >>>= 0;
  2380. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2381. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2382. }
  2383. var k;
  2384. var start = offset;
  2385. k = utfx.calculateUTF16asUTF8(stringSource(str))[1];
  2386. offset += k;
  2387. var capacity14 = this.buffer.byteLength;
  2388. if (offset > capacity14)
  2389. this.resize((capacity14 *= 2) > offset ? capacity14 : offset);
  2390. offset -= k;
  2391. utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
  2392. this.view.setUint8(offset++, b);
  2393. }.bind(this));
  2394. if (relative) {
  2395. this.offset = offset;
  2396. return this;
  2397. }
  2398. return offset - start;
  2399. };
  2400. /**
  2401. * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}.
  2402. * @function
  2403. * @param {string} str String to write
  2404. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted.
  2405. * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
  2406. * @expose
  2407. */
  2408. ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String;
  2409. /**
  2410. * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's
  2411. * `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF.
  2412. * @function
  2413. * @param {string} str String to calculate
  2414. * @returns {number} Number of UTF8 characters
  2415. * @expose
  2416. */
  2417. ByteBuffer.calculateUTF8Chars = function(str) {
  2418. return utfx.calculateUTF16asUTF8(stringSource(str))[0];
  2419. };
  2420. /**
  2421. * Calculates the number of UTF8 bytes of a string.
  2422. * @function
  2423. * @param {string} str String to calculate
  2424. * @returns {number} Number of UTF8 bytes
  2425. * @expose
  2426. */
  2427. ByteBuffer.calculateUTF8Bytes = function(str) {
  2428. return utfx.calculateUTF16asUTF8(stringSource(str))[1];
  2429. };
  2430. /**
  2431. * Reads an UTF8 encoded string.
  2432. * @param {number} length Number of characters or bytes to read.
  2433. * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to
  2434. * {@link ByteBuffer.METRICS_CHARS}.
  2435. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2436. * read if omitted.
  2437. * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
  2438. * read and the actual number of bytes read.
  2439. * @expose
  2440. */
  2441. ByteBufferPrototype.readUTF8String = function(length, metrics, offset) {
  2442. if (typeof metrics === 'number') {
  2443. offset = metrics;
  2444. metrics = undefined;
  2445. }
  2446. var relative = typeof offset === 'undefined';
  2447. if (relative) offset = this.offset;
  2448. if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS;
  2449. if (!this.noAssert) {
  2450. if (typeof length !== 'number' || length % 1 !== 0)
  2451. throw TypeError("Illegal length: "+length+" (not an integer)");
  2452. length |= 0;
  2453. if (typeof offset !== 'number' || offset % 1 !== 0)
  2454. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2455. offset >>>= 0;
  2456. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2457. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2458. }
  2459. var i = 0,
  2460. start = offset,
  2461. sd;
  2462. if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser
  2463. sd = stringDestination();
  2464. utfx.decodeUTF8(function() {
  2465. return i < length && offset < this.limit ? this.view.getUint8(offset++) : null;
  2466. }.bind(this), function(cp) {
  2467. ++i; utfx.UTF8toUTF16(cp, sd);
  2468. }.bind(this));
  2469. if (i !== length)
  2470. throw RangeError("Illegal range: Truncated data, "+i+" == "+length);
  2471. if (relative) {
  2472. this.offset = offset;
  2473. return sd();
  2474. } else {
  2475. return {
  2476. "string": sd(),
  2477. "length": offset - start
  2478. };
  2479. }
  2480. } else if (metrics === ByteBuffer.METRICS_BYTES) {
  2481. if (!this.noAssert) {
  2482. if (typeof offset !== 'number' || offset % 1 !== 0)
  2483. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2484. offset >>>= 0;
  2485. if (offset < 0 || offset + length > this.buffer.byteLength)
  2486. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength);
  2487. }
  2488. var k = offset + length;
  2489. utfx.decodeUTF8toUTF16(function() {
  2490. return offset < k ? this.view.getUint8(offset++) : null;
  2491. }.bind(this), sd = stringDestination(), this.noAssert);
  2492. if (offset !== k)
  2493. throw RangeError("Illegal range: Truncated data, "+offset+" == "+k);
  2494. if (relative) {
  2495. this.offset = offset;
  2496. return sd();
  2497. } else {
  2498. return {
  2499. 'string': sd(),
  2500. 'length': offset - start
  2501. };
  2502. }
  2503. } else
  2504. throw TypeError("Unsupported metrics: "+metrics);
  2505. };
  2506. /**
  2507. * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}.
  2508. * @function
  2509. * @param {number} length Number of characters or bytes to read
  2510. * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to
  2511. * {@link ByteBuffer.METRICS_CHARS}.
  2512. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2513. * read if omitted.
  2514. * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
  2515. * read and the actual number of bytes read.
  2516. * @expose
  2517. */
  2518. ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String;
  2519. // types/strings/vstring
  2520. /**
  2521. * Writes a length as varint32 prefixed UTF8 encoded string.
  2522. * @param {string} str String to write
  2523. * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2524. * written if omitted.
  2525. * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written
  2526. * @expose
  2527. * @see ByteBuffer#writeVarint32
  2528. */
  2529. ByteBufferPrototype.writeVString = function(str, offset) {
  2530. var relative = typeof offset === 'undefined';
  2531. if (relative) offset = this.offset;
  2532. if (!this.noAssert) {
  2533. if (typeof str !== 'string')
  2534. throw TypeError("Illegal str: Not a string");
  2535. if (typeof offset !== 'number' || offset % 1 !== 0)
  2536. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2537. offset >>>= 0;
  2538. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2539. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2540. }
  2541. var start = offset,
  2542. k, l;
  2543. k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1];
  2544. l = ByteBuffer.calculateVarint32(k);
  2545. offset += l+k;
  2546. var capacity15 = this.buffer.byteLength;
  2547. if (offset > capacity15)
  2548. this.resize((capacity15 *= 2) > offset ? capacity15 : offset);
  2549. offset -= l+k;
  2550. offset += this.writeVarint32(k, offset);
  2551. utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
  2552. this.view.setUint8(offset++, b);
  2553. }.bind(this));
  2554. if (offset !== start+k+l)
  2555. throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+k+l));
  2556. if (relative) {
  2557. this.offset = offset;
  2558. return this;
  2559. }
  2560. return offset - start;
  2561. };
  2562. /**
  2563. * Reads a length as varint32 prefixed UTF8 encoded string.
  2564. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2565. * read if omitted.
  2566. * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
  2567. * read and the actual number of bytes read.
  2568. * @expose
  2569. * @see ByteBuffer#readVarint32
  2570. */
  2571. ByteBufferPrototype.readVString = function(offset) {
  2572. var relative = typeof offset === 'undefined';
  2573. if (relative) offset = this.offset;
  2574. if (!this.noAssert) {
  2575. if (typeof offset !== 'number' || offset % 1 !== 0)
  2576. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2577. offset >>>= 0;
  2578. if (offset < 0 || offset + 1 > this.buffer.byteLength)
  2579. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
  2580. }
  2581. var temp = this.readVarint32(offset),
  2582. start = offset,
  2583. str;
  2584. offset += temp['length'];
  2585. temp = temp['value'];
  2586. var k = offset + temp,
  2587. sd = stringDestination();
  2588. utfx.decodeUTF8toUTF16(function() {
  2589. return offset < k ? this.view.getUint8(offset++) : null;
  2590. }.bind(this), sd, this.noAssert);
  2591. str = sd();
  2592. if (relative) {
  2593. this.offset = offset;
  2594. return str;
  2595. } else {
  2596. return {
  2597. 'string': str,
  2598. 'length': offset - start
  2599. };
  2600. }
  2601. };
  2602. /**
  2603. * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended
  2604. * data's length.
  2605. * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its offsets
  2606. * will be modified according to the performed read operation.
  2607. * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
  2608. * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2609. * read if omitted.
  2610. * @returns {!ByteBuffer} this
  2611. * @expose
  2612. * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|`
  2613. * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|`
  2614. */
  2615. ByteBufferPrototype.append = function(source, encoding, offset) {
  2616. if (typeof encoding === 'number' || typeof encoding !== 'string') {
  2617. offset = encoding;
  2618. encoding = undefined;
  2619. }
  2620. var relative = typeof offset === 'undefined';
  2621. if (relative) offset = this.offset;
  2622. if (!this.noAssert) {
  2623. if (typeof offset !== 'number' || offset % 1 !== 0)
  2624. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2625. offset >>>= 0;
  2626. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2627. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2628. }
  2629. if (!(source instanceof ByteBuffer))
  2630. source = ByteBuffer.wrap(source, encoding);
  2631. var length = source.limit - source.offset;
  2632. if (length <= 0) return this; // Nothing to append
  2633. offset += length;
  2634. var capacity16 = this.buffer.byteLength;
  2635. if (offset > capacity16)
  2636. this.resize((capacity16 *= 2) > offset ? capacity16 : offset);
  2637. offset -= length;
  2638. new Uint8Array(this.buffer, offset).set(new Uint8Array(source.buffer).subarray(source.offset, source.limit));
  2639. source.offset += length;
  2640. if (relative) this.offset += length;
  2641. return this;
  2642. };
  2643. /**
  2644. * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents behind the specified
  2645. * offset up to the length of this ByteBuffer's data.
  2646. * @param {!ByteBuffer} target Target ByteBuffer
  2647. * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2648. * read if omitted.
  2649. * @returns {!ByteBuffer} this
  2650. * @expose
  2651. * @see ByteBuffer#append
  2652. */
  2653. ByteBufferPrototype.appendTo = function(target, offset) {
  2654. target.append(this, offset);
  2655. return this;
  2656. };
  2657. /**
  2658. * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to
  2659. * disable them if your code already makes sure that everything is valid.
  2660. * @param {boolean} assert `true` to enable assertions, otherwise `false`
  2661. * @returns {!ByteBuffer} this
  2662. * @expose
  2663. */
  2664. ByteBufferPrototype.assert = function(assert) {
  2665. this.noAssert = !assert;
  2666. return this;
  2667. };
  2668. /**
  2669. * Gets the capacity of this ByteBuffer's backing buffer.
  2670. * @returns {number} Capacity of the backing buffer
  2671. * @expose
  2672. */
  2673. ByteBufferPrototype.capacity = function() {
  2674. return this.buffer.byteLength;
  2675. };
  2676. /**
  2677. * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the
  2678. * backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}.
  2679. * @returns {!ByteBuffer} this
  2680. * @expose
  2681. */
  2682. ByteBufferPrototype.clear = function() {
  2683. this.offset = 0;
  2684. this.limit = this.buffer.byteLength;
  2685. this.markedOffset = -1;
  2686. return this;
  2687. };
  2688. /**
  2689. * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset},
  2690. * {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}.
  2691. * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false`
  2692. * @returns {!ByteBuffer} Cloned instance
  2693. * @expose
  2694. */
  2695. ByteBufferPrototype.clone = function(copy) {
  2696. var bb = new ByteBuffer(0, this.littleEndian, this.noAssert);
  2697. if (copy) {
  2698. var buffer = new ArrayBuffer(this.buffer.byteLength);
  2699. new Uint8Array(buffer).set(this.buffer);
  2700. bb.buffer = buffer;
  2701. bb.view = new DataView(buffer);
  2702. } else {
  2703. bb.buffer = this.buffer;
  2704. bb.view = this.view;
  2705. }
  2706. bb.offset = this.offset;
  2707. bb.markedOffset = this.markedOffset;
  2708. bb.limit = this.limit;
  2709. return bb;
  2710. };
  2711. /**
  2712. * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes
  2713. * between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and
  2714. * adapt {@link ByteBuffer#markedOffset} to the same relative position if set.
  2715. * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset}
  2716. * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
  2717. * @returns {!ByteBuffer} this
  2718. * @expose
  2719. */
  2720. ByteBufferPrototype.compact = function(begin, end) {
  2721. if (typeof begin === 'undefined') begin = this.offset;
  2722. if (typeof end === 'undefined') end = this.limit;
  2723. if (!this.noAssert) {
  2724. if (typeof begin !== 'number' || begin % 1 !== 0)
  2725. throw TypeError("Illegal begin: Not an integer");
  2726. begin >>>= 0;
  2727. if (typeof end !== 'number' || end % 1 !== 0)
  2728. throw TypeError("Illegal end: Not an integer");
  2729. end >>>= 0;
  2730. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  2731. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  2732. }
  2733. if (begin === 0 && end === this.buffer.byteLength)
  2734. return this; // Already compacted
  2735. var len = end - begin;
  2736. if (len === 0) {
  2737. this.buffer = EMPTY_BUFFER;
  2738. this.view = null;
  2739. if (this.markedOffset >= 0) this.markedOffset -= begin;
  2740. this.offset = 0;
  2741. this.limit = 0;
  2742. return this;
  2743. }
  2744. var buffer = new ArrayBuffer(len);
  2745. new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(begin, end));
  2746. this.buffer = buffer;
  2747. this.view = new DataView(buffer);
  2748. if (this.markedOffset >= 0) this.markedOffset -= begin;
  2749. this.offset = 0;
  2750. this.limit = len;
  2751. return this;
  2752. };
  2753. /**
  2754. * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and
  2755. * {@link ByteBuffer#limit}.
  2756. * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
  2757. * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
  2758. * @returns {!ByteBuffer} Copy
  2759. * @expose
  2760. */
  2761. ByteBufferPrototype.copy = function(begin, end) {
  2762. if (typeof begin === 'undefined') begin = this.offset;
  2763. if (typeof end === 'undefined') end = this.limit;
  2764. if (!this.noAssert) {
  2765. if (typeof begin !== 'number' || begin % 1 !== 0)
  2766. throw TypeError("Illegal begin: Not an integer");
  2767. begin >>>= 0;
  2768. if (typeof end !== 'number' || end % 1 !== 0)
  2769. throw TypeError("Illegal end: Not an integer");
  2770. end >>>= 0;
  2771. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  2772. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  2773. }
  2774. if (begin === end)
  2775. return new ByteBuffer(0, this.littleEndian, this.noAssert);
  2776. var capacity = end - begin,
  2777. bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert);
  2778. bb.offset = 0;
  2779. bb.limit = capacity;
  2780. if (bb.markedOffset >= 0) bb.markedOffset -= begin;
  2781. this.copyTo(bb, 0, begin, end);
  2782. return bb;
  2783. };
  2784. /**
  2785. * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and
  2786. * {@link ByteBuffer#limit}.
  2787. * @param {!ByteBuffer} target Target ByteBuffer
  2788. * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset}
  2789. * by the number of bytes copied if omitted.
  2790. * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the
  2791. * number of bytes copied if omitted.
  2792. * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit}
  2793. * @returns {!ByteBuffer} this
  2794. * @expose
  2795. */
  2796. ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) {
  2797. var relative,
  2798. targetRelative;
  2799. if (!this.noAssert) {
  2800. if (!ByteBuffer.isByteBuffer(target))
  2801. throw TypeError("Illegal target: Not a ByteBuffer");
  2802. }
  2803. targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0;
  2804. sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0;
  2805. sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0;
  2806. if (targetOffset < 0 || targetOffset > target.buffer.byteLength)
  2807. throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+target.buffer.byteLength);
  2808. if (sourceOffset < 0 || sourceLimit > this.buffer.byteLength)
  2809. throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+this.buffer.byteLength);
  2810. var len = sourceLimit - sourceOffset;
  2811. if (len === 0)
  2812. return target; // Nothing to copy
  2813. target.ensureCapacity(targetOffset + len);
  2814. new Uint8Array(target.buffer).set(new Uint8Array(this.buffer).subarray(sourceOffset, sourceLimit), targetOffset);
  2815. if (relative) this.offset += len;
  2816. if (targetRelative) target.offset += len;
  2817. return this;
  2818. };
  2819. /**
  2820. * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the
  2821. * current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity,
  2822. * the required capacity will be used instead.
  2823. * @param {number} capacity Required capacity
  2824. * @returns {!ByteBuffer} this
  2825. * @expose
  2826. */
  2827. ByteBufferPrototype.ensureCapacity = function(capacity) {
  2828. var current = this.buffer.byteLength;
  2829. if (current < capacity)
  2830. return this.resize((current *= 2) > capacity ? current : capacity);
  2831. return this;
  2832. };
  2833. /**
  2834. * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between
  2835. * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}.
  2836. * @param {number|string} value Byte value to fill with. If given as a string, the first character is used.
  2837. * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes
  2838. * written if omitted. defaults to {@link ByteBuffer#offset}.
  2839. * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
  2840. * @returns {!ByteBuffer} this
  2841. * @expose
  2842. * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes
  2843. */
  2844. ByteBufferPrototype.fill = function(value, begin, end) {
  2845. var relative = typeof begin === 'undefined';
  2846. if (relative) begin = this.offset;
  2847. if (typeof value === 'string' && value.length > 0)
  2848. value = value.charCodeAt(0);
  2849. if (typeof begin === 'undefined') begin = this.offset;
  2850. if (typeof end === 'undefined') end = this.limit;
  2851. if (!this.noAssert) {
  2852. if (typeof value !== 'number' || value % 1 !== 0)
  2853. throw TypeError("Illegal value: "+value+" (not an integer)");
  2854. value |= 0;
  2855. if (typeof begin !== 'number' || begin % 1 !== 0)
  2856. throw TypeError("Illegal begin: Not an integer");
  2857. begin >>>= 0;
  2858. if (typeof end !== 'number' || end % 1 !== 0)
  2859. throw TypeError("Illegal end: Not an integer");
  2860. end >>>= 0;
  2861. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  2862. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  2863. }
  2864. if (begin >= end)
  2865. return this; // Nothing to fill
  2866. while (begin < end) this.view.setUint8(begin++, value);
  2867. if (relative) this.offset = begin;
  2868. return this;
  2869. };
  2870. /**
  2871. * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and
  2872. * `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete.
  2873. * @returns {!ByteBuffer} this
  2874. * @expose
  2875. */
  2876. ByteBufferPrototype.flip = function() {
  2877. this.limit = this.offset;
  2878. this.offset = 0;
  2879. return this;
  2880. };
  2881. /**
  2882. * Marks an offset on this ByteBuffer to be used later.
  2883. * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}.
  2884. * @returns {!ByteBuffer} this
  2885. * @throws {TypeError} If `offset` is not a valid number
  2886. * @throws {RangeError} If `offset` is out of bounds
  2887. * @see ByteBuffer#reset
  2888. * @expose
  2889. */
  2890. ByteBufferPrototype.mark = function(offset) {
  2891. offset = typeof offset === 'undefined' ? this.offset : offset;
  2892. if (!this.noAssert) {
  2893. if (typeof offset !== 'number' || offset % 1 !== 0)
  2894. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2895. offset >>>= 0;
  2896. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2897. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2898. }
  2899. this.markedOffset = offset;
  2900. return this;
  2901. };
  2902. /**
  2903. * Sets the byte order.
  2904. * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian
  2905. * @returns {!ByteBuffer} this
  2906. * @expose
  2907. */
  2908. ByteBufferPrototype.order = function(littleEndian) {
  2909. if (!this.noAssert) {
  2910. if (typeof littleEndian !== 'boolean')
  2911. throw TypeError("Illegal littleEndian: Not a boolean");
  2912. }
  2913. this.littleEndian = !!littleEndian;
  2914. return this;
  2915. };
  2916. /**
  2917. * Switches (to) little endian byte order.
  2918. * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian
  2919. * @returns {!ByteBuffer} this
  2920. * @expose
  2921. */
  2922. ByteBufferPrototype.LE = function(littleEndian) {
  2923. this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true;
  2924. return this;
  2925. };
  2926. /**
  2927. * Switches (to) big endian byte order.
  2928. * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian
  2929. * @returns {!ByteBuffer} this
  2930. * @expose
  2931. */
  2932. ByteBufferPrototype.BE = function(bigEndian) {
  2933. this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false;
  2934. return this;
  2935. };
  2936. /**
  2937. * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the
  2938. * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer
  2939. * will be resized and its contents moved accordingly.
  2940. * @param {!ByteBuffer|string|!ArrayBuffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be
  2941. * modified according to the performed read operation.
  2942. * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
  2943. * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes
  2944. * prepended if omitted.
  2945. * @returns {!ByteBuffer} this
  2946. * @expose
  2947. * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|`
  2948. * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|`
  2949. */
  2950. ByteBufferPrototype.prepend = function(source, encoding, offset) {
  2951. if (typeof encoding === 'number' || typeof encoding !== 'string') {
  2952. offset = encoding;
  2953. encoding = undefined;
  2954. }
  2955. var relative = typeof offset === 'undefined';
  2956. if (relative) offset = this.offset;
  2957. if (!this.noAssert) {
  2958. if (typeof offset !== 'number' || offset % 1 !== 0)
  2959. throw TypeError("Illegal offset: "+offset+" (not an integer)");
  2960. offset >>>= 0;
  2961. if (offset < 0 || offset + 0 > this.buffer.byteLength)
  2962. throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
  2963. }
  2964. if (!(source instanceof ByteBuffer))
  2965. source = ByteBuffer.wrap(source, encoding);
  2966. var len = source.limit - source.offset;
  2967. if (len <= 0) return this; // Nothing to prepend
  2968. var diff = len - offset;
  2969. var arrayView;
  2970. if (diff > 0) { // Not enough space before offset, so resize + move
  2971. var buffer = new ArrayBuffer(this.buffer.byteLength + diff);
  2972. arrayView = new Uint8Array(buffer);
  2973. arrayView.set(new Uint8Array(this.buffer).subarray(offset, this.buffer.byteLength), len);
  2974. this.buffer = buffer;
  2975. this.view = new DataView(buffer);
  2976. this.offset += diff;
  2977. if (this.markedOffset >= 0) this.markedOffset += diff;
  2978. this.limit += diff;
  2979. offset += diff;
  2980. } else {
  2981. arrayView = new Uint8Array(this.buffer);
  2982. }
  2983. arrayView.set(new Uint8Array(source.buffer).subarray(source.offset, source.limit), offset - len);
  2984. source.offset = source.limit;
  2985. if (relative)
  2986. this.offset -= len;
  2987. return this;
  2988. };
  2989. /**
  2990. * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the
  2991. * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer
  2992. * will be resized and its contents moved accordingly.
  2993. * @param {!ByteBuffer} target Target ByteBuffer
  2994. * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes
  2995. * prepended if omitted.
  2996. * @returns {!ByteBuffer} this
  2997. * @expose
  2998. * @see ByteBuffer#prepend
  2999. */
  3000. ByteBufferPrototype.prependTo = function(target, offset) {
  3001. target.prepend(this, offset);
  3002. return this;
  3003. };
  3004. /**
  3005. * Prints debug information about this ByteBuffer's contents.
  3006. * @param {function(string)=} out Output function to call, defaults to console.log
  3007. * @expose
  3008. */
  3009. ByteBufferPrototype.printDebug = function(out) {
  3010. if (typeof out !== 'function') out = console.log.bind(console);
  3011. out(
  3012. this.toString()+"\n"+
  3013. "-------------------------------------------------------------------\n"+
  3014. this.toDebug(/* columns */ true)
  3015. );
  3016. };
  3017. /**
  3018. * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and
  3019. * {@link ByteBuffer#limit}, so this returns `limit - offset`.
  3020. * @returns {number} Remaining readable bytes. May be negative if `offset > limit`.
  3021. * @expose
  3022. */
  3023. ByteBufferPrototype.remaining = function() {
  3024. return this.limit - this.offset;
  3025. };
  3026. /**
  3027. * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark}
  3028. * before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been
  3029. * marked, sets `offset = 0`.
  3030. * @returns {!ByteBuffer} this
  3031. * @see ByteBuffer#mark
  3032. * @expose
  3033. */
  3034. ByteBufferPrototype.reset = function() {
  3035. if (this.markedOffset >= 0) {
  3036. this.offset = this.markedOffset;
  3037. this.markedOffset = -1;
  3038. } else {
  3039. this.offset = 0;
  3040. }
  3041. return this;
  3042. };
  3043. /**
  3044. * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that
  3045. * large or larger.
  3046. * @param {number} capacity Capacity required
  3047. * @returns {!ByteBuffer} this
  3048. * @throws {TypeError} If `capacity` is not a number
  3049. * @throws {RangeError} If `capacity < 0`
  3050. * @expose
  3051. */
  3052. ByteBufferPrototype.resize = function(capacity) {
  3053. if (!this.noAssert) {
  3054. if (typeof capacity !== 'number' || capacity % 1 !== 0)
  3055. throw TypeError("Illegal capacity: "+capacity+" (not an integer)");
  3056. capacity |= 0;
  3057. if (capacity < 0)
  3058. throw RangeError("Illegal capacity: 0 <= "+capacity);
  3059. }
  3060. if (this.buffer.byteLength < capacity) {
  3061. var buffer = new ArrayBuffer(capacity);
  3062. new Uint8Array(buffer).set(new Uint8Array(this.buffer));
  3063. this.buffer = buffer;
  3064. this.view = new DataView(buffer);
  3065. }
  3066. return this;
  3067. };
  3068. /**
  3069. * Reverses this ByteBuffer's contents.
  3070. * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset}
  3071. * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
  3072. * @returns {!ByteBuffer} this
  3073. * @expose
  3074. */
  3075. ByteBufferPrototype.reverse = function(begin, end) {
  3076. if (typeof begin === 'undefined') begin = this.offset;
  3077. if (typeof end === 'undefined') end = this.limit;
  3078. if (!this.noAssert) {
  3079. if (typeof begin !== 'number' || begin % 1 !== 0)
  3080. throw TypeError("Illegal begin: Not an integer");
  3081. begin >>>= 0;
  3082. if (typeof end !== 'number' || end % 1 !== 0)
  3083. throw TypeError("Illegal end: Not an integer");
  3084. end >>>= 0;
  3085. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  3086. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  3087. }
  3088. if (begin === end)
  3089. return this; // Nothing to reverse
  3090. Array.prototype.reverse.call(new Uint8Array(this.buffer).subarray(begin, end));
  3091. this.view = new DataView(this.buffer); // FIXME: Why exactly is this necessary?
  3092. return this;
  3093. };
  3094. /**
  3095. * Skips the next `length` bytes. This will just advance
  3096. * @param {number} length Number of bytes to skip. May also be negative to move the offset back.
  3097. * @returns {!ByteBuffer} this
  3098. * @expose
  3099. */
  3100. ByteBufferPrototype.skip = function(length) {
  3101. if (!this.noAssert) {
  3102. if (typeof length !== 'number' || length % 1 !== 0)
  3103. throw TypeError("Illegal length: "+length+" (not an integer)");
  3104. length |= 0;
  3105. }
  3106. var offset = this.offset + length;
  3107. if (!this.noAssert) {
  3108. if (offset < 0 || offset > this.buffer.byteLength)
  3109. throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+this.buffer.byteLength);
  3110. }
  3111. this.offset = offset;
  3112. return this;
  3113. };
  3114. /**
  3115. * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`.
  3116. * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
  3117. * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
  3118. * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer}
  3119. * @expose
  3120. */
  3121. ByteBufferPrototype.slice = function(begin, end) {
  3122. if (typeof begin === 'undefined') begin = this.offset;
  3123. if (typeof end === 'undefined') end = this.limit;
  3124. if (!this.noAssert) {
  3125. if (typeof begin !== 'number' || begin % 1 !== 0)
  3126. throw TypeError("Illegal begin: Not an integer");
  3127. begin >>>= 0;
  3128. if (typeof end !== 'number' || end % 1 !== 0)
  3129. throw TypeError("Illegal end: Not an integer");
  3130. end >>>= 0;
  3131. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  3132. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  3133. }
  3134. var bb = this.clone();
  3135. bb.offset = begin;
  3136. bb.limit = end;
  3137. return bb;
  3138. };
  3139. /**
  3140. * Returns a copy of the backing buffer that contains this ByteBuffer's contents. Contents are the bytes between
  3141. * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will transparently {@link ByteBuffer#flip} this
  3142. * ByteBuffer if `offset > limit` but the actual offsets remain untouched.
  3143. * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory if
  3144. * possible. Defaults to `false`
  3145. * @returns {!ArrayBuffer} Contents as an ArrayBuffer
  3146. * @expose
  3147. */
  3148. ByteBufferPrototype.toBuffer = function(forceCopy) {
  3149. var offset = this.offset,
  3150. limit = this.limit;
  3151. if (offset > limit) {
  3152. var t = offset;
  3153. offset = limit;
  3154. limit = t;
  3155. }
  3156. if (!this.noAssert) {
  3157. if (typeof offset !== 'number' || offset % 1 !== 0)
  3158. throw TypeError("Illegal offset: Not an integer");
  3159. offset >>>= 0;
  3160. if (typeof limit !== 'number' || limit % 1 !== 0)
  3161. throw TypeError("Illegal limit: Not an integer");
  3162. limit >>>= 0;
  3163. if (offset < 0 || offset > limit || limit > this.buffer.byteLength)
  3164. throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.byteLength);
  3165. }
  3166. // NOTE: It's not possible to have another ArrayBuffer reference the same memory as the backing buffer. This is
  3167. // possible with Uint8Array#subarray only, but we have to return an ArrayBuffer by contract. So:
  3168. if (!forceCopy && offset === 0 && limit === this.buffer.byteLength) {
  3169. return this.buffer;
  3170. }
  3171. if (offset === limit) {
  3172. return EMPTY_BUFFER;
  3173. }
  3174. var buffer = new ArrayBuffer(limit - offset);
  3175. new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(offset, limit), 0);
  3176. return buffer;
  3177. };
  3178. /**
  3179. * Returns a raw buffer compacted to contain this ByteBuffer's contents. Contents are the bytes between
  3180. * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will transparently {@link ByteBuffer#flip} this
  3181. * ByteBuffer if `offset > limit` but the actual offsets remain untouched. This is an alias of
  3182. * {@link ByteBuffer#toBuffer}.
  3183. * @function
  3184. * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory.
  3185. * Defaults to `false`
  3186. * @returns {!ArrayBuffer} Contents as an ArrayBuffer
  3187. * @expose
  3188. */
  3189. ByteBufferPrototype.toArrayBuffer = ByteBufferPrototype.toBuffer;
  3190. /**
  3191. * Converts the ByteBuffer's contents to a string.
  3192. * @param {string=} encoding Output encoding. Returns an informative string representation if omitted but also allows
  3193. * direct conversion to "utf8", "hex", "base64" and "binary" encoding. "debug" returns a hex representation with
  3194. * highlighted offsets.
  3195. * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}
  3196. * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
  3197. * @returns {string} String representation
  3198. * @throws {Error} If `encoding` is invalid
  3199. * @expose
  3200. */
  3201. ByteBufferPrototype.toString = function(encoding, begin, end) {
  3202. if (typeof encoding === 'undefined')
  3203. return "ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")";
  3204. if (typeof encoding === 'number')
  3205. encoding = "utf8",
  3206. begin = encoding,
  3207. end = begin;
  3208. switch (encoding) {
  3209. case "utf8":
  3210. return this.toUTF8(begin, end);
  3211. case "base64":
  3212. return this.toBase64(begin, end);
  3213. case "hex":
  3214. return this.toHex(begin, end);
  3215. case "binary":
  3216. return this.toBinary(begin, end);
  3217. case "debug":
  3218. return this.toDebug();
  3219. case "columns":
  3220. return this.toColumns();
  3221. default:
  3222. throw Error("Unsupported encoding: "+encoding);
  3223. }
  3224. };
  3225. // lxiv-embeddable
  3226. /**
  3227. * lxiv-embeddable (c) 2014 Daniel Wirtz <dcode@dcode.io>
  3228. * Released under the Apache License, Version 2.0
  3229. * see: https://github.com/dcodeIO/lxiv for details
  3230. */
  3231. var lxiv = function() {
  3232. "use strict";
  3233. /**
  3234. * lxiv namespace.
  3235. * @type {!Object.<string,*>}
  3236. * @exports lxiv
  3237. */
  3238. var lxiv = {};
  3239. /**
  3240. * Character codes for output.
  3241. * @type {!Array.<number>}
  3242. * @inner
  3243. */
  3244. var aout = [
  3245. 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
  3246. 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102,
  3247. 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
  3248. 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47
  3249. ];
  3250. /**
  3251. * Character codes for input.
  3252. * @type {!Array.<number>}
  3253. * @inner
  3254. */
  3255. var ain = [];
  3256. for (var i=0, k=aout.length; i<k; ++i)
  3257. ain[aout[i]] = i;
  3258. /**
  3259. * Encodes bytes to base64 char codes.
  3260. * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if
  3261. * there are no more bytes left.
  3262. * @param {!function(number)} dst Characters destination as a function successively called with each encoded char
  3263. * code.
  3264. */
  3265. lxiv.encode = function(src, dst) {
  3266. var b, t;
  3267. while ((b = src()) !== null) {
  3268. dst(aout[(b>>2)&0x3f]);
  3269. t = (b&0x3)<<4;
  3270. if ((b = src()) !== null) {
  3271. t |= (b>>4)&0xf;
  3272. dst(aout[(t|((b>>4)&0xf))&0x3f]);
  3273. t = (b&0xf)<<2;
  3274. if ((b = src()) !== null)
  3275. dst(aout[(t|((b>>6)&0x3))&0x3f]),
  3276. dst(aout[b&0x3f]);
  3277. else
  3278. dst(aout[t&0x3f]),
  3279. dst(61);
  3280. } else
  3281. dst(aout[t&0x3f]),
  3282. dst(61),
  3283. dst(61);
  3284. }
  3285. };
  3286. /**
  3287. * Decodes base64 char codes to bytes.
  3288. * @param {!function():number|null} src Characters source as a function returning the next char code respectively
  3289. * `null` if there are no more characters left.
  3290. * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
  3291. * @throws {Error} If a character code is invalid
  3292. */
  3293. lxiv.decode = function(src, dst) {
  3294. var c, t1, t2;
  3295. function fail(c) {
  3296. throw Error("Illegal character code: "+c);
  3297. }
  3298. while ((c = src()) !== null) {
  3299. t1 = ain[c];
  3300. if (typeof t1 === 'undefined') fail(c);
  3301. if ((c = src()) !== null) {
  3302. t2 = ain[c];
  3303. if (typeof t2 === 'undefined') fail(c);
  3304. dst((t1<<2)>>>0|(t2&0x30)>>4);
  3305. if ((c = src()) !== null) {
  3306. t1 = ain[c];
  3307. if (typeof t1 === 'undefined')
  3308. if (c === 61) break; else fail(c);
  3309. dst(((t2&0xf)<<4)>>>0|(t1&0x3c)>>2);
  3310. if ((c = src()) !== null) {
  3311. t2 = ain[c];
  3312. if (typeof t2 === 'undefined')
  3313. if (c === 61) break; else fail(c);
  3314. dst(((t1&0x3)<<6)>>>0|t2);
  3315. }
  3316. }
  3317. }
  3318. }
  3319. };
  3320. /**
  3321. * Tests if a string is valid base64.
  3322. * @param {string} str String to test
  3323. * @returns {boolean} `true` if valid, otherwise `false`
  3324. */
  3325. lxiv.test = function(str) {
  3326. return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(str);
  3327. };
  3328. return lxiv;
  3329. }();
  3330. // encodings/base64
  3331. /**
  3332. * Encodes this ByteBuffer's contents to a base64 encoded string.
  3333. * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}.
  3334. * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}.
  3335. * @returns {string} Base64 encoded string
  3336. * @expose
  3337. */
  3338. ByteBufferPrototype.toBase64 = function(begin, end) {
  3339. if (typeof begin === 'undefined')
  3340. begin = this.offset;
  3341. if (typeof end === 'undefined')
  3342. end = this.limit;
  3343. if (!this.noAssert) {
  3344. if (typeof begin !== 'number' || begin % 1 !== 0)
  3345. throw TypeError("Illegal begin: Not an integer");
  3346. begin >>>= 0;
  3347. if (typeof end !== 'number' || end % 1 !== 0)
  3348. throw TypeError("Illegal end: Not an integer");
  3349. end >>>= 0;
  3350. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  3351. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  3352. }
  3353. var sd; lxiv.encode(function() {
  3354. return begin < end ? this.view.getUint8(begin++) : null;
  3355. }.bind(this), sd = stringDestination());
  3356. return sd();
  3357. };
  3358. /**
  3359. * Decodes a base64 encoded string to a ByteBuffer.
  3360. * @param {string} str String to decode
  3361. * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
  3362. * {@link ByteBuffer.DEFAULT_ENDIAN}.
  3363. * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
  3364. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  3365. * @returns {!ByteBuffer} ByteBuffer
  3366. * @expose
  3367. */
  3368. ByteBuffer.fromBase64 = function(str, littleEndian, noAssert) {
  3369. if (!noAssert) {
  3370. if (typeof str !== 'string')
  3371. throw TypeError("Illegal str: Not a string");
  3372. if (str.length % 4 !== 0)
  3373. throw TypeError("Illegal str: Length not a multiple of 4");
  3374. }
  3375. var bb = new ByteBuffer(str.length/4*3, littleEndian, noAssert),
  3376. i = 0;
  3377. lxiv.decode(stringSource(str), function(b) {
  3378. bb.view.setUint8(i++, b);
  3379. });
  3380. bb.limit = i;
  3381. return bb;
  3382. };
  3383. /**
  3384. * Encodes a binary string to base64 like `window.btoa` does.
  3385. * @param {string} str Binary string
  3386. * @returns {string} Base64 encoded string
  3387. * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa
  3388. * @expose
  3389. */
  3390. ByteBuffer.btoa = function(str) {
  3391. return ByteBuffer.fromBinary(str).toBase64();
  3392. };
  3393. /**
  3394. * Decodes a base64 encoded string to binary like `window.atob` does.
  3395. * @param {string} b64 Base64 encoded string
  3396. * @returns {string} Binary string
  3397. * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob
  3398. * @expose
  3399. */
  3400. ByteBuffer.atob = function(b64) {
  3401. return ByteBuffer.fromBase64(b64).toBinary();
  3402. };
  3403. // encodings/binary
  3404. /**
  3405. * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes.
  3406. * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}.
  3407. * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}.
  3408. * @returns {string} Binary encoded string
  3409. * @throws {RangeError} If `offset > limit`
  3410. * @expose
  3411. */
  3412. ByteBufferPrototype.toBinary = function(begin, end) {
  3413. begin = typeof begin === 'undefined' ? this.offset : begin;
  3414. end = typeof end === 'undefined' ? this.limit : end;
  3415. if (!this.noAssert) {
  3416. if (typeof begin !== 'number' || begin % 1 !== 0)
  3417. throw TypeError("Illegal begin: Not an integer");
  3418. begin >>>= 0;
  3419. if (typeof end !== 'number' || end % 1 !== 0)
  3420. throw TypeError("Illegal end: Not an integer");
  3421. end >>>= 0;
  3422. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  3423. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  3424. }
  3425. if (begin === end)
  3426. return "";
  3427. var cc = [], pt = [];
  3428. while (begin < end) {
  3429. cc.push(this.view.getUint8(begin++));
  3430. if (cc.length >= 1024)
  3431. pt.push(String.fromCharCode.apply(String, cc)),
  3432. cc = [];
  3433. }
  3434. return pt.join('') + String.fromCharCode.apply(String, cc);
  3435. };
  3436. /**
  3437. * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer.
  3438. * @param {string} str String to decode
  3439. * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
  3440. * {@link ByteBuffer.DEFAULT_ENDIAN}.
  3441. * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
  3442. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  3443. * @returns {!ByteBuffer} ByteBuffer
  3444. * @expose
  3445. */
  3446. ByteBuffer.fromBinary = function(str, littleEndian, noAssert) {
  3447. if (!noAssert) {
  3448. if (typeof str !== 'string')
  3449. throw TypeError("Illegal str: Not a string");
  3450. }
  3451. var i = 0, k = str.length, charCode,
  3452. bb = new ByteBuffer(k, littleEndian, noAssert);
  3453. while (i<k) {
  3454. charCode = str.charCodeAt(i);
  3455. if (!noAssert && charCode > 255)
  3456. throw RangeError("Illegal charCode at "+i+": 0 <= "+charCode+" <= 255");
  3457. bb.view.setUint8(i++, charCode);
  3458. }
  3459. bb.limit = k;
  3460. return bb;
  3461. };
  3462. // encodings/debug
  3463. /**
  3464. * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are:
  3465. * * `<` : offset,
  3466. * * `'` : markedOffset,
  3467. * * `>` : limit,
  3468. * * `|` : offset and limit,
  3469. * * `[` : offset and markedOffset,
  3470. * * `]` : markedOffset and limit,
  3471. * * `!` : offset, markedOffset and limit
  3472. * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false`
  3473. * @returns {string|!Array.<string>} Debug string or array of lines if `asArray = true`
  3474. * @expose
  3475. * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3`
  3476. * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4`
  3477. * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1`
  3478. * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1`
  3479. */
  3480. ByteBufferPrototype.toDebug = function(columns) {
  3481. var i = -1,
  3482. k = this.buffer.byteLength,
  3483. b,
  3484. hex = "",
  3485. asc = "",
  3486. out = "";
  3487. while (i<k) {
  3488. if (i !== -1) {
  3489. b = this.view.getUint8(i);
  3490. if (b < 0x10) hex += "0"+b.toString(16).toUpperCase();
  3491. else hex += b.toString(16).toUpperCase();
  3492. if (columns) {
  3493. asc += b > 32 && b < 127 ? String.fromCharCode(b) : '.';
  3494. }
  3495. }
  3496. ++i;
  3497. if (columns) {
  3498. if (i > 0 && i % 16 === 0 && i !== k) {
  3499. while (hex.length < 3*16+3) hex += " ";
  3500. out += hex+asc+"\n";
  3501. hex = asc = "";
  3502. }
  3503. }
  3504. if (i === this.offset && i === this.limit)
  3505. hex += i === this.markedOffset ? "!" : "|";
  3506. else if (i === this.offset)
  3507. hex += i === this.markedOffset ? "[" : "<";
  3508. else if (i === this.limit)
  3509. hex += i === this.markedOffset ? "]" : ">";
  3510. else
  3511. hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : "");
  3512. }
  3513. if (columns && hex !== " ") {
  3514. while (hex.length < 3*16+3) hex += " ";
  3515. out += hex+asc+"\n";
  3516. }
  3517. return columns ? out : hex;
  3518. };
  3519. /**
  3520. * Decodes a hex encoded string with marked offsets to a ByteBuffer.
  3521. * @param {string} str Debug string to decode (not be generated with `columns = true`)
  3522. * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
  3523. * {@link ByteBuffer.DEFAULT_ENDIAN}.
  3524. * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
  3525. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  3526. * @returns {!ByteBuffer} ByteBuffer
  3527. * @expose
  3528. * @see ByteBuffer#toDebug
  3529. */
  3530. ByteBuffer.fromDebug = function(str, littleEndian, noAssert) {
  3531. var k = str.length,
  3532. bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert);
  3533. var i = 0, j = 0, ch, b,
  3534. rs = false, // Require symbol next
  3535. ho = false, hm = false, hl = false, // Already has offset, markedOffset, limit?
  3536. fail = false;
  3537. while (i<k) {
  3538. switch (ch = str.charAt(i++)) {
  3539. case '!':
  3540. if (!noAssert) {
  3541. if (ho || hm || hl) {
  3542. fail = true; break;
  3543. }
  3544. ho = hm = hl = true;
  3545. }
  3546. bb.offset = bb.markedOffset = bb.limit = j;
  3547. rs = false;
  3548. break;
  3549. case '|':
  3550. if (!noAssert) {
  3551. if (ho || hl) {
  3552. fail = true; break;
  3553. }
  3554. ho = hl = true;
  3555. }
  3556. bb.offset = bb.limit = j;
  3557. rs = false;
  3558. break;
  3559. case '[':
  3560. if (!noAssert) {
  3561. if (ho || hm) {
  3562. fail = true; break;
  3563. }
  3564. ho = hm = true;
  3565. }
  3566. bb.offset = bb.markedOffset = j;
  3567. rs = false;
  3568. break;
  3569. case '<':
  3570. if (!noAssert) {
  3571. if (ho) {
  3572. fail = true; break;
  3573. }
  3574. ho = true;
  3575. }
  3576. bb.offset = j;
  3577. rs = false;
  3578. break;
  3579. case ']':
  3580. if (!noAssert) {
  3581. if (hl || hm) {
  3582. fail = true; break;
  3583. }
  3584. hl = hm = true;
  3585. }
  3586. bb.limit = bb.markedOffset = j;
  3587. rs = false;
  3588. break;
  3589. case '>':
  3590. if (!noAssert) {
  3591. if (hl) {
  3592. fail = true; break;
  3593. }
  3594. hl = true;
  3595. }
  3596. bb.limit = j;
  3597. rs = false;
  3598. break;
  3599. case "'":
  3600. if (!noAssert) {
  3601. if (hm) {
  3602. fail = true; break;
  3603. }
  3604. hm = true;
  3605. }
  3606. bb.markedOffset = j;
  3607. rs = false;
  3608. break;
  3609. case ' ':
  3610. rs = false;
  3611. break;
  3612. default:
  3613. if (!noAssert) {
  3614. if (rs) {
  3615. fail = true; break;
  3616. }
  3617. }
  3618. b = parseInt(ch+str.charAt(i++), 16);
  3619. if (!noAssert) {
  3620. if (isNaN(b) || b < 0 || b > 255)
  3621. throw TypeError("Illegal str: Not a debug encoded string");
  3622. }
  3623. bb.view.setUint8(j++, b);
  3624. rs = true;
  3625. }
  3626. if (fail)
  3627. throw TypeError("Illegal str: Invalid symbol at "+i);
  3628. }
  3629. if (!noAssert) {
  3630. if (!ho || !hl)
  3631. throw TypeError("Illegal str: Missing offset or limit");
  3632. if (j<bb.buffer.byteLength)
  3633. throw TypeError("Illegal str: Not a debug encoded string (is it hex?) "+j+" < "+k);
  3634. }
  3635. return bb;
  3636. };
  3637. // encodings/hex
  3638. /**
  3639. * Encodes this ByteBuffer's contents to a hex encoded string.
  3640. * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}.
  3641. * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}.
  3642. * @returns {string} Hex encoded string
  3643. * @expose
  3644. */
  3645. ByteBufferPrototype.toHex = function(begin, end) {
  3646. begin = typeof begin === 'undefined' ? this.offset : begin;
  3647. end = typeof end === 'undefined' ? this.limit : end;
  3648. if (!this.noAssert) {
  3649. if (typeof begin !== 'number' || begin % 1 !== 0)
  3650. throw TypeError("Illegal begin: Not an integer");
  3651. begin >>>= 0;
  3652. if (typeof end !== 'number' || end % 1 !== 0)
  3653. throw TypeError("Illegal end: Not an integer");
  3654. end >>>= 0;
  3655. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  3656. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  3657. }
  3658. var out = new Array(end - begin),
  3659. b;
  3660. while (begin < end) {
  3661. b = this.view.getUint8(begin++);
  3662. if (b < 0x10)
  3663. out.push("0", b.toString(16));
  3664. else out.push(b.toString(16));
  3665. }
  3666. return out.join('');
  3667. };
  3668. /**
  3669. * Decodes a hex encoded string to a ByteBuffer.
  3670. * @param {string} str String to decode
  3671. * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
  3672. * {@link ByteBuffer.DEFAULT_ENDIAN}.
  3673. * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
  3674. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  3675. * @returns {!ByteBuffer} ByteBuffer
  3676. * @expose
  3677. */
  3678. ByteBuffer.fromHex = function(str, littleEndian, noAssert) {
  3679. if (!noAssert) {
  3680. if (typeof str !== 'string')
  3681. throw TypeError("Illegal str: Not a string");
  3682. if (str.length % 2 !== 0)
  3683. throw TypeError("Illegal str: Length not a multiple of 2");
  3684. }
  3685. var k = str.length,
  3686. bb = new ByteBuffer((k / 2) | 0, littleEndian),
  3687. b;
  3688. for (var i=0, j=0; i<k; i+=2) {
  3689. b = parseInt(str.substring(i, i+2), 16);
  3690. if (!noAssert)
  3691. if (!isFinite(b) || b < 0 || b > 255)
  3692. throw TypeError("Illegal str: Contains non-hex characters");
  3693. bb.view.setUint8(j++, b);
  3694. }
  3695. bb.limit = j;
  3696. return bb;
  3697. };
  3698. // utfx-embeddable
  3699. /**
  3700. * utfx-embeddable (c) 2014 Daniel Wirtz <dcode@dcode.io>
  3701. * Released under the Apache License, Version 2.0
  3702. * see: https://github.com/dcodeIO/utfx for details
  3703. */
  3704. var utfx = function() {
  3705. "use strict";
  3706. /**
  3707. * utfx namespace.
  3708. * @inner
  3709. * @type {!Object.<string,*>}
  3710. */
  3711. var utfx = {};
  3712. /**
  3713. * Maximum valid code point.
  3714. * @type {number}
  3715. * @const
  3716. */
  3717. utfx.MAX_CODEPOINT = 0x10FFFF;
  3718. /**
  3719. * Encodes UTF8 code points to UTF8 bytes.
  3720. * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
  3721. * respectively `null` if there are no more code points left or a single numeric code point.
  3722. * @param {!function(number)} dst Bytes destination as a function successively called with the next byte
  3723. */
  3724. utfx.encodeUTF8 = function(src, dst) {
  3725. var cp = null;
  3726. if (typeof src === 'number')
  3727. cp = src,
  3728. src = function() { return null; };
  3729. while (cp !== null || (cp = src()) !== null) {
  3730. if (cp < 0x80)
  3731. dst(cp&0x7F);
  3732. else if (cp < 0x800)
  3733. dst(((cp>>6)&0x1F)|0xC0),
  3734. dst((cp&0x3F)|0x80);
  3735. else if (cp < 0x10000)
  3736. dst(((cp>>12)&0x0F)|0xE0),
  3737. dst(((cp>>6)&0x3F)|0x80),
  3738. dst((cp&0x3F)|0x80);
  3739. else
  3740. dst(((cp>>18)&0x07)|0xF0),
  3741. dst(((cp>>12)&0x3F)|0x80),
  3742. dst(((cp>>6)&0x3F)|0x80),
  3743. dst((cp&0x3F)|0x80);
  3744. cp = null;
  3745. }
  3746. };
  3747. /**
  3748. * Decodes UTF8 bytes to UTF8 code points.
  3749. * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
  3750. * are no more bytes left.
  3751. * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point.
  3752. * @throws {RangeError} If a starting byte is invalid in UTF8
  3753. * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the
  3754. * remaining bytes.
  3755. */
  3756. utfx.decodeUTF8 = function(src, dst) {
  3757. var a, b, c, d, fail = function(b) {
  3758. b = b.slice(0, b.indexOf(null));
  3759. var err = Error(b.toString());
  3760. err.name = "TruncatedError";
  3761. err['bytes'] = b;
  3762. throw err;
  3763. };
  3764. while ((a = src()) !== null) {
  3765. if ((a&0x80) === 0)
  3766. dst(a);
  3767. else if ((a&0xE0) === 0xC0)
  3768. ((b = src()) === null) && fail([a, b]),
  3769. dst(((a&0x1F)<<6) | (b&0x3F));
  3770. else if ((a&0xF0) === 0xE0)
  3771. ((b=src()) === null || (c=src()) === null) && fail([a, b, c]),
  3772. dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F));
  3773. else if ((a&0xF8) === 0xF0)
  3774. ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]),
  3775. dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F));
  3776. else throw RangeError("Illegal starting byte: "+a);
  3777. }
  3778. };
  3779. /**
  3780. * Converts UTF16 characters to UTF8 code points.
  3781. * @param {!function():number|null} src Characters source as a function returning the next char code respectively
  3782. * `null` if there are no more characters left.
  3783. * @param {!function(number)} dst Code points destination as a function successively called with each converted code
  3784. * point.
  3785. */
  3786. utfx.UTF16toUTF8 = function(src, dst) {
  3787. var c1, c2 = null;
  3788. while (true) {
  3789. if ((c1 = c2 !== null ? c2 : src()) === null)
  3790. break;
  3791. if (c1 >= 0xD800 && c1 <= 0xDFFF) {
  3792. if ((c2 = src()) !== null) {
  3793. if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
  3794. dst((c1-0xD800)*0x400+c2-0xDC00+0x10000);
  3795. c2 = null; continue;
  3796. }
  3797. }
  3798. }
  3799. dst(c1);
  3800. }
  3801. if (c2 !== null) dst(c2);
  3802. };
  3803. /**
  3804. * Converts UTF8 code points to UTF16 characters.
  3805. * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
  3806. * respectively `null` if there are no more code points left or a single numeric code point.
  3807. * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
  3808. * @throws {RangeError} If a code point is out of range
  3809. */
  3810. utfx.UTF8toUTF16 = function(src, dst) {
  3811. var cp = null;
  3812. if (typeof src === 'number')
  3813. cp = src, src = function() { return null; };
  3814. while (cp !== null || (cp = src()) !== null) {
  3815. if (cp <= 0xFFFF)
  3816. dst(cp);
  3817. else
  3818. cp -= 0x10000,
  3819. dst((cp>>10)+0xD800),
  3820. dst((cp%0x400)+0xDC00);
  3821. cp = null;
  3822. }
  3823. };
  3824. /**
  3825. * Converts and encodes UTF16 characters to UTF8 bytes.
  3826. * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null`
  3827. * if there are no more characters left.
  3828. * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
  3829. */
  3830. utfx.encodeUTF16toUTF8 = function(src, dst) {
  3831. utfx.UTF16toUTF8(src, function(cp) {
  3832. utfx.encodeUTF8(cp, dst);
  3833. });
  3834. };
  3835. /**
  3836. * Decodes and converts UTF8 bytes to UTF16 characters.
  3837. * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
  3838. * are no more bytes left.
  3839. * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
  3840. * @throws {RangeError} If a starting byte is invalid in UTF8
  3841. * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes.
  3842. */
  3843. utfx.decodeUTF8toUTF16 = function(src, dst) {
  3844. utfx.decodeUTF8(src, function(cp) {
  3845. utfx.UTF8toUTF16(cp, dst);
  3846. });
  3847. };
  3848. /**
  3849. * Calculates the byte length of an UTF8 code point.
  3850. * @param {number} cp UTF8 code point
  3851. * @returns {number} Byte length
  3852. */
  3853. utfx.calculateCodePoint = function(cp) {
  3854. return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
  3855. };
  3856. /**
  3857. * Calculates the number of UTF8 bytes required to store UTF8 code points.
  3858. * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively
  3859. * `null` if there are no more code points left.
  3860. * @returns {number} The number of UTF8 bytes required
  3861. */
  3862. utfx.calculateUTF8 = function(src) {
  3863. var cp, l=0;
  3864. while ((cp = src()) !== null)
  3865. l += utfx.calculateCodePoint(cp);
  3866. return l;
  3867. };
  3868. /**
  3869. * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes.
  3870. * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively
  3871. * `null` if there are no more characters left.
  3872. * @returns {!Array.<number>} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1.
  3873. */
  3874. utfx.calculateUTF16asUTF8 = function(src) {
  3875. var n=0, l=0;
  3876. utfx.UTF16toUTF8(src, function(cp) {
  3877. ++n; l += utfx.calculateCodePoint(cp);
  3878. });
  3879. return [n,l];
  3880. };
  3881. return utfx;
  3882. }();
  3883. // encodings/utf8
  3884. /**
  3885. * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded
  3886. * string.
  3887. * @returns {string} Hex encoded string
  3888. * @throws {RangeError} If `offset > limit`
  3889. * @expose
  3890. */
  3891. ByteBufferPrototype.toUTF8 = function(begin, end) {
  3892. if (typeof begin === 'undefined') begin = this.offset;
  3893. if (typeof end === 'undefined') end = this.limit;
  3894. if (!this.noAssert) {
  3895. if (typeof begin !== 'number' || begin % 1 !== 0)
  3896. throw TypeError("Illegal begin: Not an integer");
  3897. begin >>>= 0;
  3898. if (typeof end !== 'number' || end % 1 !== 0)
  3899. throw TypeError("Illegal end: Not an integer");
  3900. end >>>= 0;
  3901. if (begin < 0 || begin > end || end > this.buffer.byteLength)
  3902. throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
  3903. }
  3904. var sd; try {
  3905. utfx.decodeUTF8toUTF16(function() {
  3906. return begin < end ? this.view.getUint8(begin++) : null;
  3907. }.bind(this), sd = stringDestination());
  3908. } catch (e) {
  3909. if (begin !== end)
  3910. throw RangeError("Illegal range: Truncated data, "+begin+" != "+end);
  3911. }
  3912. return sd();
  3913. };
  3914. /**
  3915. * Decodes an UTF8 encoded string to a ByteBuffer.
  3916. * @param {string} str String to decode
  3917. * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
  3918. * {@link ByteBuffer.DEFAULT_ENDIAN}.
  3919. * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
  3920. * {@link ByteBuffer.DEFAULT_NOASSERT}.
  3921. * @returns {!ByteBuffer} ByteBuffer
  3922. * @expose
  3923. */
  3924. ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) {
  3925. if (!noAssert)
  3926. if (typeof str !== 'string')
  3927. throw TypeError("Illegal str: Not a string");
  3928. var bb = new ByteBuffer(utfx.calculateUTF16asUTF8(stringSource(str), true)[1], littleEndian, noAssert),
  3929. i = 0;
  3930. utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
  3931. bb.view.setUint8(i++, b);
  3932. });
  3933. bb.limit = i;
  3934. return bb;
  3935. };
  3936. return ByteBuffer;
  3937. }
  3938. /* CommonJS */ if (typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports)
  3939. module['exports'] = (function() {
  3940. var Long; try { Long = require("long"); } catch (e) {}
  3941. return loadByteBuffer(Long);
  3942. })();
  3943. /* AMD */ else if (typeof define === 'function' && define["amd"])
  3944. define("ByteBuffer", ["Long"], function(Long) { return loadByteBuffer(Long); });
  3945. /* Global */ else
  3946. (global["dcodeIO"] = global["dcodeIO"] || {})["ByteBuffer"] = loadByteBuffer(global["dcodeIO"]["Long"]);
  3947. })(this);
  3948. /*
  3949. Copyright 2013 Daniel Wirtz <dcode@dcode.io>
  3950. Licensed under the Apache License, Version 2.0 (the "License");
  3951. you may not use this file except in compliance with the License.
  3952. You may obtain a copy of the License at
  3953. http://www.apache.org/licenses/LICENSE-2.0
  3954. Unless required by applicable law or agreed to in writing, software
  3955. distributed under the License is distributed on an "AS IS" BASIS,
  3956. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  3957. See the License for the specific language governing permissions and
  3958. limitations under the License.
  3959. */
  3960. /**
  3961. * @license ProtoBuf.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
  3962. * Released under the Apache License, Version 2.0
  3963. * see: https://github.com/dcodeIO/ProtoBuf.js for details
  3964. */
  3965. (function(global) {
  3966. "use strict";
  3967. function init(ByteBuffer) {
  3968. /**
  3969. * The ProtoBuf namespace.
  3970. * @exports ProtoBuf
  3971. * @namespace
  3972. * @expose
  3973. */
  3974. var ProtoBuf = {};
  3975. /**
  3976. * ProtoBuf.js version.
  3977. * @type {string}
  3978. * @const
  3979. * @expose
  3980. */
  3981. ProtoBuf.VERSION = "3.8.0";
  3982. /**
  3983. * Wire types.
  3984. * @type {Object.<string,number>}
  3985. * @const
  3986. * @expose
  3987. */
  3988. ProtoBuf.WIRE_TYPES = {};
  3989. /**
  3990. * Varint wire type.
  3991. * @type {number}
  3992. * @expose
  3993. */
  3994. ProtoBuf.WIRE_TYPES.VARINT = 0;
  3995. /**
  3996. * Fixed 64 bits wire type.
  3997. * @type {number}
  3998. * @const
  3999. * @expose
  4000. */
  4001. ProtoBuf.WIRE_TYPES.BITS64 = 1;
  4002. /**
  4003. * Length delimited wire type.
  4004. * @type {number}
  4005. * @const
  4006. * @expose
  4007. */
  4008. ProtoBuf.WIRE_TYPES.LDELIM = 2;
  4009. /**
  4010. * Start group wire type.
  4011. * @type {number}
  4012. * @const
  4013. * @expose
  4014. */
  4015. ProtoBuf.WIRE_TYPES.STARTGROUP = 3;
  4016. /**
  4017. * End group wire type.
  4018. * @type {number}
  4019. * @const
  4020. * @expose
  4021. */
  4022. ProtoBuf.WIRE_TYPES.ENDGROUP = 4;
  4023. /**
  4024. * Fixed 32 bits wire type.
  4025. * @type {number}
  4026. * @const
  4027. * @expose
  4028. */
  4029. ProtoBuf.WIRE_TYPES.BITS32 = 5;
  4030. /**
  4031. * Packable wire types.
  4032. * @type {!Array.<number>}
  4033. * @const
  4034. * @expose
  4035. */
  4036. ProtoBuf.PACKABLE_WIRE_TYPES = [
  4037. ProtoBuf.WIRE_TYPES.VARINT,
  4038. ProtoBuf.WIRE_TYPES.BITS64,
  4039. ProtoBuf.WIRE_TYPES.BITS32
  4040. ];
  4041. /**
  4042. * Types.
  4043. * @dict
  4044. * @type {Object.<string,{name: string, wireType: number}>}
  4045. * @const
  4046. * @expose
  4047. */
  4048. ProtoBuf.TYPES = {
  4049. // According to the protobuf spec.
  4050. "int32": {
  4051. name: "int32",
  4052. wireType: ProtoBuf.WIRE_TYPES.VARINT
  4053. },
  4054. "uint32": {
  4055. name: "uint32",
  4056. wireType: ProtoBuf.WIRE_TYPES.VARINT
  4057. },
  4058. "sint32": {
  4059. name: "sint32",
  4060. wireType: ProtoBuf.WIRE_TYPES.VARINT
  4061. },
  4062. "int64": {
  4063. name: "int64",
  4064. wireType: ProtoBuf.WIRE_TYPES.VARINT
  4065. },
  4066. "uint64": {
  4067. name: "uint64",
  4068. wireType: ProtoBuf.WIRE_TYPES.VARINT
  4069. },
  4070. "sint64": {
  4071. name: "sint64",
  4072. wireType: ProtoBuf.WIRE_TYPES.VARINT
  4073. },
  4074. "bool": {
  4075. name: "bool",
  4076. wireType: ProtoBuf.WIRE_TYPES.VARINT
  4077. },
  4078. "double": {
  4079. name: "double",
  4080. wireType: ProtoBuf.WIRE_TYPES.BITS64
  4081. },
  4082. "string": {
  4083. name: "string",
  4084. wireType: ProtoBuf.WIRE_TYPES.LDELIM
  4085. },
  4086. "bytes": {
  4087. name: "bytes",
  4088. wireType: ProtoBuf.WIRE_TYPES.LDELIM
  4089. },
  4090. "fixed32": {
  4091. name: "fixed32",
  4092. wireType: ProtoBuf.WIRE_TYPES.BITS32
  4093. },
  4094. "sfixed32": {
  4095. name: "sfixed32",
  4096. wireType: ProtoBuf.WIRE_TYPES.BITS32
  4097. },
  4098. "fixed64": {
  4099. name: "fixed64",
  4100. wireType: ProtoBuf.WIRE_TYPES.BITS64
  4101. },
  4102. "sfixed64": {
  4103. name: "sfixed64",
  4104. wireType: ProtoBuf.WIRE_TYPES.BITS64
  4105. },
  4106. "float": {
  4107. name: "float",
  4108. wireType: ProtoBuf.WIRE_TYPES.BITS32
  4109. },
  4110. "enum": {
  4111. name: "enum",
  4112. wireType: ProtoBuf.WIRE_TYPES.VARINT
  4113. },
  4114. "message": {
  4115. name: "message",
  4116. wireType: ProtoBuf.WIRE_TYPES.LDELIM
  4117. },
  4118. "group": {
  4119. name: "group",
  4120. wireType: ProtoBuf.WIRE_TYPES.STARTGROUP
  4121. }
  4122. };
  4123. /**
  4124. * Minimum field id.
  4125. * @type {number}
  4126. * @const
  4127. * @expose
  4128. */
  4129. ProtoBuf.ID_MIN = 1;
  4130. /**
  4131. * Maximum field id.
  4132. * @type {number}
  4133. * @const
  4134. * @expose
  4135. */
  4136. ProtoBuf.ID_MAX = 0x1FFFFFFF;
  4137. /**
  4138. * @type {!function(new: ByteBuffer, ...[*])}
  4139. * @expose
  4140. */
  4141. ProtoBuf.ByteBuffer = ByteBuffer;
  4142. /**
  4143. * @type {?function(new: Long, ...[*])}
  4144. * @expose
  4145. */
  4146. ProtoBuf.Long = ByteBuffer.Long || null;
  4147. /**
  4148. * If set to `true`, field names will be converted from underscore notation to camel case. Defaults to `false`.
  4149. * Must be set prior to parsing.
  4150. * @type {boolean}
  4151. * @expose
  4152. */
  4153. ProtoBuf.convertFieldsToCamelCase = false;
  4154. /**
  4155. * By default, messages are populated with (setX, set_x) accessors for each field. This can be disabled by
  4156. * setting this to `false` prior to building messages.
  4157. * @type {boolean}
  4158. * @expose
  4159. */
  4160. ProtoBuf.populateAccessors = true;
  4161. /**
  4162. * @alias ProtoBuf.Util
  4163. * @expose
  4164. */
  4165. ProtoBuf.Util = (function() {
  4166. "use strict";
  4167. // Object.create polyfill
  4168. // ref: https://developer.mozilla.org/de/docs/JavaScript/Reference/Global_Objects/Object/create
  4169. if (!Object.create)
  4170. /** @expose */
  4171. Object.create = function (o) {
  4172. if (arguments.length > 1)
  4173. throw Error('Object.create polyfill only accepts the first parameter.');
  4174. function F() {}
  4175. F.prototype = o;
  4176. return new F();
  4177. };
  4178. /**
  4179. * ProtoBuf utilities.
  4180. * @exports ProtoBuf.Util
  4181. * @namespace
  4182. */
  4183. var Util = {};
  4184. /**
  4185. * Flag if running in node (fs is available) or not.
  4186. * @type {boolean}
  4187. * @const
  4188. * @expose
  4189. */
  4190. Util.IS_NODE = false;
  4191. try {
  4192. // There is no reliable way to detect node.js as an environment, so our
  4193. // best bet is to feature-detect what we actually need.
  4194. Util.IS_NODE =
  4195. typeof require === 'function' &&
  4196. typeof require("fs").readFileSync === 'function' &&
  4197. typeof require("path").resolve === 'function';
  4198. } catch (e) {}
  4199. /**
  4200. * Constructs a XMLHttpRequest object.
  4201. * @return {XMLHttpRequest}
  4202. * @throws {Error} If XMLHttpRequest is not supported
  4203. * @expose
  4204. */
  4205. Util.XHR = function() {
  4206. // No dependencies please, ref: http://www.quirksmode.org/js/xmlhttp.html
  4207. var XMLHttpFactories = [
  4208. function () {return new XMLHttpRequest()},
  4209. function () {return new ActiveXObject("Msxml2.XMLHTTP")},
  4210. function () {return new ActiveXObject("Msxml3.XMLHTTP")},
  4211. function () {return new ActiveXObject("Microsoft.XMLHTTP")}
  4212. ];
  4213. /** @type {?XMLHttpRequest} */
  4214. var xhr = null;
  4215. for (var i=0;i<XMLHttpFactories.length;i++) {
  4216. try { xhr = XMLHttpFactories[i](); }
  4217. catch (e) { continue; }
  4218. break;
  4219. }
  4220. if (!xhr)
  4221. throw Error("XMLHttpRequest is not supported");
  4222. return xhr;
  4223. };
  4224. /**
  4225. * Fetches a resource.
  4226. * @param {string} path Resource path
  4227. * @param {function(?string)=} callback Callback receiving the resource's contents. If omitted the resource will
  4228. * be fetched synchronously. If the request failed, contents will be null.
  4229. * @return {?string|undefined} Resource contents if callback is omitted (null if the request failed), else undefined.
  4230. * @expose
  4231. */
  4232. Util.fetch = function(path, callback) {
  4233. if (callback && typeof callback != 'function')
  4234. callback = null;
  4235. if (Util.IS_NODE) {
  4236. if (callback) {
  4237. require("fs").readFile(path, function(err, data) {
  4238. if (err)
  4239. callback(null);
  4240. else
  4241. callback(""+data);
  4242. });
  4243. } else
  4244. try {
  4245. return require("fs").readFileSync(path);
  4246. } catch (e) {
  4247. return null;
  4248. }
  4249. } else {
  4250. var xhr = Util.XHR();
  4251. xhr.open('GET', path, callback ? true : false);
  4252. // xhr.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
  4253. xhr.setRequestHeader('Accept', 'text/plain');
  4254. if (typeof xhr.overrideMimeType === 'function') xhr.overrideMimeType('text/plain');
  4255. if (callback) {
  4256. xhr.onreadystatechange = function() {
  4257. if (xhr.readyState != 4) return;
  4258. if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
  4259. callback(xhr.responseText);
  4260. else
  4261. callback(null);
  4262. };
  4263. if (xhr.readyState == 4)
  4264. return;
  4265. xhr.send(null);
  4266. } else {
  4267. xhr.send(null);
  4268. if (/* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
  4269. return xhr.responseText;
  4270. return null;
  4271. }
  4272. }
  4273. };
  4274. /**
  4275. * Tests if an object is an array.
  4276. * @function
  4277. * @param {*} obj Object to test
  4278. * @returns {boolean} true if it is an array, else false
  4279. * @expose
  4280. */
  4281. Util.isArray = Array.isArray || function(obj) {
  4282. return Object.prototype.toString.call(obj) === "[object Array]";
  4283. };
  4284. return Util;
  4285. })();
  4286. /**
  4287. * Language expressions.
  4288. * @type {!Object.<string,string|!RegExp>}
  4289. * @expose
  4290. */
  4291. ProtoBuf.Lang = {
  4292. OPEN: "{",
  4293. CLOSE: "}",
  4294. OPTOPEN: "[",
  4295. OPTCLOSE: "]",
  4296. OPTEND: ",",
  4297. EQUAL: "=",
  4298. END: ";",
  4299. STRINGOPEN: '"',
  4300. STRINGCLOSE: '"',
  4301. STRINGOPEN_SQ: "'",
  4302. STRINGCLOSE_SQ: "'",
  4303. COPTOPEN: '(',
  4304. COPTCLOSE: ')',
  4305. DELIM: /[\s\{\}=;\[\],'"\(\)]/g,
  4306. // KEYWORD: /^(?:package|option|import|message|enum|extend|service|syntax|extensions|group)$/,
  4307. RULE: /^(?:required|optional|repeated)$/,
  4308. TYPE: /^(?:double|float|int32|uint32|sint32|int64|uint64|sint64|fixed32|sfixed32|fixed64|sfixed64|bool|string|bytes)$/,
  4309. NAME: /^[a-zA-Z_][a-zA-Z_0-9]*$/,
  4310. TYPEDEF: /^[a-zA-Z][a-zA-Z_0-9]*$/,
  4311. TYPEREF: /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)+$/,
  4312. FQTYPEREF: /^(?:\.[a-zA-Z][a-zA-Z_0-9]*)+$/,
  4313. NUMBER: /^-?(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+|([0-9]*\.[0-9]+([Ee][+-]?[0-9]+)?))$/,
  4314. NUMBER_DEC: /^(?:[1-9][0-9]*|0)$/,
  4315. NUMBER_HEX: /^0x[0-9a-fA-F]+$/,
  4316. NUMBER_OCT: /^0[0-7]+$/,
  4317. NUMBER_FLT: /^[0-9]*\.[0-9]+([Ee][+-]?[0-9]+)?$/,
  4318. ID: /^(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+)$/,
  4319. NEGID: /^\-?(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+)$/,
  4320. WHITESPACE: /\s/,
  4321. STRING: /['"]([^'"\\]*(\\.[^"\\]*)*)['"]/g,
  4322. BOOL: /^(?:true|false)$/i
  4323. };
  4324. /**
  4325. * @alias ProtoBuf.DotProto
  4326. * @expose
  4327. */
  4328. ProtoBuf.DotProto = (function(ProtoBuf, Lang) {
  4329. "use strict";
  4330. /**
  4331. * Utilities to parse .proto files.
  4332. * @exports ProtoBuf.DotProto
  4333. * @namespace
  4334. */
  4335. var DotProto = {};
  4336. /**
  4337. * Constructs a new Tokenizer.
  4338. * @exports ProtoBuf.DotProto.Tokenizer
  4339. * @class prototype tokenizer
  4340. * @param {string} proto Proto to tokenize
  4341. * @constructor
  4342. */
  4343. var Tokenizer = function(proto) {
  4344. /**
  4345. * Source to parse.
  4346. * @type {string}
  4347. * @expose
  4348. */
  4349. this.source = ""+proto; // In case it's a buffer
  4350. /**
  4351. * Current index.
  4352. * @type {number}
  4353. * @expose
  4354. */
  4355. this.index = 0;
  4356. /**
  4357. * Current line.
  4358. * @type {number}
  4359. * @expose
  4360. */
  4361. this.line = 1;
  4362. /**
  4363. * Stacked values.
  4364. * @type {Array}
  4365. * @expose
  4366. */
  4367. this.stack = [];
  4368. /**
  4369. * Whether currently reading a string or not.
  4370. * @type {boolean}
  4371. * @expose
  4372. */
  4373. this.readingString = false;
  4374. /**
  4375. * Whatever character ends the string. Either a single or double quote character.
  4376. * @type {string}
  4377. * @expose
  4378. */
  4379. this.stringEndsWith = Lang.STRINGCLOSE;
  4380. };
  4381. /**
  4382. * @alias ProtoBuf.DotProto.Tokenizer.prototype
  4383. * @inner
  4384. */
  4385. var TokenizerPrototype = Tokenizer.prototype;
  4386. /**
  4387. * Reads a string beginning at the current index.
  4388. * @return {string} The string
  4389. * @throws {Error} If it's not a valid string
  4390. * @private
  4391. */
  4392. TokenizerPrototype._readString = function() {
  4393. Lang.STRING.lastIndex = this.index-1; // Include the open quote
  4394. var match;
  4395. if ((match = Lang.STRING.exec(this.source)) !== null) {
  4396. var s = match[1];
  4397. this.index = Lang.STRING.lastIndex;
  4398. this.stack.push(this.stringEndsWith);
  4399. return s;
  4400. }
  4401. throw Error("Unterminated string at line "+this.line+", index "+this.index);
  4402. };
  4403. /**
  4404. * Gets the next token and advances by one.
  4405. * @return {?string} Token or `null` on EOF
  4406. * @throws {Error} If it's not a valid proto file
  4407. * @expose
  4408. */
  4409. TokenizerPrototype.next = function() {
  4410. if (this.stack.length > 0)
  4411. return this.stack.shift();
  4412. if (this.index >= this.source.length)
  4413. return null; // No more tokens
  4414. if (this.readingString) {
  4415. this.readingString = false;
  4416. return this._readString();
  4417. }
  4418. var repeat, last;
  4419. do {
  4420. repeat = false;
  4421. // Strip white spaces
  4422. while (Lang.WHITESPACE.test(last = this.source.charAt(this.index))) {
  4423. this.index++;
  4424. if (last === "\n")
  4425. this.line++;
  4426. if (this.index === this.source.length)
  4427. return null;
  4428. }
  4429. // Strip comments
  4430. if (this.source.charAt(this.index) === '/') {
  4431. if (this.source.charAt(++this.index) === '/') { // Single line
  4432. while (this.source.charAt(this.index) !== "\n") {
  4433. this.index++;
  4434. if (this.index == this.source.length)
  4435. return null;
  4436. }
  4437. this.index++;
  4438. this.line++;
  4439. repeat = true;
  4440. } else if (this.source.charAt(this.index) === '*') { /* Block */
  4441. last = '';
  4442. while (last+(last=this.source.charAt(this.index)) !== '*/') {
  4443. this.index++;
  4444. if (last === "\n")
  4445. this.line++;
  4446. if (this.index === this.source.length)
  4447. return null;
  4448. }
  4449. this.index++;
  4450. repeat = true;
  4451. } else
  4452. throw Error("Unterminated comment at line "+this.line+": /"+this.source.charAt(this.index));
  4453. }
  4454. } while (repeat);
  4455. if (this.index === this.source.length) return null;
  4456. // Read the next token
  4457. var end = this.index;
  4458. Lang.DELIM.lastIndex = 0;
  4459. var delim = Lang.DELIM.test(this.source.charAt(end));
  4460. if (!delim) {
  4461. ++end;
  4462. while(end < this.source.length && !Lang.DELIM.test(this.source.charAt(end)))
  4463. end++;
  4464. } else
  4465. ++end;
  4466. var token = this.source.substring(this.index, this.index = end);
  4467. if (token === Lang.STRINGOPEN)
  4468. this.readingString = true,
  4469. this.stringEndsWith = Lang.STRINGCLOSE;
  4470. else if (token === Lang.STRINGOPEN_SQ)
  4471. this.readingString = true,
  4472. this.stringEndsWith = Lang.STRINGCLOSE_SQ;
  4473. return token;
  4474. };
  4475. /**
  4476. * Peeks for the next token.
  4477. * @return {?string} Token or `null` on EOF
  4478. * @throws {Error} If it's not a valid proto file
  4479. * @expose
  4480. */
  4481. TokenizerPrototype.peek = function() {
  4482. if (this.stack.length === 0) {
  4483. var token = this.next();
  4484. if (token === null)
  4485. return null;
  4486. this.stack.push(token);
  4487. }
  4488. return this.stack[0];
  4489. };
  4490. /**
  4491. * Returns a string representation of this object.
  4492. * @return {string} String representation as of "Tokenizer(index/length)"
  4493. * @expose
  4494. */
  4495. TokenizerPrototype.toString = function() {
  4496. return "Tokenizer("+this.index+"/"+this.source.length+" at line "+this.line+")";
  4497. };
  4498. /**
  4499. * @alias ProtoBuf.DotProto.Tokenizer
  4500. * @expose
  4501. */
  4502. DotProto.Tokenizer = Tokenizer;
  4503. /**
  4504. * Constructs a new Parser.
  4505. * @exports ProtoBuf.DotProto.Parser
  4506. * @class prototype parser
  4507. * @param {string} proto Protocol source
  4508. * @constructor
  4509. */
  4510. var Parser = function(proto) {
  4511. /**
  4512. * Tokenizer.
  4513. * @type {ProtoBuf.DotProto.Tokenizer}
  4514. * @expose
  4515. */
  4516. this.tn = new Tokenizer(proto);
  4517. };
  4518. /**
  4519. * @alias ProtoBuf.DotProto.Parser.prototype
  4520. * @inner
  4521. */
  4522. var ParserPrototype = Parser.prototype;
  4523. /**
  4524. * Runs the parser.
  4525. * @return {{package: string|null, messages: Array.<object>, enums: Array.<object>, imports: Array.<string>, options: object<string,*>}}
  4526. * @throws {Error} If the source cannot be parsed
  4527. * @expose
  4528. */
  4529. ParserPrototype.parse = function() {
  4530. var topLevel = {
  4531. "name": "[ROOT]", // temporary
  4532. "package": null,
  4533. "messages": [],
  4534. "enums": [],
  4535. "imports": [],
  4536. "options": {},
  4537. "services": []
  4538. };
  4539. var token, head = true;
  4540. while(token = this.tn.next()) {
  4541. switch (token) {
  4542. case 'package':
  4543. if (!head || topLevel["package"] !== null)
  4544. throw Error("Unexpected package at line "+this.tn.line);
  4545. topLevel["package"] = this._parsePackage(token);
  4546. break;
  4547. case 'import':
  4548. if (!head)
  4549. throw Error("Unexpected import at line "+this.tn.line);
  4550. topLevel.imports.push(this._parseImport(token));
  4551. break;
  4552. case 'message':
  4553. this._parseMessage(topLevel, null, token);
  4554. head = false;
  4555. break;
  4556. case 'enum':
  4557. this._parseEnum(topLevel, token);
  4558. head = false;
  4559. break;
  4560. case 'option':
  4561. if (!head)
  4562. throw Error("Unexpected option at line "+this.tn.line);
  4563. this._parseOption(topLevel, token);
  4564. break;
  4565. case 'service':
  4566. this._parseService(topLevel, token);
  4567. break;
  4568. case 'extend':
  4569. this._parseExtend(topLevel, token);
  4570. break;
  4571. case 'syntax':
  4572. this._parseIgnoredStatement(topLevel, token);
  4573. break;
  4574. default:
  4575. throw Error("Unexpected token at line "+this.tn.line+": "+token);
  4576. }
  4577. }
  4578. delete topLevel["name"];
  4579. return topLevel;
  4580. };
  4581. /**
  4582. * Parses a number value.
  4583. * @param {string} val Number value to parse
  4584. * @return {number} Number
  4585. * @throws {Error} If the number value is invalid
  4586. * @private
  4587. */
  4588. ParserPrototype._parseNumber = function(val) {
  4589. var sign = 1;
  4590. if (val.charAt(0) == '-')
  4591. sign = -1,
  4592. val = val.substring(1);
  4593. if (Lang.NUMBER_DEC.test(val))
  4594. return sign*parseInt(val, 10);
  4595. else if (Lang.NUMBER_HEX.test(val))
  4596. return sign*parseInt(val.substring(2), 16);
  4597. else if (Lang.NUMBER_OCT.test(val))
  4598. return sign*parseInt(val.substring(1), 8);
  4599. else if (Lang.NUMBER_FLT.test(val))
  4600. return sign*parseFloat(val);
  4601. throw Error("Illegal number at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
  4602. };
  4603. /**
  4604. * Parses a (possibly multiline) string.
  4605. * @returns {string}
  4606. * @private
  4607. */
  4608. ParserPrototype._parseString = function() {
  4609. var value = "", token;
  4610. do {
  4611. token = this.tn.next(); // Known to be = this.tn.stringEndsWith
  4612. value += this.tn.next();
  4613. token = this.tn.next();
  4614. if (token !== this.tn.stringEndsWith)
  4615. throw Error("Illegal end of string at line "+this.tn.line+": "+token);
  4616. token = this.tn.peek();
  4617. } while (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ);
  4618. return value;
  4619. };
  4620. /**
  4621. * Parses an ID value.
  4622. * @param {string} val ID value to parse
  4623. * @param {boolean=} neg Whether the ID may be negative, defaults to `false`
  4624. * @returns {number} ID
  4625. * @throws {Error} If the ID value is invalid
  4626. * @private
  4627. */
  4628. ParserPrototype._parseId = function(val, neg) {
  4629. var id = -1;
  4630. var sign = 1;
  4631. if (val.charAt(0) == '-')
  4632. sign = -1,
  4633. val = val.substring(1);
  4634. if (Lang.NUMBER_DEC.test(val))
  4635. id = parseInt(val);
  4636. else if (Lang.NUMBER_HEX.test(val))
  4637. id = parseInt(val.substring(2), 16);
  4638. else if (Lang.NUMBER_OCT.test(val))
  4639. id = parseInt(val.substring(1), 8);
  4640. else
  4641. throw Error("Illegal id at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
  4642. id = (sign*id)|0; // Force to 32bit
  4643. if (!neg && id < 0)
  4644. throw Error("Illegal id at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
  4645. return id;
  4646. };
  4647. /**
  4648. * Parses the package definition.
  4649. * @param {string} token Initial token
  4650. * @return {string} Package name
  4651. * @throws {Error} If the package definition cannot be parsed
  4652. * @private
  4653. */
  4654. ParserPrototype._parsePackage = function(token) {
  4655. token = this.tn.next();
  4656. if (!Lang.TYPEREF.test(token))
  4657. throw Error("Illegal package name at line "+this.tn.line+": "+token);
  4658. var pkg = token;
  4659. token = this.tn.next();
  4660. if (token != Lang.END)
  4661. throw Error("Illegal end of package at line "+this.tn.line+": "+token);
  4662. return pkg;
  4663. };
  4664. /**
  4665. * Parses an import definition.
  4666. * @param {string} token Initial token
  4667. * @return {string} Import file name
  4668. * @throws {Error} If the import definition cannot be parsed
  4669. * @private
  4670. */
  4671. ParserPrototype._parseImport = function(token) {
  4672. token = this.tn.peek();
  4673. if (token === "public")
  4674. this.tn.next(),
  4675. token = this.tn.peek();
  4676. if (token !== Lang.STRINGOPEN && token !== Lang.STRINGOPEN_SQ)
  4677. throw Error("Illegal start of import at line "+this.tn.line+": "+token);
  4678. var imported = this._parseString();
  4679. token = this.tn.next();
  4680. if (token !== Lang.END)
  4681. throw Error("Illegal end of import at line "+this.tn.line+": "+token);
  4682. return imported;
  4683. };
  4684. /**
  4685. * Parses a namespace option.
  4686. * @param {Object} parent Parent definition
  4687. * @param {string} token Initial token
  4688. * @throws {Error} If the option cannot be parsed
  4689. * @private
  4690. */
  4691. ParserPrototype._parseOption = function(parent, token) {
  4692. token = this.tn.next();
  4693. var custom = false;
  4694. if (token == Lang.COPTOPEN)
  4695. custom = true,
  4696. token = this.tn.next();
  4697. if (!Lang.TYPEREF.test(token))
  4698. // we can allow options of the form google.protobuf.* since they will just get ignored anyways
  4699. if (!/google\.protobuf\./.test(token))
  4700. throw Error("Illegal option name in message "+parent.name+" at line "+this.tn.line+": "+token);
  4701. var name = token;
  4702. token = this.tn.next();
  4703. if (custom) { // (my_method_option).foo, (my_method_option), some_method_option, (foo.my_option).bar
  4704. if (token !== Lang.COPTCLOSE)
  4705. throw Error("Illegal end in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
  4706. name = '('+name+')';
  4707. token = this.tn.next();
  4708. if (Lang.FQTYPEREF.test(token))
  4709. name += token,
  4710. token = this.tn.next();
  4711. }
  4712. if (token !== Lang.EQUAL)
  4713. throw Error("Illegal operator in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
  4714. var value;
  4715. token = this.tn.peek();
  4716. if (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ)
  4717. value = this._parseString();
  4718. else {
  4719. this.tn.next();
  4720. if (Lang.NUMBER.test(token))
  4721. value = this._parseNumber(token, true);
  4722. else if (Lang.BOOL.test(token))
  4723. value = token === 'true';
  4724. else if (Lang.TYPEREF.test(token))
  4725. value = token;
  4726. else
  4727. throw Error("Illegal option value in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
  4728. }
  4729. token = this.tn.next();
  4730. if (token !== Lang.END)
  4731. throw Error("Illegal end of option in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
  4732. parent["options"][name] = value;
  4733. };
  4734. /**
  4735. * Parses an ignored statement of the form ['keyword', ..., ';'].
  4736. * @param {Object} parent Parent definition
  4737. * @param {string} keyword Initial token
  4738. * @throws {Error} If the directive cannot be parsed
  4739. * @private
  4740. */
  4741. ParserPrototype._parseIgnoredStatement = function(parent, keyword) {
  4742. var token;
  4743. do {
  4744. token = this.tn.next();
  4745. if (token === null)
  4746. throw Error("Unexpected EOF in "+parent.name+", "+keyword+" at line "+this.tn.line);
  4747. if (token === Lang.END)
  4748. break;
  4749. } while (true);
  4750. };
  4751. /**
  4752. * Parses a service definition.
  4753. * @param {Object} parent Parent definition
  4754. * @param {string} token Initial token
  4755. * @throws {Error} If the service cannot be parsed
  4756. * @private
  4757. */
  4758. ParserPrototype._parseService = function(parent, token) {
  4759. token = this.tn.next();
  4760. if (!Lang.NAME.test(token))
  4761. throw Error("Illegal service name at line "+this.tn.line+": "+token);
  4762. var name = token;
  4763. var svc = {
  4764. "name": name,
  4765. "rpc": {},
  4766. "options": {}
  4767. };
  4768. token = this.tn.next();
  4769. if (token !== Lang.OPEN)
  4770. throw Error("Illegal start of service "+name+" at line "+this.tn.line+": "+token);
  4771. do {
  4772. token = this.tn.next();
  4773. if (token === "option")
  4774. this._parseOption(svc, token);
  4775. else if (token === 'rpc')
  4776. this._parseServiceRPC(svc, token);
  4777. else if (token !== Lang.CLOSE)
  4778. throw Error("Illegal type of service "+name+" at line "+this.tn.line+": "+token);
  4779. } while (token !== Lang.CLOSE);
  4780. parent["services"].push(svc);
  4781. };
  4782. /**
  4783. * Parses a RPC service definition of the form ['rpc', name, (request), 'returns', (response)].
  4784. * @param {Object} svc Parent definition
  4785. * @param {string} token Initial token
  4786. * @private
  4787. */
  4788. ParserPrototype._parseServiceRPC = function(svc, token) {
  4789. var type = token;
  4790. token = this.tn.next();
  4791. if (!Lang.NAME.test(token))
  4792. throw Error("Illegal method name in service "+svc["name"]+" at line "+this.tn.line+": "+token);
  4793. var name = token;
  4794. var method = {
  4795. "request": null,
  4796. "response": null,
  4797. "options": {}
  4798. };
  4799. token = this.tn.next();
  4800. if (token !== Lang.COPTOPEN)
  4801. throw Error("Illegal start of request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
  4802. token = this.tn.next();
  4803. if (!Lang.TYPEREF.test(token))
  4804. throw Error("Illegal request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
  4805. method["request"] = token;
  4806. token = this.tn.next();
  4807. if (token != Lang.COPTCLOSE)
  4808. throw Error("Illegal end of request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
  4809. token = this.tn.next();
  4810. if (token.toLowerCase() !== "returns")
  4811. throw Error("Illegal delimiter in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
  4812. token = this.tn.next();
  4813. if (token != Lang.COPTOPEN)
  4814. throw Error("Illegal start of response type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
  4815. token = this.tn.next();
  4816. method["response"] = token;
  4817. token = this.tn.next();
  4818. if (token !== Lang.COPTCLOSE)
  4819. throw Error("Illegal end of response type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
  4820. token = this.tn.next();
  4821. if (token === Lang.OPEN) {
  4822. do {
  4823. token = this.tn.next();
  4824. if (token === 'option')
  4825. this._parseOption(method, token); // <- will fail for the custom-options example
  4826. else if (token !== Lang.CLOSE)
  4827. throw Error("Illegal start of option inservice "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
  4828. } while (token !== Lang.CLOSE);
  4829. if (this.tn.peek() === Lang.END)
  4830. this.tn.next();
  4831. } else if (token !== Lang.END)
  4832. throw Error("Illegal delimiter in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
  4833. if (typeof svc[type] === 'undefined')
  4834. svc[type] = {};
  4835. svc[type][name] = method;
  4836. };
  4837. /**
  4838. * Parses a message definition.
  4839. * @param {Object} parent Parent definition
  4840. * @param {Object} fld Field definition if this is a group, otherwise `null`
  4841. * @param {string} token First token
  4842. * @return {Object}
  4843. * @throws {Error} If the message cannot be parsed
  4844. * @private
  4845. */
  4846. ParserPrototype._parseMessage = function(parent, fld, token) {
  4847. /** @dict */
  4848. var msg = {}; // Note: At some point we might want to exclude the parser, so we need a dict.
  4849. var isGroup = token === "group";
  4850. token = this.tn.next();
  4851. if (!Lang.NAME.test(token))
  4852. throw Error("Illegal "+(isGroup ? "group" : "message")+" name"+(parent ? " in message "+parent["name"] : "")+" at line "+this.tn.line+": "+token);
  4853. msg["name"] = token;
  4854. if (isGroup) {
  4855. token = this.tn.next();
  4856. if (token !== Lang.EQUAL)
  4857. throw Error("Illegal id assignment after group "+msg.name+" at line "+this.tn.line+": "+token);
  4858. token = this.tn.next();
  4859. try {
  4860. fld["id"] = this._parseId(token);
  4861. } catch (e) {
  4862. throw Error("Illegal field id value for group "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
  4863. }
  4864. msg["isGroup"] = true;
  4865. }
  4866. msg["fields"] = []; // Note: Using arrays to support also browser that cannot preserve order of object keys.
  4867. msg["enums"] = [];
  4868. msg["messages"] = [];
  4869. msg["options"] = {};
  4870. msg["oneofs"] = {};
  4871. token = this.tn.next();
  4872. if (token === Lang.OPTOPEN && fld)
  4873. this._parseFieldOptions(msg, fld, token),
  4874. token = this.tn.next();
  4875. if (token !== Lang.OPEN)
  4876. throw Error("Illegal start of "+(isGroup ? "group" : "message")+" "+msg.name+" at line "+this.tn.line+": "+token);
  4877. // msg["extensions"] = undefined
  4878. do {
  4879. token = this.tn.next();
  4880. if (token === Lang.CLOSE) {
  4881. token = this.tn.peek();
  4882. if (token === Lang.END)
  4883. this.tn.next();
  4884. break;
  4885. } else if (Lang.RULE.test(token))
  4886. this._parseMessageField(msg, token);
  4887. else if (token === "oneof")
  4888. this._parseMessageOneOf(msg, token);
  4889. else if (token === "enum")
  4890. this._parseEnum(msg, token);
  4891. else if (token === "message")
  4892. this._parseMessage(msg, null, token);
  4893. else if (token === "option")
  4894. this._parseOption(msg, token);
  4895. else if (token === "extensions")
  4896. msg["extensions"] = this._parseExtensions(msg, token);
  4897. else if (token === "extend")
  4898. this._parseExtend(msg, token);
  4899. else
  4900. throw Error("Illegal token in message "+msg.name+" at line "+this.tn.line+": "+token);
  4901. } while (true);
  4902. parent["messages"].push(msg);
  4903. return msg;
  4904. };
  4905. /**
  4906. * Parses a message field.
  4907. * @param {Object} msg Message definition
  4908. * @param {string} token Initial token
  4909. * @returns {!Object} Field descriptor
  4910. * @throws {Error} If the message field cannot be parsed
  4911. * @private
  4912. */
  4913. ParserPrototype._parseMessageField = function(msg, token) {
  4914. /** @dict */
  4915. var fld = {}, grp = null;
  4916. fld["rule"] = token;
  4917. /** @dict */
  4918. fld["options"] = {};
  4919. token = this.tn.next();
  4920. if (token === "group") {
  4921. // "A [legacy] group simply combines a nested message type and a field into a single declaration. In your
  4922. // code, you can treat this message just as if it had a Result type field called result (the latter name is
  4923. // converted to lower-case so that it does not conflict with the former)."
  4924. grp = this._parseMessage(msg, fld, token);
  4925. if (!/^[A-Z]/.test(grp["name"]))
  4926. throw Error('Group names must start with a capital letter');
  4927. fld["type"] = grp["name"];
  4928. fld["name"] = grp["name"].toLowerCase();
  4929. token = this.tn.peek();
  4930. if (token === Lang.END)
  4931. this.tn.next();
  4932. } else {
  4933. if (!Lang.TYPE.test(token) && !Lang.TYPEREF.test(token))
  4934. throw Error("Illegal field type in message "+msg.name+" at line "+this.tn.line+": "+token);
  4935. fld["type"] = token;
  4936. token = this.tn.next();
  4937. if (!Lang.NAME.test(token))
  4938. throw Error("Illegal field name in message "+msg.name+" at line "+this.tn.line+": "+token);
  4939. fld["name"] = token;
  4940. token = this.tn.next();
  4941. if (token !== Lang.EQUAL)
  4942. throw Error("Illegal token in field "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
  4943. token = this.tn.next();
  4944. try {
  4945. fld["id"] = this._parseId(token);
  4946. } catch (e) {
  4947. throw Error("Illegal field id in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
  4948. }
  4949. token = this.tn.next();
  4950. if (token === Lang.OPTOPEN)
  4951. this._parseFieldOptions(msg, fld, token),
  4952. token = this.tn.next();
  4953. if (token !== Lang.END)
  4954. throw Error("Illegal delimiter in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
  4955. }
  4956. msg["fields"].push(fld);
  4957. return fld;
  4958. };
  4959. /**
  4960. * Parses a message oneof.
  4961. * @param {Object} msg Message definition
  4962. * @param {string} token Initial token
  4963. * @throws {Error} If the message oneof cannot be parsed
  4964. * @private
  4965. */
  4966. ParserPrototype._parseMessageOneOf = function(msg, token) {
  4967. token = this.tn.next();
  4968. if (!Lang.NAME.test(token))
  4969. throw Error("Illegal oneof name in message "+msg.name+" at line "+this.tn.line+": "+token);
  4970. var name = token,
  4971. fld;
  4972. var fields = [];
  4973. token = this.tn.next();
  4974. if (token !== Lang.OPEN)
  4975. throw Error("Illegal start of oneof "+name+" at line "+this.tn.line+": "+token);
  4976. while (this.tn.peek() !== Lang.CLOSE) {
  4977. fld = this._parseMessageField(msg, "optional");
  4978. fld["oneof"] = name;
  4979. fields.push(fld["id"]);
  4980. }
  4981. this.tn.next();
  4982. msg["oneofs"][name] = fields;
  4983. };
  4984. /**
  4985. * Parses a set of field option definitions.
  4986. * @param {Object} msg Message definition
  4987. * @param {Object} fld Field definition
  4988. * @param {string} token Initial token
  4989. * @throws {Error} If the message field options cannot be parsed
  4990. * @private
  4991. */
  4992. ParserPrototype._parseFieldOptions = function(msg, fld, token) {
  4993. var first = true;
  4994. do {
  4995. token = this.tn.next();
  4996. if (token === Lang.OPTCLOSE)
  4997. break;
  4998. else if (token === Lang.OPTEND) {
  4999. if (first)
  5000. throw Error("Illegal start of options in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
  5001. token = this.tn.next();
  5002. }
  5003. this._parseFieldOption(msg, fld, token);
  5004. first = false;
  5005. } while (true);
  5006. };
  5007. /**
  5008. * Parses a single field option.
  5009. * @param {Object} msg Message definition
  5010. * @param {Object} fld Field definition
  5011. * @param {string} token Initial token
  5012. * @throws {Error} If the mesage field option cannot be parsed
  5013. * @private
  5014. */
  5015. ParserPrototype._parseFieldOption = function(msg, fld, token) {
  5016. var custom = false;
  5017. if (token === Lang.COPTOPEN)
  5018. token = this.tn.next(),
  5019. custom = true;
  5020. if (!Lang.TYPEREF.test(token))
  5021. throw Error("Illegal field option in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
  5022. var name = token;
  5023. token = this.tn.next();
  5024. if (custom) {
  5025. if (token !== Lang.COPTCLOSE)
  5026. throw Error("Illegal delimiter in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
  5027. name = '('+name+')';
  5028. token = this.tn.next();
  5029. if (Lang.FQTYPEREF.test(token))
  5030. name += token,
  5031. token = this.tn.next();
  5032. }
  5033. if (token !== Lang.EQUAL)
  5034. throw Error("Illegal token in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
  5035. var value;
  5036. token = this.tn.peek();
  5037. if (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ) {
  5038. value = this._parseString();
  5039. } else if (Lang.NUMBER.test(token, true))
  5040. value = this._parseNumber(this.tn.next(), true);
  5041. else if (Lang.BOOL.test(token))
  5042. value = this.tn.next().toLowerCase() === 'true';
  5043. else if (Lang.TYPEREF.test(token))
  5044. value = this.tn.next(); // TODO: Resolve?
  5045. else
  5046. throw Error("Illegal value in message "+msg.name+"#"+fld.name+", option "+name+" at line "+this.tn.line+": "+token);
  5047. fld["options"][name] = value;
  5048. };
  5049. /**
  5050. * Parses an enum.
  5051. * @param {Object} msg Message definition
  5052. * @param {string} token Initial token
  5053. * @throws {Error} If the enum cannot be parsed
  5054. * @private
  5055. */
  5056. ParserPrototype._parseEnum = function(msg, token) {
  5057. /** @dict */
  5058. var enm = {};
  5059. token = this.tn.next();
  5060. if (!Lang.NAME.test(token))
  5061. throw Error("Illegal enum name in message "+msg.name+" at line "+this.tn.line+": "+token);
  5062. enm["name"] = token;
  5063. token = this.tn.next();
  5064. if (token !== Lang.OPEN)
  5065. throw Error("Illegal start of enum "+enm.name+" at line "+this.tn.line+": "+token);
  5066. enm["values"] = [];
  5067. enm["options"] = {};
  5068. do {
  5069. token = this.tn.next();
  5070. if (token === Lang.CLOSE) {
  5071. token = this.tn.peek();
  5072. if (token === Lang.END)
  5073. this.tn.next();
  5074. break;
  5075. }
  5076. if (token == 'option')
  5077. this._parseOption(enm, token);
  5078. else {
  5079. if (!Lang.NAME.test(token))
  5080. throw Error("Illegal name in enum "+enm.name+" at line "+this.tn.line+": "+token);
  5081. this._parseEnumValue(enm, token);
  5082. }
  5083. } while (true);
  5084. msg["enums"].push(enm);
  5085. };
  5086. /**
  5087. * Parses an enum value.
  5088. * @param {Object} enm Enum definition
  5089. * @param {string} token Initial token
  5090. * @throws {Error} If the enum value cannot be parsed
  5091. * @private
  5092. */
  5093. ParserPrototype._parseEnumValue = function(enm, token) {
  5094. /** @dict */
  5095. var val = {};
  5096. val["name"] = token;
  5097. token = this.tn.next();
  5098. if (token !== Lang.EQUAL)
  5099. throw Error("Illegal token in enum "+enm.name+" at line "+this.tn.line+": "+token);
  5100. token = this.tn.next();
  5101. try {
  5102. val["id"] = this._parseId(token, true);
  5103. } catch (e) {
  5104. throw Error("Illegal id in enum "+enm.name+" at line "+this.tn.line+": "+token);
  5105. }
  5106. enm["values"].push(val);
  5107. token = this.tn.next();
  5108. if (token === Lang.OPTOPEN) {
  5109. var opt = { 'options' : {} }; // TODO: Actually expose them somehow.
  5110. this._parseFieldOptions(enm, opt, token);
  5111. token = this.tn.next();
  5112. }
  5113. if (token !== Lang.END)
  5114. throw Error("Illegal delimiter in enum "+enm.name+" at line "+this.tn.line+": "+token);
  5115. };
  5116. /**
  5117. * Parses an extensions statement.
  5118. * @param {Object} msg Message object
  5119. * @param {string} token Initial token
  5120. * @throws {Error} If the extensions statement cannot be parsed
  5121. * @private
  5122. */
  5123. ParserPrototype._parseExtensions = function(msg, token) {
  5124. /** @type {Array.<number>} */
  5125. var range = [];
  5126. token = this.tn.next();
  5127. if (token === "min") // FIXME: Does the official implementation support this?
  5128. range.push(ProtoBuf.ID_MIN);
  5129. else if (token === "max")
  5130. range.push(ProtoBuf.ID_MAX);
  5131. else
  5132. range.push(this._parseNumber(token));
  5133. token = this.tn.next();
  5134. if (token !== 'to')
  5135. throw Error("Illegal extensions delimiter in message "+msg.name+" at line "+this.tn.line+": "+token);
  5136. token = this.tn.next();
  5137. if (token === "min")
  5138. range.push(ProtoBuf.ID_MIN);
  5139. else if (token === "max")
  5140. range.push(ProtoBuf.ID_MAX);
  5141. else
  5142. range.push(this._parseNumber(token));
  5143. token = this.tn.next();
  5144. if (token !== Lang.END)
  5145. throw Error("Illegal extensions delimiter in message "+msg.name+" at line "+this.tn.line+": "+token);
  5146. return range;
  5147. };
  5148. /**
  5149. * Parses an extend block.
  5150. * @param {Object} parent Parent object
  5151. * @param {string} token Initial token
  5152. * @throws {Error} If the extend block cannot be parsed
  5153. * @private
  5154. */
  5155. ParserPrototype._parseExtend = function(parent, token) {
  5156. token = this.tn.next();
  5157. if (!Lang.TYPEREF.test(token))
  5158. throw Error("Illegal message name at line "+this.tn.line+": "+token);
  5159. /** @dict */
  5160. var ext = {};
  5161. ext["ref"] = token;
  5162. ext["fields"] = [];
  5163. token = this.tn.next();
  5164. if (token !== Lang.OPEN)
  5165. throw Error("Illegal start of extend "+ext.name+" at line "+this.tn.line+": "+token);
  5166. do {
  5167. token = this.tn.next();
  5168. if (token === Lang.CLOSE) {
  5169. token = this.tn.peek();
  5170. if (token == Lang.END)
  5171. this.tn.next();
  5172. break;
  5173. } else if (Lang.RULE.test(token))
  5174. this._parseMessageField(ext, token);
  5175. else
  5176. throw Error("Illegal token in extend "+ext.name+" at line "+this.tn.line+": "+token);
  5177. } while (true);
  5178. parent["messages"].push(ext);
  5179. return ext;
  5180. };
  5181. /**
  5182. * Returns a string representation of this object.
  5183. * @returns {string} String representation as of "Parser"
  5184. */
  5185. ParserPrototype.toString = function() {
  5186. return "Parser";
  5187. };
  5188. /**
  5189. * @alias ProtoBuf.DotProto.Parser
  5190. * @expose
  5191. */
  5192. DotProto.Parser = Parser;
  5193. return DotProto;
  5194. })(ProtoBuf, ProtoBuf.Lang);
  5195. /**
  5196. * @alias ProtoBuf.Reflect
  5197. * @expose
  5198. */
  5199. ProtoBuf.Reflect = (function(ProtoBuf) {
  5200. "use strict";
  5201. /**
  5202. * Reflection types.
  5203. * @exports ProtoBuf.Reflect
  5204. * @namespace
  5205. */
  5206. var Reflect = {};
  5207. /**
  5208. * Constructs a Reflect base class.
  5209. * @exports ProtoBuf.Reflect.T
  5210. * @constructor
  5211. * @abstract
  5212. * @param {!ProtoBuf.Builder} builder Builder reference
  5213. * @param {?ProtoBuf.Reflect.T} parent Parent object
  5214. * @param {string} name Object name
  5215. */
  5216. var T = function(builder, parent, name) {
  5217. /**
  5218. * Builder reference.
  5219. * @type {!ProtoBuf.Builder}
  5220. * @expose
  5221. */
  5222. this.builder = builder;
  5223. /**
  5224. * Parent object.
  5225. * @type {?ProtoBuf.Reflect.T}
  5226. * @expose
  5227. */
  5228. this.parent = parent;
  5229. /**
  5230. * Object name in namespace.
  5231. * @type {string}
  5232. * @expose
  5233. */
  5234. this.name = name;
  5235. /**
  5236. * Fully qualified class name
  5237. * @type {string}
  5238. * @expose
  5239. */
  5240. this.className;
  5241. };
  5242. /**
  5243. * @alias ProtoBuf.Reflect.T.prototype
  5244. * @inner
  5245. */
  5246. var TPrototype = T.prototype;
  5247. /**
  5248. * Returns the fully qualified name of this object.
  5249. * @returns {string} Fully qualified name as of ".PATH.TO.THIS"
  5250. * @expose
  5251. */
  5252. TPrototype.fqn = function() {
  5253. var name = this.name,
  5254. ptr = this;
  5255. do {
  5256. ptr = ptr.parent;
  5257. if (ptr == null)
  5258. break;
  5259. name = ptr.name+"."+name;
  5260. } while (true);
  5261. return name;
  5262. };
  5263. /**
  5264. * Returns a string representation of this Reflect object (its fully qualified name).
  5265. * @param {boolean=} includeClass Set to true to include the class name. Defaults to false.
  5266. * @return String representation
  5267. * @expose
  5268. */
  5269. TPrototype.toString = function(includeClass) {
  5270. return (includeClass ? this.className + " " : "") + this.fqn();
  5271. };
  5272. /**
  5273. * Builds this type.
  5274. * @throws {Error} If this type cannot be built directly
  5275. * @expose
  5276. */
  5277. TPrototype.build = function() {
  5278. throw Error(this.toString(true)+" cannot be built directly");
  5279. };
  5280. /**
  5281. * @alias ProtoBuf.Reflect.T
  5282. * @expose
  5283. */
  5284. Reflect.T = T;
  5285. /**
  5286. * Constructs a new Namespace.
  5287. * @exports ProtoBuf.Reflect.Namespace
  5288. * @param {!ProtoBuf.Builder} builder Builder reference
  5289. * @param {?ProtoBuf.Reflect.Namespace} parent Namespace parent
  5290. * @param {string} name Namespace name
  5291. * @param {Object.<string,*>=} options Namespace options
  5292. * @constructor
  5293. * @extends ProtoBuf.Reflect.T
  5294. */
  5295. var Namespace = function(builder, parent, name, options) {
  5296. T.call(this, builder, parent, name);
  5297. /**
  5298. * @override
  5299. */
  5300. this.className = "Namespace";
  5301. /**
  5302. * Children inside the namespace.
  5303. * @type {!Array.<ProtoBuf.Reflect.T>}
  5304. */
  5305. this.children = [];
  5306. /**
  5307. * Options.
  5308. * @type {!Object.<string, *>}
  5309. */
  5310. this.options = options || {};
  5311. };
  5312. /**
  5313. * @alias ProtoBuf.Reflect.Namespace.prototype
  5314. * @inner
  5315. */
  5316. var NamespacePrototype = Namespace.prototype = Object.create(T.prototype);
  5317. /**
  5318. * Returns an array of the namespace's children.
  5319. * @param {ProtoBuf.Reflect.T=} type Filter type (returns instances of this type only). Defaults to null (all children).
  5320. * @return {Array.<ProtoBuf.Reflect.T>}
  5321. * @expose
  5322. */
  5323. NamespacePrototype.getChildren = function(type) {
  5324. type = type || null;
  5325. if (type == null)
  5326. return this.children.slice();
  5327. var children = [];
  5328. for (var i=0, k=this.children.length; i<k; ++i)
  5329. if (this.children[i] instanceof type)
  5330. children.push(this.children[i]);
  5331. return children;
  5332. };
  5333. /**
  5334. * Adds a child to the namespace.
  5335. * @param {ProtoBuf.Reflect.T} child Child
  5336. * @throws {Error} If the child cannot be added (duplicate)
  5337. * @expose
  5338. */
  5339. NamespacePrototype.addChild = function(child) {
  5340. var other;
  5341. if (other = this.getChild(child.name)) {
  5342. // Try to revert camelcase transformation on collision
  5343. if (other instanceof Message.Field && other.name !== other.originalName && this.getChild(other.originalName) === null)
  5344. other.name = other.originalName; // Revert previous first (effectively keeps both originals)
  5345. else if (child instanceof Message.Field && child.name !== child.originalName && this.getChild(child.originalName) === null)
  5346. child.name = child.originalName;
  5347. else
  5348. throw Error("Duplicate name in namespace "+this.toString(true)+": "+child.name);
  5349. }
  5350. this.children.push(child);
  5351. };
  5352. /**
  5353. * Gets a child by its name or id.
  5354. * @param {string|number} nameOrId Child name or id
  5355. * @return {?ProtoBuf.Reflect.T} The child or null if not found
  5356. * @expose
  5357. */
  5358. NamespacePrototype.getChild = function(nameOrId) {
  5359. var key = typeof nameOrId === 'number' ? 'id' : 'name';
  5360. for (var i=0, k=this.children.length; i<k; ++i)
  5361. if (this.children[i][key] === nameOrId)
  5362. return this.children[i];
  5363. return null;
  5364. };
  5365. /**
  5366. * Resolves a reflect object inside of this namespace.
  5367. * @param {string} qn Qualified name to resolve
  5368. * @param {boolean=} excludeFields Excludes fields, defaults to `false`
  5369. * @return {?ProtoBuf.Reflect.Namespace} The resolved type or null if not found
  5370. * @expose
  5371. */
  5372. NamespacePrototype.resolve = function(qn, excludeFields) {
  5373. var part = qn.split("."),
  5374. ptr = this,
  5375. i = 0;
  5376. if (part[i] === "") { // Fully qualified name, e.g. ".My.Message'
  5377. while (ptr.parent !== null)
  5378. ptr = ptr.parent;
  5379. i++;
  5380. }
  5381. var child;
  5382. do {
  5383. do {
  5384. child = ptr.getChild(part[i]);
  5385. if (!child || !(child instanceof Reflect.T) || (excludeFields && child instanceof Reflect.Message.Field)) {
  5386. ptr = null;
  5387. break;
  5388. }
  5389. ptr = child; i++;
  5390. } while (i < part.length);
  5391. if (ptr != null)
  5392. break; // Found
  5393. // Else search the parent
  5394. if (this.parent !== null) {
  5395. return this.parent.resolve(qn, excludeFields);
  5396. }
  5397. } while (ptr != null);
  5398. return ptr;
  5399. };
  5400. /**
  5401. * Builds the namespace and returns the runtime counterpart.
  5402. * @return {Object.<string,Function|Object>} Runtime namespace
  5403. * @expose
  5404. */
  5405. NamespacePrototype.build = function() {
  5406. /** @dict */
  5407. var ns = {};
  5408. var children = this.children;
  5409. for (var i=0, k=children.length, child; i<k; ++i) {
  5410. child = children[i];
  5411. if (child instanceof Namespace)
  5412. ns[child.name] = child.build();
  5413. }
  5414. if (Object.defineProperty)
  5415. Object.defineProperty(ns, "$options", { "value": this.buildOpt() });
  5416. return ns;
  5417. };
  5418. /**
  5419. * Builds the namespace's '$options' property.
  5420. * @return {Object.<string,*>}
  5421. */
  5422. NamespacePrototype.buildOpt = function() {
  5423. var opt = {},
  5424. keys = Object.keys(this.options);
  5425. for (var i=0, k=keys.length; i<k; ++i) {
  5426. var key = keys[i],
  5427. val = this.options[keys[i]];
  5428. // TODO: Options are not resolved, yet.
  5429. // if (val instanceof Namespace) {
  5430. // opt[key] = val.build();
  5431. // } else {
  5432. opt[key] = val;
  5433. // }
  5434. }
  5435. return opt;
  5436. };
  5437. /**
  5438. * Gets the value assigned to the option with the specified name.
  5439. * @param {string=} name Returns the option value if specified, otherwise all options are returned.
  5440. * @return {*|Object.<string,*>}null} Option value or NULL if there is no such option
  5441. */
  5442. NamespacePrototype.getOption = function(name) {
  5443. if (typeof name === 'undefined')
  5444. return this.options;
  5445. return typeof this.options[name] !== 'undefined' ? this.options[name] : null;
  5446. };
  5447. /**
  5448. * @alias ProtoBuf.Reflect.Namespace
  5449. * @expose
  5450. */
  5451. Reflect.Namespace = Namespace;
  5452. /**
  5453. * Constructs a new Message.
  5454. * @exports ProtoBuf.Reflect.Message
  5455. * @param {!ProtoBuf.Builder} builder Builder reference
  5456. * @param {!ProtoBuf.Reflect.Namespace} parent Parent message or namespace
  5457. * @param {string} name Message name
  5458. * @param {Object.<string,*>=} options Message options
  5459. * @param {boolean=} isGroup `true` if this is a legacy group
  5460. * @constructor
  5461. * @extends ProtoBuf.Reflect.Namespace
  5462. */
  5463. var Message = function(builder, parent, name, options, isGroup) {
  5464. Namespace.call(this, builder, parent, name, options);
  5465. /**
  5466. * @override
  5467. */
  5468. this.className = "Message";
  5469. /**
  5470. * Extensions range.
  5471. * @type {!Array.<number>}
  5472. * @expose
  5473. */
  5474. this.extensions = [ProtoBuf.ID_MIN, ProtoBuf.ID_MAX];
  5475. /**
  5476. * Runtime message class.
  5477. * @type {?function(new:ProtoBuf.Builder.Message)}
  5478. * @expose
  5479. */
  5480. this.clazz = null;
  5481. /**
  5482. * Whether this is a legacy group or not.
  5483. * @type {boolean}
  5484. * @expose
  5485. */
  5486. this.isGroup = !!isGroup;
  5487. // The following cached collections are used to efficiently iterate over or look up fields when decoding.
  5488. /**
  5489. * Cached fields.
  5490. * @type {?Array.<!ProtoBuf.Reflect.Message.Field>}
  5491. * @private
  5492. */
  5493. this._fields = null;
  5494. /**
  5495. * Cached fields by id.
  5496. * @type {?Object.<number,!ProtoBuf.Reflect.Message.Field>}
  5497. * @private
  5498. */
  5499. this._fieldsById = null;
  5500. /**
  5501. * Cached fields by name.
  5502. * @type {?Object.<string,!ProtoBuf.Reflect.Message.Field>}
  5503. * @private
  5504. */
  5505. this._fieldsByName = null;
  5506. };
  5507. /**
  5508. * @alias ProtoBuf.Reflect.Message.prototype
  5509. * @inner
  5510. */
  5511. var MessagePrototype = Message.prototype = Object.create(Namespace.prototype);
  5512. /**
  5513. * Builds the message and returns the runtime counterpart, which is a fully functional class.
  5514. * @see ProtoBuf.Builder.Message
  5515. * @param {boolean=} rebuild Whether to rebuild or not, defaults to false
  5516. * @return {ProtoBuf.Reflect.Message} Message class
  5517. * @throws {Error} If the message cannot be built
  5518. * @expose
  5519. */
  5520. MessagePrototype.build = function(rebuild) {
  5521. if (this.clazz && !rebuild)
  5522. return this.clazz;
  5523. // Create the runtime Message class in its own scope
  5524. var clazz = (function(ProtoBuf, T) {
  5525. var fields = T.getChildren(ProtoBuf.Reflect.Message.Field),
  5526. oneofs = T.getChildren(ProtoBuf.Reflect.Message.OneOf);
  5527. /**
  5528. * Constructs a new runtime Message.
  5529. * @name ProtoBuf.Builder.Message
  5530. * @class Barebone of all runtime messages.
  5531. * @param {!Object.<string,*>|string} values Preset values
  5532. * @param {...string} var_args
  5533. * @constructor
  5534. * @throws {Error} If the message cannot be created
  5535. */
  5536. var Message = function(values, var_args) {
  5537. ProtoBuf.Builder.Message.call(this);
  5538. // Create virtual oneof properties
  5539. for (var i=0, k=oneofs.length; i<k; ++i)
  5540. this[oneofs[i].name] = null;
  5541. // Create fields and set default values
  5542. for (i=0, k=fields.length; i<k; ++i) {
  5543. var field = fields[i];
  5544. this[field.name] = field.repeated ? [] : null;
  5545. if (field.required && field.defaultValue !== null)
  5546. this[field.name] = field.defaultValue;
  5547. }
  5548. if (arguments.length > 0) {
  5549. // Set field values from a values object
  5550. if (arguments.length === 1 && typeof values === 'object' &&
  5551. /* not another Message */ typeof values.encode !== 'function' &&
  5552. /* not a repeated field */ !ProtoBuf.Util.isArray(values) &&
  5553. /* not a ByteBuffer */ !(values instanceof ByteBuffer) &&
  5554. /* not an ArrayBuffer */ !(values instanceof ArrayBuffer) &&
  5555. /* not a Long */ !(ProtoBuf.Long && values instanceof ProtoBuf.Long)) {
  5556. var keys = Object.keys(values);
  5557. for (i=0, k=keys.length; i<k; ++i)
  5558. this.$set(keys[i], values[keys[i]]); // May throw
  5559. } else // Set field values from arguments, in declaration order
  5560. for (i=0, k=arguments.length; i<k; ++i)
  5561. this.$set(fields[i].name, arguments[i]); // May throw
  5562. }
  5563. };
  5564. /**
  5565. * @alias ProtoBuf.Builder.Message.prototype
  5566. * @inner
  5567. */
  5568. var MessagePrototype = Message.prototype = Object.create(ProtoBuf.Builder.Message.prototype);
  5569. /**
  5570. * Adds a value to a repeated field.
  5571. * @name ProtoBuf.Builder.Message#add
  5572. * @function
  5573. * @param {string} key Field name
  5574. * @param {*} value Value to add
  5575. * @param {boolean=} noAssert Whether to assert the value or not (asserts by default)
  5576. * @throws {Error} If the value cannot be added
  5577. * @expose
  5578. */
  5579. MessagePrototype.add = function(key, value, noAssert) {
  5580. var field = T._fieldsByName[key];
  5581. if (!noAssert) {
  5582. if (!field)
  5583. throw Error(this+"#"+key+" is undefined");
  5584. if (!(field instanceof ProtoBuf.Reflect.Message.Field))
  5585. throw Error(this+"#"+key+" is not a field: "+field.toString(true)); // May throw if it's an enum or embedded message
  5586. if (!field.repeated)
  5587. throw Error(this+"#"+key+" is not a repeated field");
  5588. }
  5589. if (this[field.name] === null)
  5590. this[field.name] = [];
  5591. this[field.name].push(noAssert ? value : field.verifyValue(value, true));
  5592. };
  5593. /**
  5594. * Adds a value to a repeated field. This is an alias for {@link ProtoBuf.Builder.Message#add}.
  5595. * @name ProtoBuf.Builder.Message#$add
  5596. * @function
  5597. * @param {string} key Field name
  5598. * @param {*} value Value to add
  5599. * @param {boolean=} noAssert Whether to assert the value or not (asserts by default)
  5600. * @throws {Error} If the value cannot be added
  5601. * @expose
  5602. */
  5603. MessagePrototype.$add = MessagePrototype.add;
  5604. /**
  5605. * Sets a field's value.
  5606. * @name ProtoBuf.Builder.Message#set
  5607. * @function
  5608. * @param {string} key Key
  5609. * @param {*} value Value to set
  5610. * @param {boolean=} noAssert Whether to not assert for an actual field / proper value type, defaults to `false`
  5611. * @returns {!ProtoBuf.Builder.Message} this
  5612. * @throws {Error} If the value cannot be set
  5613. * @expose
  5614. */
  5615. MessagePrototype.set = function(key, value, noAssert) {
  5616. if (key && typeof key === 'object') {
  5617. for (var i in key)
  5618. if (key.hasOwnProperty(i))
  5619. this.$set(i, key[i], noAssert);
  5620. return this;
  5621. }
  5622. var field = T._fieldsByName[key];
  5623. if (!noAssert) {
  5624. if (!field)
  5625. throw Error(this+"#"+key+" is not a field: undefined");
  5626. if (!(field instanceof ProtoBuf.Reflect.Message.Field))
  5627. throw Error(this+"#"+key+" is not a field: "+field.toString(true));
  5628. this[field.name] = (value = field.verifyValue(value)); // May throw
  5629. } else {
  5630. this[field.name] = value;
  5631. }
  5632. if (field.oneof) {
  5633. if (value !== null) {
  5634. if (this[field.oneof.name] !== null)
  5635. this[this[field.oneof.name]] = null; // Unset the previous (field name is the oneof field's value)
  5636. this[field.oneof.name] = field.name;
  5637. } else if (field.oneof.name === key)
  5638. this[field.oneof.name] = null;
  5639. }
  5640. return this;
  5641. };
  5642. /**
  5643. * Sets a field's value. This is an alias for [@link ProtoBuf.Builder.Message#set}.
  5644. * @name ProtoBuf.Builder.Message#$set
  5645. * @function
  5646. * @param {string} key Key
  5647. * @param {*} value Value to set
  5648. * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
  5649. * @throws {Error} If the value cannot be set
  5650. * @expose
  5651. */
  5652. MessagePrototype.$set = MessagePrototype.set;
  5653. /**
  5654. * Gets a field's value.
  5655. * @name ProtoBuf.Builder.Message#get
  5656. * @function
  5657. * @param {string} key Key
  5658. * @param {boolean=} noAssert Whether to not assert for an actual field, defaults to `false`
  5659. * @return {*} Value
  5660. * @throws {Error} If there is no such field
  5661. * @expose
  5662. */
  5663. MessagePrototype.get = function(key, noAssert) {
  5664. if (noAssert)
  5665. return this[key];
  5666. var field = T._fieldsByName[key];
  5667. if (!field || !(field instanceof ProtoBuf.Reflect.Message.Field))
  5668. throw Error(this+"#"+key+" is not a field: undefined");
  5669. if (!(field instanceof ProtoBuf.Reflect.Message.Field))
  5670. throw Error(this+"#"+key+" is not a field: "+field.toString(true));
  5671. return this[field.name];
  5672. };
  5673. /**
  5674. * Gets a field's value. This is an alias for {@link ProtoBuf.Builder.Message#$get}.
  5675. * @name ProtoBuf.Builder.Message#$get
  5676. * @function
  5677. * @param {string} key Key
  5678. * @return {*} Value
  5679. * @throws {Error} If there is no such field
  5680. * @expose
  5681. */
  5682. MessagePrototype.$get = MessagePrototype.get;
  5683. // Getters and setters
  5684. for (var i=0; i<fields.length; i++) {
  5685. var field = fields[i];
  5686. // no setters for extension fields as these are named by their fqn
  5687. if (field instanceof ProtoBuf.Reflect.Message.ExtensionField)
  5688. continue;
  5689. if (T.builder.options['populateAccessors'])
  5690. (function(field) {
  5691. // set/get[SomeValue]
  5692. var Name = field.originalName.replace(/(_[a-zA-Z])/g, function(match) {
  5693. return match.toUpperCase().replace('_','');
  5694. });
  5695. Name = Name.substring(0,1).toUpperCase() + Name.substring(1);
  5696. // set/get_[some_value] FIXME: Do we really need these?
  5697. var name = field.originalName.replace(/([A-Z])/g, function(match) {
  5698. return "_"+match;
  5699. });
  5700. /**
  5701. * The current field's unbound setter function.
  5702. * @function
  5703. * @param {*} value
  5704. * @param {boolean=} noAssert
  5705. * @returns {!ProtoBuf.Builder.Message}
  5706. * @inner
  5707. */
  5708. var setter = function(value, noAssert) {
  5709. this[field.name] = noAssert ? value : field.verifyValue(value);
  5710. return this;
  5711. };
  5712. /**
  5713. * The current field's unbound getter function.
  5714. * @function
  5715. * @returns {*}
  5716. * @inner
  5717. */
  5718. var getter = function() {
  5719. return this[field.name];
  5720. };
  5721. /**
  5722. * Sets a value. This method is present for each field, but only if there is no name conflict with
  5723. * another field.
  5724. * @name ProtoBuf.Builder.Message#set[SomeField]
  5725. * @function
  5726. * @param {*} value Value to set
  5727. * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
  5728. * @returns {!ProtoBuf.Builder.Message} this
  5729. * @abstract
  5730. * @throws {Error} If the value cannot be set
  5731. */
  5732. if (T.getChild("set"+Name) === null)
  5733. MessagePrototype["set"+Name] = setter;
  5734. /**
  5735. * Sets a value. This method is present for each field, but only if there is no name conflict with
  5736. * another field.
  5737. * @name ProtoBuf.Builder.Message#set_[some_field]
  5738. * @function
  5739. * @param {*} value Value to set
  5740. * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
  5741. * @returns {!ProtoBuf.Builder.Message} this
  5742. * @abstract
  5743. * @throws {Error} If the value cannot be set
  5744. */
  5745. if (T.getChild("set_"+name) === null)
  5746. MessagePrototype["set_"+name] = setter;
  5747. /**
  5748. * Gets a value. This method is present for each field, but only if there is no name conflict with
  5749. * another field.
  5750. * @name ProtoBuf.Builder.Message#get[SomeField]
  5751. * @function
  5752. * @abstract
  5753. * @return {*} The value
  5754. */
  5755. if (T.getChild("get"+Name) === null)
  5756. MessagePrototype["get"+Name] = getter;
  5757. /**
  5758. * Gets a value. This method is present for each field, but only if there is no name conflict with
  5759. * another field.
  5760. * @name ProtoBuf.Builder.Message#get_[some_field]
  5761. * @function
  5762. * @return {*} The value
  5763. * @abstract
  5764. */
  5765. if (T.getChild("get_"+name) === null)
  5766. MessagePrototype["get_"+name] = getter;
  5767. })(field);
  5768. }
  5769. // En-/decoding
  5770. /**
  5771. * Encodes the message.
  5772. * @name ProtoBuf.Builder.Message#$encode
  5773. * @function
  5774. * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted.
  5775. * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
  5776. * @return {!ByteBuffer} Encoded message as a ByteBuffer
  5777. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  5778. * returns the encoded ByteBuffer in the `encoded` property on the error.
  5779. * @expose
  5780. * @see ProtoBuf.Builder.Message#encode64
  5781. * @see ProtoBuf.Builder.Message#encodeHex
  5782. * @see ProtoBuf.Builder.Message#encodeAB
  5783. */
  5784. MessagePrototype.encode = function(buffer, noVerify) {
  5785. if (typeof buffer === 'boolean')
  5786. noVerify = buffer,
  5787. buffer = undefined;
  5788. var isNew = false;
  5789. if (!buffer)
  5790. buffer = new ByteBuffer(),
  5791. isNew = true;
  5792. var le = buffer.littleEndian;
  5793. try {
  5794. T.encode(this, buffer.LE(), noVerify);
  5795. return (isNew ? buffer.flip() : buffer).LE(le);
  5796. } catch (e) {
  5797. buffer.LE(le);
  5798. throw(e);
  5799. }
  5800. };
  5801. /**
  5802. * Calculates the byte length of the message.
  5803. * @name ProtoBuf.Builder.Message#calculate
  5804. * @function
  5805. * @returns {number} Byte length
  5806. * @throws {Error} If the message cannot be calculated or if required fields are missing.
  5807. * @expose
  5808. */
  5809. MessagePrototype.calculate = function() {
  5810. return T.calculate(this);
  5811. };
  5812. /**
  5813. * Encodes the varint32 length-delimited message.
  5814. * @name ProtoBuf.Builder.Message#encodeDelimited
  5815. * @function
  5816. * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted.
  5817. * @return {!ByteBuffer} Encoded message as a ByteBuffer
  5818. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  5819. * returns the encoded ByteBuffer in the `encoded` property on the error.
  5820. * @expose
  5821. */
  5822. MessagePrototype.encodeDelimited = function(buffer) {
  5823. var isNew = false;
  5824. if (!buffer)
  5825. buffer = new ByteBuffer(),
  5826. isNew = true;
  5827. var enc = new ByteBuffer().LE();
  5828. T.encode(this, enc).flip();
  5829. buffer.writeVarint32(enc.remaining());
  5830. buffer.append(enc);
  5831. return isNew ? buffer.flip() : buffer;
  5832. };
  5833. /**
  5834. * Directly encodes the message to an ArrayBuffer.
  5835. * @name ProtoBuf.Builder.Message#encodeAB
  5836. * @function
  5837. * @return {ArrayBuffer} Encoded message as ArrayBuffer
  5838. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  5839. * returns the encoded ArrayBuffer in the `encoded` property on the error.
  5840. * @expose
  5841. */
  5842. MessagePrototype.encodeAB = function() {
  5843. try {
  5844. return this.encode().toArrayBuffer();
  5845. } catch (e) {
  5846. if (e["encoded"]) e["encoded"] = e["encoded"].toArrayBuffer();
  5847. throw(e);
  5848. }
  5849. };
  5850. /**
  5851. * Returns the message as an ArrayBuffer. This is an alias for {@link ProtoBuf.Builder.Message#encodeAB}.
  5852. * @name ProtoBuf.Builder.Message#toArrayBuffer
  5853. * @function
  5854. * @return {ArrayBuffer} Encoded message as ArrayBuffer
  5855. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  5856. * returns the encoded ArrayBuffer in the `encoded` property on the error.
  5857. * @expose
  5858. */
  5859. MessagePrototype.toArrayBuffer = MessagePrototype.encodeAB;
  5860. /**
  5861. * Directly encodes the message to a node Buffer.
  5862. * @name ProtoBuf.Builder.Message#encodeNB
  5863. * @function
  5864. * @return {!Buffer}
  5865. * @throws {Error} If the message cannot be encoded, not running under node.js or if required fields are
  5866. * missing. The later still returns the encoded node Buffer in the `encoded` property on the error.
  5867. * @expose
  5868. */
  5869. MessagePrototype.encodeNB = function() {
  5870. try {
  5871. return this.encode().toBuffer();
  5872. } catch (e) {
  5873. if (e["encoded"]) e["encoded"] = e["encoded"].toBuffer();
  5874. throw(e);
  5875. }
  5876. };
  5877. /**
  5878. * Returns the message as a node Buffer. This is an alias for {@link ProtoBuf.Builder.Message#encodeNB}.
  5879. * @name ProtoBuf.Builder.Message#toBuffer
  5880. * @function
  5881. * @return {!Buffer}
  5882. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  5883. * returns the encoded node Buffer in the `encoded` property on the error.
  5884. * @expose
  5885. */
  5886. MessagePrototype.toBuffer = MessagePrototype.encodeNB;
  5887. /**
  5888. * Directly encodes the message to a base64 encoded string.
  5889. * @name ProtoBuf.Builder.Message#encode64
  5890. * @function
  5891. * @return {string} Base64 encoded string
  5892. * @throws {Error} If the underlying buffer cannot be encoded or if required fields are missing. The later
  5893. * still returns the encoded base64 string in the `encoded` property on the error.
  5894. * @expose
  5895. */
  5896. MessagePrototype.encode64 = function() {
  5897. try {
  5898. return this.encode().toBase64();
  5899. } catch (e) {
  5900. if (e["encoded"]) e["encoded"] = e["encoded"].toBase64();
  5901. throw(e);
  5902. }
  5903. };
  5904. /**
  5905. * Returns the message as a base64 encoded string. This is an alias for {@link ProtoBuf.Builder.Message#encode64}.
  5906. * @name ProtoBuf.Builder.Message#toBase64
  5907. * @function
  5908. * @return {string} Base64 encoded string
  5909. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  5910. * returns the encoded base64 string in the `encoded` property on the error.
  5911. * @expose
  5912. */
  5913. MessagePrototype.toBase64 = MessagePrototype.encode64;
  5914. /**
  5915. * Directly encodes the message to a hex encoded string.
  5916. * @name ProtoBuf.Builder.Message#encodeHex
  5917. * @function
  5918. * @return {string} Hex encoded string
  5919. * @throws {Error} If the underlying buffer cannot be encoded or if required fields are missing. The later
  5920. * still returns the encoded hex string in the `encoded` property on the error.
  5921. * @expose
  5922. */
  5923. MessagePrototype.encodeHex = function() {
  5924. try {
  5925. return this.encode().toHex();
  5926. } catch (e) {
  5927. if (e["encoded"]) e["encoded"] = e["encoded"].toHex();
  5928. throw(e);
  5929. }
  5930. };
  5931. /**
  5932. * Returns the message as a hex encoded string. This is an alias for {@link ProtoBuf.Builder.Message#encodeHex}.
  5933. * @name ProtoBuf.Builder.Message#toHex
  5934. * @function
  5935. * @return {string} Hex encoded string
  5936. * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
  5937. * returns the encoded hex string in the `encoded` property on the error.
  5938. * @expose
  5939. */
  5940. MessagePrototype.toHex = MessagePrototype.encodeHex;
  5941. /**
  5942. * Clones a message object to a raw object.
  5943. * @param {*} obj Object to clone
  5944. * @param {boolean} includeBinaryAsBase64 Whether to include binary data as base64 strings or not
  5945. * @returns {*} Cloned object
  5946. * @inner
  5947. */
  5948. function cloneRaw(obj, includeBinaryAsBase64) {
  5949. var clone = {};
  5950. for (var i in obj)
  5951. if (obj.hasOwnProperty(i)) {
  5952. if (obj[i] === null || typeof obj[i] !== 'object')
  5953. clone[i] = obj[i];
  5954. else if (obj[i] instanceof ByteBuffer) {
  5955. if (includeBinaryAsBase64)
  5956. clone[i] = obj[i].toBase64();
  5957. } else // is a non-null object
  5958. clone[i] = cloneRaw(obj[i], includeBinaryAsBase64);
  5959. }
  5960. return clone;
  5961. }
  5962. /**
  5963. * Returns the message's raw payload.
  5964. * @param {boolean=} includeBinaryAsBase64 Whether to include binary data as base64 strings or not, defaults to `false`
  5965. * @returns {Object.<string,*>} Raw payload
  5966. * @expose
  5967. */
  5968. MessagePrototype.toRaw = function(includeBinaryAsBase64) {
  5969. return cloneRaw(this, !!includeBinaryAsBase64);
  5970. };
  5971. /**
  5972. * Decodes a message from the specified buffer or string.
  5973. * @name ProtoBuf.Builder.Message.decode
  5974. * @function
  5975. * @param {!ByteBuffer|!ArrayBuffer|!Buffer|string} buffer Buffer to decode from
  5976. * @param {string=} enc Encoding if buffer is a string: hex, utf8 (not recommended), defaults to base64
  5977. * @return {!ProtoBuf.Builder.Message} Decoded message
  5978. * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
  5979. * returns the decoded message with missing fields in the `decoded` property on the error.
  5980. * @expose
  5981. * @see ProtoBuf.Builder.Message.decode64
  5982. * @see ProtoBuf.Builder.Message.decodeHex
  5983. */
  5984. Message.decode = function(buffer, enc) {
  5985. if (typeof buffer === 'string')
  5986. buffer = ByteBuffer.wrap(buffer, enc ? enc : "base64");
  5987. buffer = buffer instanceof ByteBuffer ? buffer : ByteBuffer.wrap(buffer); // May throw
  5988. var le = buffer.littleEndian;
  5989. try {
  5990. var msg = T.decode(buffer.LE());
  5991. buffer.LE(le);
  5992. return msg;
  5993. } catch (e) {
  5994. buffer.LE(le);
  5995. throw(e);
  5996. }
  5997. };
  5998. /**
  5999. * Decodes a varint32 length-delimited message from the specified buffer or string.
  6000. * @name ProtoBuf.Builder.Message.decodeDelimited
  6001. * @function
  6002. * @param {!ByteBuffer|!ArrayBuffer|!Buffer|string} buffer Buffer to decode from
  6003. * @param {string=} enc Encoding if buffer is a string: hex, utf8 (not recommended), defaults to base64
  6004. * @return {ProtoBuf.Builder.Message} Decoded message or `null` if not enough bytes are available yet
  6005. * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
  6006. * returns the decoded message with missing fields in the `decoded` property on the error.
  6007. * @expose
  6008. */
  6009. Message.decodeDelimited = function(buffer, enc) {
  6010. if (typeof buffer === 'string')
  6011. buffer = ByteBuffer.wrap(buffer, enc ? enc : "base64");
  6012. buffer = buffer instanceof ByteBuffer ? buffer : ByteBuffer.wrap(buffer); // May throw
  6013. if (buffer.remaining() < 1)
  6014. return null;
  6015. var off = buffer.offset,
  6016. len = buffer.readVarint32();
  6017. if (buffer.remaining() < len) {
  6018. buffer.offset = off;
  6019. return null;
  6020. }
  6021. try {
  6022. var msg = T.decode(buffer.slice(buffer.offset, buffer.offset + len).LE());
  6023. buffer.offset += len;
  6024. return msg;
  6025. } catch (err) {
  6026. buffer.offset += len;
  6027. throw err;
  6028. }
  6029. };
  6030. /**
  6031. * Decodes the message from the specified base64 encoded string.
  6032. * @name ProtoBuf.Builder.Message.decode64
  6033. * @function
  6034. * @param {string} str String to decode from
  6035. * @return {!ProtoBuf.Builder.Message} Decoded message
  6036. * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
  6037. * returns the decoded message with missing fields in the `decoded` property on the error.
  6038. * @expose
  6039. */
  6040. Message.decode64 = function(str) {
  6041. return Message.decode(str, "base64");
  6042. };
  6043. /**
  6044. * Decodes the message from the specified hex encoded string.
  6045. * @name ProtoBuf.Builder.Message.decodeHex
  6046. * @function
  6047. * @param {string} str String to decode from
  6048. * @return {!ProtoBuf.Builder.Message} Decoded message
  6049. * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
  6050. * returns the decoded message with missing fields in the `decoded` property on the error.
  6051. * @expose
  6052. */
  6053. Message.decodeHex = function(str) {
  6054. return Message.decode(str, "hex");
  6055. };
  6056. // Utility
  6057. /**
  6058. * Returns a string representation of this Message.
  6059. * @name ProtoBuf.Builder.Message#toString
  6060. * @function
  6061. * @return {string} String representation as of ".Fully.Qualified.MessageName"
  6062. * @expose
  6063. */
  6064. MessagePrototype.toString = function() {
  6065. return T.toString();
  6066. };
  6067. // Properties
  6068. /**
  6069. * Options.
  6070. * @name ProtoBuf.Builder.Message.$options
  6071. * @type {Object.<string,*>}
  6072. * @expose
  6073. */
  6074. var $options; // cc
  6075. /**
  6076. * Reflection type.
  6077. * @name ProtoBuf.Builder.Message#$type
  6078. * @type {!ProtoBuf.Reflect.Message}
  6079. * @expose
  6080. */
  6081. var $type; // cc
  6082. if (Object.defineProperty)
  6083. Object.defineProperty(Message, '$options', { "value": T.buildOpt() }),
  6084. Object.defineProperty(MessagePrototype, "$type", {
  6085. get: function() { return T; }
  6086. });
  6087. return Message;
  6088. })(ProtoBuf, this);
  6089. // Static enums and prototyped sub-messages / cached collections
  6090. this._fields = [];
  6091. this._fieldsById = {};
  6092. this._fieldsByName = {};
  6093. for (var i=0, k=this.children.length, child; i<k; i++) {
  6094. child = this.children[i];
  6095. if (child instanceof Enum)
  6096. clazz[child.name] = child.build();
  6097. else if (child instanceof Message)
  6098. clazz[child.name] = child.build();
  6099. else if (child instanceof Message.Field)
  6100. child.build(),
  6101. this._fields.push(child),
  6102. this._fieldsById[child.id] = child,
  6103. this._fieldsByName[child.name] = child;
  6104. else if (!(child instanceof Message.OneOf) && !(child instanceof Extension)) // Not built
  6105. throw Error("Illegal reflect child of "+this.toString(true)+": "+children[i].toString(true));
  6106. }
  6107. return this.clazz = clazz;
  6108. };
  6109. /**
  6110. * Encodes a runtime message's contents to the specified buffer.
  6111. * @param {!ProtoBuf.Builder.Message} message Runtime message to encode
  6112. * @param {ByteBuffer} buffer ByteBuffer to write to
  6113. * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
  6114. * @return {ByteBuffer} The ByteBuffer for chaining
  6115. * @throws {Error} If required fields are missing or the message cannot be encoded for another reason
  6116. * @expose
  6117. */
  6118. MessagePrototype.encode = function(message, buffer, noVerify) {
  6119. var fieldMissing = null,
  6120. field;
  6121. for (var i=0, k=this._fields.length, val; i<k; ++i) {
  6122. field = this._fields[i];
  6123. val = message[field.name];
  6124. if (field.required && val === null) {
  6125. if (fieldMissing === null)
  6126. fieldMissing = field;
  6127. } else
  6128. field.encode(noVerify ? val : field.verifyValue(val), buffer);
  6129. }
  6130. if (fieldMissing !== null) {
  6131. var err = Error("Missing at least one required field for "+this.toString(true)+": "+fieldMissing);
  6132. err["encoded"] = buffer; // Still expose what we got
  6133. throw(err);
  6134. }
  6135. return buffer;
  6136. };
  6137. /**
  6138. * Calculates a runtime message's byte length.
  6139. * @param {!ProtoBuf.Builder.Message} message Runtime message to encode
  6140. * @returns {number} Byte length
  6141. * @throws {Error} If required fields are missing or the message cannot be calculated for another reason
  6142. * @expose
  6143. */
  6144. MessagePrototype.calculate = function(message) {
  6145. for (var n=0, i=0, k=this._fields.length, field, val; i<k; ++i) {
  6146. field = this._fields[i];
  6147. val = message[field.name];
  6148. if (field.required && val === null)
  6149. throw Error("Missing at least one required field for "+this.toString(true)+": "+field);
  6150. else
  6151. n += field.calculate(val);
  6152. }
  6153. return n;
  6154. };
  6155. /**
  6156. * Skips all data until the end of the specified group has been reached.
  6157. * @param {number} expectedId Expected GROUPEND id
  6158. * @param {!ByteBuffer} buf ByteBuffer
  6159. * @returns {boolean} `true` if a value as been skipped, `false` if the end has been reached
  6160. * @throws {Error} If it wasn't possible to find the end of the group (buffer overrun or end tag mismatch)
  6161. * @inner
  6162. */
  6163. function skipTillGroupEnd(expectedId, buf) {
  6164. var tag = buf.readVarint32(), // Throws on OOB
  6165. wireType = tag & 0x07,
  6166. id = tag >> 3;
  6167. switch (wireType) {
  6168. case ProtoBuf.WIRE_TYPES.VARINT:
  6169. do tag = buf.readUint8();
  6170. while ((tag & 0x80) === 0x80);
  6171. break;
  6172. case ProtoBuf.WIRE_TYPES.BITS64:
  6173. buf.offset += 8;
  6174. break;
  6175. case ProtoBuf.WIRE_TYPES.LDELIM:
  6176. tag = buf.readVarint32(); // reads the varint
  6177. buf.offset += tag; // skips n bytes
  6178. break;
  6179. case ProtoBuf.WIRE_TYPES.STARTGROUP:
  6180. skipTillGroupEnd(id, buf);
  6181. break;
  6182. case ProtoBuf.WIRE_TYPES.ENDGROUP:
  6183. if (id === expectedId)
  6184. return false;
  6185. else
  6186. throw Error("Illegal GROUPEND after unknown group: "+id+" ("+expectedId+" expected)");
  6187. case ProtoBuf.WIRE_TYPES.BITS32:
  6188. buf.offset += 4;
  6189. break;
  6190. default:
  6191. throw Error("Illegal wire type in unknown group "+expectedId+": "+wireType);
  6192. }
  6193. return true;
  6194. }
  6195. /**
  6196. * Decodes an encoded message and returns the decoded message.
  6197. * @param {ByteBuffer} buffer ByteBuffer to decode from
  6198. * @param {number=} length Message length. Defaults to decode all the available data.
  6199. * @param {number=} expectedGroupEndId Expected GROUPEND id if this is a legacy group
  6200. * @return {ProtoBuf.Builder.Message} Decoded message
  6201. * @throws {Error} If the message cannot be decoded
  6202. * @expose
  6203. */
  6204. MessagePrototype.decode = function(buffer, length, expectedGroupEndId) {
  6205. length = typeof length === 'number' ? length : -1;
  6206. var start = buffer.offset,
  6207. msg = new (this.clazz)(),
  6208. tag, wireType, id, field;
  6209. while (buffer.offset < start+length || (length === -1 && buffer.remaining() > 0)) {
  6210. tag = buffer.readVarint32();
  6211. wireType = tag & 0x07;
  6212. id = tag >> 3;
  6213. if (wireType === ProtoBuf.WIRE_TYPES.ENDGROUP) {
  6214. if (id !== expectedGroupEndId)
  6215. throw Error("Illegal group end indicator for "+this.toString(true)+": "+id+" ("+(expectedGroupEndId ? expectedGroupEndId+" expected" : "not a group")+")");
  6216. break;
  6217. }
  6218. if (!(field = this._fieldsById[id])) {
  6219. // "messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing."
  6220. switch (wireType) {
  6221. case ProtoBuf.WIRE_TYPES.VARINT:
  6222. buffer.readVarint32();
  6223. break;
  6224. case ProtoBuf.WIRE_TYPES.BITS32:
  6225. buffer.offset += 4;
  6226. break;
  6227. case ProtoBuf.WIRE_TYPES.BITS64:
  6228. buffer.offset += 8;
  6229. break;
  6230. case ProtoBuf.WIRE_TYPES.LDELIM:
  6231. var len = buffer.readVarint32();
  6232. buffer.offset += len;
  6233. break;
  6234. case ProtoBuf.WIRE_TYPES.STARTGROUP:
  6235. while (skipTillGroupEnd(id, buffer)) {}
  6236. break;
  6237. default:
  6238. throw Error("Illegal wire type for unknown field "+id+" in "+this.toString(true)+"#decode: "+wireType);
  6239. }
  6240. continue;
  6241. }
  6242. if (field.repeated && !field.options["packed"])
  6243. msg[field.name].push(field.decode(wireType, buffer));
  6244. else {
  6245. msg[field.name] = field.decode(wireType, buffer);
  6246. if (field.oneof) {
  6247. if (this[field.oneof.name] !== null)
  6248. this[this[field.oneof.name]] = null;
  6249. msg[field.oneof.name] = field.name;
  6250. }
  6251. }
  6252. }
  6253. // Check if all required fields are present and set default values for optional fields that are not
  6254. for (var i=0, k=this._fields.length; i<k; ++i) {
  6255. field = this._fields[i];
  6256. if (msg[field.name] === null)
  6257. if (field.required) {
  6258. var err = Error("Missing at least one required field for "+this.toString(true)+": "+field.name);
  6259. err["decoded"] = msg; // Still expose what we got
  6260. throw(err);
  6261. } else if (field.defaultValue !== null)
  6262. msg[field.name] = field.defaultValue;
  6263. }
  6264. return msg;
  6265. };
  6266. /**
  6267. * @alias ProtoBuf.Reflect.Message
  6268. * @expose
  6269. */
  6270. Reflect.Message = Message;
  6271. /**
  6272. * Constructs a new Message Field.
  6273. * @exports ProtoBuf.Reflect.Message.Field
  6274. * @param {!ProtoBuf.Builder} builder Builder reference
  6275. * @param {!ProtoBuf.Reflect.Message} message Message reference
  6276. * @param {string} rule Rule, one of requried, optional, repeated
  6277. * @param {string} type Data type, e.g. int32
  6278. * @param {string} name Field name
  6279. * @param {number} id Unique field id
  6280. * @param {Object.<string,*>=} options Options
  6281. * @param {!ProtoBuf.Reflect.Message.OneOf=} oneof Enclosing OneOf
  6282. * @constructor
  6283. * @extends ProtoBuf.Reflect.T
  6284. */
  6285. var Field = function(builder, message, rule, type, name, id, options, oneof) {
  6286. T.call(this, builder, message, name);
  6287. /**
  6288. * @override
  6289. */
  6290. this.className = "Message.Field";
  6291. /**
  6292. * Message field required flag.
  6293. * @type {boolean}
  6294. * @expose
  6295. */
  6296. this.required = rule === "required";
  6297. /**
  6298. * Message field repeated flag.
  6299. * @type {boolean}
  6300. * @expose
  6301. */
  6302. this.repeated = rule === "repeated";
  6303. /**
  6304. * Message field type. Type reference string if unresolved, protobuf type if resolved.
  6305. * @type {string|{name: string, wireType: number}}
  6306. * @expose
  6307. */
  6308. this.type = type;
  6309. /**
  6310. * Resolved type reference inside the global namespace.
  6311. * @type {ProtoBuf.Reflect.T|null}
  6312. * @expose
  6313. */
  6314. this.resolvedType = null;
  6315. /**
  6316. * Unique message field id.
  6317. * @type {number}
  6318. * @expose
  6319. */
  6320. this.id = id;
  6321. /**
  6322. * Message field options.
  6323. * @type {!Object.<string,*>}
  6324. * @dict
  6325. * @expose
  6326. */
  6327. this.options = options || {};
  6328. /**
  6329. * Default value.
  6330. * @type {*}
  6331. * @expose
  6332. */
  6333. this.defaultValue = null;
  6334. /**
  6335. * Enclosing OneOf.
  6336. * @type {?ProtoBuf.Reflect.Message.OneOf}
  6337. * @expose
  6338. */
  6339. this.oneof = oneof || null;
  6340. /**
  6341. * Original field name.
  6342. * @type {string}
  6343. * @expose
  6344. */
  6345. this.originalName = this.name; // Used to revert camelcase transformation on naming collisions
  6346. // Convert field names to camel case notation if the override is set
  6347. if (this.builder.options['convertFieldsToCamelCase'] && !(this instanceof Message.ExtensionField))
  6348. this.name = Field._toCamelCase(this.name);
  6349. };
  6350. /**
  6351. * Converts a field name to camel case.
  6352. * @param {string} name Likely underscore notated name
  6353. * @returns {string} Camel case notated name
  6354. * @private
  6355. */
  6356. Field._toCamelCase = function(name) {
  6357. return name.replace(/_([a-zA-Z])/g, function($0, $1) {
  6358. return $1.toUpperCase();
  6359. });
  6360. };
  6361. /**
  6362. * @alias ProtoBuf.Reflect.Message.Field.prototype
  6363. * @inner
  6364. */
  6365. var FieldPrototype = Field.prototype = Object.create(T.prototype);
  6366. /**
  6367. * Builds the field.
  6368. * @override
  6369. * @expose
  6370. */
  6371. FieldPrototype.build = function() {
  6372. this.defaultValue = typeof this.options['default'] !== 'undefined'
  6373. ? this.verifyValue(this.options['default']) : null;
  6374. };
  6375. /**
  6376. * Makes a Long from a value.
  6377. * @param {{low: number, high: number, unsigned: boolean}|string|number} value Value
  6378. * @param {boolean=} unsigned Whether unsigned or not, defaults to reuse it from Long-like objects or to signed for
  6379. * strings and numbers
  6380. * @returns {!Long}
  6381. * @throws {Error} If the value cannot be converted to a Long
  6382. * @inner
  6383. */
  6384. function mkLong(value, unsigned) {
  6385. if (value && typeof value.low === 'number' && typeof value.high === 'number' && typeof value.unsigned === 'boolean'
  6386. && value.low === value.low && value.high === value.high)
  6387. return new ProtoBuf.Long(value.low, value.high, typeof unsigned === 'undefined' ? value.unsigned : unsigned);
  6388. if (typeof value === 'string')
  6389. return ProtoBuf.Long.fromString(value, unsigned || false, 10);
  6390. if (typeof value === 'number')
  6391. return ProtoBuf.Long.fromNumber(value, unsigned || false);
  6392. throw Error("not convertible to Long");
  6393. }
  6394. /**
  6395. * Checks if the given value can be set for this field.
  6396. * @param {*} value Value to check
  6397. * @param {boolean=} skipRepeated Whether to skip the repeated value check or not. Defaults to false.
  6398. * @return {*} Verified, maybe adjusted, value
  6399. * @throws {Error} If the value cannot be set for this field
  6400. * @expose
  6401. */
  6402. FieldPrototype.verifyValue = function(value, skipRepeated) {
  6403. skipRepeated = skipRepeated || false;
  6404. var fail = function(val, msg) {
  6405. throw Error("Illegal value for "+this.toString(true)+" of type "+this.type.name+": "+val+" ("+msg+")");
  6406. }.bind(this);
  6407. if (value === null) { // NULL values for optional fields
  6408. if (this.required)
  6409. fail(typeof value, "required");
  6410. return null;
  6411. }
  6412. var i;
  6413. if (this.repeated && !skipRepeated) { // Repeated values as arrays
  6414. if (!ProtoBuf.Util.isArray(value))
  6415. value = [value];
  6416. var res = [];
  6417. for (i=0; i<value.length; i++)
  6418. res.push(this.verifyValue(value[i], true));
  6419. return res;
  6420. }
  6421. // All non-repeated fields expect no array
  6422. if (!this.repeated && ProtoBuf.Util.isArray(value))
  6423. fail(typeof value, "no array expected");
  6424. switch (this.type) {
  6425. // Signed 32bit
  6426. case ProtoBuf.TYPES["int32"]:
  6427. case ProtoBuf.TYPES["sint32"]:
  6428. case ProtoBuf.TYPES["sfixed32"]:
  6429. // Account for !NaN: value === value
  6430. if (typeof value !== 'number' || (value === value && value % 1 !== 0))
  6431. fail(typeof value, "not an integer");
  6432. return value > 4294967295 ? value | 0 : value;
  6433. // Unsigned 32bit
  6434. case ProtoBuf.TYPES["uint32"]:
  6435. case ProtoBuf.TYPES["fixed32"]:
  6436. if (typeof value !== 'number' || (value === value && value % 1 !== 0))
  6437. fail(typeof value, "not an integer");
  6438. return value < 0 ? value >>> 0 : value;
  6439. // Signed 64bit
  6440. case ProtoBuf.TYPES["int64"]:
  6441. case ProtoBuf.TYPES["sint64"]:
  6442. case ProtoBuf.TYPES["sfixed64"]: {
  6443. if (ProtoBuf.Long)
  6444. try {
  6445. return mkLong(value, false);
  6446. } catch (e) {
  6447. fail(typeof value, e.message);
  6448. }
  6449. else
  6450. fail(typeof value, "requires Long.js");
  6451. }
  6452. // Unsigned 64bit
  6453. case ProtoBuf.TYPES["uint64"]:
  6454. case ProtoBuf.TYPES["fixed64"]: {
  6455. if (ProtoBuf.Long)
  6456. try {
  6457. return mkLong(value, true);
  6458. } catch (e) {
  6459. fail(typeof value, e.message);
  6460. }
  6461. else
  6462. fail(typeof value, "requires Long.js");
  6463. }
  6464. // Bool
  6465. case ProtoBuf.TYPES["bool"]:
  6466. if (typeof value !== 'boolean')
  6467. fail(typeof value, "not a boolean");
  6468. return value;
  6469. // Float
  6470. case ProtoBuf.TYPES["float"]:
  6471. case ProtoBuf.TYPES["double"]:
  6472. if (typeof value !== 'number')
  6473. fail(typeof value, "not a number");
  6474. return value;
  6475. // Length-delimited string
  6476. case ProtoBuf.TYPES["string"]:
  6477. if (typeof value !== 'string' && !(value && value instanceof String))
  6478. fail(typeof value, "not a string");
  6479. return ""+value; // Convert String object to string
  6480. // Length-delimited bytes
  6481. case ProtoBuf.TYPES["bytes"]:
  6482. if (ByteBuffer.isByteBuffer(value))
  6483. return value;
  6484. return ByteBuffer.wrap(value, "base64");
  6485. // Constant enum value
  6486. case ProtoBuf.TYPES["enum"]: {
  6487. var values = this.resolvedType.getChildren(Enum.Value);
  6488. for (i=0; i<values.length; i++)
  6489. if (values[i].name == value)
  6490. return values[i].id;
  6491. else if (values[i].id == value)
  6492. return values[i].id;
  6493. fail(value, "not a valid enum value");
  6494. }
  6495. // Embedded message
  6496. case ProtoBuf.TYPES["group"]:
  6497. case ProtoBuf.TYPES["message"]: {
  6498. if (!value || typeof value !== 'object')
  6499. fail(typeof value, "object expected");
  6500. if (value instanceof this.resolvedType.clazz)
  6501. return value;
  6502. if (value instanceof ProtoBuf.Builder.Message) {
  6503. // Mismatched type: Convert to object (see: https://github.com/dcodeIO/ProtoBuf.js/issues/180)
  6504. var obj = {};
  6505. for (var i in value)
  6506. if (value.hasOwnProperty(i))
  6507. obj[i] = value[i];
  6508. value = obj;
  6509. }
  6510. // Else let's try to construct one from a key-value object
  6511. return new (this.resolvedType.clazz)(value); // May throw for a hundred of reasons
  6512. }
  6513. }
  6514. // We should never end here
  6515. throw Error("[INTERNAL] Illegal value for "+this.toString(true)+": "+value+" (undefined type "+this.type+")");
  6516. };
  6517. /**
  6518. * Encodes the specified field value to the specified buffer.
  6519. * @param {*} value Verified field value
  6520. * @param {ByteBuffer} buffer ByteBuffer to encode to
  6521. * @return {ByteBuffer} The ByteBuffer for chaining
  6522. * @throws {Error} If the field cannot be encoded
  6523. * @expose
  6524. */
  6525. FieldPrototype.encode = function(value, buffer) {
  6526. if (this.type === null || typeof this.type !== 'object')
  6527. throw Error("[INTERNAL] Unresolved type in "+this.toString(true)+": "+this.type);
  6528. if (value === null || (this.repeated && value.length == 0))
  6529. return buffer; // Optional omitted
  6530. try {
  6531. if (this.repeated) {
  6532. var i;
  6533. // "Only repeated fields of primitive numeric types (types which use the varint, 32-bit, or 64-bit wire
  6534. // types) can be declared 'packed'."
  6535. if (this.options["packed"] && ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
  6536. // "All of the elements of the field are packed into a single key-value pair with wire type 2
  6537. // (length-delimited). Each element is encoded the same way it would be normally, except without a
  6538. // tag preceding it."
  6539. buffer.writeVarint32((this.id << 3) | ProtoBuf.WIRE_TYPES.LDELIM);
  6540. buffer.ensureCapacity(buffer.offset += 1); // We do not know the length yet, so let's assume a varint of length 1
  6541. var start = buffer.offset; // Remember where the contents begin
  6542. for (i=0; i<value.length; i++)
  6543. this.encodeValue(value[i], buffer);
  6544. var len = buffer.offset-start,
  6545. varintLen = ByteBuffer.calculateVarint32(len);
  6546. if (varintLen > 1) { // We need to move the contents
  6547. var contents = buffer.slice(start, buffer.offset);
  6548. start += varintLen-1;
  6549. buffer.offset = start;
  6550. buffer.append(contents);
  6551. }
  6552. buffer.writeVarint32(len, start-varintLen);
  6553. } else {
  6554. // "If your message definition has repeated elements (without the [packed=true] option), the encoded
  6555. // message has zero or more key-value pairs with the same tag number"
  6556. for (i=0; i<value.length; i++)
  6557. buffer.writeVarint32((this.id << 3) | this.type.wireType),
  6558. this.encodeValue(value[i], buffer);
  6559. }
  6560. } else
  6561. buffer.writeVarint32((this.id << 3) | this.type.wireType),
  6562. this.encodeValue(value, buffer);
  6563. } catch (e) {
  6564. throw Error("Illegal value for "+this.toString(true)+": "+value+" ("+e+")");
  6565. }
  6566. return buffer;
  6567. };
  6568. /**
  6569. * Encodes a value to the specified buffer. Does not encode the key.
  6570. * @param {*} value Field value
  6571. * @param {ByteBuffer} buffer ByteBuffer to encode to
  6572. * @return {ByteBuffer} The ByteBuffer for chaining
  6573. * @throws {Error} If the value cannot be encoded
  6574. * @expose
  6575. */
  6576. FieldPrototype.encodeValue = function(value, buffer) {
  6577. if (value === null) return buffer; // Nothing to encode
  6578. // Tag has already been written
  6579. switch (this.type) {
  6580. // 32bit signed varint
  6581. case ProtoBuf.TYPES["int32"]:
  6582. // "If you use int32 or int64 as the type for a negative number, the resulting varint is always ten bytes
  6583. // long – it is, effectively, treated like a very large unsigned integer." (see #122)
  6584. if (value < 0)
  6585. buffer.writeVarint64(value);
  6586. else
  6587. buffer.writeVarint32(value);
  6588. break;
  6589. // 32bit unsigned varint
  6590. case ProtoBuf.TYPES["uint32"]:
  6591. buffer.writeVarint32(value);
  6592. break;
  6593. // 32bit varint zig-zag
  6594. case ProtoBuf.TYPES["sint32"]:
  6595. buffer.writeVarint32ZigZag(value);
  6596. break;
  6597. // Fixed unsigned 32bit
  6598. case ProtoBuf.TYPES["fixed32"]:
  6599. buffer.writeUint32(value);
  6600. break;
  6601. // Fixed signed 32bit
  6602. case ProtoBuf.TYPES["sfixed32"]:
  6603. buffer.writeInt32(value);
  6604. break;
  6605. // 64bit varint as-is
  6606. case ProtoBuf.TYPES["int64"]:
  6607. case ProtoBuf.TYPES["uint64"]:
  6608. buffer.writeVarint64(value); // throws
  6609. break;
  6610. // 64bit varint zig-zag
  6611. case ProtoBuf.TYPES["sint64"]:
  6612. buffer.writeVarint64ZigZag(value); // throws
  6613. break;
  6614. // Fixed unsigned 64bit
  6615. case ProtoBuf.TYPES["fixed64"]:
  6616. buffer.writeUint64(value); // throws
  6617. break;
  6618. // Fixed signed 64bit
  6619. case ProtoBuf.TYPES["sfixed64"]:
  6620. buffer.writeInt64(value); // throws
  6621. break;
  6622. // Bool
  6623. case ProtoBuf.TYPES["bool"]:
  6624. if (typeof value === 'string')
  6625. buffer.writeVarint32(value.toLowerCase() === 'false' ? 0 : !!value);
  6626. else
  6627. buffer.writeVarint32(value ? 1 : 0);
  6628. break;
  6629. // Constant enum value
  6630. case ProtoBuf.TYPES["enum"]:
  6631. buffer.writeVarint32(value);
  6632. break;
  6633. // 32bit float
  6634. case ProtoBuf.TYPES["float"]:
  6635. buffer.writeFloat32(value);
  6636. break;
  6637. // 64bit float
  6638. case ProtoBuf.TYPES["double"]:
  6639. buffer.writeFloat64(value);
  6640. break;
  6641. // Length-delimited string
  6642. case ProtoBuf.TYPES["string"]:
  6643. buffer.writeVString(value);
  6644. break;
  6645. // Length-delimited bytes
  6646. case ProtoBuf.TYPES["bytes"]:
  6647. if (value.remaining() < 0)
  6648. throw Error("Illegal value for "+this.toString(true)+": "+value.remaining()+" bytes remaining");
  6649. var prevOffset = value.offset;
  6650. buffer.writeVarint32(value.remaining());
  6651. buffer.append(value);
  6652. value.offset = prevOffset;
  6653. break;
  6654. // Embedded message
  6655. case ProtoBuf.TYPES["message"]:
  6656. var bb = new ByteBuffer().LE();
  6657. this.resolvedType.encode(value, bb);
  6658. buffer.writeVarint32(bb.offset);
  6659. buffer.append(bb.flip());
  6660. break;
  6661. // Legacy group
  6662. case ProtoBuf.TYPES["group"]:
  6663. this.resolvedType.encode(value, buffer);
  6664. buffer.writeVarint32((this.id << 3) | ProtoBuf.WIRE_TYPES.ENDGROUP);
  6665. break;
  6666. default:
  6667. // We should never end here
  6668. throw Error("[INTERNAL] Illegal value to encode in "+this.toString(true)+": "+value+" (unknown type)");
  6669. }
  6670. return buffer;
  6671. };
  6672. /**
  6673. * Calculates the length of this field's value on the network level.
  6674. * @param {*} value Field value
  6675. * @returns {number} Byte length
  6676. * @expose
  6677. */
  6678. FieldPrototype.calculate = function(value) {
  6679. value = this.verifyValue(value); // May throw
  6680. if (this.type === null || typeof this.type !== 'object')
  6681. throw Error("[INTERNAL] Unresolved type in "+this.toString(true)+": "+this.type);
  6682. if (value === null || (this.repeated && value.length == 0))
  6683. return 0; // Optional omitted
  6684. var n = 0;
  6685. try {
  6686. if (this.repeated) {
  6687. var i, ni;
  6688. if (this.options["packed"] && ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
  6689. n += ByteBuffer.calculateVarint32((this.id << 3) | ProtoBuf.WIRE_TYPES.LDELIM);
  6690. ni = 0;
  6691. for (i=0; i<value.length; i++)
  6692. ni += this.calculateValue(value[i]);
  6693. n += ByteBuffer.calculateVarint32(ni);
  6694. n += ni;
  6695. } else {
  6696. for (i=0; i<value.length; i++)
  6697. n += ByteBuffer.calculateVarint32((this.id << 3) | this.type.wireType),
  6698. n += this.calculateValue(value[i]);
  6699. }
  6700. } else {
  6701. n += ByteBuffer.calculateVarint32((this.id << 3) | this.type.wireType);
  6702. n += this.calculateValue(value);
  6703. }
  6704. } catch (e) {
  6705. throw Error("Illegal value for "+this.toString(true)+": "+value+" ("+e+")");
  6706. }
  6707. return n;
  6708. };
  6709. /**
  6710. * Calculates the byte length of a value.
  6711. * @param {*} value Field value
  6712. * @returns {number} Byte length
  6713. * @throws {Error} If the value cannot be calculated
  6714. * @expose
  6715. */
  6716. FieldPrototype.calculateValue = function(value) {
  6717. if (value === null) return 0; // Nothing to encode
  6718. // Tag has already been written
  6719. var n;
  6720. switch (this.type) {
  6721. case ProtoBuf.TYPES["int32"]:
  6722. return value < 0 ? ByteBuffer.calculateVarint64(value) : ByteBuffer.calculateVarint32(value);
  6723. case ProtoBuf.TYPES["uint32"]:
  6724. return ByteBuffer.calculateVarint32(value);
  6725. case ProtoBuf.TYPES["sint32"]:
  6726. return ByteBuffer.calculateVarint32(ByteBuffer.zigZagEncode32(value));
  6727. case ProtoBuf.TYPES["fixed32"]:
  6728. case ProtoBuf.TYPES["sfixed32"]:
  6729. case ProtoBuf.TYPES["float"]:
  6730. return 4;
  6731. case ProtoBuf.TYPES["int64"]:
  6732. case ProtoBuf.TYPES["uint64"]:
  6733. return ByteBuffer.calculateVarint64(value);
  6734. case ProtoBuf.TYPES["sint64"]:
  6735. return ByteBuffer.calculateVarint64(ByteBuffer.zigZagEncode64(value));
  6736. case ProtoBuf.TYPES["fixed64"]:
  6737. case ProtoBuf.TYPES["sfixed64"]:
  6738. return 8;
  6739. case ProtoBuf.TYPES["bool"]:
  6740. return 1;
  6741. case ProtoBuf.TYPES["enum"]:
  6742. return ByteBuffer.calculateVarint32(value);
  6743. case ProtoBuf.TYPES["double"]:
  6744. return 8;
  6745. case ProtoBuf.TYPES["string"]:
  6746. n = ByteBuffer.calculateUTF8Bytes(value);
  6747. return ByteBuffer.calculateVarint32(n) + n;
  6748. case ProtoBuf.TYPES["bytes"]:
  6749. if (value.remaining() < 0)
  6750. throw Error("Illegal value for "+this.toString(true)+": "+value.remaining()+" bytes remaining");
  6751. return ByteBuffer.calculateVarint32(value.remaining()) + value.remaining();
  6752. case ProtoBuf.TYPES["message"]:
  6753. n = this.resolvedType.calculate(value);
  6754. return ByteBuffer.calculateVarint32(n) + n;
  6755. case ProtoBuf.TYPES["group"]:
  6756. n = this.resolvedType.calculate(value);
  6757. return n + ByteBuffer.calculateVarint32((this.id << 3) | ProtoBuf.WIRE_TYPES.ENDGROUP);
  6758. }
  6759. // We should never end here
  6760. throw Error("[INTERNAL] Illegal value to encode in "+this.toString(true)+": "+value+" (unknown type)");
  6761. };
  6762. /**
  6763. * Decode the field value from the specified buffer.
  6764. * @param {number} wireType Leading wire type
  6765. * @param {ByteBuffer} buffer ByteBuffer to decode from
  6766. * @param {boolean=} skipRepeated Whether to skip the repeated check or not. Defaults to false.
  6767. * @return {*} Decoded value
  6768. * @throws {Error} If the field cannot be decoded
  6769. * @expose
  6770. */
  6771. FieldPrototype.decode = function(wireType, buffer, skipRepeated) {
  6772. var value, nBytes;
  6773. if (wireType != this.type.wireType && (skipRepeated || (wireType != ProtoBuf.WIRE_TYPES.LDELIM || !this.repeated)))
  6774. throw Error("Illegal wire type for field "+this.toString(true)+": "+wireType+" ("+this.type.wireType+" expected)");
  6775. if (wireType == ProtoBuf.WIRE_TYPES.LDELIM && this.repeated && this.options["packed"] && ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
  6776. if (!skipRepeated) {
  6777. nBytes = buffer.readVarint32();
  6778. nBytes = buffer.offset + nBytes; // Limit
  6779. var values = [];
  6780. while (buffer.offset < nBytes)
  6781. values.push(this.decode(this.type.wireType, buffer, true));
  6782. return values;
  6783. }
  6784. // Read the next value otherwise...
  6785. }
  6786. switch (this.type) {
  6787. // 32bit signed varint
  6788. case ProtoBuf.TYPES["int32"]:
  6789. return buffer.readVarint32() | 0;
  6790. // 32bit unsigned varint
  6791. case ProtoBuf.TYPES["uint32"]:
  6792. return buffer.readVarint32() >>> 0;
  6793. // 32bit signed varint zig-zag
  6794. case ProtoBuf.TYPES["sint32"]:
  6795. return buffer.readVarint32ZigZag() | 0;
  6796. // Fixed 32bit unsigned
  6797. case ProtoBuf.TYPES["fixed32"]:
  6798. return buffer.readUint32() >>> 0;
  6799. case ProtoBuf.TYPES["sfixed32"]:
  6800. return buffer.readInt32() | 0;
  6801. // 64bit signed varint
  6802. case ProtoBuf.TYPES["int64"]:
  6803. return buffer.readVarint64();
  6804. // 64bit unsigned varint
  6805. case ProtoBuf.TYPES["uint64"]:
  6806. return buffer.readVarint64().toUnsigned();
  6807. // 64bit signed varint zig-zag
  6808. case ProtoBuf.TYPES["sint64"]:
  6809. return buffer.readVarint64ZigZag();
  6810. // Fixed 64bit unsigned
  6811. case ProtoBuf.TYPES["fixed64"]:
  6812. return buffer.readUint64();
  6813. // Fixed 64bit signed
  6814. case ProtoBuf.TYPES["sfixed64"]:
  6815. return buffer.readInt64();
  6816. // Bool varint
  6817. case ProtoBuf.TYPES["bool"]:
  6818. return !!buffer.readVarint32();
  6819. // Constant enum value (varint)
  6820. case ProtoBuf.TYPES["enum"]:
  6821. // The following Builder.Message#set will already throw
  6822. return buffer.readVarint32();
  6823. // 32bit float
  6824. case ProtoBuf.TYPES["float"]:
  6825. return buffer.readFloat();
  6826. // 64bit float
  6827. case ProtoBuf.TYPES["double"]:
  6828. return buffer.readDouble();
  6829. // Length-delimited string
  6830. case ProtoBuf.TYPES["string"]:
  6831. return buffer.readVString();
  6832. // Length-delimited bytes
  6833. case ProtoBuf.TYPES["bytes"]: {
  6834. nBytes = buffer.readVarint32();
  6835. if (buffer.remaining() < nBytes)
  6836. throw Error("Illegal number of bytes for "+this.toString(true)+": "+nBytes+" required but got only "+buffer.remaining());
  6837. value = buffer.clone(); // Offset already set
  6838. value.limit = value.offset+nBytes;
  6839. buffer.offset += nBytes;
  6840. return value;
  6841. }
  6842. // Length-delimited embedded message
  6843. case ProtoBuf.TYPES["message"]: {
  6844. nBytes = buffer.readVarint32();
  6845. return this.resolvedType.decode(buffer, nBytes);
  6846. }
  6847. // Legacy group
  6848. case ProtoBuf.TYPES["group"]:
  6849. return this.resolvedType.decode(buffer, -1, this.id);
  6850. }
  6851. // We should never end here
  6852. throw Error("[INTERNAL] Illegal wire type for "+this.toString(true)+": "+wireType);
  6853. };
  6854. /**
  6855. * @alias ProtoBuf.Reflect.Message.Field
  6856. * @expose
  6857. */
  6858. Reflect.Message.Field = Field;
  6859. /**
  6860. * Constructs a new Message ExtensionField.
  6861. * @exports ProtoBuf.Reflect.Message.ExtensionField
  6862. * @param {!ProtoBuf.Builder} builder Builder reference
  6863. * @param {!ProtoBuf.Reflect.Message} message Message reference
  6864. * @param {string} rule Rule, one of requried, optional, repeated
  6865. * @param {string} type Data type, e.g. int32
  6866. * @param {string} name Field name
  6867. * @param {number} id Unique field id
  6868. * @param {Object.<string,*>=} options Options
  6869. * @constructor
  6870. * @extends ProtoBuf.Reflect.Message.Field
  6871. */
  6872. var ExtensionField = function(builder, message, rule, type, name, id, options) {
  6873. Field.call(this, builder, message, rule, type, name, id, options);
  6874. /**
  6875. * Extension reference.
  6876. * @type {!ProtoBuf.Reflect.Extension}
  6877. * @expose
  6878. */
  6879. this.extension;
  6880. };
  6881. // Extends Field
  6882. ExtensionField.prototype = Object.create(Field.prototype);
  6883. /**
  6884. * @alias ProtoBuf.Reflect.Message.ExtensionField
  6885. * @expose
  6886. */
  6887. Reflect.Message.ExtensionField = ExtensionField;
  6888. /**
  6889. * Constructs a new Message OneOf.
  6890. * @exports ProtoBuf.Reflect.Message.OneOf
  6891. * @param {!ProtoBuf.Builder} builder Builder reference
  6892. * @param {!ProtoBuf.Reflect.Message} message Message reference
  6893. * @param {string} name OneOf name
  6894. * @constructor
  6895. * @extends ProtoBuf.Reflect.T
  6896. */
  6897. var OneOf = function(builder, message, name) {
  6898. T.call(this, builder, message, name);
  6899. /**
  6900. * Enclosed fields.
  6901. * @type {!Array.<!ProtoBuf.Reflect.Message.Field>}
  6902. * @expose
  6903. */
  6904. this.fields = [];
  6905. };
  6906. /**
  6907. * @alias ProtoBuf.Reflect.Message.OneOf
  6908. * @expose
  6909. */
  6910. Reflect.Message.OneOf = OneOf;
  6911. /**
  6912. * Constructs a new Enum.
  6913. * @exports ProtoBuf.Reflect.Enum
  6914. * @param {!ProtoBuf.Builder} builder Builder reference
  6915. * @param {!ProtoBuf.Reflect.T} parent Parent Reflect object
  6916. * @param {string} name Enum name
  6917. * @param {Object.<string,*>=} options Enum options
  6918. * @constructor
  6919. * @extends ProtoBuf.Reflect.Namespace
  6920. */
  6921. var Enum = function(builder, parent, name, options) {
  6922. Namespace.call(this, builder, parent, name, options);
  6923. /**
  6924. * @override
  6925. */
  6926. this.className = "Enum";
  6927. /**
  6928. * Runtime enum object.
  6929. * @type {Object.<string,number>|null}
  6930. * @expose
  6931. */
  6932. this.object = null;
  6933. };
  6934. /**
  6935. * @alias ProtoBuf.Reflect.Enum.prototype
  6936. * @inner
  6937. */
  6938. var EnumPrototype = Enum.prototype = Object.create(Namespace.prototype);
  6939. /**
  6940. * Builds this enum and returns the runtime counterpart.
  6941. * @return {Object<string,*>}
  6942. * @expose
  6943. */
  6944. EnumPrototype.build = function() {
  6945. var enm = {},
  6946. values = this.getChildren(Enum.Value);
  6947. for (var i=0, k=values.length; i<k; ++i)
  6948. enm[values[i]['name']] = values[i]['id'];
  6949. if (Object.defineProperty)
  6950. Object.defineProperty(enm, '$options', { "value": this.buildOpt() });
  6951. return this.object = enm;
  6952. };
  6953. /**
  6954. * @alias ProtoBuf.Reflect.Enum
  6955. * @expose
  6956. */
  6957. Reflect.Enum = Enum;
  6958. /**
  6959. * Constructs a new Enum Value.
  6960. * @exports ProtoBuf.Reflect.Enum.Value
  6961. * @param {!ProtoBuf.Builder} builder Builder reference
  6962. * @param {!ProtoBuf.Reflect.Enum} enm Enum reference
  6963. * @param {string} name Field name
  6964. * @param {number} id Unique field id
  6965. * @constructor
  6966. * @extends ProtoBuf.Reflect.T
  6967. */
  6968. var Value = function(builder, enm, name, id) {
  6969. T.call(this, builder, enm, name);
  6970. /**
  6971. * @override
  6972. */
  6973. this.className = "Enum.Value";
  6974. /**
  6975. * Unique enum value id.
  6976. * @type {number}
  6977. * @expose
  6978. */
  6979. this.id = id;
  6980. };
  6981. // Extends T
  6982. Value.prototype = Object.create(T.prototype);
  6983. /**
  6984. * @alias ProtoBuf.Reflect.Enum.Value
  6985. * @expose
  6986. */
  6987. Reflect.Enum.Value = Value;
  6988. /**
  6989. * An extension (field).
  6990. * @exports ProtoBuf.Reflect.Extension
  6991. * @constructor
  6992. * @param {!ProtoBuf.Builder} builder Builder reference
  6993. * @param {!ProtoBuf.Reflect.T} parent Parent object
  6994. * @param {string} name Object name
  6995. * @param {!ProtoBuf.Reflect.Message.Field} field Extension field
  6996. */
  6997. var Extension = function(builder, parent, name, field) {
  6998. T.call(this, builder, parent, name);
  6999. /**
  7000. * Extended message field.
  7001. * @type {!ProtoBuf.Reflect.Message.Field}
  7002. * @expose
  7003. */
  7004. this.field = field;
  7005. };
  7006. // Extends T
  7007. Extension.prototype = Object.create(T.prototype);
  7008. /**
  7009. * @alias ProtoBuf.Reflect.Extension
  7010. * @expose
  7011. */
  7012. Reflect.Extension = Extension;
  7013. /**
  7014. * Constructs a new Service.
  7015. * @exports ProtoBuf.Reflect.Service
  7016. * @param {!ProtoBuf.Builder} builder Builder reference
  7017. * @param {!ProtoBuf.Reflect.Namespace} root Root
  7018. * @param {string} name Service name
  7019. * @param {Object.<string,*>=} options Options
  7020. * @constructor
  7021. * @extends ProtoBuf.Reflect.Namespace
  7022. */
  7023. var Service = function(builder, root, name, options) {
  7024. Namespace.call(this, builder, root, name, options);
  7025. /**
  7026. * @override
  7027. */
  7028. this.className = "Service";
  7029. /**
  7030. * Built runtime service class.
  7031. * @type {?function(new:ProtoBuf.Builder.Service)}
  7032. */
  7033. this.clazz = null;
  7034. };
  7035. /**
  7036. * @alias ProtoBuf.Reflect.Service.prototype
  7037. * @inner
  7038. */
  7039. var ServicePrototype = Service.prototype = Object.create(Namespace.prototype);
  7040. /**
  7041. * Builds the service and returns the runtime counterpart, which is a fully functional class.
  7042. * @see ProtoBuf.Builder.Service
  7043. * @param {boolean=} rebuild Whether to rebuild or not
  7044. * @return {Function} Service class
  7045. * @throws {Error} If the message cannot be built
  7046. * @expose
  7047. */
  7048. ServicePrototype.build = function(rebuild) {
  7049. if (this.clazz && !rebuild)
  7050. return this.clazz;
  7051. // Create the runtime Service class in its own scope
  7052. return this.clazz = (function(ProtoBuf, T) {
  7053. /**
  7054. * Constructs a new runtime Service.
  7055. * @name ProtoBuf.Builder.Service
  7056. * @param {function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))=} rpcImpl RPC implementation receiving the method name and the message
  7057. * @class Barebone of all runtime services.
  7058. * @constructor
  7059. * @throws {Error} If the service cannot be created
  7060. */
  7061. var Service = function(rpcImpl) {
  7062. ProtoBuf.Builder.Service.call(this);
  7063. /**
  7064. * Service implementation.
  7065. * @name ProtoBuf.Builder.Service#rpcImpl
  7066. * @type {!function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))}
  7067. * @expose
  7068. */
  7069. this.rpcImpl = rpcImpl || function(name, msg, callback) {
  7070. // This is what a user has to implement: A function receiving the method name, the actual message to
  7071. // send (type checked) and the callback that's either provided with the error as its first
  7072. // argument or null and the actual response message.
  7073. setTimeout(callback.bind(this, Error("Not implemented, see: https://github.com/dcodeIO/ProtoBuf.js/wiki/Services")), 0); // Must be async!
  7074. };
  7075. };
  7076. /**
  7077. * @alias ProtoBuf.Builder.Service.prototype
  7078. * @inner
  7079. */
  7080. var ServicePrototype = Service.prototype = Object.create(ProtoBuf.Builder.Service.prototype);
  7081. if (Object.defineProperty)
  7082. Object.defineProperty(Service, "$options", { "value": T.buildOpt() }),
  7083. Object.defineProperty(ServicePrototype, "$options", { "value": Service["$options"] });
  7084. /**
  7085. * Asynchronously performs an RPC call using the given RPC implementation.
  7086. * @name ProtoBuf.Builder.Service.[Method]
  7087. * @function
  7088. * @param {!function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))} rpcImpl RPC implementation
  7089. * @param {ProtoBuf.Builder.Message} req Request
  7090. * @param {function(Error, (ProtoBuf.Builder.Message|ByteBuffer|Buffer|string)=)} callback Callback receiving
  7091. * the error if any and the response either as a pre-parsed message or as its raw bytes
  7092. * @abstract
  7093. */
  7094. /**
  7095. * Asynchronously performs an RPC call using the instance's RPC implementation.
  7096. * @name ProtoBuf.Builder.Service#[Method]
  7097. * @function
  7098. * @param {ProtoBuf.Builder.Message} req Request
  7099. * @param {function(Error, (ProtoBuf.Builder.Message|ByteBuffer|Buffer|string)=)} callback Callback receiving
  7100. * the error if any and the response either as a pre-parsed message or as its raw bytes
  7101. * @abstract
  7102. */
  7103. var rpc = T.getChildren(ProtoBuf.Reflect.Service.RPCMethod);
  7104. for (var i=0; i<rpc.length; i++) {
  7105. (function(method) {
  7106. // service#Method(message, callback)
  7107. ServicePrototype[method.name] = function(req, callback) {
  7108. try {
  7109. if (!req || !(req instanceof method.resolvedRequestType.clazz)) {
  7110. setTimeout(callback.bind(this, Error("Illegal request type provided to service method "+T.name+"#"+method.name)), 0);
  7111. return;
  7112. }
  7113. this.rpcImpl(method.fqn(), req, function(err, res) { // Assumes that this is properly async
  7114. if (err) {
  7115. callback(err);
  7116. return;
  7117. }
  7118. try { res = method.resolvedResponseType.clazz.decode(res); } catch (notABuffer) {}
  7119. if (!res || !(res instanceof method.resolvedResponseType.clazz)) {
  7120. callback(Error("Illegal response type received in service method "+ T.name+"#"+method.name));
  7121. return;
  7122. }
  7123. callback(null, res);
  7124. });
  7125. } catch (err) {
  7126. setTimeout(callback.bind(this, err), 0);
  7127. }
  7128. };
  7129. // Service.Method(rpcImpl, message, callback)
  7130. Service[method.name] = function(rpcImpl, req, callback) {
  7131. new Service(rpcImpl)[method.name](req, callback);
  7132. };
  7133. if (Object.defineProperty)
  7134. Object.defineProperty(Service[method.name], "$options", { "value": method.buildOpt() }),
  7135. Object.defineProperty(ServicePrototype[method.name], "$options", { "value": Service[method.name]["$options"] });
  7136. })(rpc[i]);
  7137. }
  7138. return Service;
  7139. })(ProtoBuf, this);
  7140. };
  7141. /**
  7142. * @alias ProtoBuf.Reflect.Service
  7143. * @expose
  7144. */
  7145. Reflect.Service = Service;
  7146. /**
  7147. * Abstract service method.
  7148. * @exports ProtoBuf.Reflect.Service.Method
  7149. * @param {!ProtoBuf.Builder} builder Builder reference
  7150. * @param {!ProtoBuf.Reflect.Service} svc Service
  7151. * @param {string} name Method name
  7152. * @param {Object.<string,*>=} options Options
  7153. * @constructor
  7154. * @extends ProtoBuf.Reflect.T
  7155. */
  7156. var Method = function(builder, svc, name, options) {
  7157. T.call(this, builder, svc, name);
  7158. /**
  7159. * @override
  7160. */
  7161. this.className = "Service.Method";
  7162. /**
  7163. * Options.
  7164. * @type {Object.<string, *>}
  7165. * @expose
  7166. */
  7167. this.options = options || {};
  7168. };
  7169. /**
  7170. * @alias ProtoBuf.Reflect.Service.Method.prototype
  7171. * @inner
  7172. */
  7173. var MethodPrototype = Method.prototype = Object.create(T.prototype);
  7174. /**
  7175. * Builds the method's '$options' property.
  7176. * @name ProtoBuf.Reflect.Service.Method#buildOpt
  7177. * @function
  7178. * @return {Object.<string,*>}
  7179. */
  7180. MethodPrototype.buildOpt = NamespacePrototype.buildOpt;
  7181. /**
  7182. * @alias ProtoBuf.Reflect.Service.Method
  7183. * @expose
  7184. */
  7185. Reflect.Service.Method = Method;
  7186. /**
  7187. * RPC service method.
  7188. * @exports ProtoBuf.Reflect.Service.RPCMethod
  7189. * @param {!ProtoBuf.Builder} builder Builder reference
  7190. * @param {!ProtoBuf.Reflect.Service} svc Service
  7191. * @param {string} name Method name
  7192. * @param {string} request Request message name
  7193. * @param {string} response Response message name
  7194. * @param {Object.<string,*>=} options Options
  7195. * @constructor
  7196. * @extends ProtoBuf.Reflect.Service.Method
  7197. */
  7198. var RPCMethod = function(builder, svc, name, request, response, options) {
  7199. Method.call(this, builder, svc, name, options);
  7200. /**
  7201. * @override
  7202. */
  7203. this.className = "Service.RPCMethod";
  7204. /**
  7205. * Request message name.
  7206. * @type {string}
  7207. * @expose
  7208. */
  7209. this.requestName = request;
  7210. /**
  7211. * Response message name.
  7212. * @type {string}
  7213. * @expose
  7214. */
  7215. this.responseName = response;
  7216. /**
  7217. * Resolved request message type.
  7218. * @type {ProtoBuf.Reflect.Message}
  7219. * @expose
  7220. */
  7221. this.resolvedRequestType = null;
  7222. /**
  7223. * Resolved response message type.
  7224. * @type {ProtoBuf.Reflect.Message}
  7225. * @expose
  7226. */
  7227. this.resolvedResponseType = null;
  7228. };
  7229. // Extends Method
  7230. RPCMethod.prototype = Object.create(Method.prototype);
  7231. /**
  7232. * @alias ProtoBuf.Reflect.Service.RPCMethod
  7233. * @expose
  7234. */
  7235. Reflect.Service.RPCMethod = RPCMethod;
  7236. return Reflect;
  7237. })(ProtoBuf);
  7238. /**
  7239. * @alias ProtoBuf.Builder
  7240. * @expose
  7241. */
  7242. ProtoBuf.Builder = (function(ProtoBuf, Lang, Reflect) {
  7243. "use strict";
  7244. /**
  7245. * Constructs a new Builder.
  7246. * @exports ProtoBuf.Builder
  7247. * @class Provides the functionality to build protocol messages.
  7248. * @param {Object.<string,*>=} options Options
  7249. * @constructor
  7250. */
  7251. var Builder = function(options) {
  7252. /**
  7253. * Namespace.
  7254. * @type {ProtoBuf.Reflect.Namespace}
  7255. * @expose
  7256. */
  7257. this.ns = new Reflect.Namespace(this, null, ""); // Global namespace
  7258. /**
  7259. * Namespace pointer.
  7260. * @type {ProtoBuf.Reflect.T}
  7261. * @expose
  7262. */
  7263. this.ptr = this.ns;
  7264. /**
  7265. * Resolved flag.
  7266. * @type {boolean}
  7267. * @expose
  7268. */
  7269. this.resolved = false;
  7270. /**
  7271. * The current building result.
  7272. * @type {Object.<string,ProtoBuf.Builder.Message|Object>|null}
  7273. * @expose
  7274. */
  7275. this.result = null;
  7276. /**
  7277. * Imported files.
  7278. * @type {Array.<string>}
  7279. * @expose
  7280. */
  7281. this.files = {};
  7282. /**
  7283. * Import root override.
  7284. * @type {?string}
  7285. * @expose
  7286. */
  7287. this.importRoot = null;
  7288. /**
  7289. * Options.
  7290. * @type {!Object.<string, *>}
  7291. * @expose
  7292. */
  7293. this.options = options || {};
  7294. };
  7295. /**
  7296. * @alias ProtoBuf.Builder.prototype
  7297. * @inner
  7298. */
  7299. var BuilderPrototype = Builder.prototype;
  7300. /**
  7301. * Resets the pointer to the root namespace.
  7302. * @expose
  7303. */
  7304. BuilderPrototype.reset = function() {
  7305. this.ptr = this.ns;
  7306. };
  7307. /**
  7308. * Defines a package on top of the current pointer position and places the pointer on it.
  7309. * @param {string} pkg
  7310. * @param {Object.<string,*>=} options
  7311. * @return {ProtoBuf.Builder} this
  7312. * @throws {Error} If the package name is invalid
  7313. * @expose
  7314. */
  7315. BuilderPrototype.define = function(pkg, options) {
  7316. if (typeof pkg !== 'string' || !Lang.TYPEREF.test(pkg))
  7317. throw Error("Illegal package: "+pkg);
  7318. var part = pkg.split("."), i;
  7319. for (i=0; i<part.length; i++) // To be absolutely sure
  7320. if (!Lang.NAME.test(part[i]))
  7321. throw Error("Illegal package: "+part[i]);
  7322. for (i=0; i<part.length; i++) {
  7323. if (this.ptr.getChild(part[i]) === null) // Keep existing namespace
  7324. this.ptr.addChild(new Reflect.Namespace(this, this.ptr, part[i], options));
  7325. this.ptr = this.ptr.getChild(part[i]);
  7326. }
  7327. return this;
  7328. };
  7329. /**
  7330. * Tests if a definition is a valid message definition.
  7331. * @param {Object.<string,*>} def Definition
  7332. * @return {boolean} true if valid, else false
  7333. * @expose
  7334. */
  7335. Builder.isValidMessage = function(def) {
  7336. // Messages require a string name
  7337. if (typeof def["name"] !== 'string' || !Lang.NAME.test(def["name"]))
  7338. return false;
  7339. // Messages must not contain values (that'd be an enum) or methods (that'd be a service)
  7340. if (typeof def["values"] !== 'undefined' || typeof def["rpc"] !== 'undefined')
  7341. return false;
  7342. // Fields, enums and messages are arrays if provided
  7343. var i;
  7344. if (typeof def["fields"] !== 'undefined') {
  7345. if (!ProtoBuf.Util.isArray(def["fields"]))
  7346. return false;
  7347. var ids = [], id; // IDs must be unique
  7348. for (i=0; i<def["fields"].length; i++) {
  7349. if (!Builder.isValidMessageField(def["fields"][i]))
  7350. return false;
  7351. id = parseInt(def["fields"][i]["id"], 10);
  7352. if (ids.indexOf(id) >= 0)
  7353. return false;
  7354. ids.push(id);
  7355. }
  7356. ids = null;
  7357. }
  7358. if (typeof def["enums"] !== 'undefined') {
  7359. if (!ProtoBuf.Util.isArray(def["enums"]))
  7360. return false;
  7361. for (i=0; i<def["enums"].length; i++)
  7362. if (!Builder.isValidEnum(def["enums"][i]))
  7363. return false;
  7364. }
  7365. if (typeof def["messages"] !== 'undefined') {
  7366. if (!ProtoBuf.Util.isArray(def["messages"]))
  7367. return false;
  7368. for (i=0; i<def["messages"].length; i++)
  7369. if (!Builder.isValidMessage(def["messages"][i]) && !Builder.isValidExtend(def["messages"][i]))
  7370. return false;
  7371. }
  7372. if (typeof def["extensions"] !== 'undefined')
  7373. if (!ProtoBuf.Util.isArray(def["extensions"]) || def["extensions"].length !== 2 || typeof def["extensions"][0] !== 'number' || typeof def["extensions"][1] !== 'number')
  7374. return false;
  7375. return true;
  7376. };
  7377. /**
  7378. * Tests if a definition is a valid message field definition.
  7379. * @param {Object} def Definition
  7380. * @return {boolean} true if valid, else false
  7381. * @expose
  7382. */
  7383. Builder.isValidMessageField = function(def) {
  7384. // Message fields require a string rule, name and type and an id
  7385. if (typeof def["rule"] !== 'string' || typeof def["name"] !== 'string' || typeof def["type"] !== 'string' || typeof def["id"] === 'undefined')
  7386. return false;
  7387. if (!Lang.RULE.test(def["rule"]) || !Lang.NAME.test(def["name"]) || !Lang.TYPEREF.test(def["type"]) || !Lang.ID.test(""+def["id"]))
  7388. return false;
  7389. if (typeof def["options"] !== 'undefined') {
  7390. // Options are objects
  7391. if (typeof def["options"] !== 'object')
  7392. return false;
  7393. // Options are <string,string|number|boolean>
  7394. var keys = Object.keys(def["options"]);
  7395. for (var i=0, key; i<keys.length; i++)
  7396. if (typeof (key = keys[i]) !== 'string' || (typeof def["options"][key] !== 'string' && typeof def["options"][key] !== 'number' && typeof def["options"][key] !== 'boolean'))
  7397. return false;
  7398. }
  7399. return true;
  7400. };
  7401. /**
  7402. * Tests if a definition is a valid enum definition.
  7403. * @param {Object} def Definition
  7404. * @return {boolean} true if valid, else false
  7405. * @expose
  7406. */
  7407. Builder.isValidEnum = function(def) {
  7408. // Enums require a string name
  7409. if (typeof def["name"] !== 'string' || !Lang.NAME.test(def["name"]))
  7410. return false;
  7411. // Enums require at least one value
  7412. if (typeof def["values"] === 'undefined' || !ProtoBuf.Util.isArray(def["values"]) || def["values"].length == 0)
  7413. return false;
  7414. for (var i=0; i<def["values"].length; i++) {
  7415. // Values are objects
  7416. if (typeof def["values"][i] != "object")
  7417. return false;
  7418. // Values require a string name and an id
  7419. if (typeof def["values"][i]["name"] !== 'string' || typeof def["values"][i]["id"] === 'undefined')
  7420. return false;
  7421. if (!Lang.NAME.test(def["values"][i]["name"]) || !Lang.NEGID.test(""+def["values"][i]["id"]))
  7422. return false;
  7423. }
  7424. // It's not important if there are other fields because ["values"] is already unique
  7425. return true;
  7426. };
  7427. /**
  7428. * Creates ths specified protocol types at the current pointer position.
  7429. * @param {Array.<Object.<string,*>>} defs Messages, enums or services to create
  7430. * @return {ProtoBuf.Builder} this
  7431. * @throws {Error} If a message definition is invalid
  7432. * @expose
  7433. */
  7434. BuilderPrototype.create = function(defs) {
  7435. if (!defs)
  7436. return this; // Nothing to create
  7437. if (!ProtoBuf.Util.isArray(defs))
  7438. defs = [defs];
  7439. if (defs.length == 0)
  7440. return this;
  7441. // It's quite hard to keep track of scopes and memory here, so let's do this iteratively.
  7442. var stack = [];
  7443. stack.push(defs); // One level [a, b, c]
  7444. while (stack.length > 0) {
  7445. defs = stack.pop();
  7446. if (ProtoBuf.Util.isArray(defs)) { // Stack always contains entire namespaces
  7447. while (defs.length > 0) {
  7448. var def = defs.shift(); // Namespace always contains an array of messages, enums and services
  7449. if (Builder.isValidMessage(def)) {
  7450. var obj = new Reflect.Message(this, this.ptr, def["name"], def["options"], def["isGroup"]);
  7451. // Create OneOfs
  7452. var oneofs = {};
  7453. if (def["oneofs"]) {
  7454. var keys = Object.keys(def["oneofs"]);
  7455. for (var i=0, k=keys.length; i<k; ++i)
  7456. obj.addChild(oneofs[keys[i]] = new Reflect.Message.OneOf(this, obj, keys[i]));
  7457. }
  7458. // Create fields
  7459. if (def["fields"] && def["fields"].length > 0) {
  7460. for (i=0, k=def["fields"].length; i<k; ++i) { // i:k=Fields
  7461. var fld = def['fields'][i];
  7462. if (obj.getChild(fld['id']) !== null)
  7463. throw Error("Duplicate field id in message "+obj.name+": "+fld['id']);
  7464. if (fld["options"]) {
  7465. var opts = Object.keys(fld["options"]);
  7466. for (var j= 0,l=opts.length; j<l; ++j) { // j:l=Option names
  7467. if (typeof opts[j] !== 'string')
  7468. throw Error("Illegal field option name in message "+obj.name+"#"+fld["name"]+": "+opts[j]);
  7469. if (typeof fld["options"][opts[j]] !== 'string' && typeof fld["options"][opts[j]] !== 'number' && typeof fld["options"][opts[j]] !== 'boolean')
  7470. throw Error("Illegal field option value in message "+obj.name+"#"+fld["name"]+"#"+opts[j]+": "+fld["options"][opts[j]]);
  7471. }
  7472. }
  7473. var oneof = null;
  7474. if (typeof fld["oneof"] === 'string') {
  7475. oneof = oneofs[fld["oneof"]];
  7476. if (typeof oneof === 'undefined')
  7477. throw Error("Illegal oneof in message "+obj.name+"#"+fld["name"]+": "+fld["oneof"]);
  7478. }
  7479. fld = new Reflect.Message.Field(this, obj, fld["rule"], fld["type"], fld["name"], fld["id"], fld["options"], oneof);
  7480. if (oneof)
  7481. oneof.fields.push(fld);
  7482. obj.addChild(fld);
  7483. }
  7484. }
  7485. // Push enums and messages to stack
  7486. var subObj = [];
  7487. if (typeof def["enums"] !== 'undefined' && def['enums'].length > 0)
  7488. for (i=0; i<def["enums"].length; i++)
  7489. subObj.push(def["enums"][i]);
  7490. if (def["messages"] && def["messages"].length > 0)
  7491. for (i=0; i<def["messages"].length; i++)
  7492. subObj.push(def["messages"][i]);
  7493. // Set extension range
  7494. if (def["extensions"]) {
  7495. obj.extensions = def["extensions"];
  7496. if (obj.extensions[0] < ProtoBuf.ID_MIN)
  7497. obj.extensions[0] = ProtoBuf.ID_MIN;
  7498. if (obj.extensions[1] > ProtoBuf.ID_MAX)
  7499. obj.extensions[1] = ProtoBuf.ID_MAX;
  7500. }
  7501. this.ptr.addChild(obj); // Add to current namespace
  7502. if (subObj.length > 0) {
  7503. stack.push(defs); // Push the current level back
  7504. defs = subObj; // Continue processing sub level
  7505. subObj = null;
  7506. this.ptr = obj; // And move the pointer to this namespace
  7507. obj = null;
  7508. continue;
  7509. }
  7510. subObj = null;
  7511. obj = null;
  7512. } else if (Builder.isValidEnum(def)) {
  7513. obj = new Reflect.Enum(this, this.ptr, def["name"], def["options"]);
  7514. for (i=0; i<def["values"].length; i++)
  7515. obj.addChild(new Reflect.Enum.Value(this, obj, def["values"][i]["name"], def["values"][i]["id"]));
  7516. this.ptr.addChild(obj);
  7517. obj = null;
  7518. } else if (Builder.isValidService(def)) {
  7519. obj = new Reflect.Service(this, this.ptr, def["name"], def["options"]);
  7520. for (i in def["rpc"])
  7521. if (def["rpc"].hasOwnProperty(i))
  7522. obj.addChild(new Reflect.Service.RPCMethod(this, obj, i, def["rpc"][i]["request"], def["rpc"][i]["response"], def["rpc"][i]["options"]));
  7523. this.ptr.addChild(obj);
  7524. obj = null;
  7525. } else if (Builder.isValidExtend(def)) {
  7526. obj = this.ptr.resolve(def["ref"]);
  7527. if (obj) {
  7528. for (i=0; i<def["fields"].length; i++) { // i=Fields
  7529. if (obj.getChild(def['fields'][i]['id']) !== null)
  7530. throw Error("Duplicate extended field id in message "+obj.name+": "+def['fields'][i]['id']);
  7531. if (def['fields'][i]['id'] < obj.extensions[0] || def['fields'][i]['id'] > obj.extensions[1])
  7532. throw Error("Illegal extended field id in message "+obj.name+": "+def['fields'][i]['id']+" ("+obj.extensions.join(' to ')+" expected)");
  7533. // Convert extension field names to camel case notation if the override is set
  7534. var name = def["fields"][i]["name"];
  7535. if (this.options['convertFieldsToCamelCase'])
  7536. name = Reflect.Message.Field._toCamelCase(def["fields"][i]["name"]);
  7537. // see #161: Extensions use their fully qualified name as their runtime key and...
  7538. fld = new Reflect.Message.ExtensionField(this, obj, def["fields"][i]["rule"], def["fields"][i]["type"], this.ptr.fqn()+'.'+name, def["fields"][i]["id"], def["fields"][i]["options"]);
  7539. // ...are added on top of the current namespace as an extension which is used for
  7540. // resolving their type later on (the extension always keeps the original name to
  7541. // prevent naming collisions)
  7542. var ext = new Reflect.Extension(this, this.ptr, def["fields"][i]["name"], fld);
  7543. fld.extension = ext;
  7544. this.ptr.addChild(ext);
  7545. obj.addChild(fld);
  7546. }
  7547. } else if (!/\.?google\.protobuf\./.test(def["ref"])) // Silently skip internal extensions
  7548. throw Error("Extended message "+def["ref"]+" is not defined");
  7549. } else
  7550. throw Error("Not a valid definition: "+JSON.stringify(def));
  7551. def = null;
  7552. }
  7553. // Break goes here
  7554. } else
  7555. throw Error("Not a valid namespace: "+JSON.stringify(defs));
  7556. defs = null;
  7557. this.ptr = this.ptr.parent; // This namespace is s done
  7558. }
  7559. this.resolved = false; // Require re-resolve
  7560. this.result = null; // Require re-build
  7561. return this;
  7562. };
  7563. /**
  7564. * Imports another definition into this builder.
  7565. * @param {Object.<string,*>} json Parsed import
  7566. * @param {(string|{root: string, file: string})=} filename Imported file name
  7567. * @return {ProtoBuf.Builder} this
  7568. * @throws {Error} If the definition or file cannot be imported
  7569. * @expose
  7570. */
  7571. BuilderPrototype["import"] = function(json, filename) {
  7572. if (typeof filename === 'string') {
  7573. if (ProtoBuf.Util.IS_NODE)
  7574. filename = require("path")['resolve'](filename);
  7575. if (this.files[filename] === true) {
  7576. this.reset();
  7577. return this; // Skip duplicate imports
  7578. }
  7579. this.files[filename] = true;
  7580. }
  7581. if (!!json['imports'] && json['imports'].length > 0) {
  7582. var importRoot, delim = '/', resetRoot = false;
  7583. if (typeof filename === 'object') { // If an import root is specified, override
  7584. this.importRoot = filename["root"]; resetRoot = true; // ... and reset afterwards
  7585. importRoot = this.importRoot;
  7586. filename = filename["file"];
  7587. if (importRoot.indexOf("\\") >= 0 || filename.indexOf("\\") >= 0) delim = '\\';
  7588. } else if (typeof filename === 'string') {
  7589. if (this.importRoot) // If import root is overridden, use it
  7590. importRoot = this.importRoot;
  7591. else { // Otherwise compute from filename
  7592. if (filename.indexOf("/") >= 0) { // Unix
  7593. importRoot = filename.replace(/\/[^\/]*$/, "");
  7594. if (/* /file.proto */ importRoot === "")
  7595. importRoot = "/";
  7596. } else if (filename.indexOf("\\") >= 0) { // Windows
  7597. importRoot = filename.replace(/\\[^\\]*$/, "");
  7598. delim = '\\';
  7599. } else
  7600. importRoot = ".";
  7601. }
  7602. } else
  7603. importRoot = null;
  7604. for (var i=0; i<json['imports'].length; i++) {
  7605. if (typeof json['imports'][i] === 'string') { // Import file
  7606. if (!importRoot)
  7607. throw Error("Cannot determine import root: File name is unknown");
  7608. var importFilename = json['imports'][i];
  7609. if (/^google\/protobuf\//.test(importFilename))
  7610. continue; // Not needed and therefore not used
  7611. importFilename = importRoot+delim+importFilename;
  7612. if (this.files[importFilename] === true)
  7613. continue; // Already imported
  7614. if (/\.proto$/i.test(importFilename) && !ProtoBuf.DotProto) // If this is a NOPARSE build
  7615. importFilename = importFilename.replace(/\.proto$/, ".json"); // always load the JSON file
  7616. var contents = ProtoBuf.Util.fetch(importFilename);
  7617. if (contents === null)
  7618. throw Error("Failed to import '"+importFilename+"' in '"+filename+"': File not found");
  7619. if (/\.json$/i.test(importFilename)) // Always possible
  7620. this["import"](JSON.parse(contents+""), importFilename); // May throw
  7621. else
  7622. this["import"]((new ProtoBuf.DotProto.Parser(contents+"")).parse(), importFilename); // May throw
  7623. } else // Import structure
  7624. if (!filename)
  7625. this["import"](json['imports'][i]);
  7626. else if (/\.(\w+)$/.test(filename)) // With extension: Append _importN to the name portion to make it unique
  7627. this["import"](json['imports'][i], filename.replace(/^(.+)\.(\w+)$/, function($0, $1, $2) { return $1+"_import"+i+"."+$2; }));
  7628. else // Without extension: Append _importN to make it unique
  7629. this["import"](json['imports'][i], filename+"_import"+i);
  7630. }
  7631. if (resetRoot) // Reset import root override when all imports are done
  7632. this.importRoot = null;
  7633. }
  7634. if (json['messages']) {
  7635. if (json['package'])
  7636. this.define(json['package'], json["options"]);
  7637. this.create(json['messages']);
  7638. this.reset();
  7639. }
  7640. if (json['enums']) {
  7641. if (json['package'])
  7642. this.define(json['package'], json["options"]);
  7643. this.create(json['enums']);
  7644. this.reset();
  7645. }
  7646. if (json['services']) {
  7647. if (json['package'])
  7648. this.define(json['package'], json["options"]);
  7649. this.create(json['services']);
  7650. this.reset();
  7651. }
  7652. if (json['extends']) {
  7653. if (json['package'])
  7654. this.define(json['package'], json["options"]);
  7655. this.create(json['extends']);
  7656. this.reset();
  7657. }
  7658. return this;
  7659. };
  7660. /**
  7661. * Tests if a definition is a valid service definition.
  7662. * @param {Object} def Definition
  7663. * @return {boolean} true if valid, else false
  7664. * @expose
  7665. */
  7666. Builder.isValidService = function(def) {
  7667. // Services require a string name and an rpc object
  7668. return !(typeof def["name"] !== 'string' || !Lang.NAME.test(def["name"]) || typeof def["rpc"] !== 'object');
  7669. };
  7670. /**
  7671. * Tests if a definition is a valid extension.
  7672. * @param {Object} def Definition
  7673. * @returns {boolean} true if valid, else false
  7674. * @expose
  7675. */
  7676. Builder.isValidExtend = function(def) {
  7677. if (typeof def["ref"] !== 'string' || !Lang.TYPEREF.test(def["ref"]))
  7678. return false;
  7679. var i;
  7680. if (typeof def["fields"] !== 'undefined') {
  7681. if (!ProtoBuf.Util.isArray(def["fields"]))
  7682. return false;
  7683. var ids = [], id; // IDs must be unique (does not yet test for the extended message's ids)
  7684. for (i=0; i<def["fields"].length; i++) {
  7685. if (!Builder.isValidMessageField(def["fields"][i]))
  7686. return false;
  7687. id = parseInt(def["id"], 10);
  7688. if (ids.indexOf(id) >= 0)
  7689. return false;
  7690. ids.push(id);
  7691. }
  7692. ids = null;
  7693. }
  7694. return true;
  7695. };
  7696. /**
  7697. * Resolves all namespace objects.
  7698. * @throws {Error} If a type cannot be resolved
  7699. * @expose
  7700. */
  7701. BuilderPrototype.resolveAll = function() {
  7702. // Resolve all reflected objects
  7703. var res;
  7704. if (this.ptr == null || typeof this.ptr.type === 'object')
  7705. return; // Done (already resolved)
  7706. if (this.ptr instanceof Reflect.Namespace) {
  7707. // Build all children
  7708. var children = this.ptr.children;
  7709. for (var i= 0, k=children.length; i<k; ++i)
  7710. this.ptr = children[i],
  7711. this.resolveAll();
  7712. } else if (this.ptr instanceof Reflect.Message.Field) {
  7713. if (!Lang.TYPE.test(this.ptr.type)) { // Resolve type...
  7714. if (!Lang.TYPEREF.test(this.ptr.type))
  7715. throw Error("Illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.type);
  7716. res = (this.ptr instanceof Reflect.Message.ExtensionField ? this.ptr.extension.parent : this.ptr.parent).resolve(this.ptr.type, true);
  7717. if (!res)
  7718. throw Error("Unresolvable type reference in "+this.ptr.toString(true)+": "+this.ptr.type);
  7719. this.ptr.resolvedType = res;
  7720. if (res instanceof Reflect.Enum)
  7721. this.ptr.type = ProtoBuf.TYPES["enum"];
  7722. else if (res instanceof Reflect.Message)
  7723. this.ptr.type = res.isGroup ? ProtoBuf.TYPES["group"] : ProtoBuf.TYPES["message"];
  7724. else
  7725. throw Error("Illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.type);
  7726. } else
  7727. this.ptr.type = ProtoBuf.TYPES[this.ptr.type];
  7728. } else if (this.ptr instanceof ProtoBuf.Reflect.Enum.Value) {
  7729. // No need to build enum values (built in enum)
  7730. } else if (this.ptr instanceof ProtoBuf.Reflect.Service.Method) {
  7731. if (this.ptr instanceof ProtoBuf.Reflect.Service.RPCMethod) {
  7732. res = this.ptr.parent.resolve(this.ptr.requestName);
  7733. if (!res || !(res instanceof ProtoBuf.Reflect.Message))
  7734. throw Error("Illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.requestName);
  7735. this.ptr.resolvedRequestType = res;
  7736. res = this.ptr.parent.resolve(this.ptr.responseName);
  7737. if (!res || !(res instanceof ProtoBuf.Reflect.Message))
  7738. throw Error("Illegal type reference in "+this.ptr.toString(true)+": "+this.ptr.responseName);
  7739. this.ptr.resolvedResponseType = res;
  7740. } else {
  7741. // Should not happen as nothing else is implemented
  7742. throw Error("Illegal service type in "+this.ptr.toString(true));
  7743. }
  7744. } else if (!(this.ptr instanceof ProtoBuf.Reflect.Message.OneOf) && !(this.ptr instanceof ProtoBuf.Reflect.Extension))
  7745. throw Error("Illegal object in namespace: "+typeof(this.ptr)+":"+this.ptr);
  7746. this.reset();
  7747. };
  7748. /**
  7749. * Builds the protocol. This will first try to resolve all definitions and, if this has been successful,
  7750. * return the built package.
  7751. * @param {string=} path Specifies what to return. If omitted, the entire namespace will be returned.
  7752. * @return {ProtoBuf.Builder.Message|Object.<string,*>}
  7753. * @throws {Error} If a type could not be resolved
  7754. * @expose
  7755. */
  7756. BuilderPrototype.build = function(path) {
  7757. this.reset();
  7758. if (!this.resolved)
  7759. this.resolveAll(),
  7760. this.resolved = true,
  7761. this.result = null; // Require re-build
  7762. if (this.result == null) // (Re-)Build
  7763. this.result = this.ns.build();
  7764. if (!path)
  7765. return this.result;
  7766. else {
  7767. var part = path.split(".");
  7768. var ptr = this.result; // Build namespace pointer (no hasChild etc.)
  7769. for (var i=0; i<part.length; i++)
  7770. if (ptr[part[i]])
  7771. ptr = ptr[part[i]];
  7772. else {
  7773. ptr = null;
  7774. break;
  7775. }
  7776. return ptr;
  7777. }
  7778. };
  7779. /**
  7780. * Similar to {@link ProtoBuf.Builder#build}, but looks up the internal reflection descriptor.
  7781. * @param {string=} path Specifies what to return. If omitted, the entire namespace wiil be returned.
  7782. * @return {ProtoBuf.Reflect.T} Reflection descriptor or `null` if not found
  7783. */
  7784. BuilderPrototype.lookup = function(path) {
  7785. return path ? this.ns.resolve(path) : this.ns;
  7786. };
  7787. /**
  7788. * Returns a string representation of this object.
  7789. * @return {string} String representation as of "Builder"
  7790. * @expose
  7791. */
  7792. BuilderPrototype.toString = function() {
  7793. return "Builder";
  7794. };
  7795. // Pseudo types documented in Reflect.js.
  7796. // Exist for the sole purpose of being able to "... instanceof ProtoBuf.Builder.Message" etc.
  7797. Builder.Message = function() {};
  7798. Builder.Service = function() {};
  7799. return Builder;
  7800. })(ProtoBuf, ProtoBuf.Lang, ProtoBuf.Reflect);
  7801. /**
  7802. * Loads a .proto string and returns the Builder.
  7803. * @param {string} proto .proto file contents
  7804. * @param {(ProtoBuf.Builder|string|{root: string, file: string})=} builder Builder to append to. Will create a new one if omitted.
  7805. * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
  7806. * @return {ProtoBuf.Builder} Builder to create new messages
  7807. * @throws {Error} If the definition cannot be parsed or built
  7808. * @expose
  7809. */
  7810. ProtoBuf.loadProto = function(proto, builder, filename) {
  7811. if (typeof builder === 'string' || (builder && typeof builder["file"] === 'string' && typeof builder["root"] === 'string'))
  7812. filename = builder,
  7813. builder = undefined;
  7814. return ProtoBuf.loadJson((new ProtoBuf.DotProto.Parser(proto)).parse(), builder, filename);
  7815. };
  7816. /**
  7817. * Loads a .proto string and returns the Builder. This is an alias of {@link ProtoBuf.loadProto}.
  7818. * @function
  7819. * @param {string} proto .proto file contents
  7820. * @param {(ProtoBuf.Builder|string)=} builder Builder to append to. Will create a new one if omitted.
  7821. * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
  7822. * @return {ProtoBuf.Builder} Builder to create new messages
  7823. * @throws {Error} If the definition cannot be parsed or built
  7824. * @expose
  7825. */
  7826. ProtoBuf.protoFromString = ProtoBuf.loadProto; // Legacy
  7827. /**
  7828. * Loads a .proto file and returns the Builder.
  7829. * @param {string|{root: string, file: string}} filename Path to proto file or an object specifying 'file' with
  7830. * an overridden 'root' path for all imported files.
  7831. * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
  7832. * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
  7833. * file will be read synchronously and this function will return the Builder.
  7834. * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
  7835. * @return {?ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
  7836. * request has failed), else undefined
  7837. * @expose
  7838. */
  7839. ProtoBuf.loadProtoFile = function(filename, callback, builder) {
  7840. if (callback && typeof callback === 'object')
  7841. builder = callback,
  7842. callback = null;
  7843. else if (!callback || typeof callback !== 'function')
  7844. callback = null;
  7845. if (callback)
  7846. return ProtoBuf.Util.fetch(typeof filename === 'string' ? filename : filename["root"]+"/"+filename["file"], function(contents) {
  7847. if (contents === null) {
  7848. callback(Error("Failed to fetch file"));
  7849. return;
  7850. }
  7851. try {
  7852. callback(null, ProtoBuf.loadProto(contents, builder, filename));
  7853. } catch (e) {
  7854. callback(e);
  7855. }
  7856. });
  7857. var contents = ProtoBuf.Util.fetch(typeof filename === 'object' ? filename["root"]+"/"+filename["file"] : filename);
  7858. return contents === null ? null : ProtoBuf.loadProto(contents, builder, filename);
  7859. };
  7860. /**
  7861. * Loads a .proto file and returns the Builder. This is an alias of {@link ProtoBuf.loadProtoFile}.
  7862. * @function
  7863. * @param {string|{root: string, file: string}} filename Path to proto file or an object specifying 'file' with
  7864. * an overridden 'root' path for all imported files.
  7865. * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
  7866. * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
  7867. * file will be read synchronously and this function will return the Builder.
  7868. * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
  7869. * @return {!ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
  7870. * request has failed), else undefined
  7871. * @expose
  7872. */
  7873. ProtoBuf.protoFromFile = ProtoBuf.loadProtoFile; // Legacy
  7874. /**
  7875. * Constructs a new empty Builder.
  7876. * @param {Object.<string,*>=} options Builder options, defaults to global options set on ProtoBuf
  7877. * @return {!ProtoBuf.Builder} Builder
  7878. * @expose
  7879. */
  7880. ProtoBuf.newBuilder = function(options) {
  7881. options = options || {};
  7882. if (typeof options['convertFieldsToCamelCase'] === 'undefined')
  7883. options['convertFieldsToCamelCase'] = ProtoBuf.convertFieldsToCamelCase;
  7884. if (typeof options['populateAccessors'] === 'undefined')
  7885. options['populateAccessors'] = ProtoBuf.populateAccessors;
  7886. return new ProtoBuf.Builder(options);
  7887. };
  7888. /**
  7889. * Loads a .json definition and returns the Builder.
  7890. * @param {!*|string} json JSON definition
  7891. * @param {(ProtoBuf.Builder|string|{root: string, file: string})=} builder Builder to append to. Will create a new one if omitted.
  7892. * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
  7893. * @return {ProtoBuf.Builder} Builder to create new messages
  7894. * @throws {Error} If the definition cannot be parsed or built
  7895. * @expose
  7896. */
  7897. ProtoBuf.loadJson = function(json, builder, filename) {
  7898. if (typeof builder === 'string' || (builder && typeof builder["file"] === 'string' && typeof builder["root"] === 'string'))
  7899. filename = builder,
  7900. builder = null;
  7901. if (!builder || typeof builder !== 'object')
  7902. builder = ProtoBuf.newBuilder();
  7903. if (typeof json === 'string')
  7904. json = JSON.parse(json);
  7905. builder["import"](json, filename);
  7906. builder.resolveAll();
  7907. builder.build();
  7908. return builder;
  7909. };
  7910. /**
  7911. * Loads a .json file and returns the Builder.
  7912. * @param {string|!{root: string, file: string}} filename Path to json file or an object specifying 'file' with
  7913. * an overridden 'root' path for all imported files.
  7914. * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
  7915. * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
  7916. * file will be read synchronously and this function will return the Builder.
  7917. * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
  7918. * @return {?ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
  7919. * request has failed), else undefined
  7920. * @expose
  7921. */
  7922. ProtoBuf.loadJsonFile = function(filename, callback, builder) {
  7923. if (callback && typeof callback === 'object')
  7924. builder = callback,
  7925. callback = null;
  7926. else if (!callback || typeof callback !== 'function')
  7927. callback = null;
  7928. if (callback)
  7929. return ProtoBuf.Util.fetch(typeof filename === 'string' ? filename : filename["root"]+"/"+filename["file"], function(contents) {
  7930. if (contents === null) {
  7931. callback(Error("Failed to fetch file"));
  7932. return;
  7933. }
  7934. try {
  7935. callback(null, ProtoBuf.loadJson(JSON.parse(contents), builder, filename));
  7936. } catch (e) {
  7937. callback(e);
  7938. }
  7939. });
  7940. var contents = ProtoBuf.Util.fetch(typeof filename === 'object' ? filename["root"]+"/"+filename["file"] : filename);
  7941. return contents === null ? null : ProtoBuf.loadJson(JSON.parse(contents), builder, filename);
  7942. };
  7943. return ProtoBuf;
  7944. }
  7945. /* CommonJS */ if (typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports)
  7946. module['exports'] = init(require("bytebuffer"));
  7947. /* AMD */ else if (typeof define === 'function' && define["amd"])
  7948. define(["ByteBuffer"], init);
  7949. /* Global */ else
  7950. (global["dcodeIO"] = global["dcodeIO"] || {})["ProtoBuf"] = init(global["dcodeIO"]["ByteBuffer"]);
  7951. })(this);