jiter-0.7.1/.cargo_vcs_info.json0000644000000001520000000000100121540ustar { "git": { "sha1": "1fbdb1e7d6d45a54496a4e59c60000ccaab92380" }, "path_in_vcs": "crates/jiter" }jiter-0.7.1/Cargo.toml0000644000000055650000000000100101670ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "jiter" version = "0.7.1" authors = ["Samuel Colvin "] build = "build.rs" autobins = false autoexamples = false autotests = false autobenches = false description = "Fast Iterable JSON parser" homepage = "https://github.com/pydantic/jiter/" readme = "README.md" keywords = [ "JSON", "parsing", "deserialization", "iter", ] categories = [ "parser-implementations", "parsing", ] license = "MIT" repository = "https://github.com/pydantic/jiter/" [package.metadata.docs.rs] all-features = true [lib] name = "jiter" path = "src/lib.rs" [[test]] name = "main" path = "tests/main.rs" [[test]] name = "python" path = "tests/python.rs" required-features = ["python"] [[bench]] name = "main" path = "benches/main.rs" harness = false [[bench]] name = "python" path = "benches/python.rs" harness = false required-features = ["python"] [dependencies.ahash] version = "0.8.0" [dependencies.bitvec] version = "1.0.1" [dependencies.lexical-parse-float] version = "0.8.5" features = ["format"] [dependencies.num-bigint] version = "0.4.4" optional = true [dependencies.num-traits] version = "0.2.16" [dependencies.pyo3] version = "0.22.0" optional = true [dependencies.smallvec] version = "1.11.0" [dev-dependencies.bencher] version = "0.1.5" [dev-dependencies.codspeed-bencher-compat] version = "2.7.1" [dev-dependencies.paste] version = "1.0.7" [dev-dependencies.pyo3] version = "0.22.0" features = ["auto-initialize"] [dev-dependencies.serde] version = "1.0.147" [dev-dependencies.serde_json] version = "1.0.87" features = [ "preserve_order", "arbitrary_precision", "float_roundtrip", ] [build-dependencies.pyo3-build-config] version = "0.22.0" optional = true [features] default = ["num-bigint"] num-bigint = [ "dep:num-bigint", "pyo3?/num-bigint", ] python = [ "dep:pyo3", "dep:pyo3-build-config", ] [lints.clippy] cast_lossless = "allow" cast_possible_truncation = "allow" cast_possible_wrap = "allow" cast_precision_loss = "allow" dbg_macro = "deny" doc_markdown = "allow" if_not_else = "allow" implicit_clone = "allow" inline_always = "allow" iter_without_into_iter = "allow" match_bool = "allow" match_same_arms = "allow" missing_errors_doc = "allow" module_name_repetitions = "allow" must_use_candidate = "allow" print_stderr = "deny" print_stdout = "deny" return_self_not_must_use = "allow" [lints.clippy.pedantic] level = "deny" priority = -1 jiter-0.7.1/Cargo.toml.orig000064400000000000000000000040751046102023000136430ustar 00000000000000[package] name = "jiter" description = "Fast Iterable JSON parser" readme = "../../README.md" version = { workspace = true } edition = { workspace = true } authors = { workspace = true } license = { workspace = true } keywords = { workspace = true } categories = { workspace = true } homepage = { workspace = true } repository = { workspace = true } [dependencies] num-bigint = { version = "0.4.4", optional = true } num-traits = "0.2.16" ahash = "0.8.0" smallvec = "1.11.0" pyo3 = { workspace = true, optional = true } lexical-parse-float = { version = "0.8.5", features = ["format"] } bitvec = "1.0.1" [features] default = ["num-bigint"] python = ["dep:pyo3", "dep:pyo3-build-config"] num-bigint = ["dep:num-bigint", "pyo3?/num-bigint"] [dev-dependencies] bencher = "0.1.5" paste = "1.0.7" serde_json = { version = "1.0.87", features = [ "preserve_order", "arbitrary_precision", "float_roundtrip", ] } serde = "1.0.147" pyo3 = { workspace = true, features = ["auto-initialize"] } codspeed-bencher-compat = "2.7.1" [build-dependencies] pyo3-build-config = { workspace = true, optional = true } [[test]] name = "python" required-features = ["python"] [[bench]] name = "main" harness = false [[bench]] name = "python" required-features = ["python"] harness = false # get docs.rs to include python docs [package.metadata.docs.rs] all-features = true [lints.clippy] dbg_macro = "deny" print_stdout = "deny" print_stderr = "deny" # in general we lint against the pedantic group, but we will whitelist # certain lints which we don't want to enforce (for now) pedantic = { level = "deny", priority = -1 } missing_errors_doc = "allow" module_name_repetitions = "allow" must_use_candidate = "allow" if_not_else = "allow" cast_lossless = "allow" cast_possible_wrap = "allow" cast_possible_truncation = "allow" cast_precision_loss = "allow" match_bool = "allow" doc_markdown = "allow" implicit_clone = "allow" iter_without_into_iter = "allow" return_self_not_must_use = "allow" inline_always = "allow" # TODO remove? match_same_arms = "allow" # TODO remove? jiter-0.7.1/LICENSE000064400000000000000000000021031046102023000117470ustar 00000000000000The MIT License (MIT) Copyright (c) 2022 to present Samuel Colvin Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. jiter-0.7.1/README.md000064400000000000000000000150251046102023000122300ustar 00000000000000# jiter [![CI](https://github.com/pydantic/jiter/actions/workflows/ci.yml/badge.svg?event=push)](https://github.com/pydantic/jiter/actions/workflows/ci.yml?query=branch%3Amain) [![Crates.io](https://img.shields.io/crates/v/jiter?color=green)](https://crates.io/crates/jiter) [![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/pydantic/jiter) Fast iterable JSON parser. Documentation is available at [docs.rs/jiter](https://docs.rs/jiter). jiter has three interfaces: * [`JsonValue`] an enum representing JSON data * [`Jiter`] an iterator over JSON data * [`PythonParse`] which parses a JSON string into a Python object ## JsonValue Example See [the `JsonValue` docs][JsonValue] for more details. ```rust use jiter::JsonValue; let json_data = r#" { "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] }"#; let json_value = JsonValue::parse(json_data.as_bytes(), true).unwrap(); println!("{:#?}", json_value); ``` returns: ```text Object( { "name": Str("John Doe"), "age": Int(43), "phones": Array( [ Str("+44 1234567"), Str("+44 2345678"), ], ), }, ) ``` ## Jiter Example To use [Jiter], you need to know what schema you're expecting: ```rust use jiter::{Jiter, NumberInt, Peek}; let json_data = r#" { "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] }"#; let mut jiter = Jiter::new(json_data.as_bytes()).with_allow_inf_nan(); assert_eq!(jiter.next_object().unwrap(), Some("name")); assert_eq!(jiter.next_str().unwrap(), "John Doe"); assert_eq!(jiter.next_key().unwrap(), Some("age")); assert_eq!(jiter.next_int().unwrap(), NumberInt::Int(43)); assert_eq!(jiter.next_key().unwrap(), Some("phones")); assert_eq!(jiter.next_array().unwrap(), Some(Peek::String)); // we know the next value is a string as we just asserted so assert_eq!(jiter.known_str().unwrap(), "+44 1234567"); assert_eq!(jiter.array_step().unwrap(), Some(Peek::String)); // same again assert_eq!(jiter.known_str().unwrap(), "+44 2345678"); // next we'll get `None` from `array_step` as the array is finished assert_eq!(jiter.array_step().unwrap(), None); // and `None` from `next_key` as the object is finished assert_eq!(jiter.next_key().unwrap(), None); // and we check there's nothing else in the input jiter.finish().unwrap(); ``` ## Benchmarks _There are lies, damned lies and benchmarks._ In particular, serde-json benchmarks use `serde_json::Value` which is significantly slower than deserializing to a string. For more details, see [the benchmarks](https://github.com/pydantic/jiter/tree/main/benches). ```text running 48 tests test big_jiter_iter ... bench: 3,662,616 ns/iter (+/- 88,878) test big_jiter_value ... bench: 6,998,605 ns/iter (+/- 292,383) test big_serde_value ... bench: 29,793,191 ns/iter (+/- 576,173) test bigints_array_jiter_iter ... bench: 11,836 ns/iter (+/- 414) test bigints_array_jiter_value ... bench: 28,979 ns/iter (+/- 938) test bigints_array_serde_value ... bench: 129,797 ns/iter (+/- 5,096) test floats_array_jiter_iter ... bench: 19,302 ns/iter (+/- 631) test floats_array_jiter_value ... bench: 31,083 ns/iter (+/- 921) test floats_array_serde_value ... bench: 208,932 ns/iter (+/- 6,167) test lazy_map_lookup_1_10 ... bench: 615 ns/iter (+/- 15) test lazy_map_lookup_2_20 ... bench: 1,776 ns/iter (+/- 36) test lazy_map_lookup_3_50 ... bench: 4,291 ns/iter (+/- 77) test massive_ints_array_jiter_iter ... bench: 62,244 ns/iter (+/- 1,616) test massive_ints_array_jiter_value ... bench: 82,889 ns/iter (+/- 1,916) test massive_ints_array_serde_value ... bench: 498,650 ns/iter (+/- 47,759) test medium_response_jiter_iter ... bench: 0 ns/iter (+/- 0) test medium_response_jiter_value ... bench: 3,521 ns/iter (+/- 101) test medium_response_jiter_value_owned ... bench: 6,088 ns/iter (+/- 180) test medium_response_serde_value ... bench: 9,383 ns/iter (+/- 342) test pass1_jiter_iter ... bench: 0 ns/iter (+/- 0) test pass1_jiter_value ... bench: 3,048 ns/iter (+/- 79) test pass1_serde_value ... bench: 6,588 ns/iter (+/- 232) test pass2_jiter_iter ... bench: 384 ns/iter (+/- 9) test pass2_jiter_value ... bench: 1,259 ns/iter (+/- 44) test pass2_serde_value ... bench: 1,237 ns/iter (+/- 38) test sentence_jiter_iter ... bench: 283 ns/iter (+/- 10) test sentence_jiter_value ... bench: 357 ns/iter (+/- 15) test sentence_serde_value ... bench: 428 ns/iter (+/- 9) test short_numbers_jiter_iter ... bench: 0 ns/iter (+/- 0) test short_numbers_jiter_value ... bench: 18,085 ns/iter (+/- 613) test short_numbers_serde_value ... bench: 87,253 ns/iter (+/- 1,506) test string_array_jiter_iter ... bench: 615 ns/iter (+/- 18) test string_array_jiter_value ... bench: 1,410 ns/iter (+/- 44) test string_array_jiter_value_owned ... bench: 2,863 ns/iter (+/- 151) test string_array_serde_value ... bench: 3,467 ns/iter (+/- 60) test true_array_jiter_iter ... bench: 299 ns/iter (+/- 8) test true_array_jiter_value ... bench: 995 ns/iter (+/- 29) test true_array_serde_value ... bench: 1,207 ns/iter (+/- 36) test true_object_jiter_iter ... bench: 2,482 ns/iter (+/- 84) test true_object_jiter_value ... bench: 2,058 ns/iter (+/- 45) test true_object_serde_value ... bench: 7,991 ns/iter (+/- 370) test unicode_jiter_iter ... bench: 315 ns/iter (+/- 7) test unicode_jiter_value ... bench: 389 ns/iter (+/- 6) test unicode_serde_value ... bench: 445 ns/iter (+/- 6) test x100_jiter_iter ... bench: 12 ns/iter (+/- 0) test x100_jiter_value ... bench: 20 ns/iter (+/- 1) test x100_serde_iter ... bench: 72 ns/iter (+/- 3) test x100_serde_value ... bench: 83 ns/iter (+/- 3) ``` jiter-0.7.1/benches/bigints_array.json000064400000000000000000000421571046102023000161160ustar 00000000000000[-988705390355151, -905834754076502, -103632019616477, -316545588917286, 490779389534829, -953493388874162, -243006771752239, -744025192631980, -359016919000159, 732901781366502, -104773647740791, -286481351498865, 1027561665338462, -123563885683323, -778611441148419, 960167215353837, -535796870414128, -407290660154826, -783018892592292, -647509354641701, 919621526248276, 85546598576532, 247664997821096, -532964163462505, 1102930398831693, 511750375836837, 391566968564879, -30088081623192, 870074451521159, 422783352752786, -752404068034058, 273126039552480, -1112378526824179, -810678636525244, 96429053513874, -197153575112881, -338660527941979, 874279430413142, 959217801504784, -846627508529606, 145522168773349, -223488193094310, 768135463506990, 173123489075291, -514033032961709, 418626953186771, -279727614653123, 23333512608960, 859417391330454, 331877305422123, -976074027850508, -454976794242595, -825976206456296, 307854522721772, 733794815062524, 51500859319357, 50287208041289, 58656859135819, 892600618900566, 446631400051377, 875610606076539, 1112038204400279, -629213238648357, -577055498844378, -996684682754418, 330103393324719, 779413142604725, 387182940826300, -56542528643706, -730616366312838, 816370577509875, 448684358107563, -1050709454243847, -688917906175987, 1073319326402270, -791380589797488, 722637909805156, -411040270277397, 184176997363231, -869421991358315, -552508789984637, 1094976976592030, 269224830664724, 55754694134550, -645604911041525, 1120343995477345, -1122566252092263, 834477351701237, 192827316068643, -125522448780388, -552757882694521, -312055161426779, 319825229839468, -279715385042019, -533142725046953, -997790140659501, -100950642610622, -87766579331816, 980654702022165, -531831430847554, 4739046943333, -23128276099200, -106166459572754, 736408087587240, 289062642712291, 930233877126717, 77764357182416, -450174307894161, -296173809788624, 931861580541581, -129851042962204, -293087464659959, 1116466762761964, -118822783385624, -931893015968007, -585335818262979, -249647342072052, -399005413403026, 290631332150680, -271235975257165, 960700470183818, 339724323258436, -778514562925105, -455578790229797, 820598153868011, -632361376871135, 170035906823228, -289961814723300, 1020092385539773, -212307506286549, 749065887545963, -1106751197579685, 694930372121405, -979416410281839, -627024301598283, -930462021479034, 907430974888217, 1008473792843562, -91216313350653, 109727626452659, 103314712168157, 509545786235923, -286784961619988, 1064251094762820, 997165842892216, 469944521626954, 1087278611407001, -1108452735291705, -864198430816471, -966722391151462, 151551631636749, 218908781840392, -508079597127107, 278257309671280, -211486365386816, -186778870987021, 363634300784002, 101621183780108, 26428167283446, -179642809987759, 645855656435636, 974276788414182, 151992650260855, -740683087569956, 1018656472882769, 45609525239378, -42622304242628, -754308828282822, -854028801556510, -999365670030395, 154057708609293, 374784775949716, 361495289515170, -707040739622560, -1068219573712335, -1024170497183496, 1070776055212169, 990690917208036, 932200709652558, -491563708056186, -49133681507950, -530789520927108, -593671028501760, -872895040066249, 470305380432482, 834557012161111, -857185072643503, -621982386272810, -298591002896505, 842219757498543, -514887262859796, 404320536881152, -641011955283082, 303239733234310, -1036887876000571, 1027489944852863, 981242602516223, -1104320219708144, -835193836849718, 340049831284306, -413604960517438, -780194068305202, -431981163540261, -298881545243623, 597648026587379, -317432940308790, -40807192145838, -1120785419310125, -330464192997345, 124351376233453, -800095904452143, -179579226223493, 992889224778654, 945915125052595, 980271928859414, 904690107713841, -899777257399666, 51343613909386, -688234023650781, 441204726684403, -371176624407714, 72300442591487, 51971474177113, -16426545464487, -428366430720291, 669353970752476, -438189985582259, -39369546535377, -363546768164753, 337462631524285, 622213468329766, 166905513363491, -692581211765331, -1099357506067864, 395822698802187, -37595012442566, -1047580776936861, -1045600752163795, -335540916148738, -410343429708108, -450799582411571, 347117092995623, 765943595462423, 855757263854890, -399907166223604, 1054378928353332, 306658204592241, 191640680458107, 390455294206366, -941774346541233, 336367819998737, 1021400933405918, 953099346256185, 1073859748633945, 763678798334149, -798047780084254, -559079024522666, -993971216432208, 675476890597714, -1122840898879534, -317677438164615, 620422080081923, 222639279977067, 1002506258451267, 480602461693015, -830743537858656, -304633451961870, 218540745814260, -509152381299138, -933381794723113, 579623656225647, -482229312551939, -1113544765586269, -600219910225613, -466060866985367, 832364873470823, -32049108990677, 37167750430610, 35918485064459, 950401822458041, -824325213720244, -511489583450976, -542199451459094, 905595777966004, -343092238022947, -1117174074410652, -734011479521055, 76231098906867, -1055061432914948, -881232388917530, 292352484032022, 764856237718099, -695351086381417, -665657799052262, 686535513361552, -710322854171819, 8981036502547, 45817279305737, 187585171642842, 84456369830973, -67888321234800, -204174414236870, -195374036988284, 414583334911515, 397691078217491, 159655051501829, 730659396893397, 959028039889174, 480720505184102, 301693796002437, 587919005784982, -966938410192648, -286578850388856, -98631838582778, 1104482166663713, -1005526292425240, 418945357818386, 1059665704660883, 737377295031600, 291143017368096, -419753619071078, -398720616906262, 143937541787224, -628703503207113, 1009734705623195, -600275739305204, 821748259782539, -657135745816216, 958492700048475, -33451666225860, 344607420230813, 76230576190201, -341958452248121, 879377810295953, -620323674317212, -464891366206414, -622543062773193, -195543012182485, -772013173800212, -261995345084260, 977899057820640, 995174655321076, 596128802996829, 913469211517203, 540965627160582, 311095585905645, 885874489248488, 1008426969431472, 468572188275949, -317120792105793, 193797534596578, 741355975454540, 99526256200974, 853348362327402, 877537022129670, 493279492162893, 594351199946549, 1079603478773545, 611668544706423, 698453854647244, 632951364006977, -944071568600794, 307694378799760, 157014812453004, 853486045800829, 835194717224839, 675953569983438, 234311161087235, -886729140965650, -888788984102839, -689573086860369, 612369210280216, -865794167739272, -392930288109946, 1050514315725764, 295854810009161, 315378431848622, -885668466092261, -431412868864228, -96593989614625, -776621483732053, -811957966913861, 474102849977151, 52870621520725, -474964613706707, -408707939062299, 783709996586638, -724017097889866, -969301234849340, 751231395655793, 988992140186726, 112002546252954, 341505810689226, -549158727280033, 409101776227568, 972038339154912, 135566449730292, -42800573136166, -890269132324741, 654601051732390, -849839417809201, 501100857323250, 868071925910339, -915178253892999, 71814011280822, -1003030727463715, 1060232860192790, 934500166825949, -923450385976399, 1100048374533488, -31070546246066, 777072914429395, -402953127590, 461799827091248, 826993099752919, -1082104258172510, -1156161279358, -388273641923198, -694416833279147, 988850855553385, 1028554730280646, -554330909326732, 792386649307434, -697588204027121, 1017518864400011, -1024426130050646, -1098971895372240, 1021626197601787, -1070980679316579, -131275451604692, 259712829836542, -936188432025706, 753637181753623, 569897843493593, -314812166378166, -476934723343417, 29870929380610, 52758500586383, 262278900582783, 315296255584711, 513580881991793, -687140097592059, -54001891374895, -189572664503503, -190237170782316, -955843298417822, 920004157872909, 1009576728558253, -136175778721381, 624444902432239, -181488118030013, -62102097309187, 61934003608074, -311556431246389, -86814768044392, -406589343230392, 149741500055655, 558018021915558, -265295471195438, 363450791494565, -747879221019691, 492698776576997, 283462289724972, 1020618124699625, 716275193159212, 316920812076025, -735922556616389, 700988927735122, 880079991609422, 496810102751613, 961438822931072, -428250922138622, 815521557912831, 494395822898618, 743550805715955, 124995981587963, 1041377295982863, 773957515188259, 27555834856986, 202062307485285, -888774789373661, 278088985869791, 992902840246865, 446415571505556, -791227889405819, -368419392595369, -459101757093159, 168610514227098, -355223146890902, -857109874777313, -426722147106860, -467216217090754, 353787975389174, 519803233466040, -1089778639056042, 225873280389682, -1083106720500790, -1035944381632398, -591909761383445, -762559586517407, -168567237367256, -158232680479784, -826739846800799, 309588265886899, -933272676782316, -353373147714511, -50704034923487, -18632680557817, 742519357869834, 33620784260669, -695372925188600, -53887336671091, -1096415999069942, 30209233886529, -351067136661584, -367997739266235, 119796096837598, -859649087168824, 995887454612616, 970310391561146, 922978283016993, -286428401008868, -670701254258184, -327136126361668, -306476803359504, 978576268751174, -103287345735014, 633257843963675, -493003664352117, 805821124680191, 628081644444347, -464846777662615, 664215228684185, 1065811786350373, -510344289557500, 441509020585575, -1028585465842689, 199926130445187, -593492055778316, -174376421931430, -699353450032296, -194589682228716, 473580501238, 1095097005252818, -538291527687858, 1056763862994800, 300001529803084, 943344737566322, 343939148687535, 1107836994646394, 595214836771722, -427914314565199, 1120639238983515, -1041852347292077, 613426930353647, 495914984763308, -341594875117500, -981924211109605, 496293055096218, 726735729586034, 634848465666173, 669151768740188, 570188457069319, 552431000907780, -119908858477219, -1071962346200891, -820546796228010, -1123392627305213, -125624454440357, -326301510046154, -452192001905496, -569055770573081, 10552212107, 1106190180928626, -126996582967796, -266157078848538, 368735163030279, -1002624159347923, -891460796959439, -463015934934208, -330060939991584, -245980444433967, 209321423890816, 67345600919767, -560749190666689, 763300300099041, -860274932240710, -813652868375928, 817133225734306, 31268247365553, 1073729135598137, -662795386039320, -13856526634411, -502014819445974, -149621606877450, -342322468323003, -505944042149658, 338189356892039, 373619031271703, 42327338842811, 98378227351343, -1111070783557021, -1072319619915991, -991547088577104, -539379502464645, 695679279357450, 726938253871986, 26959650240761, 286412211112913, 937840561735032, -505417430169180, -267317383540102, 1083021222582566, 354847794325587, -349357710751512, 77460996925948, -417443999828308, 872786543082860, 392666608918147, -762669381417237, -475355312834064, 662064037301589, 962840933354910, 494562111612758, -14524811930117, -727382575753294, -134442888815051, 361516407684592, 647651712246476, 926986701828378, -533108657514294, 1050181646177121, 829411345065084, -588998510407499, -361975235014231, 89805361518005, -306919263772024, 360960388715134, 732784014961262, -186502480347380, 543066211915801, -320028797168274, -359452294407072, -118431417787989, -1106750691881705, -1090742264534790, -1100248941922456, 1091219142258980, -631672124074979, 1112358142001494, -938764124556259, 386977818014254, -1055843861066784, -997728070289152, -357411743472123, -221616666736268, -478185353769849, -112973178151888, -773022068481207, -2845403486878, -653705873455472, -65730822756372, 240491511824022, -557996790919487, -898223285285615, 1053565406691902, -691551798924319, -709117812698948, 987176589961859, 209611118951132, -267262137022231, -353593890942843, 180903076968367, -77284041972494, 576615768643418, -208389671580134, -202299754794491, 13298971450010, 619945763694731, 779748573663556, -763470741717488, -414127160374701, 540418625569865, 122853754942691, 899410647296154, 359084330384040, -68417635999602, 462363975354085, 305935105799253, -782013796755724, 1020724104142023, -117942828824866, -437961250902590, 1060627763726651, 752703787958586, -546686685185147, 680052396737075, 202976162939771, 533081389620154, 1042369699052297, -462036935489911, -947800636049342, 478748215005727, -224155316063120, -736161718866411, 875641461719469, -882729158426870, -972429577996981, 463825136753312, -171265792085214, 520969678701714, -245735234127429, -56855020347059, -875113456203229, 460923088765317, 106466061790776, -612101869083070, -207466366705276, 1063751632102172, -263119738154847, -1046902855841426, 671943589814256, 309727229326078, -137836950211440, -710754923901197, -840059174715819, -1060957251111180, -364514631332549, -161420382162189, 162451504597593, -260170449264758, -637206251869872, -235913472870681, -565459997524097, -690607133679932, -337416654540828, 368621347360870, 596723446312724, -707514816394475, -496820741803964, 779697765781302, -595993825810763, 334105987847154, -1117025826233719, -573131218261301, 542955914214666, 235620166523698, -1075857935831740, -108648207115215, 754992864212238, -391966122664867, -1115561736753876, 312309427398057, -268027426614228, 316796350077952, 316882832411623, 215328709863222, -555441606177047, -367577818243664, -867906387333377, -1108665360936363, 91377028687721, 847355850947164, 152812258264154, 869249600912182, -863425547254824, -107492769515576, 447528055736208, -778980467343931, 716581059284762, -878441641795297, 917083020929485, 44869964520767, 632773893345282, -256604478366975, -645991188109760, -485045130900478, -296344973813878, 801023777071707, 936946268289448, 236656254772612, 837179615223556, 890096658841842, 311927132226557, -187366197774278, -825990601456241, -284501055396602, 1053133546048411, -379895591941564, 48781942472674, 4923355449226, 502969039830554, -618664083073569, 924387513057356, 564006988224030, 476729859360055, 1057565377286361, -716748293983190, 740903464538272, -105515379762826, -600500967999974, -156275192506458, -247601715583665, -973740842021948, -889934005321609, 296901571425922, -81192051432994, -593028951574836, 75989294161335, 395753186496214, 558090843358897, -486911184209278, 673720853106159, 821584460385320, 290818038033403, 561513563958724, -668451217223360, -833583437570069, 901717147410008, -322311956856341, -952886582187034, 869576854284795, 796436200216732, -884220500138601, 609387292720141, 141517382610779, 936843410761798, -577081736567526, 307724524252743, 649135433354797, 1119850375947736, -25593479984473, -1082755337446368, -478242108070817, -1028598074056038, 982996655131851, 520523344838071, -1121914759131742, 13263114442106, 457644715960836, 343193238425350, 177936067081613, 67292921503309, 452545542877090, 485982325910914, -353934059869849, 1042538393917458, -12736317105416, 1086021543696114, -951085655090452, -530414715595890, -627861055250282, 989726059853174, -834125835710196, -175133158498594, -777736761593318, 431913467504048, -204676474586795, 151988307210251, -296473171728292, -616405342285736, -99070037785964, 749916922018030, 945142332885495, -478885425976300, 853942641941112, 601516202244742, -876451854840070, 519271382363313, -247338585156031, 773823924321169, 176603093825403, -843398849203056, -1003460663385920, -342030241800761, -1105697391113173, 1010522363958957, -996422913823888, 63920563911400, 606255200853280, -468259567556262, 281002308407639, 641544060861186, 306143760393413, -149628546536953, 878036210906797, -835433375253030, -814163980606393, -475714273366660, 431887015184789, 823930583336596, -53137669700119, 18114364036133, -691502159654486, 283015682866272, -674499118545381, -528435012669823, -259952414045377, -311379042119019, 88700564470642, -90705392833427, -411499629134461, 78450246558806, -922957151753702, -70067789041383, 574747773849631, 1111843764747681, 556486123769620, -1102878946698377, -136863044866596, -1106393145917732, -30729440223262, -530628460754164, 1010925210117085, 305282964816319, -1029269181752756, 972624487451147, -71376930688293, -137125442366393, 430536724204647, -589383792392177, -351135375495573, 166286385101848, -1063536508945647, -1004002241541499, -670079022967573, -1030176100132425, 39468984860645, 936217348957610, -1107643885397440, -972004404673293, -909172614639342, 411106699067221, 1063814249447753, -271733839114761, -481499727798729, 842681564887068, -319415976457250, -821257397999660, 636357070303509, 139822338006841, 107548476263711, 703220413010103, -378414167905101, -347441424591530, -890410645913867, -107094605916117, -208418142479036, -699133308954750, -327801389504978, 498481408354366, 714087744115672, 425978817385295, 356534027337197, 1112443171047230, 231581211410989, 626509626576886, 948595981359844, -69356712568210, -1081511210769377, 692827020282321, -990289210235591, 231350112712985, 1124061038793010, -756300580677405, 992651606088817, -454333571608461, 53539606592668, 994968393656004, 1011246234850529, -862881811975678, 1020005580371674, -392150246809229, -46912353662655, 441831211339677, 631688758508998, -263995624443529, 557081705721439, 1087625288208526, 636200280550649, -892185600125844, -459063820818901, 43356432917366, 279405045624695, 356179155634132, -244935345524274, -496287643105961, -393830676213120, -219367044162349, 498982785542215, 341005061245918, 1096792390042542, -1095280901962219, -1117811041784134, -364813500830627, 956064967397004, -838210316488918, -866043274507890, -789343783501549, 367795352831366]jiter-0.7.1/benches/floats_array.json000064400000000000000000000456341046102023000157520ustar 00000000000000[445.32175578228936, 71.26165361584043, 327.3961663419041, 552.5762343844564, 203.16202449559069, 61.87158509781195, 181.1916474886267, 411.0600805327249, 51.13357400226682, 18.3569347847777, 397.06198965403996, 66.00996749548081, 59.93629503208731, 44.614894665393464, 242.32589396940202, 669.1281195067415, 154.16982516961266, 127.77699886854342, 434.14278477745677, 477.91542865948026, 64.44252945381155, 8.548677011139418, 1.1350098088662484, 7.269712236660293, 21.794314862404388, 383.74186840042296, 432.56987579061195, 33.02688406073059, 575.9371925935393, 123.11786931870564, 734.9658356313023, 67.64746113803403, 428.6298352558726, 130.64525490551839, 323.65366624957187, 545.6337078740843, 569.1013227633094, 134.62065923071816, 28.312826901890894, 260.8438877163715, 100.6948540283588, 5.023193545521323, 8.603472950782084, 30.74057348441437, 653.4814966711328, 28.932473592297622, 210.07809804847903, 613.938957468352, 171.7510567509926, 64.64728141895893, 155.20849467683027, 651.4746311462322, 596.6951839878459, 11.983122725302033, 34.579429488940804, 116.54478000347623, 378.17157975953626, 305.72105986103526, 825.0352254017706, 1.3170242008271678, 138.94953959508095, 179.88775582540754, 166.28428670416034, 248.47782480523526, 330.12477798070637, 737.9809075726357, 901.8302778717807, 180.68345550251252, 200.28929446791864, 258.6982218419452, 463.4004033949486, 303.64877563084156, 536.4559771676156, 228.39105264757083, 307.7602900320842, 37.337718277367145, 4.60984622412697, 23.279278122501392, 503.9696628330601, 215.32987516848362, 916.3454701042798, 49.756933922770315, 5.500754890483946, 97.51393525933204, 470.1389768909831, 13.331209722468516, 135.32191680089636, 242.91097572453853, 10.167697114335331, 644.2102588612323, 129.9680411483549, 637.4137672624372, 5.362137634109969, 715.5942994951512, 256.7003824855991, 17.10296093067267, 212.52046743220842, 156.61539411364026, 8.800214256755925, 558.1822911309316, 623.968417517606, 300.6310830784058, 633.0099257352596, 239.01544612193908, 132.68085404884633, 35.394232426497915, 291.13995021084116, 267.4396403266604, 443.7809198443098, 585.5339263475531, 460.1870316484034, 706.8439896002166, 683.7038228645612, 133.15532509422064, 50.88067734316441, 92.92091164555448, 99.0304944941999, 5.742396426514162, 725.9186676208419, 304.0366123252118, 49.90557098745663, 2.6447287431641087, 364.6316587087531, 208.98427596599137, 655.2159087331534, 16.87684003844798, 82.21618832447284, 38.572345028892514, 169.29611711296815, 9.735889876392571, 214.58982194472063, 3.977812808283264, 438.6197210319962, 24.020756838329767, 226.24105955600166, 205.45097309738105, 159.74774481170462, 428.97995073158893, 286.41088148512125, 40.16999689158506, 28.680136347126, 319.101348713989, 251.17135417011968, 128.2294466057225, 294.4304429191598, 831.2232685675125, 767.0257776268041, 494.0037399961167, 177.22525872545108, 0.6390616994176508, 174.68268639141112, 315.18071411687004, 4.339411116961037, 59.58905996161401, 192.6500585083209, 10.735943566452566, 731.4657441347897, 63.93227557517375, 245.55517114740573, 52.497405922783834, 27.705481306404725, 50.93575675897262, 547.7704184185275, 808.5333746720481, 684.399785422834, 391.6466965270882, 843.9941237149388, 344.92859299895804, 368.1067876071478, 37.037748349881774, 85.90344508360413, 53.845186188853674, 42.856028161455974, 147.13052571126943, 57.53539888364649, 64.62376454747512, 110.51377245382618, 64.82491944076041, 840.8739042702485, 655.2348022942175, 111.91766527356444, 126.20472491835368, 400.9180266103902, 157.06014324818338, 6.52942516720119, 240.38712817414566, 350.0664591158972, 307.3525988041587, 247.22826612339287, 0.09707591533940096, 8.038989605185723, 271.33494719166276, 35.77477103521802, 355.0131377535041, 252.2661375056943, 349.8262199779361, 113.35339768677981, 209.29224745383817, 201.06427662090374, 498.19413593238596, 377.5036366547618, 244.54811620786288, 1.8739820315741376, 173.43122504807266, 569.0628632698871, 81.74599620803372, 16.214016006071503, 626.7271276149148, 477.82121028777306, 235.6920758045615, 60.48939401072075, 273.00229488032426, 211.77411474051496, 22.683679352293517, 143.60624805613136, 73.35060317117896, 567.6573148045935, 7.988195323291154, 53.789466671443435, 7.624632833972108, 240.9597235479452, 9.681496016531796, 94.98454305453856, 826.5274857444654, 170.2392952942253, 290.2713746302211, 468.1933424606523, 525.4170527234169, 12.18532300607243, 20.121013158954945, 165.56164194015525, 46.39985228909274, 133.83541556008748, 513.7234038710303, 344.0954979206531, 44.80254384297389, 703.7420063041723, 52.49137002442659, 216.70064896672613, 245.6461339429587, 76.38158400848377, 102.34738302686796, 33.22396788168437, 460.9342035319171, 381.28572125335995, 132.39091064735555, 165.3530756462124, 388.4223105152839, 549.3294792617493, 203.54342076712607, 304.8151652940343, 35.7173588480667, 77.69572823682614, 542.3636991313757, 448.7914744618647, 356.59005018249957, 697.7316466311345, 99.20261646058884, 797.5826364514579, 93.34527458618311, 799.1228668091054, 740.0693609607321, 22.4782034102246, 31.568432039761095, 17.339692119950417, 487.56183745759216, 562.4879784852417, 61.45982555161015, 37.61834609225103, 205.9003745784705, 1.1172467724096915, 58.48697087019619, 408.0579406989306, 153.63745535960948, 71.12371992011731, 339.7875400364345, 247.47697957761235, 42.14594685893278, 769.7873485517104, 269.8086511202552, 278.56746262882723, 562.9234936446597, 168.1596704204697, 104.90184446492593, 73.06235730081491, 818.6183411795297, 4.082963817029678, 331.5370213847028, 657.1931071346148, 121.78184300989133, 98.98476973613162, 438.0472967026435, 73.4959875645188, 83.16286028804947, 257.62357658797816, 260.1044410403613, 303.95751085437814, 259.8028536039712, 101.58422151232044, 76.56448091172797, 42.77646283155196, 23.707347991848838, 123.57804479555688, 12.79425388258776, 150.0050545898871, 55.20727389033323, 357.29356054258517, 560.3794255500779, 386.5821248583325, 805.9098106952594, 799.0796419953177, 175.23290693368196, 93.98676416431299, 392.85860435387576, 212.1437124829545, 86.43687791106021, 674.2617231864782, 505.5736914268391, 31.14415677409285, 5.1925448454011445, 55.832889602430896, 112.18022376561106, 69.27544830073845, 413.35461070441517, 173.81135848438694, 675.7712211397725, 57.569456088410334, 260.09117419583345, 29.19011778251706, 168.17424337132087, 98.7591450116124, 15.707141435753542, 199.8398650358158, 432.5001130031162, 84.38073312175776, 330.72075965782204, 793.3265682815392, 700.5982264954687, 194.37548080747482, 316.5707551567287, 198.38036493043975, 43.602650587057816, 209.46250917155712, 296.0962418545932, 308.5457180935021, 221.09074519918875, 275.1667316824933, 237.7974509234259, 116.02715471216071, 19.83346120206655, 204.51351164615107, 116.65552017864772, 188.88030558765766, 73.26771746771084, 223.25728657235996, 21.479295649508575, 903.7940249888794, 426.2410500627051, 120.04139724670023, 164.25380529520285, 592.3130669739119, 77.52865552471147, 240.81401844271446, 206.70168811877562, 214.97738222878564, 419.2408103972946, 510.0962975026028, 141.74399576806118, 12.592112839650765, 78.66392901923666, 699.3035783747086, 133.82498225216352, 36.271321804535646, 730.8885621023458, 139.18098081011954, 531.7229472686662, 185.82193999703554, 408.5294808293853, 242.28078595870915, 490.5542212062478, 938.292022251062, 313.2637799866804, 250.32313314144497, 92.67139265313966, 284.5699646225197, 2.8724761931867615, 77.33030028939044, 566.9700335068081, 38.23954278944219, 11.62573149142236, 36.37691799060333, 97.87773229868303, 12.43146326053684, 277.4080850208361, 268.7387311215239, 236.74183599949504, 67.378525215967, 308.61758705859245, 212.80630809503018, 224.18350535048037, 137.52742211289342, 7.554168968332686, 3.684803384618582, 748.8130977421112, 28.693889817989746, 12.382770846505519, 703.1479691879869, 82.82315980434639, 584.4564989184796, 166.70618599626317, 352.58948019899594, 66.50472763781937, 50.69119488390004, 346.9713598757074, 16.056166391295914, 230.04690091747406, 525.7752742011932, 97.71593236029803, 302.48621091587154, 551.1131081822043, 584.3818579484189, 150.72093442202817, 253.01420633573397, 170.3511289138442, 66.44739845404273, 566.1068665767139, 209.31365722257257, 54.4725477199841, 406.8630316097342, 99.01383592874018, 372.8570497659973, 628.2854043077125, 117.06086928249445, 693.7735597098745, 82.00163209737896, 367.9368360681948, 7.115302301189714, 34.915661590352066, 6.672573371596743, 109.66196276712851, 383.0440527514553, 3.6800923096904414, 145.59364163389316, 5.210060018754351, 376.30763904885384, 303.4957043183403, 267.80005776866875, 594.6929220595489, 19.02734873988605, 518.8492554417912, 302.5910932776552, 705.0800947085012, 180.6575863491539, 612.308361553487, 214.6376069164151, 150.2614361798107, 213.53871295383206, 108.98630669395709, 315.7505522332845, 13.98689948529595, 288.8620204514602, 241.6615756413137, 308.74664546558887, 356.78030409999957, 423.47442300866265, 475.1033904214788, 557.5184248637977, 14.01824822208497, 192.46596374707278, 122.89020057544461, 355.47839068460803, 212.7230572106499, 554.2817956062656, 5.839216846382353, 27.6008171640561, 31.861534326911652, 91.8838590961286, 304.9207726040466, 495.31796328649096, 209.24896482482842, 55.71375022253595, 12.251492752625195, 362.75600248702636, 470.6675179884329, 281.68582669750623, 123.83502666060463, 214.66885650712845, 798.1426101698205, 142.80789382379317, 123.32879813824428, 550.3700190654939, 773.625506951824, 67.24261050884704, 176.8156172114429, 189.7978830258287, 176.24197850116468, 460.64820974914164, 912.2548729947903, 2.9112203646286208, 191.00378195584227, 791.8572814264063, 628.4840162113923, 828.5252185673664, 129.99282343915021, 273.3616641301517, 58.46634792077818, 131.7115933550258, 283.1301404428292, 690.0991680164408, 10.815804978729538, 282.37476171127673, 308.1937141637751, 47.4772475341292, 722.6035632742331, 221.7478768063414, 102.1830297913463, 21.27021569453931, 481.5100544835709, 468.45080676662485, 202.52176708912805, 439.4282552683798, 335.5550314798056, 43.017931706854064, 384.1832767197708, 102.4993239761275, 348.17850840995175, 312.45633754722553, 98.69450196909517, 0.36862192922553005, 68.83599996816186, 744.3244645818734, 345.54863483914806, 28.18491482671706, 12.576573811346918, 14.625978296198937, 379.31830551019874, 282.2807070213743, 89.5894197597805, 716.872568195045, 4.548077404616239, 21.587812150366908, 310.6776428759006, 165.6241289722075, 521.3146051357534, 319.08710544794764, 164.462445548839, 39.00129751158379, 78.09717702601645, 345.4360599262151, 60.854288465417554, 127.29441913097031, 58.857860394574885, 41.72105738192397, 146.14247265993112, 399.3502403830897, 163.7087652157697, 543.3228568606839, 524.8044040506846, 264.05318458670547, 65.55627409504241, 727.5017499650331, 490.1001534145944, 736.6487913245434, 397.6917478844272, 272.38432169050964, 42.49861362995276, 89.456439822773, 34.742524070489296, 248.3908047549283, 191.73532921997628, 67.32465535875617, 293.9379092749961, 371.1705560237598, 31.167011997191516, 217.58680959618232, 141.81028128425461, 267.2333323016145, 300.27775978019605, 406.3912214851415, 635.6799059118379, 81.25370515151691, 366.81602572582614, 219.3892928078017, 621.7710159155212, 118.85700302197844, 172.29676564446535, 397.17992672489066, 285.61128754346413, 94.36052369119474, 307.0280067936588, 202.43177178505368, 249.61864809543076, 6.394538208814945, 578.7400045719694, 6.308963717494551, 337.11401800616767, 429.10661894745266, 127.60790949145945, 213.57567605529798, 519.5852014490839, 4.612957447866025, 116.57974199638272, 65.52498598964927, 107.01594881974272, 289.56584258847636, 265.2824868323073, 829.7757422274365, 219.00028451425106, 206.12310755613925, 145.66813867741322, 772.2380401868755, 769.7758958742545, 451.40725270056987, 106.69133981279079, 75.39655876966403, 63.7449791431225, 84.48122117266087, 629.5314248981857, 606.4293987903917, 741.4516434151102, 31.29827444105853, 73.36061979151333, 466.3070386480815, 33.686993809903825, 270.0084400784738, 193.06991796596347, 450.43095889805653, 64.25344123190116, 147.73739835023673, 120.90498667265022, 566.41449662011, 134.65427899309913, 502.17768892789064, 163.94943331625603, 170.97306137289084, 253.8643482001839, 14.2954685323058, 810.6203260910991, 714.0271144902787, 24.936684221838906, 415.03291379665194, 695.6877968263259, 366.5330448028534, 48.88978784736481, 299.05402539997175, 255.2850118264632, 817.3129953729247, 353.5327539332803, 182.64144870676049, 601.5747570710837, 34.98302496818031, 23.139366009887873, 392.65651576412057, 115.95520250702147, 573.8014925918196, 202.0648784759529, 326.8535201604161, 84.8319627692996, 919.2534044244509, 105.28034683490789, 135.9744191736028, 83.43097334760246, 0.19802736401193632, 798.9520572949897, 499.2797319693313, 67.98284796434831, 46.93019462272395, 42.46459224270669, 368.3137945139897, 295.5678548565214, 106.92120216312038, 54.36158185378826, 464.6622366470618, 587.2540732122891, 333.241136260474, 0.6541126876010326, 369.42253834376527, 126.08952546012058, 752.382306789718, 424.2937344413127, 4.768318152561781, 52.82198582141276, 418.91268311140345, 594.2028347205832, 365.3420635164094, 43.278597408913654, 2.4368715275803066, 734.1320130671853, 8.02950629502742, 76.94832141301544, 592.3102098420899, 243.57039052714504, 404.78212655469775, 547.8522682917043, 105.93238936992397, 583.6557578630186, 122.19770948909616, 74.99520771880002, 53.70966257599581, 582.5097722565954, 28.252006192818442, 88.12416011921736, 377.89713308314094, 81.39623604675376, 2.3838529168302225, 214.8844226703588, 163.42273563531907, 62.12373827261207, 114.76588828718678, 226.75508511643687, 470.89290590869865, 235.60174639446066, 312.2114899286692, 75.12316178232729, 375.8585434937535, 9.410723249433914, 16.964406175641454, 153.9735190891219, 95.59111600490377, 292.376237231672, 567.9932795461151, 39.0446920715525, 16.6985512851649, 73.54119954060134, 480.90031594131364, 21.08816047213026, 557.4061443602437, 5.691566717745852, 115.51747801599385, 145.94859308775406, 54.148234325683376, 22.370992646888908, 336.5583595169807, 804.4926238978975, 38.3906857077388, 234.78529049987583, 152.9453648496889, 412.1942062269916, 216.94242213423487, 676.8164819032093, 547.0176864564813, 205.41043078622795, 208.30376160173154, 385.2333123726966, 709.5060852943249, 70.71333429523138, 363.77014004185725, 32.621262594824515, 315.8889379985525, 490.5225175314045, 141.36262244423807, 298.3426657788165, 86.89048761087594, 9.70213823303741, 185.61392529311803, 132.10671583162357, 472.52473629674006, 741.7269294933733, 52.66430688028271, 162.013077868942, 123.55068519630767, 55.713777718996134, 507.0054522099067, 108.62167237699882, 0.08502341553352755, 178.06355578576984, 282.3531438526133, 117.04929841392241, 445.0724350009568, 132.85597814284756, 5.932498114572707, 754.6790846053725, 767.8886219652737, 88.61891585831583, 60.88302666680231, 251.0264966058801, 319.97387264795884, 60.97062056439855, 99.26191737448633, 467.7797367349051, 531.5437120386682, 66.58994574173593, 128.49052834308227, 66.13497589110179, 793.5321246803908, 230.45644474922156, 288.909337464941, 14.885362245625343, 44.68435732254761, 120.0317849088159, 599.7498918080062, 59.68244284708463, 760.4806511901286, 289.97756610197905, 107.45790741289119, 42.384564293847085, 555.5483649030391, 421.39833297960934, 144.86270716766282, 483.6710863582512, 823.5324650740175, 281.3022944090922, 48.05934416183614, 278.1201146803361, 43.60474325173029, 50.82102509459469, 243.67667808104412, 696.6530515720195, 740.525974576397, 433.0000072893932, 582.2107707544733, 339.0381274940293, 44.64367677694766, 125.6156336880198, 33.703435313268734, 157.62228642808887, 334.31400699968736, 226.94988596479487, 449.55559047572996, 24.132118126868313, 324.6534013693348, 370.62021066478167, 76.0391920324559, 589.9782842429947, 684.070743093206, 108.379298695269, 42.65503780575997, 154.59504796936565, 13.574049466559753, 96.59102328222231, 576.0053124205883, 854.7102190036604, 219.42384576133136, 300.3138976065237, 555.5733973973445, 293.3484338725666, 306.75126837434914, 162.27960005368183, 230.44106110650068, 894.0923692929359, 296.64685465716406, 131.54075642506146, 712.0619549863698, 243.6174186353626, 337.687988989945, 24.771431640549164, 157.56048565738294, 438.0797964127827, 4.676713964829472, 372.9939673692317, 75.05947453146541, 98.62647780839376, 66.95664900916918, 575.4488046474394, 162.8526341939642, 703.9616863875566, 207.8689231599697, 132.50987888354217, 177.46609707080503, 91.03929964239619, 29.46224143458952, 383.43354147521035, 332.9767748985491, 55.88498235502823, 113.38583994306536, 143.3447900810264, 30.49163891078285, 399.6558110103479, 5.417270310158783, 61.344303896304865, 176.90370383958336, 66.88125932598086, 704.5622426089699, 507.9479981888596, 499.0776024346966, 543.9642935895987, 490.43759669230286, 278.5753787447815, 281.1616233186713, 616.7127508474805, 24.038741414422425, 687.6568325140552, 271.39119861391174, 173.99631483905978, 172.49774991021178, 436.61927591379515, 840.9865048203441, 459.1131435967032, 817.0672430968907, 44.31250829329462, 24.967703098111272, 10.061816697594633, 171.69685019271316, 92.03313368732067, 501.1661828719429, 224.67821338027613, 44.300757973524696, 107.77933879241503, 385.6363105416585, 57.790632482981515, 408.83118253852535, 39.429424278195654, 30.424264793719, 382.55358924905596, 72.01747599112, 406.97352323560136, 278.62330120725693, 133.5940915626496, 348.00999916543066, 50.893860033579536, 1.6638368413799753, 87.14940924794156, 1.5632610710493595, 337.51249281818724, 29.30058114932345, 136.5368526757847, 711.7255015153168, 32.235551435475415, 515.2061778746104, 50.57301010706302, 320.62585844839083, 209.75728757645558, 153.12143816133332, 297.9202390535216, 31.295893959714483, 402.5438384911535, 463.86930755779616, 26.611251590970358, 73.48363522344313, 111.52791362153408, 378.15838968304075, 281.02573528780624, 283.67205612075134, 355.53262585938035, 218.00667297175713, 452.673094429716, 67.80552089566407, 92.02922247712017, 192.96373571821178, 10.540440369438004, 505.2239747261604, 77.83013661653726, 153.93437833693838, 98.31900241098504, 604.7719735395757, 227.16150132650824, 354.48082871190627, 723.8178792654102, 46.669712561768286, 382.2807089938516, 88.07486261761102, 80.4909653057407, 509.92721907561634, 257.1758029384339, 66.0322767223044, 29.301157989997012, 757.5157400503309, 376.74602321581045, 400.6846627405593, 598.7645767511439, 408.5197918313817, 10.309133641859743, 672.0131049050337, 433.8989397721204, 16.62778638768705, 21.812484225397565, 122.01441100689564, 421.36773515058155, 437.82604717794544, 1.6896492370711003, 70.66543492924538, 95.25192721759788, 173.36378934716478, 10.051993123808485, 867.1879282408413, 71.63682445913597, 527.4072798679473, 319.32356093949784, 22.460599064757094, 48.739512637401255, 504.9141187050938, 45.477106107759944, 230.01956811385023, 45.35182174856778, 41.903542226103625, 352.60623774158523, 249.32248076432614, 0.45828722743258477, 79.61687709391326, 493.64972642333686, 10.23756975734348, 578.399256484223, 219.68276457281706, 3.296330883059834, 50.53600167391153, 280.2729005848514, 402.65157259977497, 809.8789488403143, 333.1244916676535, 28.247777108336294]jiter-0.7.1/benches/generate_big.py000075500000000000000000000010221046102023000153400ustar 00000000000000#!/usr/bin/env python3 import json from random import random from pathlib import Path THIS_DIR = Path(__file__).parent data = [] no_strings = True for i in range(1_000): if random() > 0.5: if no_strings: data.append([v*random() for v in range(int(random()*500))]) else: data.append({str(random()): v*random() for v in range(int(random()*500))}) else: data.append(list(range(int(random()*500)))) (THIS_DIR / 'big.json').write_text(json.dumps(data, separators=(',', ':'))) jiter-0.7.1/benches/main.rs000064400000000000000000000272331046102023000136560ustar 00000000000000use codspeed_bencher_compat::{benchmark_group, benchmark_main, Bencher}; use std::hint::black_box; use std::fs::File; use std::io::Read; use jiter::{Jiter, JsonValue, LazyIndexMap, PartialMode, Peek}; use serde_json::Value; fn read_file(path: &str) -> String { let mut file = File::open(path).unwrap(); let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); contents } fn jiter_value(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = json.as_bytes(); bench.iter(|| { let v = JsonValue::parse(black_box(json_data), false).unwrap(); black_box(v) }) } fn jiter_skip(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); jiter.next_skip().unwrap(); }) } fn jiter_iter_big(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); jiter.next_array().unwrap(); loop { if let Some(peek) = jiter.next_array().unwrap() { let i = jiter.known_float(peek).unwrap(); black_box(i); while let Some(peek) = jiter.array_step().unwrap() { let i = jiter.known_float(peek).unwrap(); black_box(i); } } if jiter.array_step().unwrap().is_none() { break; } } }) } fn find_string(jiter: &mut Jiter) -> String { let peek = jiter.peek().unwrap(); match peek { Peek::String => jiter.known_str().unwrap().to_string(), Peek::Array => { assert!(jiter.known_array().unwrap().is_some()); let s = find_string(jiter).to_string(); assert!(jiter.array_step().unwrap().is_none()); s } _ => panic!("Expected string or array"), } } fn jiter_iter_pass2(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); let string = find_string(&mut jiter); jiter.finish().unwrap(); black_box(string) }) } fn jiter_iter_string_array(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); jiter.next_array().unwrap(); let i = jiter.known_str().unwrap(); // record len instead of allocating the string to simulate something like constructing a PyString black_box(i.len()); while jiter.array_step().unwrap().is_some() { let i = jiter.known_str().unwrap(); black_box(i.len()); } jiter.finish().unwrap(); }) } fn jiter_iter_true_array(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); let first_peek = jiter.next_array().unwrap().unwrap(); let i = jiter.known_bool(first_peek).unwrap(); black_box(i); while let Some(peek) = jiter.array_step().unwrap() { let i = jiter.known_bool(peek).unwrap(); black_box(i); } }) } fn jiter_iter_true_object(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); if let Some(first_key) = jiter.next_object().unwrap() { let first_key = first_key.to_string(); let first_value = jiter.next_bool().unwrap(); black_box((first_key, first_value)); while let Some(key) = jiter.next_key().unwrap() { let key = key.to_string(); let value = jiter.next_bool().unwrap(); black_box((key, value)); } } }) } fn jiter_iter_ints_array(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); let first_peek = jiter.next_array().unwrap().unwrap(); let i = jiter.known_int(first_peek).unwrap(); black_box(i); while let Some(peek) = jiter.array_step().unwrap() { let i = jiter.known_int(peek).unwrap(); black_box(i); } }) } fn jiter_iter_floats_array(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); let first_peek = jiter.next_array().unwrap().unwrap(); let i = jiter.known_float(first_peek).unwrap(); black_box(i); while let Some(peek) = jiter.array_step().unwrap() { let i = jiter.known_float(peek).unwrap(); black_box(i); } }) } fn jiter_string(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let mut jiter = Jiter::new(json_data); let string = jiter.next_str().unwrap(); black_box(string); jiter.finish().unwrap(); }) } fn serde_value(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let value: Value = serde_json::from_slice(json_data).unwrap(); black_box(value); }) } fn serde_str(path: &str, bench: &mut Bencher) { let json = read_file(path); let json_data = black_box(json.as_bytes()); bench.iter(|| { let value: String = serde_json::from_slice(json_data).unwrap(); black_box(value); }) } macro_rules! test_cases { ($file_name:ident) => { paste::item! { fn [< $file_name _jiter_value >](bench: &mut Bencher) { let file_path = format!("./benches/{}.json", stringify!($file_name)); jiter_value(&file_path, bench); } fn [< $file_name _jiter_iter >](bench: &mut Bencher) { let file_name = stringify!($file_name); let file_path = format!("./benches/{}.json", file_name); if file_name == "big" { jiter_iter_big(&file_path, bench); } else if file_name == "pass2" { jiter_iter_pass2(&file_path, bench); } else if file_name == "string_array" { jiter_iter_string_array(&file_path, bench); } else if file_name == "true_array" { jiter_iter_true_array(&file_path, bench); } else if file_name == "true_object" { jiter_iter_true_object(&file_path, bench); } else if file_name == "bigints_array" { jiter_iter_ints_array(&file_path, bench); } else if file_name == "massive_ints_array" { jiter_iter_ints_array(&file_path, bench); } else if file_name == "floats_array" { jiter_iter_floats_array(&file_path, bench); } else if file_name == "x100" || file_name == "sentence" || file_name == "unicode" { jiter_string(&file_path, bench); } } fn [< $file_name _jiter_skip >](bench: &mut Bencher) { let file_path = format!("./benches/{}.json", stringify!($file_name)); jiter_skip(&file_path, bench); } fn [< $file_name _serde_value >](bench: &mut Bencher) { let file_path = format!("./benches/{}.json", stringify!($file_name)); serde_value(&file_path, bench); } } }; } // https://json.org/JSON_checker/test/pass1.json // see https://github.com/python/cpython/blob/main/Lib/test/test_json/test_pass1.py test_cases!(pass1); // this needs ./benches/generate_big.py to be called test_cases!(big); // https://json.org/JSON_checker/test/pass2.json test_cases!(pass2); test_cases!(string_array); test_cases!(true_array); test_cases!(true_object); test_cases!(bigints_array); test_cases!(massive_ints_array); test_cases!(floats_array); // from https://github.com/json-iterator/go-benchmark/blob/179abe5e3f72acce34fb5a16f3473b901fbdd6b9/ // src/github.com/json-iterator/go-benchmark/benchmark.go#L30C17-L30C29 test_cases!(medium_response); test_cases!(x100); test_cases!(sentence); test_cases!(unicode); test_cases!(short_numbers); fn string_array_jiter_value_owned(bench: &mut Bencher) { let json = read_file("./benches/string_array.json"); let json_data = json.as_bytes(); bench.iter(|| { let v = JsonValue::parse_owned(black_box(json_data), false, PartialMode::Off).unwrap(); black_box(v) }) } fn medium_response_jiter_value_owned(bench: &mut Bencher) { let json = read_file("./benches/medium_response.json"); let json_data = json.as_bytes(); bench.iter(|| { let v = JsonValue::parse_owned(black_box(json_data), false, PartialMode::Off).unwrap(); black_box(v) }) } fn x100_serde_iter(bench: &mut Bencher) { serde_str("./benches/x100.json", bench); } fn lazy_map_lookup(length: i64, bench: &mut Bencher) { bench.iter(|| { let mut map: LazyIndexMap = LazyIndexMap::new(); for i in 0..length { let key = i.to_string(); map.insert(key, JsonValue::Int(i)); } // best case we get the next value each time for i in 0..length { black_box(map.get(&i.to_string()).unwrap()); } }) } fn lazy_map_lookup_1_10(bench: &mut Bencher) { lazy_map_lookup(10, bench); } fn lazy_map_lookup_2_20(bench: &mut Bencher) { lazy_map_lookup(20, bench); } fn lazy_map_lookup_3_50(bench: &mut Bencher) { lazy_map_lookup(50, bench); } benchmark_group!( benches, big_jiter_iter, big_jiter_skip, big_jiter_value, big_serde_value, bigints_array_jiter_iter, bigints_array_jiter_skip, bigints_array_jiter_value, bigints_array_serde_value, floats_array_jiter_iter, floats_array_jiter_skip, floats_array_jiter_value, floats_array_serde_value, massive_ints_array_jiter_iter, massive_ints_array_jiter_skip, massive_ints_array_jiter_value, massive_ints_array_serde_value, medium_response_jiter_iter, medium_response_jiter_skip, medium_response_jiter_value, medium_response_jiter_value_owned, medium_response_serde_value, x100_jiter_iter, x100_jiter_skip, x100_jiter_value, x100_serde_iter, x100_serde_value, sentence_jiter_iter, sentence_jiter_skip, sentence_jiter_value, sentence_serde_value, unicode_jiter_iter, unicode_jiter_skip, unicode_jiter_value, unicode_serde_value, pass1_jiter_iter, pass1_jiter_skip, pass1_jiter_value, pass1_serde_value, pass2_jiter_iter, pass2_jiter_skip, pass2_jiter_value, pass2_serde_value, string_array_jiter_iter, string_array_jiter_skip, string_array_jiter_value, string_array_jiter_value_owned, string_array_serde_value, true_array_jiter_iter, true_array_jiter_skip, true_array_jiter_value, true_array_serde_value, true_object_jiter_iter, true_object_jiter_skip, true_object_jiter_value, true_object_serde_value, lazy_map_lookup_1_10, lazy_map_lookup_2_20, lazy_map_lookup_3_50, short_numbers_jiter_iter, short_numbers_jiter_skip, short_numbers_jiter_value, short_numbers_serde_value, ); benchmark_main!(benches); jiter-0.7.1/benches/massive_ints_array.json000064400000000000000000001715741046102023000171710ustar 00000000000000[128211105508572780711029371688501678008775479163271034841903, 585506593780215952124797935069780450355598334818861212366426, 1374395522329715192850977015105418998328502929300072210949771, 1139021064826394479639418521990008659026930473013371830793937, 1606679838490855529035341524029223326294219547950217257677161, 1123775304556143229023200693882877847488385986583573932780016, 704764849268732673750540590503099950297674361237229928124925, 247490846188342255828817248142654363661873447027261638342094, 661585036922495044671862638593720686010545193341380758050147, 787896401280357918770386812653526957855274334487056881600573, 1064937270557399112667752972586549603026301845503125893059789, 247392697218230522967416476401251890527999908623311693379653, 715589973392661682592206899890321396706815276171959576577476, 1451664439094687088726264662695534668272480540307752778413350, 864286459061317351371720609680610260568174448106441205182545, 1019614058196968140715189128156834122071010888806819018380296, 1368112548628657163562866701739059138791627822199788696359635, 1218649430570996500064882526778797213670832433497997117376127, 1057665121710968252910193210232879555633897247919798778171121, 445449755438709978251559418140786029003931106034376256523161, 990657536736775114300447474112782141390588987742468857859230, 732447691142513269873008439824606820908112525366039305215369, 759795543559640447820609940195030067585868187252532355891187, 391743196050713597194783084635512137059994643714498537514771, 1024189836534648711820423534926936685070478673676592617896861, 364164515709342092808281945099259426910311175954709273087043, 1144183527678670136116708173213921273756420138466810337062059, 332008942853537880034698187299802174339937700489519910483454, 1016238005594194482818137360376033149754646363832142928245076, 1312982393720517951343904574588695352545273338282231505583507, 580468257822908022503578058447010713060409233413306377516250, 563879647255277975357455712598158055518500657130426063948993, 1130011671219886938902920485778156003173756994969589133621569, 1055300414996400613883405259397121193739742592455784972634275, 631694720998630161469689477016278844530317473286203415413238, 656476428779597566163265796063417498724800920625818560241280, 1152402673156422055793628430083593579123129926712306630583894, 567557698563861259687323490243418770257281032261028048768374, 258269606421047199653432008125142001125650546507140691902709, 877741867106711787333289760593820580851738373211665309024603, 373982905990010580024665623066458920029075238473299474794862, 692786861159236617587002387969269623137253972090930973204038, 774112805199119193383980644097648737613553376694579525134178, 1203016150966461834009376636718420521376166662407964611925402, 1257448430171714163468985970202391981451048186140816684097905, 1560430040238728854454235765755691452986710833144978019076359, 290030421629029680802816202037843178895002965696282481007449, 545873490594716691537779491819207716682977434954515700272994, 804922149291713640595420958413715636802920081556766188497373, 58108193633655908112170742666164013654059866391595473997149, 877260088963598047841473855680016918087713682794090207309924, 311785111389620896153938306167679652281200496901850081112567, 336352158175570655152719599047355409303564360320732450913944, 1080942181953924905274502538094396093951220896147435944287459, 1211635316814359072048934509153501231364878496199246853045066, 539841648545347931113931269990009376969233313112373583529980, 444728564563734679326310795420770026938742968282943581367948, 34375765725736474914566188169900682484543340565258945469757, 753472199686076219359691784103549137966915968339348825292679, 1334599119550568403315361143097348233504395223071044970611912, 1186522175805109587885837141691067435468253873901094990963743, 55751600724727998748922740604486079471655634613877381789673, 1196971518231355367967787778934578403533839193924989780303412, 788114833941350889984127943156698188476238040301148464200821, 80322022092603430989073700052828433901177233843197310314403, 1360538235143796415129904678804768224286112110800863868555430, 295431172214856750340543709074169640447549498207071289864798, 675993214463873238646578937078448518612074876058802539725548, 900368345719336005310294149596446915043857813971748835422458, 998143957004229430724567190528350492084937174853801748381321, 297497757636612995778882390333725094956241058994757343706504, 370179717297783736166868525755233250557043773543515911880534, 579188320551951729909857823973838213233480859754127578115718, 1162169555892900581493807629737650445238059764574288570731168, 686834130625210407233414556546481783841866623170929835560303, 473521360016127309411863217073647974781772426781635835467482, 671043427868869822520916894245791973881489421432401569025907, 305879962273593795617316462701531424343741206356203922962829, 860242020909737283917226135454195996017494316174381798960555, 1435626654561102941608579735732061332481733323070242926825795, 370951094396124194253740269303583668491367887025940995456468, 656627975750327088870154107312041851132308807625104672775887, 187042269650393464953725163081350027565350897999997784482498, 388682703015370283304765193278665029769510859655910504148466, 977247970590207286367481184015059392523223178056638619247306, 197259742805714052100078756063773051001154508595808130380702, 453384019457775185688224048507447596983148809356851143865675, 1294174101043617612994978510573095839416860587526264689355977, 1522531085639841895282229343200111908464493085319966126990485, 711109551313246811325359640347112281982113279456622557320694, 58800045502033061560659873471324990203008193998050806128638, 1519195080295583617891727093230206965517211357397952643756383, 563330160147117905781212525749980539465009719443099834494310, 20861621951763575404239446546670517739732945022723874187685, 1045775247088342666581523445389957120592199849226369600687153, 372665618723872303446144812198168614492295081997079168900348, 1326157644698387052724090615664959743818254332484018783472271, 801260430265999054905834130128180698113572523729072698025090, 1035197486767324715276361093492679263956779046653139894154170, 1401930714444538938054883773547642479382346290552954671651251, 1008284083577278390398982419960619167306266968385961700560772, 592313821823312381822852045120715478653729864871445324552099, 1467285992428385996182974504134398700833629759559227215568929, 626515135934395934846279853970328912713592676230347872873554, 608751947955139961075036599085968740942335642522116647360263, 1450270083351259112041939324015714644865335576971079729193035, 747609833352589804425118312888099328912468421633638897687385, 689921631397343539504043854056612821681483238681446139213915, 635786027393818116963103462459432335023025075936331950921789, 775722509047710409223326628547429833956656138285663803228756, 1123123903881823989768152109621789667205483283085294890286844, 515524901900473565323192109124214410738544291813690282470628, 1327993602918768823630459209978238787627786181873096430186379, 398495148946834837715278912353878095232765923650443774852800, 515008239865015435687310420331599782508769681074581858783529, 685789405490065407378224196493527596050391119876072333956162, 1370136665765470568349731950171899832427217555323416418215625, 359720033515033515271839186600814162444504664097319145770833, 77701363841447522521307272818287597913781991793155014797200, 1460881513500092251532947610782645720629526443547583729916834, 1288955053804157996139140366934814292653476591749737405018432, 434465170850690252487972050538692460974665097907166706046967, 1224743882509085931292442019423352527441788948073909511704271, 530381449266659049916874181353993785516372256592206190260411, 279592885536173484690788979431421994732745392415200132343638, 854810203644759475753346141625851060272320681451176335262148, 351039665102709141948960050651549038245657957056589982578856, 451197021388914442534056675561617313193422338319866670603880, 1445501038265610046555960941709953947150550949031668914151102, 232296132143870310909234594693575373123633874467582371668508, 744825321070957825816232654205006980519213539503713627669339, 351723490453427286323738155873657681872947275998633801995233, 1002246372580011933158787011101601653256279301997299495911952, 1415197963689042235512232804762685181636316206077150352819008, 1169299076354464945183198828692184329241316056829179699894234, 404909136432037886219847499522871587911146252567232322692556, 1010349633940802123782032719581105768639747076839314322431370, 1229253142345736517767560835019342803173253383684283943591357, 203506501748554433415069894317053744047755059861011557908361, 582675497635524273826101401913012478531762633755748986796181, 1126801416184412351869461615011611640185844293201845332272540, 1247731914936343956981083003320335610448056339687332979785296, 395769004527444388427057553669489039749202730522700618068552, 1253710790878249187998456492749933493486539037846230078766163, 456509085949834021402993924950392952264285812602629570986747, 462891466424474633595487215701470574280899142493486301749813, 93443244089611332819388418002789863779854932305134372236936, 1254947463141610964742121325185126472912849767728212149822835, 1592412556429928706245433081001418078450798571703465727482987, 926237587172493380524618904725721399164442046925746967997442, 310245348835091003897546450633965864894147411335844113761536, 134905883244518719858423234631598300831735628381078255904532, 661221268438043461429660916952566724535056408467642561683048, 1212338972930055316377673317574609423795174501380217355622896, 34516705328781634724287022178202527607806667787539141099869, 288874787382877408691506705112158137170375327221960190721521, 1057837186357315961552357267065551085481700590959726271342433, 1011428117535473394532964882137034979368560656557540385137083, 1421138889712086202223326440594967959839215054524441817433552, 1476690649493606897186063943321261984376508114119894604826720, 1227997028892449169044375474771749114925845403032731573371988, 293198811610762792765460222235327885226765792970407349437267, 28771224178028509464701760934793315925060774063760299221687, 856019386656475562050560344641584543064680934585968834716193, 351975900482951161041043342915527158573401470236081656183736, 583600409254528224364166300579209664960030182546373794507564, 1375357246097555653392461240838084402819146274249271689419107, 1027066652192388518474005556802151436275584931302847149890379, 764631254628281798117238944813945145402634442495215522812486, 449408483010558990817448095889940671594395922469120592523864, 906757709923052872379586334911208652957915074598628721365479, 1002669060899127259761645467299895860323668762136482338218815, 107160106830433392428757755069920305817285579180536725731826, 372411103249016078656025356242343281229370318898070176746826, 1606194165042574223104680612407824746532955047113855807633930, 589429784451035605726008670286914999675538824592812481998695, 797466659229061119813043917096268363542429114713632612619561, 1223062740535188931736170685566899322308622533384442022891093, 1041616839033032760556060704100189969662261446966178405979819, 771058425516496528624236270416684326805921059841997837366849, 658761863729680639293067979807593457027630972062762797170644, 185887519043873158988133597367181979012356294143878473613274, 837792516866810330737774890846583597258637424449944256420223, 1321934857696764703817670423821292866014812489821950619880973, 715156872243886416522265973401786826522782116472365482323046, 249411596612538008971775157203387234729346990549970199624283, 716617785924359683977939731043191476516517754063475589818051, 1352886451947192152979374841440721452192268482520882182920386, 242068523696182913000581002214574386337166691084972777194192, 348808386338305398265543262767968962866762860990677614552105, 929003754625827379897384309171820019403155870199834971095628, 798176701395287276555182055553967885235535089003046820403694, 954082651926021163634786189494537358810627516045698861032044, 1570469979435065752206916615390017833366558934177042216542440, 297236575528709587862080474877138447852856277253806498827852, 614809466621280577266775381474602038111864654949621482279660, 1003479128675893128123986036294834342718428242746066786909576, 1251542646028683177122306701177941565806337040172531131265798, 1040542653664181211360336592540552674584216634798788825404857, 845868214392061087264236683800821514323570515796104022501560, 1166126471882789517179257627613863252545571145882848326241922, 577442061441620135571143744112930826330471597860757179334198, 953577652411010931009160249352633520889024088970522222841563, 604952919746994130364712970991502617634426216517254871958623, 231748910264049526834816558763503291957338267998493432894315, 17726648179836050307430536500111128919358480537963326996794, 1166517660293727499119147387851736580050262305157148443929168, 1367092489957543707180763475372540831757316565060385233590543, 489616016970201672777969095053982262409939912908906353290688, 313384639031168772177943718097706255333531192417524689300318, 619824727442343048033862421059576756498032586942065801908939, 1106400066062694719719875364389826030912064656855510645713406, 1010615042187352043620097829285774842547820021998973850540380, 838653407605328084374213912948120857237997394541672392465992, 300773680255971355028118580952018395562494516644483908976796, 1292499753878642522996182561983804221363367138144875183731770, 842681266724000784278045104391403774282061829112213568727762, 1400126748972566887090229544876946026806816602234210259266434, 1606476636178311837120355454199563678225381251463344648855780, 1325000513074469590056967411256262424918271949609637950040231, 1039117260610369156531626536267463430236937908365023023354113, 1099598312625173999932586532342115648267863312218362183681227, 426149081799230103838810381397700632035761890659809757993106, 1416195799694471859429376224943257315425143122799494621707862, 351228701375574477501809464448885035234946817610029186721191, 741856719646624471732561181875037324756549055490207057614736, 102551836594913248079215364027278244168182754267633374655811, 1135659611217247160855308979724719567430775919632458390687454, 144659254488277181292900051595114300175677774644924783112125, 1038101593696566399918805854746683235389807148243632231608761, 214610235854918760875813735555608072452084676692833778101353, 1407067946654084518115655946188646130066276988071588895276249, 1070413780301411388386953310895118513000315531161007186025250, 270381640448114890815662048063002333495292580993041145567293, 415210211723728268762294817030326194601742467130094221277013, 530569636674891171342574729122568193985525581390466759320332, 515604881950114767280780143484915263008598437999694686554483, 154588801181507426025122225654006890822371462980484705313305, 809758877582497268161590165070638375600935014404952367332220, 1363945171223667988959213866261072278764941520478204122928013, 775225499473813590628269062523657464862520837990542973255390, 609501139708859596579078228309645884182405870394079818602604, 951726601592046591906811037747308776721253983303763478657145, 376762707690215132287734608804469678895125403529377041931011, 423760221639790740048586830204273909202504375476746916432450, 1384030920781452946598612834195189488815928542628521060458000, 636135312145725443450090915989483421386584310265365077948408, 270804834721649113175500286097668561000282523633412977422872, 916170933613691869754689187531495215841724028463754967546767, 1606547883803703308091746584113746262351173228726448362669180, 1275675757836125598029569274387703319901441300064494810340209, 1390788465515270990612545335789993163743809420383911019514465, 374117461302608789537959486394267488214967317778041642957370, 752982894376646537983962105357067272843804594078727978221225, 1320307720293584434757721054695354318485358019404007017818494, 950302963040920086868051237543442909669041599521563849684202, 1092595580708788290344824086530893438430970931899364156369276, 188383383902596018783283199556459086611848971594234455302815, 821961697694325191767944307054297765964484551979360417491706, 884720820927167585864632123365552834734461597703231354205974, 251757332840050533333913852292777680958755037108947819343643, 1230706381238778593520553813682303546794101498158299358633658, 929024852877605111117949729915371760711443012486346565368269, 1023575212124950701465869186381103876375664413841943583991234, 964158783095419701499268691007275243710021739659527491056432, 1025010312155453037570878055338026239915116073828421169101884, 1182642631089626174856804160471723223888685140986198491450925, 249919704323303108297110273183080547802401344179227148270116, 675519721047682874485516976060748726177284908753838779546966, 278317329192816547872290563855385732197366767288144579249853, 56336003679968869981050015103142951140016210525379217089282, 1540652015928922772543109615058961905894533744035314644899344, 1239114228224644344751815667190628111970949444903608158101809, 574213807158114548547557603298895976773468183676065226694862, 45220235409314632567503794723001409012752529443074626628778, 527401139314228416914573438845641189888922818508409879950993, 141426730868330901721466918862830243968897771216103582892953, 1408552680413108417084928325495076099253680205607511559095788, 1604887555393042849864248610269770555925257353427772712185094, 711245023991905646507391508989985731467756494363196587523678, 842008486395427165348493422281426665640184360666121526254728, 686467033809506694249767832896461069890538743972034101178310, 703001789349562951611717797319569406270089695587736464021553, 1299735110752321555673323722196697651398177971384502910497348, 1351032953737829223967877491309488957955867741625845346980250, 125546785065118635436580264839096694062371851211295614858533, 729948991788606754921021719733828971719445271753109123396055, 472491337554273395402733330134397423361219758095841587395911, 822269728826364718476230794452880053495086722193884920477006, 532635377907763096070738116872484599695357426076980946273258, 258019744851568726559829581111647151861704056673504190990522, 1159970211515454545183022587197192968400948244629860671451655, 1405754941530405837187904550201304091983478427403914406050578, 149339357249438173342960949777787815309643213859091638491169, 1049666479874674399713071773327148174828142922389174625576711, 13136568048441361462092575885811732547907462723122132098594, 1235411152902242237858729537150898971437349132018840747051973, 954917045345100170626030844784292763322426811612513112665240, 1249549261754696967177828972737740607435535081699930314355838, 982921702557232338415312350597501521383986218639877573243994, 150126109812365066391065303319457539587530917187426768878825, 1133419716174379216370034291134355619226795393294608944062035, 650099554412241789435342249360185885320495056133438267893758, 233572168740427070985005095545040128438537337649893043121251, 145521450843150453725255580633577402464783991838428616545017, 365394094391316386493828807996105057146565336212680088015609, 259712979218098545676821296546155062030517015480024154709854, 803509426731294350191637697829724895559069746346136196645786, 665712591803905711630600132334670631739677703603312381064819, 919205745871215761980942907409605818240167743591209914929530, 185727255420742415657383542705890224644190198674933029717994, 105262522375553884196317020323664536465377257901273663634874, 1127197107500500210386599671811581943428316274862966537071456, 632223507973521557177805265090868074861358440708661678317123, 956210276495728805684452584052866605759127239868917596621576, 536203998978710266347898358218679436961173408908387655425796, 47977128753904235013294039098788135265672559066446280253101, 978803449257358955332342738854505421150577414005243351783526, 827752455901691365940007507560109748724232123228769364772227, 80342324754665844820925779868760652721937657682527019425191, 1598180334333453578567311920059759226902648804008625836098979, 146262518617378673337737324680506931869642282084632704022439, 476147365794456762655489905424560211232277606888311868739621, 482954710220091248995180512775099534426772826998949936422387, 50206656551320268636173740536792777850444701483562840776751, 1421974197719284039096999518851671443316427450062466322869625, 1175445982104442615425611803739895412619680547176331017506889, 483429038847202916637794236805675775098503253361546027476212, 591789060633324860542151916244632175720371365100742539457860, 490720402687203193652240114675427157545118147913080273508472, 808146091973136883781607131202530989579456991893390842330563, 354652385934278144649547953425811776759011070412461312334002, 894109118139258111461911712240195975726610943369052788720642, 227386223494435246991099056144194413214331493965224366179432, 1093176296213701662021613524926958176402887006370784290227695, 951282859446646252059196178999606899460222726974247506134380, 569428931474632127264720696006229982204583577894795886020818, 573682550283424722655497414997635947576605590756651807804497, 1005688882357497255785500875919327289431262660150373439021769, 1180103353431322698759338460908252383506915637077035592203940, 948130607872934931916779038350871062559556354384754285224298, 453634549146597087115070279376483664402538219796122767689322, 1243374620010529472202741791961063704927127634694671827933926, 126991197763914685901332627837075571722929040215389414407118, 559661984671729701450600732295504235623820895318223689672025, 203655832812464240662307658256568413468028146707321665609759, 1121449446113304338808897361189702076270580191011745775598535, 1097105000887586981833054317620049207769279405127966288807640, 826644755974684109311507783508643061973104236738140724281216, 170627243898648851441878149803128877508719580169084316818297, 1275675127836094000401039210746592663412867545490576668214665, 1203400802985337018206874652917929937198099062585054896481120, 526861119624665360759402172842490947048641873443654705741520, 1575000194428213523504970310504102182185184050015897025003506, 488211529358851838127117485220765166043686761444968366406289, 1592295917783225900212277171053444143631099196470379349613399, 1220151883636493775933993909038317167529899360272008666761081, 348004654440692748136733544504528622514153980009143736661524, 485504430942692406787624321298390258509768231577675515074754, 1284491594653957415271446978812714901899630880373488584119218, 534580452238523778911085983545950102466439943356912180195090, 587964092253413684979681328468730539785983535813688405831099, 293867127158913109256863613963250705899990865246736555420133, 1445689763551499310329404327823259671038956875655738011940145, 1423100512826006585696747638341286585537608142081357817625663, 157019916792981927735867740493284632573010588721454975712312, 1206857726623366325964812061349780727207983757321592363444159, 67982025926665522382170463633681980627806979078713291590700, 1415728548048694339917350435335412149272703913580721038657931, 677570019264045923042601100810111799198053930968542096558270, 1113153922723978417749045258679454191061637022214304252255779, 1483168766523428974522579138055505528442378185923204760776207, 189634340898292581516218253802178667939119899564598916767790, 1183726019130781810575969793305824057172210431138398377360566, 1085898151730701031977944871169211489866977859748955254693469, 1319014973752455820295242454009416816451810807047974590313271, 844212150954493408115881307262280212825934840178273700216558, 650836783790206006735139963591508995751419551454611985752608, 26535082380331755456186058391649933863073094237473378867170, 1288937253841589582978804108638296096792609672479009912339608, 1214865440615789800975643761134709709997746559582764835777128, 36896449812127341876831667457601691531943032087950299871509, 1572391939182179302148847944585586173283085416971812503421251, 1094897655940255405690183441970871445005899427018317525831196, 1503421987355667457689902449525689983070608985241440225516205, 199100211351166698696714272958671227146881479667171838935764, 1098423274511745556300337912252516490190049546862380899507870, 1503427310047990371158799411243967218590267370076381204520228, 928598235651226016975039811813769076021373518443276612377985, 911042576030840184058236834976834895312391979354020406895955, 951760784959401446394139592811333075379372375050881390676516, 1024354905866283051513199377064276780148681660161610134366153, 999650204956927240406519157825836195156467447951791055940089, 452752198958059263726448600709080203642388362363068108529231, 1431498591199305806388223083066833116848466885693749775401046, 1285122845582118508272966686781295931894415523919610710757642, 111921024871627730237166259188564654186892451365919444872988, 378274748000776647078591660957751428887891407558723165556529, 303471621346728066302503129329070699979926697859776355268215, 1420360645287843789476668491653629259771849409790237197311335, 793398946745400002590303088713052042241929906364719522652550, 1305354755141239311317748910240332884536502427963937596049763, 176682403967977235775585314562475393621899686976046376356763, 1073635683053186810698912416236273219323879008937570903507799, 1481385925306315636442174422260363767079005254656373804804108, 106190760035560743095297484096859000353777654881371714488375, 1284672667482123506931581921531308644914008055490572774106463, 1311655389434281333820938061551538137958054024301196271876424, 1541713994836193616708745033028820272293004915316259362752836, 166241336478188823039777220831901685769347390295166155363095, 609109330588077568282763030603310971898901843519071072708702, 443885354029534041264311156700586477871863642538895910095732, 743096758169942129399823147481041357738995772735370165529652, 1412535946592038796671887288245431217033285100793573940694550, 999853598557635642849636108786851329359332526850084128211949, 1140464205112584062871888869285817805394455150430655801140500, 1073835812297287201198664609788152961675912075606950827211268, 864691901115930206779449835945444521058399927209391628667015, 179816713382690453369119400007303262306424369013006107834386, 1402246047904692274617749865588457925857561031804437591953827, 925585294254334199815406834236528545765999342232386123616986, 325130775634230547581566517081518252278001073846822269328295, 302371344965016931780162264779730571130973703260006252247891, 744975469339551620236123769708723639875906542820659943262671, 344113247477951769861986666688725373305286024889928604051489, 221076147461135738715740982944445271571370361647414162428851, 926328702240837602186330038220445736928760479060042051619757, 741813203020762067261568926784272808051568492552174070136108, 1336809154226807815890507068445464023135721880135842268060471, 224877201465865586231897302296768042862231425531262892289239, 187566916839875792529694003674122383920689984547106972131746, 256499622566176305925974844096751368465432402744318586849708, 726857672802030289440571970153118258583297517008458013521876, 599959032013669658275519917671153616108846045163137267853666, 784865005247156999285698455996326572271187272793334031226425, 579013530342645151383217345275026369406536760039214841199133, 1390225386327112638466561174309168181823781360679592301441682, 599831967641431897444502498612837059022555477950534098300529, 285329896888208471784272654023570017844763113901243017188562, 582616351883386060786280634141818715177221234278395173961126, 1530648486482847125574934251450831655831477571947200897412258, 607674406840912793289657318642318724248044838487532912380849, 544199583307301881834075223625310997296750998132740481481777, 394900794215867162926121559572037884792671439788473995634353, 455077762851358521386554433221373946399855429876091383884473, 395315867707985092511029668584081405998278658079112472651069, 1041780440911429254173905760655776749939652825440244515370577, 1178532715718345777534699557781983346959606776261748749251368, 311703768236566780566563172443386066628805407882886450901670, 288757049817695382972102528821341045928637351036675732788866, 441163716563536739552030334776539223511727885411451791139751, 1339158496506569258793883129948982483612153328456771224852022, 1038834139648016603693061054437264197248245087912690616436248, 1043428550730526758876524299034026831697803934135186394619537, 1129305178914432032093307951946058924053316985299348974763350, 1003965226612201606123482093037743527302581283818487279639868, 448769389812885240326893805838850722268523317317404693577032, 1351823587373639521101821627407147340112472182808237404252990, 158459449272741938564885173442506263083990641331229413750564, 350567299099933612899688948127818122848193807625167987250633, 848911389025328208373965618483591854280884435188301670585955, 1566375838133033797325125978826033964810965173483567206878893, 522557415417425377060498283902961193544213399929950062492771, 1094153205291324438245650214137028139490852093091633149499473, 77345638374394896011177302432890375296541700759133796782333, 743620525275767868081379006671071147933211993902596852560652, 33333974086587874286772778892849840894930931262180055087571, 1070476332312671979355562271263364664010228513386105409322900, 881739597818999702109652468173577554201524212445313065528099, 1174807198501421576174356255011782677364903321511255338363359, 447658100796527091695490527279989650227367237734523674570105, 488582164400305840646235589999828028598740422269287671680087, 331260762671845130493312264202545178992267189842747289375668, 804215993572017274484757697375326448879927176962090982312597, 1251030424235444230689552044922857730679764998688612577956430, 1136804101570882958390069074578137021712278939161232513863212, 694619492477471333765784586135915909307016749052376572351780, 1544688062104305239926764040777129122089488453560759779739806, 1202567316631936478831965245182239945089268611027345540055473, 1531055363764077616260949293130235533128786425439393118193932, 136587022084030465375929878228419763058285264588448905924366, 761580792083982823711830307963536262195652012380424704281913, 722220269959849796507934185387184716849642651714918171467732, 402912407987404564436130634640949671363450847490642044036460, 1306680307089055900253895262843762509653858073507006710027147, 443677571588261359682648304011192208088217134998522211552528, 1391537683292528755452929958887308768245669297821998702922861, 1343602873035797537470571406254178111784233631810297881286161, 338011809263601140323793571284369871415251182185799666364758, 233211935247207379235870032693612453095276865427773473101770, 670596795555589282196247278776056632190210943049659662144821, 8384242564169174838257216399678917416924406609334659927822, 1405970686156962008805069429498701444257170382693028415151011, 763052179096697799278516243345946708362105930280155241804674, 1400271890354828986012878576406361170367748044041216541873346, 1091111285049720310086668655071226621078614100655975098076707, 989180632322333427293698176561459206641334950115290759061454, 1055498788515982018684883561061252057360657881248463430977330, 1533625856883883828161964307165966995820189413589924424395242, 58486390964261738620998002593640689225774012719069414986125, 1538664786233577706324717088186931860573169325130543354059724, 54684521253356762733509425717372617037262486231136158330278, 483400073383159935522753244221168049304836715278513397388800, 1152453707968421842568901819753753907645097173995940047723828, 778494007662732342901239724108226807546705201168412275522677, 769053029124879411318417181164490044859809861758558848346313, 1048986021721579402202886679805279313757754914104800676558720, 780041319518591253363623690673018941381725296276319696468558, 1588063556563558032453039693673579607153792728509959240422343, 339485601863506029103003275473934206557229415944622099463628, 897448986015393178545315586390365403847622594252368530510837, 657282055168518310818163840116823211936553420897769876796205, 259966461055313587232904316622850330345363975102274686574135, 805345800514679564964193596663705293884058637260876731251738, 1204763016997012924490781452489175804832684336062849610231187, 129775977222453055217842897603088717372109637303724385606274, 192642995706793495666276933280939804136903800862949596274479, 405395964504294353844415158723440431612135429773945529849457, 14942521602139432641882201384774935320880008100068357450643, 1324016617040871312283650829436776069308054086543263044715538, 1559580372376555194936930391253220984124506567306606934855476, 168416663391342671512619044840247091611954322196962027971873, 1204796570210145137651001083259803014797501938039393853299900, 524811340685475150050066991834490235462931697529717013335618, 1421274221161922237683937901415247670093454004444516292655786, 1033798186076544447010789698719131498681206285321921730452417, 1097013332198234499722941543142890103009282926369126149078869, 459194043982282490945485040201212072691574069352984139814982, 1180566555967270076266426824488162373789763556326372668240262, 36723591792197105604413818562232228173093318921308770555803, 1555336594114628913589110230318966749883948137516058448129409, 807126782209200364276024046398846441679649994943706614995348, 98299042606496585688877916521264637941171419031260615384993, 916559927098943411320542631470627903901904781126305682187543, 497176511782819899288563814337691231326824849258197973026881, 1376416712308453171199462977188236013952270901679211327568707, 90897056590539903732192895555041053574750254937396596635127, 715001424621855740410630136269834689972839009966889414296268, 222904977096484425181638333793569006684007420660992777176800, 229173555203646118914915839997046874866534474250921808943519, 166416787337263033602188654317572434139077736598690668546459, 1196527869404600314570049244826057819159110848316303054355675, 500493140381812813764349985249903474064880543567431934996351, 1094134766818669933562258701295234807433490920294309078811272, 1392965104637151368110312547924111870645824495363553539676651, 393939834061843008965511399355300395319845153212078640729073, 654926929207270972724609418496493553973733230260053797162400, 721846376555712940092283831365135500707508208912014402136330, 228430455030380307372714795587534077021700323307625722728478, 1058067749803682481198281305376064234692634896954829628274589, 380228756395987088526719816762483253242172471901050651696601, 1430744893213296502630584761266230223979790626837409913128821, 829284775146059930464901457045259469779778529195773869942211, 660065796741995081225150050956349596257456215283934612332150, 325321057546255173587088953186882286062811120136544886676088, 216658837513239211160407730192305126777920755060237907655717, 879702794503104015643848973175612821725000303419850510732198, 1063818851198108680290742710522554096591135403469239043075062, 1258641551938772963358087047114454194589886960741194741777018, 608187456873965634041995416522755564814069102469484762771823, 804818148002295982525572047666251214450653104864115274199942, 1298234070979761719617432999613400856903836773003924130348427, 1197303128982482297185248723277404081505808595567906816729292, 202788333315682368225219085615432183345289342639461461807113, 41060382862210507287969013441454087225756384706470850446584, 870096164660254024620929192361833258497904341661530233749383, 557990228223019826809929515711983977336421421013354711273283, 708705695091858186013903175759831513706112118053571000462409, 1557878671579653912146825826921188665625997059442396698904676, 1157675570786512140385945947030240872839087345612752232661728, 579505232851953148245709074221563770324913315698027040811406, 1057146261896114689178042137795965662896744035492663517364398, 1332596357797316895706279094299714618126985124671024768841257, 1254030008704558783890489195188037525845806589027779841990078, 1507149629161634258042523906029950414483623694686069636569968, 1196191772012938207373924678973864986163987041361118656333195, 827040516500324102299977947539941982563287600305704948248811, 198421490386307561681065993444612427828351840803191245631759, 534645873572048332799292882273379487509010384639289265080539, 769377535270529812060855427050767374961121074653257675542188, 1500151899209104842674750214715254831594117939723918578580185, 88973379453949744479834003462478702618670101924499962843144, 1033905733440010867343283201292722883849353928549924538345507, 1556999471111674911848865342152487515917300701109373861618000, 560116533270635996427693426929173094242046785253769544669832, 560526410687098768873199004754603040609547514758346243308393, 292159474606814182111942785800334538783266434084088196402746, 926434854605800306165540019188166149856704660956347307581983, 522339012926732525512466405398026240033093928523271774761066, 1512503387524583934232234370498734257706425818452904228408862, 1182144273741243225606035868640844251463785450609457014391881, 106668425454194817659813893850910975581061898278358904521282, 17277488999938693848378367929556077886120861480669470480587, 8606138098936979496189372696815227420448010314483984955694, 427146174599996326573557069751843241056261822371609213489328, 233247148393074459622774648187524488029829724308233318186323, 178403380977125502799467310338035372691827357179053124901777, 872168225934121184783599168011575412192349277951633255924153, 88551177747171820874385609119406884315210705098291316826493, 1247821397731582335891218909040214500756348387504512305845438, 243803492769396712546496113906448668697562260672269376544667, 1065622389074631930133661632548906838810071147063494222165858, 1508803937643852465662880484788527933275046171181123480769120, 980497307308548043329529207033061209240197039437659944615987, 415838382622078809404163783717872210951642733195259797225657, 1476745874299097723284163571659542078848845077782972163244552, 1419417711452788003467191353561027870080400826324039765216512, 1340925677816761305402989431480659842998339504625914738250223, 702672167691346875065773429085270032683837789096653085025881, 161352020236530648084801446172484559923926685335408088258870, 1010489739807173853206062543210256440082413857275199386400867, 369990657102656629622219146513299884324455087630642183413248, 1236419427301187271182406898096478076622075036683428882498026, 1468621798340515809687599820220859829621175155078085909463540, 733328378217878842332187161645720568411069784446333817248805, 264255810195824701488834025994255168156294345835857334837858, 954477722767966771959131725963984669094106961252495587132696, 1183589874727527642738067553026349378585186401897511368248859, 264407228620730421020749252519463903963868814279077442437980, 1172716448261614993239499512520395982501159242011119550459253, 1044852223098281934501722468664628667862207603983328147350752, 511401256189975583468942368912339169761994635730199605684224, 152300225436739249976902183388493053492116472821073794735501, 763809979473683373930324701674828935379416785171694348716067, 1210058498677210966658075177832912763331634298224867788614839, 847171702022460799896830190886654098795128240084022788927730, 948877653435479831181082937016234682282915659083590876930213, 1140849815487072358596119527488971844118377246087713480620799, 1571464837501304566348050424730369332968799544725096762009396, 1496344900594206135729493807218076781517276463632382492626119, 1127810141280820280378345645737154623977814004792181671706525, 278959518260955131418496014193469093379095727273254650023134, 833806747893346592578100307779006364744915814123883531363375, 1142239866387412718546490718105954859393827667719113580465538, 151274171943994827350207582910879986120548715837313230745962, 1105182544747779099701248319494534781823434207398864400442458, 890712325341322768555187033608236790126282875923457366344600, 918892301722695898434638014659911586512534714354343452426458, 1260194165538643117003394582358312928084666689134970235023440, 806756770207843270078270694027230816489675685453452169735250, 304467845555350029693113867511994335002669275879554284000397, 689826096984266590211563844560867053211042654636754140179895, 441686554870327442503912399291876309693171879408187057334688, 795480080131433220956146726179467588627374306487903848104498, 1411020142276177444318260412000803368519842506673636530545803, 1263887745629517654240075944646299743093095141260546968234123, 136167479702687958455772539949715501273553852070536480934806, 317388919621176777894268391017955274553932041194935999001760, 761266438707118152496304702814238255900758535252570854520070, 907745924573993707207279781433186805113094424837990311234044, 784188740364412574454719350319359717727362851860156939963426, 36705500821384049596644552133699531327018219039375204808042, 826870303096182902196415191034968339043833951575487863485303, 1586169947770544835185704941251621712586915012431938628024030, 1510905830107237645149111183115054206168948979061806628835896, 36897969974545082965910325805526826927261127254782133439468, 923771563247873166038535261454939007070765885755433606977712, 780981949032976798972773191090804757480342473556603816596100, 795177920717964322384605591096705248674292669728434205540744, 1354175650636621023655781384559030822453450150419705651767224, 1282393846810386868324546008785609982111179851641166854083168, 1390111894504349726595913276302819915540467605219774189772191, 12331223012138431168793220415128819899803398010537795545258, 593296422932771175670253283924720239794905569294132658947700, 1316229058207861067169737136859578548267194735609103220846570, 1220925318545065006201351160101654850629741503515515683751449, 1547273655814477026204492194515044485660575113539255899224631, 867461379273524712371595412754342504089849782220345190330293, 1264180165165253064054554866620041487612297839744275591400478, 843255004834752134028302701614168941251936362392486012531380, 613712363635750759348220756132555735529675946756113469400669, 1213598729421701343435311245821321823640196942858021752603975, 1294451487227698652395777834588139386746913140000941356797161, 976169646964394934618003503939783983818318702989222569491060, 998658784906598361922317926875143415141869067021407870089854, 1438053144432241490456979460513031333989346085387098388510839, 1511754170567303947476964052600640997062633683779499281719878, 1224827954986305982068627689722554724838917179970257689101948, 142817584619139266103317993547624637007427283646619436633841, 1223624098137641485553271120726565223349371541954829362633597, 1558360498655112232631391596444964052704429685789557664765653, 1374812434557560907557323605963335991506549407599590324652444, 386688188264487874117265708623819246797907606638245798185985, 1110809838102635810202079063783725648825091134943689622488951, 449148442908537400093902714687894677199409979699861585164649, 1011458705542225800034071348103268285636566557125357743745097, 202562205887349629671885787306129830253225487341611823909022, 1243658567676627850204135756323911210760073002453514560071655, 718039762335230076001725928154383786889918309775017961842604, 647150619480994786178142029156669622975703377568655961957527, 1235265391777322285032479249700911490561524548926211405846344, 955949793778637437047509207362512136496332354486008538216285, 1406095937632157084265986794626372766977759193092772126306083, 700430215309847563732755172711367160490086875655423436180806, 1149031191265658037202759519769900249345936833286945242370087, 1093350459230218035921826368141078212235138473746026387488991, 297994426440746452551016083027302396341285618601533910229519, 1089101723985293064842923947451642335196745029003923421762905, 975230084317513435847922823544366944391445674352350907548326, 79857304123943112737475843768988463119196870541957034023461, 1367804231315096261847571909101288174045054074049995031212408, 516179732716303352494152380976775812407877983469217969863328, 597872921061193588019432734157546112118462019521191241297498, 389678938047926287088649038826750631190504302787512133191589, 435115018962010167171725617375507759337668378969131251120842, 831724683806180336680504401336904491463408876382817139949704, 720397662083918594074977288961421845124679172038978389596977, 1562382778619513403949890500941431219182569513470867328263775, 650293767092248246201778960983905856211051912273863019191266, 1491710513937068724659494935296051048067060848703165641893872, 1130323298298798932392490186849327960892195620157877927040021, 677155723473540736691124552103732737975126547468966750111181, 1597709562751185423108036022144647940604026116171201679857966, 470709931180605089764388823452804542435283866548635580922350, 579840495948847956325811538177151872411665022723530822021377, 1242561741084986116581319545724357469109499768423028457174915, 93257012011619193112235309691782742760070642906146033623365, 270570547061209519220785550541563062464960635549860464678065, 415574237331529169561624889046547880974952883120687555433420, 977056605228671159607314370152141300844174810975209229411728, 141882828411254408874102415519371344009110393947287604791363, 1099585168251640111488747711983011241163508074944350318824337, 928690359395553619358322198283157506054836257121409550095057, 333834847193548511063973512741480098784249532850467268497112, 337733979072707619416331576565851273244356100960910644719258, 1081512865498516641546264243907548786688328915538680752858790, 297339771845112606133467858793039924218244709700239455562058, 1543072642342122275025981218690265498990466900701913564978920, 784882733182484433764776758271819802450304625456280057191456, 1606363737892910876333354416381855342537848839583272808553707, 807631785876872389928185943165462134052497094666644891592461, 1040121052202310620594591185933940490664399443924367225125050, 319335510758931346500789436566467108137200719419441190476950, 308270008187133039282386968672386096316780948584775793913905, 270626596256239274277907123972431952064778867299960510563626, 1136463848735290348978054614961017540395027866457117292837024, 344347374914703323502155865555237418163149659525281111643336, 1482856309538802552993826153898833825483010018467052317622183, 685761980178743737602070429548322661440088439888711415673600, 862322122577664949955773539483880723172764577613283529654239, 1422097220228530784250858721366204574152567211586940600810109, 705863141168279657130539452176424224337443838275591798553084, 248063290347869397550045436016421302427610579488334533859558, 187213455601640526487232344386640793408305285532661991013181, 790126291945344275019391050082079317821380327388791288597105, 560044958850004346491152946133011150666420028887708735869740, 406027194567545352047328067386612518186099611584601118330548, 582005657180958096682678670703055719175590707921631609731225, 207002425722354787268240936274303586920764813075952516147583, 1073648267939733897908600399901456676083080044613404244899638, 1591806584128062463519454445407008659265505718324594495854475, 427969089935751882972495120743742533434326055829350371833581, 794064500970365667217600026568735218563373046631260596035115, 1126083718342556952866570067015329564344161994096408933439705, 929593351558658855863268679005955822533949120130805624560971, 1371175202146644757757313693790996047330320966353666272576503, 1082072352325185869381962729604309492510115615924468897747384, 140428234216076772272941241605437383112864556466691693969567, 1368665649372578660299981813439751647451263164001839952521458, 855018472390204655317299992614704789751363313944356030150970, 653525100743221988217563981953742065813600455051153486286875, 1494865029560397433050466242907212504794612812226746198937484, 210203589556348143605479762761583503305086674968841125308387, 862049222045249187824971840266106473253805506676769365184985, 1577581547451113834414085964599415741939797042978741029286525, 471437266146529067508510795269351435421872279522999696921765, 761935604390527016631292165134539351104507575575335852278212, 851520861945222750063825351542917095528380860547688184880916, 532722428747002715242342942237076864348598993170300591209624, 1366946802647645384706049966818998572311920319000581727721344, 1197056208231374933973454657157276776499603697426069231607661, 472299975148900524740119536947207451866956880045113513343546, 412096687349485347588587125882473856540890064844562231084343, 849632246988465624401366628946471850506887890805557091899170, 1578927558789326052599022581638099189063401805938390642883650, 1594871823209230429489228926165239051312713776760534373475513, 1431280073878808639333252223250258970365705025775988542314164, 641240897027389112532151045478087089621935834711772722905824, 476211684462315277999906872144782451128395866646302967757180, 488210121464249295031569017789494928060006196270284745461284, 164533971916156434367771334524960667707156302898500920201010, 1234028544667903196013666121281747808312083050927030437597323, 239453486877702205254440798737694975096433078316538404313387, 1304137288079498622599739834208105735747516213399000933603828, 595355406644884406393002187209412783548485346103622068474680, 1567604613134099054644587486966837753748957587673339284368709, 1103590187702984927862289093430680522922963729314547068448132, 636544528187742291448851617535724626400442615959340136926189, 64257824115326142564357620629788492771294971800923290516484, 1389728419968719076570555716487542749327598510655742298767267, 1311505328063809250793856423799438234532348562736532390350439, 207125822856744718615841015032147303160088703952598532439673, 1387548077572261053846748487065627145332761055877567777919761, 836483209783981274780300143197838845523916670660294989844393, 804672758195182322337586852531224092830110489965498907805326, 901433181527065594559722123395237016919470977000382135094942, 731854960992865485059262207365178662166918829239894528051214, 945201808089228280372240057745918242984731192075904583714555, 1015922743730936066869640650525356217559562254650845220867126, 631637799367225277150698103441507965714453632891525609652469, 1273132979697391926590151339197906649652016388385730512578082, 1584522418695222525344197724790593624444387271486364917833448, 798903989968533349137118253627367338849591155285553903193935, 1174097556624888838460864748389294648828484542658055026009927, 1473476567949076315282509051558496271710957936333274399584431, 242844670512928067325474968940568679216745517293759603767574, 964261059416635800490545925218709215671910031932884561673070, 577639640497473623959546719684069547931722601979445495357608, 1317530824150391849258190033342876607952506401104672814860145, 394611651781941925505711982121238860491804294044080664318809, 802989912033631737889099220603698090670036240761710531242827, 511547000939991928731327635422399227840494211948150586346749, 899543079910199920123730721829009647671227185015815421611549, 29125887561475834008606867276389959046898417645046475427996, 868727975388451191341915273082623261453477675457096184200154, 588297547098166068828085434057058258975809825656780686980677, 1468133467013052620513782978811481860231997371414340322506109, 1199849989353190583782457886679090938565671890869012428407656, 1313042495702597342304644754172326980219030875094902891661355, 907185834687574314706813064686179450454574456968030654914050, 545848018725279407359477159864149763170241416884360576851895, 376683377642991208862590859278940102178118504948481082373344, 1217999496574739166378821005241809855177440850266916523757941, 486014068754122460772416000672955955001587336320389840224666, 910174291680252630092978070004379154251527362650649506221066, 638858564605438626167330755596699136318156216590953777329107, 1351742427380336342719146850036183731523590680360089424069517, 23724148732153812363417328154920115611183827423265610920981, 17253527166277205708549444624845084730391459745219586982085, 1067183402908360559081866978921803818593410296999270800319913, 37996878368888224564695459737702726389692817042317588839724, 217022787371123629528795419855569043064008437151209413710936, 1100411746737112636933393925202161537033297317537972631473044, 1153352126290360834693084730476619370583123599378861733424348, 555919654067408436296669205409375921150047347839793937319423, 515430561885895555034433275216426827073049812994148134850359, 250055252431444893815801888304619770442464272438617887279737, 618603502077527324787017041046272214244107695763348725170596, 1254724712041423669115673964807685832525101212827301845076829, 1417177042618706737944165602071715227670727725013707843680125, 373086938094097688249532968133115014590679723834552352833719, 1390954135405036542674031049682668870268472290395121934204133, 245316577195972824788849873057055957187377971398138685601828, 1171582569391143157549158086723681366837453696258208823924645, 556894571057326940031110980668177382303825430591750862741869, 1035924194522326514198669656416595857222051841314248263421352, 460768819312240325722371084755526711669054787668397111927940, 420998293837486208463327536631939905873541522115276636575256, 653275978005185670127724094661434124324892166460089294992321, 534857753104469344822066948445099242573741593161600610560001, 916722827695791692777575037887872589888219270637058425550211, 1552427439739749812912284323898701587697241950712840342280095, 941969624481248883178851927161930934310299435885696374045434, 1323039563839131734184187087895986035263899849595256985053957, 1079210287746824449062765543481735828779311313568839549243576, 1321395742777985059925174876099463984924216313585279150403760, 882834957515447737542709542858381513680794972185369757585717, 1444144675723608653003595783197368414508368776549438023642014, 1522497129375354703322228621179755273755840726778679753941902, 116935211288244377971343583284865766297881547060316963278906, 366549311211229171973699337391031359624102458490213284665286, 561879680683320371529639143516559031645986240139770999050847, 777573586004671235278703350431703976331346202748420102631689, 50920855034544291667988528489313232720744204048618362947991, 263930910001993152423611011001233784919980443273957040662430, 223525548818151897761882072975747942758996674558573218177729, 100957508400010838102612187114692875313365308682461459420404, 1462941092761100683171782373305968932965109442703157983936554, 1560405053475511427276466086500514549675182481462404964793794, 368763228299079200230379949782053720014355072465686082172206, 1111668228681618459418229858174899766292250464794585924745339, 50629698206734221345351667349273579919260157454982601909256, 1089869371523749162257643421827628852657916675328726703441241, 869477803544193834314974404652550751372125156796414266039296, 1044197147457907972355079071687716606000912365511570812542041, 583550595954454446235186648607761383302944265315113777635227, 806342999782271979274643859714960370308431772960371869863977, 1128428242336574101636343300982301603591762894524802207407224, 1442717819069850688580592667146358568670219796749755731287182, 969243014460384919681120973703382199180297943889791117212481, 43723472663182976739769634525664524953183188283285223577996, 612700124269684323353853057531547153924531482395057991719849, 322691953484814821170720261726630377782320104480522045906179, 250983314855354101450620819998037645870612243083258320048284, 675422555381029809450771803730715649208533376497530243051528, 370601340474550681562187510875425314082357081975914241884163, 309345545621279136998842360539039539711474220809830741593893, 882822456729201231190748800851022628404966729750573954212419, 64255225529337739599556809085083084549815443059038896410880, 880340930195886568469757157265119506362066901997760262602978, 382667094277327093293802854495098812123086358139418123187454, 249654312427011129199514393760938174363769393659511485750257, 1061200383552356770953198455373841926877746790535654676702881, 362032631662560472070938706552673402896144966537526261046155, 1276516898591153328427201040392246641202359895926832337808750, 340691178282672363106660513190116923705010431189750665624361, 1164129670930909952185565403199204912228487524910000668352276, 186090382990398482860888424158526203341668343614535323679992, 1197812142037858665778935381204657370328367034690293013799619, 1372814288471901243569258350280653346671386641985659721293396, 582946770354742251817622748779680513558431438712944581885090, 1412193885998521784546307279300902777338462937453274828031479, 430984006232590165568410300646805411735794083538416679971396, 1193236358253093713531015293654790115988652693862347663838313, 1246292161160890142160518237641361105778343731082302701869036, 704241434636868403182001570654569717481418211724542807043377, 886395503386184147432499196223282131834417023148159315006940, 1143353455370191043188350871060340041432284367598116446593447, 524704599141430450242317049193630344130926178577055748472375, 184450619811680006667937464535823297063408215510156441311130, 1398168620097498291434593074832738086038749815520796338206337, 1268979192528601463331180531243135180785546231169411529856528, 626175873098179265231565450425306001676374591245867205184129, 313682085382201324776278641589668765600716066373831730259273, 1519061959679841139099529944448383579116151251922492241185895, 583664490538664076741573392749033206477493544684307754720068, 818910361007395169915221704939199726487740022291760214359884, 1189136529015831104959528691165447742875291367643661798925388, 1597935811882853744271289422203517745499676401855331068814605, 697056605347514548915901818771835165075614164677352100624077, 1229788969702890643162983151874427730151655939160849441731163, 1530413462248976316418278428502254838311298548091169501076189, 1375037749730958192023654498745944548488713393120524968377248, 1335984994762543452013875086995519309788124513993670920202156, 1301074674435739590909146714727206530392432089016606893614244, 1504851419164979858323703304693192654739091404843822649022240, 315115677682348153029716244568199953573470642837065533791695, 499155348173092658758128607767406495792878458234845860693023, 248781160130563791249916347686557049360104319172341910171756, 542470754024465902171612528202779885316243053968174959181591, 463361307453281167822583108216981096643790731183733611975661, 635396995802027265843439630367718821502514328276491372560982, 400550152995687526351535594345297128548630785303989694303739, 772770702889029123634773808272122160891629997955477557304946, 1592393369321245970972754797893009866333834717101593515494516, 1068300272141780389998050701096675392811228794377831348614631, 755201476126063106220427343250094123236799342668731052047437, 1200332922409071951889021969521052461077406864027764264263983, 123903294801648089265569812857253091474223520784777981089753, 749379393870583105583928651526264553782481680031369720869962, 1224819822805317907138019433191791880707881378056763580947413, 1234848327443262899235532057556948833718839432146292359067115, 1296922842552039123436062227452056949967060573722520172076044, 1481812463841618536517540810967654072960063800614095645656014, 847069845607697043812568985521787397715628115413588495746048, 387149353917398511205551349920660548030968839616526734269737, 1518136343762559464450544883488913547460394190599559380962288, 1589077209052102505645264360365320630975291657399075545607749, 1115260152639446140908439422798945952041747399831517060342903, 1071963404626941552895989857920774571374312634197006276643282, 1154437442702036888712243685993448159645639227190048196465407, 557455667099095245556929267448209785715185359465862343436749, 1259164037105571808898988693626234312998386703574905343016316, 732481199511924517960278102877412225051268472963000601669362, 843291983059040317227732143561127393392865047798162466824816, 1066904841445602352305033111657556900432072445697670584356386, 354251809497481986653912503063865954768487135487125481145138, 561362597585572432911441624517342085273534458839115091312687, 304588778682824802386917608088329896141276803242646178642395, 1303574554977684515836177684005596697633331449165075193414756, 331483545130957528234515998825236156647750795983447190625675, 1303904594728388131807486225331515693105791240006271337763240, 684436163211514123035723867541491912832849568187088703394221, 968328472783710783383863443033224498888490174234865450304143, 624239721423434215881118473214826220356173647151094299469123, 861027343198004821703744925702873413148455331226171511581777, 877784502823305807878577844726071488399078873492925465529611, 956041743565649326798432018323464832997583970452173094675350, 589386463210604449969559123742650233496402602567549469515197, 52470265472502538112714453450460367003371153094522750535298, 1353933724945540813074592280111634316747940225053916522520655, 158512211378804092794139465735883475498886918147186451166637, 1199079450831898712741843356249212244443280748533171080497064, 143732690951218339937224426375244323449627898425586984033357, 1218631759049943420144951276943294809739977592852578415071018, 953617479479437444716151681446354189637935568320944013256924, 205297109076823454916525031730083483365146801452147676439125, 1373673768428424760225732646241787204647728318557133845253386, 694398669770069522814566802347682855496759197768126664463607, 1471137926628595947763249697068574917623088725236459791185521, 1333956928792662606782857727454747714455646606135034826566588, 1396721645819471166961174692987514289128547312392048669416717, 1513544402659076768106625444728587705625725462087819738987587, 930904085698278412494048045505890745659024652492872453916544, 728703661570645881821947368745992098102140854658082153426, 1151300622949142092136386932649739720520601941623784349087507, 392340797507429374808759184816685793575827614998820140083476, 715822120074294894680179077020047092420651843275639209676570, 1086447429807286558853977806053477459923654190880271845959884, 1131160872171513331232095221463290448852692061984377626363918, 1454646532046614553920073591496345016083349199069415622066811, 422333985265779541830009748383614181389753758935984645858667, 598856624062407937747706073128805885773713260477618047516755, 572787074311979999600206195740823335420977618995676979120471, 573208891310782504984967420826948333083659395448737415477254, 1166200582848374462345448711752214061348036931887466174043465, 604349615992290977207089276259947181583115187977526189089113, 1438714303777979951801289892041260247625253756841303956256554, 1134771341237886746928399281379818916646777378528823008040502, 1075006011535502328635476185316520074006917254747885836283199]jiter-0.7.1/benches/medium_response.json000064400000000000000000000044311046102023000164500ustar 00000000000000{ "person": { "id": "d50887ca-a6ce-4e59-b89f-14f0b5d03b03", "name": { "fullName": "Leonid Bugaev", "givenName": "Leonid", "familyName": "Bugaev" }, "email": "leonsbox@gmail.com", "gender": "male", "location": "Saint Petersburg, Saint Petersburg, RU", "geo": { "city": "Saint Petersburg", "state": "Saint Petersburg", "country": "Russia", "lat": 59.9342802, "lng": 30.3350986 }, "bio": "Senior engineer at Granify.com", "site": "http://flickfaver.com", "avatar": "https://d1ts43dypk8bqh.cloudfront.net/v1/avatars/d50887ca-a6ce-4e59-b89f-14f0b5d03b03", "employment": { "name": "www.latera.ru", "title": "Software Engineer", "domain": "gmail.com" }, "facebook": { "handle": "leonid.bugaev" }, "github": { "handle": "buger", "id": 14009, "avatar": "https://avatars.githubusercontent.com/u/14009?v=3", "company": "Granify", "blog": "http://leonsbox.com", "followers": 95, "following": 10 }, "twitter": { "handle": "flickfaver", "id": 77004410, "bio": null, "followers": 2, "following": 1, "statuses": 5, "favorites": 0, "location": "", "site": "http://flickfaver.com", "avatar": null }, "linkedin": { "handle": "in/leonidbugaev" }, "googleplus": { "handle": null }, "angellist": { "handle": "leonid-bugaev", "id": 61541, "bio": "Senior engineer at Granify.com", "blog": "http://buger.github.com", "site": "http://buger.github.com", "followers": 41, "avatar": "https://d1qb2nb5cznatu.cloudfront.net/users/61541-medium_jpg?1405474390" }, "klout": { "handle": null, "score": null }, "foursquare": { "handle": null }, "aboutme": { "handle": "leonid.bugaev", "bio": null, "avatar": null }, "gravatar": { "handle": "buger", "urls": [ ], "avatar": "http://1.gravatar.com/avatar/f7c8edd577d13b8930d5522f28123510", "avatars": [ { "url": "http://1.gravatar.com/avatar/f7c8edd577d13b8930d5522f28123510", "type": "thumbnail" } ] }, "fuzzy": false }, "company": null } jiter-0.7.1/benches/pass1.json000064400000000000000000000026411046102023000143020ustar 00000000000000[ "JSON Test Pattern pass1", {"object with 1 member":["array with 1 element"]}, {}, [], -42, true, false, null, { "integer": 1234567890, "real": -9876.543210, "e": 0.123456789e-12, "E": 1.234567890E+34, "": 23456789012E66, "zero": 0, "one": 1, "space": " ", "quote": "\"", "backslash": "\\", "controls": "\b\f\n\r\t", "slash": "/ & \/", "alpha": "abcdefghijklmnopqrstuvwyz", "ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", "digit": "0123456789", "0123456789": "digit", "special": "`1~!@#$%^&*()_+-={':[,]}|;.?", "hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", "true": true, "false": false, "null": null, "array":[ ], "object":{ }, "address": "50 St. James Street", "url": "http://www.JSON.org/", "comment": "// /* */": " ", " s p a c e d " :[1,2 , 3 , 4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], "jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", "quotes": "" \u0022 %22 0x22 034 "", "\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" : "A key can be any string" }, 0.5 ,98.6 , 99.44 , 1066, 1e1, 0.1e1, 1e-1, 1e00,2e+00,2e-00 ,"rosebud"]jiter-0.7.1/benches/pass2.json000064400000000000000000000000641046102023000143000ustar 00000000000000[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]jiter-0.7.1/benches/python.rs000064400000000000000000000072011046102023000142440ustar 00000000000000use codspeed_bencher_compat::{benchmark_group, benchmark_main, Bencher}; use std::fs::File; use std::io::Read; use pyo3::Python; use jiter::{cache_clear, PythonParse, StringCacheMode}; fn python_parse_numeric(bench: &mut Bencher) { Python::with_gil(|py| { cache_clear(py); bench.iter(|| { PythonParse::default() .python_parse( py, br#" { "int": 1, "bigint": 123456789012345678901234567890, "float": 1.2} "#, ) .unwrap() }); }) } fn python_parse_other(bench: &mut Bencher) { Python::with_gil(|py| { cache_clear(py); bench.iter(|| { PythonParse::default() .python_parse(py, br#"["string", true, false, null]"#) .unwrap() }); }) } fn _python_parse_file(path: &str, bench: &mut Bencher, cache_mode: StringCacheMode) { let mut file = File::open(path).unwrap(); let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); let json_data = contents.as_bytes(); Python::with_gil(|py| { cache_clear(py); bench.iter(|| { PythonParse { cache_mode, ..Default::default() } .python_parse(py, json_data) .unwrap() }); }) } fn python_parse_massive_ints_array(bench: &mut Bencher) { _python_parse_file("./benches/massive_ints_array.json", bench, StringCacheMode::All); } fn python_parse_medium_response_not_cached(bench: &mut Bencher) { _python_parse_file("./benches/medium_response.json", bench, StringCacheMode::None); } fn python_parse_medium_response(bench: &mut Bencher) { _python_parse_file("./benches/medium_response.json", bench, StringCacheMode::All); } fn python_parse_true_object_not_cached(bench: &mut Bencher) { _python_parse_file("./benches/true_object.json", bench, StringCacheMode::None); } fn python_parse_string_array_not_cached(bench: &mut Bencher) { _python_parse_file("./benches/string_array.json", bench, StringCacheMode::None); } fn python_parse_string_array(bench: &mut Bencher) { _python_parse_file("./benches/string_array.json", bench, StringCacheMode::All); } fn python_parse_x100_not_cached(bench: &mut Bencher) { _python_parse_file("./benches/x100.json", bench, StringCacheMode::None); } fn python_parse_x100(bench: &mut Bencher) { _python_parse_file("./benches/x100.json", bench, StringCacheMode::All); } fn python_parse_string_array_unique_not_cached(bench: &mut Bencher) { _python_parse_file("./benches/string_array_unique.json", bench, StringCacheMode::None); } fn python_parse_string_array_unique(bench: &mut Bencher) { _python_parse_file("./benches/string_array_unique.json", bench, StringCacheMode::All); } fn python_parse_true_object(bench: &mut Bencher) { _python_parse_file("./benches/true_object.json", bench, StringCacheMode::All); } /// Note - caching strings should make no difference here fn python_parse_true_array(bench: &mut Bencher) { _python_parse_file("./benches/true_array.json", bench, StringCacheMode::All); } benchmark_group!( benches, python_parse_numeric, python_parse_other, python_parse_medium_response_not_cached, python_parse_medium_response, python_parse_true_object_not_cached, python_parse_string_array_not_cached, python_parse_string_array, python_parse_string_array_unique_not_cached, python_parse_string_array_unique, python_parse_x100_not_cached, python_parse_x100, python_parse_true_object, python_parse_true_array, python_parse_massive_ints_array, ); benchmark_main!(benches); jiter-0.7.1/benches/sentence.json000064400000000000000000000005661046102023000150630ustar 00000000000000"Fast iterable JSON parser.\n\nDocumentation is available at [docs.rs/jiter](https://docs.rs/jiter).\n\njiter has three interfaces:\n* [`JsonValue`] an enum representing JSON data\n* [`Jiter`] an iterator over JSON data\n* [`python_parse`] which parses a JSON string into a Python object\n\n## JsonValue Example\n\nSee [the `JsonValue` docs][JsonValue] for more details.\n" jiter-0.7.1/benches/short_numbers.json000064400000000000000000000113011046102023000161360ustar 00000000000000[0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942, 0, 142, 242, 342, 442, 542, 642, 742, 842, 942] jiter-0.7.1/benches/string_array.json000064400000000000000000000012741046102023000157600ustar 00000000000000["xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx", "xxx"]jiter-0.7.1/benches/string_array_unique.json000064400000000000000000002576201046102023000173560ustar 00000000000000["IOAmW", "xACXI", "cTTBz", "nhreT", "HJCUf", "frRin", "SVujq", "eLmNv", "ThOmn", "BiDDj", "ORkKe", "wrnMb", "TWuOY", "tgvDe", "HfngV", "WuOxl", "EFgrf", "DSEQf", "yBuCl", "cQcTl", "RQPUh", "ojTIP", "kMWsO", "VwoxC", "SxpdN", "fnKod", "xeVCD", "zOeeN", "Idgsc", "GWGIl", "OLHOc", "pXkBv", "cVvSC", "CxuHC", "BrXbV", "BaQDh", "NDLxb", "rOZfB", "PIael", "nOKUA", "uzbpH", "XiZmk", "cLQZC", "tqRWO", "hyHHl", "eCxhh", "gigwq", "ZXWuh", "FUHRH", "RvgdC", "XAaHT", "dHkUt", "pFfyu", "GzAmj", "sCwDu", "QUWJj", "UmaLe", "Sdvto", "MgROw", "OlmQT", "wNgvL", "uKyMV", "oXYhL", "ccZvS", "xsIdG", "YlSkL", "dippR", "TdRsb", "yxWFC", "ukqHm", "YGWXY", "DQyNb", "NGHeM", "gBLNK", "hsVMd", "tIiXN", "odUXC", "qivfA", "PegEO", "xOBGF", "ItJbJ", "FPHPy", "zMPJL", "cQfxh", "hMmbK", "jBGNp", "AjRpe", "htqmb", "oDCDy", "VXZTx", "WwKWe", "TuqfM", "hmCaj", "SpUCL", "BbvWL", "jQQUm", "iwQKL", "sIBab", "XfjxF", "XHDHq", "gSNEF", "JmLfQ", "Fuyro", "YQbvP", "VhTpD", "ExYmm", "OyxUt", "MfwXx", "FUDsd", "KeJKd", "fLxfj", "gOtxR", "DmfyD", "esEUf", "Uegqa", "AYQqC", "vUUak", "lNrzL", "vNEaK", "aRsER", "DIVGY", "pjUTl", "nclpN", "JmMjl", "TRcPx", "hlIKN", "XgMwQ", "GneLE", "xGYDQ", "gQJmC", "JhNBf", "TASUm", "Lpstc", "zHnLi", "lFOOh", "Xexgm", "puruP", "ulYIi", "CLYFt", "AwWXE", "MkWOb", "MFpEq", "KYydI", "UvAvU", "zcxvb", "grIEV", "WWVkk", "bKjnB", "zQjAP", "fwCsr", "MjWsv", "ZpitC", "VPijY", "yvWAp", "ImtUR", "IWmVZ", "NURzo", "VYvVl", "eRUaV", "AsJKf", "jbTmn", "TODbL", "EjSFy", "wRiFm", "jiNQQ", "hHnuf", "OWpAC", "ZvrUT", "OOnUC", "NGetk", "qABCl", "RUlIO", "qXhgt", "DtxYs", "jRoAS", "TkCCe", "QJGxg", "zZBKa", "nSVFj", "DBwyZ", "lEdiw", "hypRM", "jcMBG", "BTAJb", "eoYpo", "ltmPS", "mWFgN", "gkgXt", "pxOCU", "XtiEO", "xSOTb", "MLGgK", "elFTz", "rfnAE", "rdjwP", "kBigm", "KIiuz", "Djjio", "pycMm", "aTlqk", "YNFPY", "jDUGk", "dTKtB", "mPREW", "RebtM", "NbOPo", "svEPH", "QveIH", "WWnQM", "VUloH", "NRBbv", "zQaHp", "oBqgU", "dWtbY", "DiCSu", "asWzv", "Puumd", "dGyEh", "Prfkg", "tqlLl", "wDdzU", "qhgHc", "BGIHu", "oMxgC", "uOsnN", "wCQJs", "eOcdq", "SDpzH", "QvAaP", "qvKjg", "IrfEq", "PyfHq", "CBqld", "TKNpi", "KqHhQ", "vbBzF", "oNzYY", "dOdJl", "WRYtw", "FPLTZ", "crdhn", "ushwe", "gyhPY", "YcgOn", "JZrIj", "HKQnY", "mNOeZ", "pSfXP", "gRSMr", "GTxke", "FIoVV", "QguIS", "fmbBh", "Ebucq", "OiFhq", "fARhg", "kKwLU", "AWamF", "uoAPJ", "VZUED", "wGgOx", "STKlu", "suvDs", "DhXAm", "MOmqK", "pvgXN", "xrPZK", "FAQaM", "YJgPS", "ACTSs", "bqpJi", "INvzd", "idFTX", "ayHVw", "ejMhF", "dbzCP", "mDtma", "YxEsH", "bUTfD", "OjPPB", "KWdTx", "ciEzN", "gyuzZ", "jncLM", "VisQz", "YsaSr", "dFmGL", "DTvgS", "ivUts", "WVNqy", "tBnxB", "rNMre", "QXWMu", "hOBpa", "ymJTz", "EcOoZ", "ObDwo", "LdsmK", "mSGpi", "QYzhK", "gwdTi", "kctUx", "BcbeT", "AYivA", "cQPHN", "wtWkB", "dbzUq", "LXODX", "RmQLY", "CUhFr", "PtbRP", "lVNrV", "PZnNQ", "CPedc", "IAoZF", "Vwnqv", "JLzRa", "DkDWj", "jSmjZ", "YHHZW", "kMWMA", "yZGmU", "ZbDWD", "hJuyf", "reRht", "oRwRD", "eMewx", "wbSeL", "tcMAk", "hecHR", "cvWRz", "OMTMo", "KvNUa", "ICyaV", "fLCUC", "aRSGd", "PuCpt", "gSZSO", "hUqVV", "lJQas", "rkNwC", "kghXs", "Dcgqn", "bawUA", "uSNGN", "pCMxk", "MWFwt", "NJELt", "OmTVj", "wdtEs", "FiKbZ", "XgFoI", "BjxsX", "noTOQ", "AmzuY", "hzylJ", "BRyVS", "awWfu", "IejjB", "EGedL", "yoFuo", "GBDhD", "akCDz", "CNBHt", "nwhoi", "Zfjdu", "hyyNX", "jOSkV", "GjxxA", "vXqBk", "tsrNM", "RZSzP", "iUipF", "oXJSs", "tzZNb", "NMFpl", "FhXCV", "EKFJr", "XJfhM", "ScEji", "DoCtW", "fnolx", "nVaRn", "JfUGK", "RBbyS", "RYsiJ", "KCanS", "HrjiI", "OKeQZ", "bEUCW", "urEow", "oKimH", "qwVBw", "ErLgq", "BpGZh", "fKuLb", "kbGHN", "JnrXB", "RsMpM", "yKnax", "CMjlW", "pZjDO", "lbynN", "xLIgW", "fuBxD", "BmDCF", "YUvty", "douIc", "LFltd", "pyXMl", "ATTfh", "cYvaN", "WwkDi", "KCsEb", "tBDtP", "Cnjzf", "lxtUS", "zeTpp", "fQSjN", "Swjrw", "qjwVk", "BwPuI", "RlBWf", "oxVNI", "TyHRb", "dhupU", "lPCFn", "ozIHs", "TrbPK", "TYvLO", "QtkhT", "UTgYt", "PVLbH", "KVqNo", "QBiQl", "EWtkh", "JCfgg", "BAQFF", "TdTnM", "GcZOb", "fEePZ", "lFQqP", "FmwCJ", "fBGox", "qVKQj", "UoNVw", "SnmxG", "EOeOh", "VRMLl", "VznXu", "CfmTp", "JfzDd", "Yjndg", "YJWuz", "lMCaY", "ndGHn", "UyEcp", "ndnLm", "RQEhT", "Dxcbn", "RRQOJ", "UsCwS", "fYrOx", "iWjda", "nzuXI", "wyCwg", "Mzszp", "yHeWC", "nbxsT", "fgeef", "DMzVV", "xsgko", "pLdgu", "aiHlg", "QMncS", "RsIMM", "kJwei", "XYbjV", "cTzqC", "eVBba", "sfikp", "aCwMp", "XvvAx", "NjJcY", "YbQww", "DaKIW", "Yhtkd", "PtHbC", "AUBrm", "fOEdk", "cChTt", "DJFUI", "kNTIb", "eEJbH", "kDuHr", "Deafs", "PpXJt", "KcXHI", "nKvSj", "oDbrL", "SCmlO", "VCeLe", "CLZij", "reEwA", "nCVVi", "LQfAf", "tPJAR", "Ndhfw", "BffOC", "aWYcO", "nJGXv", "mhAWo", "eLife", "oMbra", "TrkYV", "FOvyv", "xqoru", "kzoUg", "OGuMh", "WrSPg", "pNcHB", "azljI", "hrese", "CDKtd", "bzmWk", "Ohtbp", "zbxJk", "MGwoE", "XcDsR", "ftDOh", "zwjbI", "JpNPS", "kZUfH", "IZUrj", "ILEpc", "wQDBc", "YWQUz", "Qweii", "LRpSr", "RuyXO", "nvIDF", "cMpzT", "ySVTQ", "RVhrV", "tOvgr", "knbXc", "pOkGy", "xATxJ", "vOgrS", "ODfam", "GHlkY", "nUmpA", "MQoSb", "gCxoi", "azUJB", "Wqfem", "hTikp", "OEwgX", "sDzFK", "GoAQB", "RiKcs", "Kdmyv", "Ytrsw", "muuZg", "vQasy", "zrSBI", "CpLOk", "AgMyH", "eTIAP", "OnAVW", "IcYcO", "Hlygy", "NxRlh", "tJfYL", "MKdCg", "JTIwU", "hQbvV", "rcwCN", "CuRcK", "bHhyv", "wNbSS", "UpOzk", "ZKnDR", "AaqHo", "FAIHl", "JSlMC", "Dqatl", "NKWIb", "ynyhi", "nkXfu", "drocD", "qEqrM", "xEFkG", "EOoSl", "gMbnD", "BJlVK", "Masud", "KtrUN", "PWUfA", "zFpUQ", "MOyNX", "czARR", "qragE", "ALHED", "uXiWo", "jWJca", "OVawY", "XCCWi", "kcEhq", "CaMYI", "WXhLo", "QUnZX", "pCogL", "nzcet", "EGBwE", "TiCYz", "UUeyZ", "vqaxO", "oQlWh", "yXeTb", "avtsr", "AbqyT", "EnDFA", "zTuYq", "jIfJT", "IakNs", "FcUUI", "eBXDO", "rzgun", "GQOzA", "qNkZJ", "ftxTE", "meLrV", "pZELt", "adTnO", "IUWwp", "ULDdS", "nhzaU", "KJRCF", "scWRf", "shZZb", "AmEBX", "YoSDQ", "YMoJM", "Wjldp", "IiDPx", "fWarH", "Ueipt", "jhuzQ", "iRiXz", "OeRzZ", "RMoBl", "lfIwM", "eZhPM", "yZbZF", "xhHlj", "eAkZh", "rdTen", "iDaUj", "mMMKL", "vbqvF", "DDAcs", "QHAGU", "FzQzF", "PPCOQ", "euVxf", "qjTzx", "KKDpx", "BIXKB", "yGthC", "DjhKH", "jAykr", "pIhOt", "jndAH", "WJvxr", "Kadih", "HbnVB", "DqXhi", "USwSK", "UILgy", "kmGJa", "aPWFe", "YEODp", "UKEHr", "PwsWk", "wCDSz", "JpHTC", "BMwZW", "GHcYk", "Anmvn", "Zrudn", "lXokW", "FaulC", "VLrGS", "bylef", "hktpE", "zbuyN", "zrogs", "wQOEI", "OMKUJ", "RADzL", "ZVUaB", "gTulO", "awXCq", "lHhiJ", "SPHCK", "WziOu", "RmTNE", "gSzpJ", "gUKwM", "ifqZp", "Uofle", "KTCTd", "byTDR", "KhLUr", "KRhIl", "jKHzL", "OyBcj", "dnlBy", "cDohZ", "bdAmq", "lgaMm", "WAyQS", "jjMyA", "MHHRN", "oNXoj", "nXTDe", "EZDKh", "qBDwG", "WyDkd", "YKshY", "gPFPN", "oIFRV", "gKKjE", "YYCZk", "orpCk", "LUAWM", "QiwRP", "uQbPt", "dAcRO", "BOKPM", "eWwDw", "KSlDm", "jxMoz", "BVeEb", "NCIsS", "ePRQE", "cQNLf", "XYkfA", "XJCJb", "UXbMD", "ZLSkY", "aIgbL", "OuRpv", "FNINz", "TWgcN", "tmcXw", "wVJvk", "Opivi", "IrBGj", "xMfzO", "FFEnX", "XIPXP", "bhsLG", "DJwnI", "CDwkN", "dwgPy", "SzyTo", "mYFld", "SbjTx", "tyYYN", "IGEUP", "fURZE", "QlLwm", "jSXZk", "TzIvx", "CRlzj", "obqtx", "HMaGi", "OUIea", "YOkDk", "mDKqP", "idtZi", "IkEsH", "rKaai", "hJvFd", "OPCZr", "WFzUT", "LjgSO", "iUuap", "KzlPI", "aGnmk", "XSzJJ", "LRJfd", "nFUAq", "SefyU", "JLWDj", "SxpVz", "axUZd", "SdeDl", "WuopC", "UrFlM", "GofsS", "iJZtb", "sYXtk", "oMOHG", "EtjvZ", "NLfZV", "jQhlU", "bKKPM", "MXBnj", "hcqJq", "kwupO", "KPNME", "ntXxq", "hNxmg", "zLnSF", "YnFyu", "EdLVA", "JRGno", "oPtts", "PDuxk", "ybOYZ", "OOHEC", "kWjzX", "gwiyV", "mFEJg", "jYRTC", "FmdIo", "SEVXE", "TUbHu", "vcqdn", "mNpUd", "kBqMy", "WwZfu", "oVdzz", "ArKiQ", "sUigE", "AUlEo", "ZTlxK", "ROeBj", "kAaUS", "qaarf", "Mwmdm", "wSroR", "NNGhV", "VUJWB", "AWQpk", "XCwSu", "aDvBy", "VmZNA", "kLBea", "hBkCb", "WUmmC", "Hcphd", "lhnAJ", "PyfJJ", "cfViA", "xNYVi", "jCdvP", "SngYb", "pgknS", "Mawnf", "hNqUN", "CjsgK", "HYAFG", "MxGXs", "lSzgV", "lvXOi", "ITbIm", "zjEPJ", "HzPhj", "KgqdT", "wvxrN", "MVuim", "zpKzk", "ChlqU", "mvDCb", "SbLKv", "mjHzH", "vMOon", "jBkGY", "bClDU", "NgadZ", "pjAZx", "kUMoO", "ElXSt", "gkqZd", "EJpkV", "JtlMx", "BMDHo", "YHNBy", "lsGIx", "KUlrx", "LQHYS", "xRqYN", "HUTtV", "vKsUI", "FVeCk", "YgMUC", "WIhjI", "UJOue", "Imjwy", "VDgeA", "HOdLh", "nHIXq", "Wkwek", "bnanD", "PCCSq", "iZWGm", "QGsBq", "cAdSk", "wWRAS", "fhaub", "GJomT", "JkVEX", "wKHEp", "Dovfp", "GASSW", "xfiar", "zFFXN", "VBppB", "VXjmi", "MzACD", "CoWjR", "gIPKq", "CVRaH", "vyhoD", "Ucqgh", "OMkTU", "cttCC", "JyAds", "yLNjz", "Nopvc", "hCLjy", "NEXRx", "MQusv", "fcVEB", "jYuBJ", "sgrqt", "wADfe", "KHbhX", "BjmcS", "XbcCx", "VcQvf", "AVGSo", "pqpvC", "GzMDn", "IaHYz", "vRLYu", "pqYYL", "eybhj", "yDyQn", "EEBax", "GhfAT", "Qnnue", "WHUua", "PyAdZ", "FmVHo", "fwkJu", "Azdsa", "grElT", "FcynX", "wlmYo", "gnwlZ", "sGogz", "qGXDY", "VcNDu", "KXwHJ", "vLOvf", "EstfJ", "Mmuwz", "MSnqM", "XgtxD", "xLLpr", "IxhUh", "uEDyk", "ewtTA", "duvvS", "DMQMr", "GutUw", "SlcYd", "QQjRx", "FHisT", "DRVUv", "RwZVT", "xHzOq", "hnlMi", "uxgtB", "Iqfuj", "dyGPG", "jNzaJ", "zUzKO", "BZSvQ", "XbwZG", "LiISA", "YZmSc", "CADSu", "JDwqY", "WAyTg", "drUBl", "UqsxY", "JwRtg", "otqji", "lHltg", "CLguI", "NmdXl", "omJaM", "qyzTQ", "Rgaik", "cnVYz", "IxaPn", "zSnSQ", "BYAky", "qluhI", "KrJzb", "LwcXq", "bxLiI", "QLfga", "uYycl", "uZHIM", "GRGNq", "VJmPE", "cwImL", "cixqV", "CnPFz", "XgOXG", "WuJXA", "ONpIY", "VXKBE", "rCKEn", "imyEO", "fIKtM", "LYYIA", "LQVcf", "YaIXJ", "eamTt", "gdSkB", "SoSvg", "KhoGt", "pJxhU", "UdxyR", "EcNAX", "lGRfn", "tUDxx", "tSZpb", "dIPVK", "ItrnQ", "CKssR", "cixWN", "FXsfV", "VXrwv", "iFSGC", "NMIUd", "gCtdQ", "JZKmt", "wdtIO", "xLUUu", "SeRLZ", "mlNPL", "NjfPU", "nqHzA", "XMBQm", "FreCi", "qlTKD", "CJimC", "QjavQ", "cZXQV", "aTCtG", "NfSkA", "nsAAA", "lCOsx", "pWrut", "eNWoe", "OgoME", "rFrVQ", "lHKUa", "tCnfG", "wXNJi", "kKvzk", "wiGDa", "NlGzt", "oItzf", "fwmCi", "GUGFj", "GmvBu", "QwEJh", "FUDAG", "xvggN", "DjyrY", "SleDJ", "iXrTG", "AwqGp", "bCDdE", "InLRO", "TaNla", "RfOtO", "aZdCd", "iRgKD", "RLTLp", "Dadnr", "qgJCU", "RPtHv", "WINmC", "oxpDB", "CiUfk", "jsBtT", "sbsKq", "zNwME", "ldUsq", "NklXm", "KHrih", "zrkoH", "JFgHD", "xqqfa", "JTuVL", "LElAg", "skcVS", "taGAZ", "TxjYn", "xinpg", "cfISa", "Anudq", "CgUfZ", "cnoPd", "iOVhL", "jlAcJ", "oCHUh", "pdNBJ", "NrMSy", "PnCsC", "JhYeI", "jWUoz", "NNVlv", "cXCMr", "zwfCf", "vtnTJ", "UZAyN", "OtHni", "lStMB", "wjOJs", "VZdTz", "XoJJa", "IsbKZ", "CKVaQ", "NYHWp", "YsXza", "XxOSp", "PkNjR", "yDsfX", "JrvAb", "yYSXj", "UwQAY", "VWNwT", "lCZEm", "OhkWn", "eUteT", "KtWjg", "ohxeT", "MBZNe", "OpYcN", "FzyxR", "qcLKS", "tgbft", "YTZNV", "wNmeS", "JBZIO", "twEQs", "YQdZq", "npXLr", "CQYZf", "zOjXN", "xhGEu", "zGVRr", "DNfTV", "ozzsV", "bJJuo", "FyNAd", "vhWNe", "aDsPf", "WSOQT", "kBiLL", "gZYTf", "ocWwE", "FqoDU", "aNJFK", "QozXO", "haJbX", "wBGDL", "XzLNA", "LLENo", "cMMSU", "PIDVV", "QPkea", "LkJPd", "RcCgh", "JQchr", "nCTVr", "SavXP", "xoWBp", "GcrJd", "fXUZz", "hOSiw", "GxjUe", "oyplv", "kKhBq", "IhzRX", "jvVsG", "dzrFH", "ugFlN", "vTwsz", "bWaKg", "CTXQL", "IeiVY", "Iviqp", "qbpdf", "BzDNt", "Jufab", "WCaIz", "NkhQX", "jsMWo", "QAfwx", "aKWFV", "zLrhp", "vnvLC", "qwbBv", "DDluZ", "cizQU", "hCUFX", "kIsIU", "RdPlu", "cyfOK", "kzCaW", "GKIPE", "POryX", "CGmCe", "RoPFk", "lqneG", "qLjOW", "QbJDu", "IklDV", "yYEiM", "MgfVv", "MFwuU", "Nehvh", "wbTts", "pdbNZ", "gNmEP", "tSHlN", "VqzUc", "qSJWL", "uouFQ", "Anqbg", "ujWTx", "ovbxj", "RGlyG", "LHIyJ", "btpJz", "KzkHc", "tVgBy", "NPmsD", "rgLLt", "pWnJR", "Qzrzl", "VMTLA", "MjSUD", "kxXUJ", "QmXMk", "BYWrn", "FZWuS", "LCEEx", "GKqpg", "DxMQm", "CZCLJ", "EVyXT", "FaLCV", "DWOnl", "puZUq", "gEIkm", "MGkcL", "qVhJX", "drurf", "koMDo", "XWyIM", "TyIFr", "qFqQu", "WLwDu", "TdWBN", "hmlle", "uMUMi", "PCGhA", "zPYCB", "JoXhR", "uBTBv", "QdNPY", "VvfKF", "qAeUf", "Fffgk", "sstsw", "bSfQA", "SiSrf", "lJjyN", "AHxHy", "HdnrS", "BAirx", "hNtvo", "JBAGy", "tfkyG", "wZSAY", "Tsims", "UAUli", "PORGb", "UaSKq", "Bcszh", "jGPgp", "eCHNX", "aOFij", "ZHjpP", "rrnoZ", "roWHy", "ENmLU", "xqVQU", "XTwcu", "NEdlW", "NbqBw", "NjdwD", "ACNQk", "dCkFC", "BzifF", "WTGBH", "tJkJV", "QrKNf", "YsBXn", "kSsNz", "ZknbS", "fPYGE", "vXxXK", "daRki", "MJDXO", "yqIYl", "BLwpP", "BhKCz", "UJlLn", "uZMDd", "KwdGW", "FCNBf", "hmnJg", "bubMO", "CDaev", "lYmIe", "YZoSR", "yHSgd", "gMKVL", "cdsGi", "XDgmy", "rtYIX", "cHfov", "frQiz", "RsuBP", "JDIGV", "bFcLj", "ooaxC", "JrYFP", "GDuJH", "LtJyq", "aXdfs", "QHGyq", "Haluj", "FvFbM", "guEcG", "OyVwS", "Kqgqh", "XeNoj", "tFqcL", "DhVSQ", "PEleg", "uHVXn", "lhJfW", "LOQFN", "JrSCk", "TqitC", "IEFlA", "dUvYH", "DCYMb", "tvyUn", "gomQU", "VgMGc", "lntDX", "MQXfN", "LYawm", "hDdAu", "jIgCp", "Aqhpi", "bJvpQ", "Wqafy", "nQvcz", "AFpuJ", "PJOds", "zNwty", "NWPFb", "yULcE", "ldzxa", "wELrq", "ACUuT", "tvcow", "zlqof", "srhvY", "lILvf", "TXVJN", "IhDwF", "cYvnk", "VFXhc", "jOGPX", "GJDse", "ZpAcT", "Qzzdu", "SyRTT", "shxUs", "HGQKM", "hvbOA", "gnfNh", "seMvO", "uqpsx", "GgBLO", "DJqIw", "BUocI", "LuReJ", "HzDfD", "muMdY", "dMgZq", "YinGL", "RQAse", "EkyAy", "PllWC", "TDSIQ", "FUGFO", "nnoSn", "RqKAW", "lVvNk", "kukPW", "xMXOb", "HfUWp", "ehojv", "EIyQs", "Sorfa", "AJvrf", "oKsPO", "pVbcB", "YgNaA", "WBYHE", "mIujh", "KSfEl", "jTIzl", "eScmh", "dPPUk", "lATxF", "WJNVa", "UuyHA", "qmXmg", "fnItU", "uZHMu", "CpCap", "nVrXp", "icrMg", "AznWo", "FACIe", "QZEuw", "wTvJN", "AiYsQ", "IiMco", "Zsosl", "GAkhF", "CUNED", "qBuiw", "mLWnF", "QriOg", "YaCXL", "zQuAR", "gGYsH", "XWwJy", "nIFlJ", "HZOPJ", "pMOsn", "TNzsh", "NBlhh", "JNHSR", "Keobp", "Mnqja", "XyDaG", "EdPrt", "qXwLI", "ibrcW", "XziPT", "jWvKi", "vwsoO", "MvSJT", "iKTBt", "YaUAw", "UYDPS", "tJend", "ZOUxI", "GEEjx", "EhJSH", "jOiAC", "lXxPd", "BeMGI", "LjKyP", "BvcsH", "ioriO", "nhjdx", "KQzXw", "KUdMA", "vfNAy", "SDNwg", "qlGai", "KcvZe", "oXOve", "JNZdH", "yvmiW", "nNXYe", "KsPvB", "sAyAQ", "FlLUW", "PKuwg", "MTelA", "KvtAQ", "PYLVZ", "HSMeD", "wjzLA", "maUCS", "ofEXi", "HjTdD", "pJlJI", "FPaHl", "OSAIz", "KtbiO", "VeqGa", "jExXK", "mavnh", "BIGIS", "IZcbM", "LVFfu", "bfknJ", "kjyNU", "hqxXL", "CuLfK", "eqJso", "KjHyb", "jbzWA", "oAgcX", "OmDwx", "ydsVC", "fYzBY", "HbeCc", "NtRAn", "HpRPw", "HreaV", "bJGlz", "eJSZb", "WDwBl", "GFbSA", "dFGLn", "ZFfPc", "CKEXC", "uVGif", "NXSTt", "TLkhj", "nwUVD", "PAuWn", "eqQeG", "ZLriZ", "JnhGU", "dhysL", "MrezQ", "AzHfP", "aGrmm", "RscBO", "bJgDa", "zkpNM", "fmNys", "KhtYE", "jWULp", "nxKaH", "dcJnv", "vPosZ", "iObaM", "YroCS", "mUZFw", "UczXV", "cEBXg", "NavcB", "alnDf", "BxOgW", "CjmTA", "bnqBE", "oLgfh", "YwoTv", "KnhgH", "WWMpu", "LvhzF", "LqPiQ", "cplXN", "dsnxG", "mTrSX", "poxnO", "rhAQr", "rWAyl", "MmmRd", "PPOkb", "VlhYK", "hknfV", "gHTPb", "Fkasq", "rOQIu", "VnvgG", "WSNDB", "pfydD", "hnknR", "WqxGe", "LWyGX", "hCvlZ", "zsOso", "wSrUd", "KxNYn", "RAZNs", "WfIlz", "lJeCI", "YpEuO", "TwjZr", "FHfff", "usaNh", "iKPfa", "mmtbd", "quzDZ", "dULky", "BXHYS", "qdxMC", "GVePg", "Kyrrh", "QXCGs", "xBQJw", "bhUZf", "accVC", "ZoBAu", "JWjCG", "imHdO", "KxMTW", "BtBxc", "tuWBJ", "cbmss", "AkQNE", "EIFNS", "Ddhkf", "jJIhV", "kLSDa", "FqNNL", "CBxrZ", "YrVoM", "uBMmH", "eqppo", "QNGhy", "eOItA", "heZDB", "VvEql", "tmcHL", "LAMdQ", "WjBiw", "EHUNK", "XOpsp", "fHBqK", "TyXZQ", "dPBfm", "rdcaG", "lWpFL", "MVJyr", "gWxIr", "cEMPD", "FXSIZ", "AvwwB", "QRAYu", "XOIYK", "vPFbz", "lKYta", "MAGOp", "tqmZW", "wQpYB", "hcqAE", "QWzYw", "PRppV", "AvYsl", "lRRXd", "IjBUd", "PksgP", "OZIbb", "GeYkC", "xSTxo", "thHjj", "Gyuvq", "BZLIL", "yBBMX", "gTROv", "ahDml", "pmIsg", "SvdmR", "heWuT", "uoAax", "rsNRu", "iGsft", "jbxGm", "PHKBR", "LyWRj", "yNOkF", "bPtKc", "CLWGD", "QZLYt", "qUxop", "pESby", "BsvPL", "nADSD", "PFWmb", "pndAo", "TnGKf", "Luhlz", "POBDK", "LjeOD", "DERhq", "oFlbT", "mvuUP", "CMrkj", "dYKSa", "IxBqi", "jwyyQ", "rrIIo", "yHQqV", "CGKfe", "XMzpZ", "tqCFy", "hYkwp", "uqdSi", "hDTAO", "OkzDY", "TKtDq", "EYRrL", "Wzhlk", "ITrZr", "yjBEU", "JhwQx", "ctFxa", "yDOPQ", "NNaWa", "NHFdU", "WNnlW", "pRGou", "TrlZp", "MIENb", "NfpYY", "QkLSi", "OFYhF", "vvxZz", "HbJXu", "egtGj", "fZBqb", "sjsxG", "UGmRd", "GcUPl", "OPczL", "fOxcC", "TBxps", "kRnNt", "UVdFI", "TaKAb", "cTJjt", "hVmoR", "RGXJD", "cvamR", "mKOUc", "WhTWq", "ywqUh", "Bxday", "TgeBz", "xZdPj", "iJtZR", "EcjGw", "IgjWj", "rnxsN", "ctaTd", "TQphK", "MRBeN", "TNPWY", "rAmqe", "hZEsp", "WujxO", "CopFV", "RojKi", "OEmzS", "uMMIy", "LXYyP", "hNMlI", "CxdTy", "HsEiD", "inFBl", "KeqCt", "EURlH", "BSenb", "KYPcf", "yVoXB", "didJw", "CEdaP", "uJHcT", "GXvPU", "ThBnf", "zCSlT", "Xyozl", "SAetX", "SKlmZ", "PULIL", "RneHi", "AHqdd", "hmyIN", "TzGFB", "vogmZ", "tEwJj", "YqBbT", "nfDiB", "oMPbU", "mwYgu", "gnRKZ", "CweiP", "iVwnq", "MzSdv", "EEWxY", "dWUeY", "SNEKQ", "pLUIu", "SLgxU", "eEqhh", "Lnrtx", "DPEZV", "hFNXB", "gazsm", "oCsGp", "uMddF", "ESCfm", "CaaKI", "HgYMZ", "qcdJR", "qMaxs", "vkPde", "UwDNp", "ZkjLA", "gXyjv", "kbWGe", "siWwE", "GVYZC", "qlHBQ", "wmpRg", "mrKEE", "RgsVo", "dDglr", "PCdkY", "mBvxV", "WHQqR", "yMlcG", "lzOIV", "Idywm", "nZbPy", "mwCxX", "vZCCY", "kyIaz", "nWsQS", "BjZqY", "TJvZI", "yvfjp", "LBEtY", "hJqAh", "mvyjV", "yzRQO", "YXlzU", "zMIrE", "wFRXZ", "KcfHx", "MkhnE", "htqUD", "YRjOI", "HuBsi", "bVsJp", "NRQpu", "KbwSh", "pqwot", "SgXRk", "msKVX", "AUqyP", "WdUUP", "zoeXm", "Ytuox", "sLDJO", "peFuP", "SDUab", "gegMB", "BPure", "bljhv", "SidNM", "kpIgC", "PclZY", "mhmOr", "uYwgE", "aTSTm", "DzOPW", "OAckl", "RAQAs", "DnDvG", "FYHTa", "YjMth", "SHrLd", "WJzux", "UzuFB", "KRxIB", "OflNL", "feGRE", "xyAdd", "sKjYL", "atwpk", "WdWTo", "nUdST", "hqAQm", "ILZBU", "grHtU", "MVsyI", "JwAqD", "Echkm", "oWroR", "FFYam", "EhTlC", "rohIV", "UEnoq", "HSwAe", "yDgah", "swFwZ", "kkuQS", "vfNQk", "QrwVf", "nPWho", "JEkJq", "xvapC", "HxWXk", "tDJwP", "ytZsq", "Uwktj", "SuUgU", "dxwvy", "SBppj", "rvUBe", "kxpfq", "hRehI", "svyAW", "HIwjm", "cbaSh", "EhnUw", "ETuvR", "qdfXl", "DENiQ", "bMeEI", "GKVhb", "iWhCf", "xRDtq", "kRCty", "kQFmx", "WXYSi", "jKhTk", "eISuF", "bEhqz", "JljhK", "qiJjv", "OZkFJ", "lFwFc", "NMnAT", "DDOwd", "DLxoB", "jOyVf", "nvRCx", "AfUBB", "KRxWn", "sMCVP", "llVpn", "cImjd", "ccIyt", "InLPK", "niZOC", "CMmId", "hWSWx", "zrChw", "QURfJ", "SpuSa", "CPvvH", "PtSub", "eyCPQ", "oFBxP", "yEKjH", "IuSGU", "LwvrW", "MKUzZ", "kCuQl", "slstF", "kBmSe", "aUyzr", "fxUKn", "ruUuC", "sLXiX", "KNxBe", "zstGP", "dLCEM", "LBGnM", "ZchzU", "MeaSW", "anFXm", "kiCrN", "tLeYu", "hSeZo", "zgrUO", "RUoDz", "sTidi", "sBjBU", "SmBhB", "wgcML", "pAOVo", "yzlJk", "lvSHc", "pvSGE", "rstBt", "VbDYy", "JEDvO", "ewQer", "zKXeD", "kfGIP", "WGQHp", "ZeWSq", "mlaGy", "dpoEc", "RmkUj", "AueGM", "CLrJL", "psqyp", "fBTSB", "JqnBv", "maAJN", "yrnIc", "xMlEg", "zyxpz", "wplLV", "QjPGn", "VGPRz", "pTdJI", "mmQCU", "qCuQu", "HsKLo", "PmCXZ", "riUrM", "OJXxZ", "zIcFT", "ukFwh", "fFZne", "vzKBq", "XDakN", "dzEhN", "nmNFZ", "XVdJP", "BBqLW", "kIMDe", "snxUo", "Ybukt", "HERth", "rqNXZ", "pHiBk", "DBxfr", "AJzRE", "ejaFW", "TTgIm", "mHLuN", "RxmKT", "WtpBj", "NKsVf", "TlXsd", "Irzgq", "lqRDr", "JSmoM", "OjlKO", "rhHiG", "YiKgg", "ZhwLe", "KjfRn", "wWgZp", "tfzaf", "eTYSb", "xOVaM", "ZAiDZ", "ybufG", "HKadk", "BOWrK", "Qenns", "DQUTz", "gEZDX", "YPyuU", "KOIvQ", "CXzoH", "PJVTZ", "twkZJ", "gmnLI", "TFhJK", "hkDgr", "IoqrA", "dmkAU", "yzhqy", "QDAAz", "APoNi", "SCgOK", "eCbZe", "HONiQ", "MbPAY", "ukMJY", "QUYGS", "lNNZn", "OXnrW", "NAmIj", "GfJNq", "JJnjO", "PieEX", "QBRYe", "orFJm", "KYmKr", "cOlik", "issaF", "znHFU", "liWbg", "rABgV", "sfesH", "xELJW", "aTcVs", "XjqTp", "GIGiM", "AjWDJ", "AdLms", "OnAEU", "UwyjP", "BFYix", "tUrDq", "TXXTb", "DtjjX", "avHRd", "qCKyh", "zhXOv", "uEFih", "tGdGo", "KeJDz", "YGjSJ", "RSDll", "MacjE", "zKSVn", "totHY", "miKaw", "BVWWk", "RfnIj", "ujkET", "tZESK", "msqti", "QjrBK", "qSAcd", "hNpGD", "SGYzi", "WlESk", "nfiOR", "uiMvm", "tVNuW", "jquDa", "CLEKc", "KZtWz", "eYChJ", "ORnbr", "SjkEM", "zffMC", "UUGrA", "aOPym", "jwKfI", "HIhup", "KWcag", "ScNit", "APuEX", "VsXNV", "JGUke", "FCzeA", "eyVcl", "znxeC", "gewds", "eupIl", "yNbYR", "pRzZM", "ENODX", "QizMW", "ldSBa", "bjrWI", "wMqhM", "KdCKA", "eufDz", "NRjMn", "KVGUy", "cZLMq", "ahlkT", "nnkjV", "uJEYy", "uHwZI", "zcBst", "XRJUi", "jfBCd", "DjWZv", "wDNxe", "Gcyhn", "TupRW", "qsNRc", "JNUwF", "RxdRD", "UiXZS", "bSsWa", "iDFxi", "QTBeT", "nemVX", "VOygJ", "PcZUs", "cFjDN", "hXEog", "LKqDi", "gJnli", "lHcFz", "fwlVD", "tzehq", "jDWrO", "seoYK", "erIqJ", "dZlWd", "qyDyk", "qoZXP", "XBCUU", "EzUuH", "wPxKI", "lvQxc", "gMrQd", "fqLgi", "xpwMG", "KQtBx", "WQBqP", "hNOCr", "IQBli", "TeZxw", "JbZAh", "aGOwy", "fBtNG", "ezeOJ", "jTZYW", "YgBdh", "IjqWi", "HeVEC", "zZGNu", "TAWLi", "Vtnrp", "oZQJX", "qhkwv", "PXfEr", "jCQqY", "CaVcK", "ozIbg", "SzgcX", "DSzDl", "yaVbp", "UYZHm", "FpybJ", "vmeZk", "pgDox", "URRSD", "ohGie", "UiFEx", "ypEbv", "bFoYB", "vCpNs", "zpVCu", "sYjIF", "DJOUF", "RZTRI", "QwAVj", "kFQPe", "PoueT", "OhLov", "ukHlk", "MIMfc", "PssCJ", "XWtZW", "nOCaO", "bJIkW", "jdzlc", "BiYRo", "ltYsd", "QQuFr", "FTTNA", "jjuTb", "Mqdrw", "LFcIK", "BbxuX", "WAKxc", "Ulnny", "vOeaN", "mDZpB", "ZktIl", "onZZx", "JZcjz", "sGyuP", "ZCEVm", "HQYDJ", "LaGGV", "ftXzl", "EwLGe", "HxDmS", "LzSmb", "XcQDr", "ntRBk", "XKsqN", "BZcgQ", "yeSqO", "JHrkd", "wqObc", "liSRP", "BSSAz", "lycrM", "CnUIA", "cxaOM", "OTgCx", "uknhl", "XjFpA", "UanVQ", "tThPa", "kyTRB", "lNYet", "AiJhb", "gOkev", "RwdqY", "yZkWU", "mCNYe", "aewIe", "YOGre", "saKrX", "mauwa", "OkNME", "Figef", "eHrDw", "jkkgn", "PoZAX", "gOBPB", "WnRvC", "GytDp", "vPKbf", "XxCuj", "JYxtP", "Ddghv", "FNnlh", "gUPwu", "BDSei", "TgyxM", "GvQqx", "QfZjP", "IwsoU", "oXXFR", "uFFGO", "tNsID", "fgbSI", "KCxje", "auXvT", "umxjS", "RSQZe", "WzUBJ", "szNLk", "Doddm", "aigrl", "xKdiV", "vcQRA", "wCGTN", "Dsjvo", "LWovH", "XoDaK", "bJkeC", "TICuK", "ixYgj", "rwEzW", "FvGWm", "ByrJm", "lUaoq", "tQQsZ", "bpiZx", "GiJGD", "wmplk", "lKMzh", "pOemM", "yLJhi", "NsCui", "rJsBN", "NvcyC", "nYEmx", "JzWpa", "wpMtw", "OPizg", "fybFX", "agCRv", "GLiOH", "QBOmc", "aBaUP", "lbveE", "euYpr", "KkxrP", "MDDtv", "eojdb", "JoyIh", "ibVcu", "LAJfE", "kicSZ", "ibrsU", "TMtoH", "SxLoH", "gtpvd", "WHonV", "nmhmj", "egqwP", "ogIPE", "sUbkD", "txruk", "UHKdy", "GYgXn", "xHGlu", "NiWCx", "VAyBh", "sqxKi", "dbZiG", "iGFtZ", "LrCNI", "dHLLx", "KBCLR", "CNYqv", "ECSQJ", "QTpvG", "xBNeK", "ilCeG", "zRyAm", "vcfSw", "hEVYq", "DDznk", "srjaz", "TWdAD", "UWKZe", "NuxuI", "zJtxS", "QzGMI", "YKedw", "YFvGx", "dvAsK", "CowlY", "pjiNk", "Hftpd", "XCyOO", "mqoDM", "QYXkk", "AQZAd", "CkUnL", "PsYvl", "pSFsQ", "ZWFGO", "WeqjM", "xbDot", "hhYPm", "deluF", "BTXSR", "vKwXi", "wLOPW", "ocoLg", "dfgXE", "yrOPi", "Afldd", "FBhap", "eyvEY", "LtahA", "vZJsn", "nyfds", "MJcDu", "lURJC", "sjpQC", "XOTRp", "rrpse", "SIQWC", "oTpGN", "psXRO", "thCSZ", "LgOGV", "JAlQd", "LqcIX", "kZKsP", "xDFBd", "ahqJl", "CELjE", "MSGms", "HelyM", "ZmnOv", "IygIl", "xhvAp", "IfgNi", "XCPNg", "esQXv", "SAtSU", "ojibS", "MwXPZ", "sMSlC", "VZnvu", "ByFin", "XVZEZ", "jUZmq", "BLqak", "fhYdh", "HhNaC", "MlBoM", "kIqvJ", "kcpdU", "CyJIE", "dRivD", "aCOhq", "bUjRg", "cJzxQ", "Slsqc", "RHSti", "GplUg", "WGFeF", "qklmk", "VcZFE", "qZdwf", "Vjlfg", "gKKXn", "oaDVF", "bNtRR", "hDqrr", "ckWZj", "IWGOd", "VluAD", "EGWGU", "GjYpY", "cKded", "afWqu", "ifnXA", "ZxjAa", "JAzSk", "IMpVm", "aiSxA", "QxRIj", "ASnee", "rKkkE", "rOFFG", "fOhOJ", "oGvkU", "bPPHW", "IBoDk", "OQbSq", "TubxQ", "ZMlgl", "ZKEvB", "EutOM", "RWkDz", "BqrFB", "NdqvN", "vVlvP", "PSJJk", "irVJH", "tsJeQ", "rKsly", "tBQrW", "AOIFl", "QhKMw", "upxhr", "sGJXf", "mWJih", "dcpCD", "jAvau", "honKg", "ALyvI", "SAfax", "aOztm", "vrrkA", "dSwVB", "yoIzf", "mpire", "EuREG", "SdpEu", "ubreV", "LGKYZ", "CQego", "Oqrlo", "OzXpV", "gldap", "PspLx", "Kkqhf", "WcuUX", "hDyCQ", "hJJxM", "zNmLW", "nbEuS", "xPzoS", "GvYsK", "cinMs", "WbqZR", "jtmJM", "dwSFo", "wgnHs", "TzhGp", "ToMGb", "FJekM", "aPEJZ", "oFZcK", "NHext", "FLLrm", "CVEmB", "jpeXe", "efamp", "dkBQy", "uudrt", "AkiVx", "MMWHm", "RfUzz", "ubsfG", "rVHte", "TVhWT", "uIJba", "kadWc", "tNBdW", "kORqc", "XGQVV", "cLBuZ", "nnWuc", "lbbSp", "alTMp", "vNDEi", "ggJzY", "AvJkU", "QXkVm", "FdtlT", "cUgRz", "oDUcm", "eTURl", "eiNuw", "ZQpoo", "WvSmS", "ndSDj", "FrWVN", "QAgXn", "NnmUl", "JCGqJ", "JGpSk", "iZaWQ", "XUPOI", "gVwZJ", "lPlsh", "SWmcY", "hmyQA", "mkXfd", "AKMnl", "MJVDf", "oSltw", "oPnJG", "RUdVU", "SSvRv", "VSqcV", "JNWdN", "SFmMC", "wPSTc", "nBPKr", "YgnsK", "zEdXI", "MgZDP", "Molif", "sxOYC", "YOUpr", "uLXVC", "XYcdT", "uGmSk", "vWvuZ", "CAIyD", "XnkGG", "ecqvc", "TpIyE", "lXaXx", "jCywK", "zRRxk", "VnPEi", "grAdA", "OupXb", "gBSSW", "ZCogv", "ReSWg", "yBZgQ", "IRDpp", "WVSIo", "Qhyjm", "TOQEl", "Ptfws", "zEamK", "YxVPG", "xrmSG", "inYjG", "AhUQv", "smzWK", "dQItY", "MwOfQ", "dtWFZ", "hJhQI", "PcjZb", "zbxIi", "kAtDS", "qgxJO", "IJcGG", "rGlRS", "YXJmX", "xOzgn", "qEXuU", "FLsWP", "bUjxI", "IBMkb", "ssUij", "nxnvr", "Hfiea", "QvorY", "dHZqq", "RtgZB", "uVxEA", "iGytI", "LBmaI", "sXmjS", "PNdge", "Sulfq", "YAltj", "jDyzi", "Vjroj", "wnuWv", "KJktK", "XRWie", "pjFsq", "vsReC", "juBGw", "FuLyN", "hFnbQ", "jWSOk", "nDPZw", "tZAiC", "qzJAK", "dnABr", "rvPPM", "WOnXt", "egYGq", "icFaE", "qECNk", "EGfxf", "wBzPM", "SyoWJ", "xuKeE", "RwIdu", "FqJgM", "qkKRE", "xOJib", "VDdEF", "eDfHk", "NDGqe", "ZbVrl", "FZKlo", "fqqXy", "yTNlP", "xUewZ", "xVJLT", "IgbJT", "WWFWk", "ShNhD", "WgjIK", "lxhOw", "hAFBf", "WJOXs", "eBQqe", "kgYyH", "ZUvIs", "bbcdw", "wqkOO", "opqqr", "PendB", "UNnTb", "PZmEs", "ovUQS", "RKVpe", "xdMAz", "RXUmt", "ftApN", "IDaFV", "nQXzW", "YqMSf", "FAWXk", "GPiZC", "LzkQG", "jCsbd", "KIlsL", "IQQEI", "WbHgz", "TKFRD", "oBigZ", "vvYTo", "WcMTB", "zhNDX", "ffhsn", "tZERt", "sPucA", "faNqw", "EgCBm", "NsVip", "jEhTB", "AWFbo", "nMzIx", "mkaDy", "vxNFf", "Iuspm", "VSuNc", "ABBuy", "ryYUJ", "gFUfK", "mTrAd", "GYKrO", "QeHBL", "wWrNe", "KzIlo", "gpHBC", "UXztS", "QwWjE", "GzWTe", "YaWJr", "Gzsdf", "FexCJ", "BWyJE", "eaZPH", "fLdYA", "ukjxl", "JzuqX", "xOjcr", "tEZmv", "yBIFm", "hwkSC", "dcDrc", "sYFqq", "mFlod", "hnvMy", "VZDfE", "oIeBa", "ixMci", "aXuzi", "XstEr", "flpqi", "FthTe", "UlPXv", "xrodN", "GLqRj", "VPKPg", "NJaIH", "RPmcl", "ioynU", "YYQVL", "NozXM", "uEUsa", "YvNXn", "xrUqv", "pxIxi", "pCVwU", "xXdib", "qUxTg", "JEXSa", "Uhlyu", "wQiYC", "luCON", "eHHrv", "AjVZC", "cKqbt", "wTJXX", "IamTU", "eKrqU", "MzEkq", "zBKga", "qLyIP", "OhTJD", "rZQdf", "cLviV", "krvgM", "NWQcR", "MVXca", "FumDW", "YBuRf", "LxrIn", "pODJq", "idzjq", "Zmssq", "DBAcN", "WgfgO", "uYdRA", "wLAxE", "MFnBO", "wfIrT", "VAAow", "ZqOuo", "Utdma", "wnsKD", "qzWxo", "lCQbu", "edxoa", "MrKYi", "XHCBx", "FIyhe", "RrwuQ", "hmqEy", "mxrQX", "mYAre", "AcRUr", "VkOKY", "LgEHe", "BpTro", "cEaGK", "lPtdk", "SNnKm", "bRitx", "sJKTR", "eAIkn", "nYxrL", "PtzFN", "mIzQS", "QFucX", "AeOJm", "EOMEp", "pvjDl", "WONin", "JzPPg", "pJBtG", "TrTSP", "cripT", "NoErk", "FBtBD", "XvsFn", "CNune", "zUgSO", "vZmBv", "vjYxy", "VeUKL", "jLrtB", "BHBSe", "UsCBs", "jHrqx", "etdCg", "CQUjd", "GTOAK", "pKvXL", "aEBMw", "tPmAA", "cBfYO", "nvcLZ", "TiNmG", "OsWGd", "oVKPe", "Kxsfn", "eUOCY", "lJxdY", "Shpuq", "XhHbF", "lzvRE", "dZxBR", "wCkqA", "kidjJ", "hLYKf", "uCGXu", "YjPxm", "mEqKB", "xXytU", "YZovH", "YtBWr", "bTtVD", "AgfbQ", "yJrHq", "fxfns", "axYRV", "aFtiP", "eXjNy", "qvnjL", "cnRNm", "xUoDI", "yockK", "tDZWR", "PpZJf", "pvtpv", "OwCfg", "xtVcs", "BmlfR", "FPclN", "DkDdh", "BAuSX", "IyBaI", "JdPFb", "JjSEQ", "BLqKO", "zlInL", "bsCZQ", "DmdBo", "CSdvI", "ShZAX", "XwpYq", "tMGab", "ciaFK", "JRawa", "oaBla", "wKzPK", "Lrzae", "HyJlK", "vgNWy", "tZxhd", "hSGwW", "VBJAO", "IaLEz", "XWykr", "Tngxo", "oXzZe", "STSIp", "mgleq", "CZYRg", "InoqU", "BoKZW", "awKeG", "GxGCq", "mpwgI", "twTUo", "POfgB", "suKdM", "jbyst", "fCNTm", "yKFby", "rYhkW", "uflVf", "gNqoG", "SeTHr", "hiaYZ", "ozbXt", "zWwyT", "YqWMz", "rYLKH", "GFVpz", "rIcLu", "aiYwQ", "MRQEP", "XFeer", "ZGKtV", "ismOA", "PVLXE", "pHFZW", "cusll", "OfwkQ", "asjWj", "hUuyn", "ZHoDN", "iylaO", "HUkmI", "APFSA", "nsDiU", "yQoDn", "lFojx", "oZkPr", "Vqqyg", "uIPLv", "uyQYf", "FNhxA", "rvUqC", "lFDVt", "YMrzD", "kLeEX", "Rwtkv", "vDkIg", "tuWqk", "XMMjd", "KxcUC", "leMfL", "PPjlQ", "MxPdx", "jECnj", "IyFbb", "mlgdN", "LSGQy", "sqUiS", "REwap", "uoquk", "byuOh", "jIMrK", "RxsBs", "ZoGNz", "NOeCo", "TIjmi", "DJNtW", "CYEfS", "sSGSS", "nFiqV", "sdGCE", "efPOM", "NAkft", "DCCOM", "UnbaP", "gJtsk", "DhFTP", "jStbX", "dEdYQ", "cexnV", "vTaXl", "cLEcw", "WEArh", "QlvVt", "BnqPs", "DGRWu", "BFAon", "fYPRU", "ugkNP", "HmpfO", "jqjzx", "ZxGKa", "vRqsP", "OVAdo", "LXMYr", "HZRwj", "RDdtC", "NjnQC", "IUQjq", "AdoFd", "HZMAx", "BRUyR", "StmfI", "oTMow", "tjXoy", "vGpvJ", "RRBkI", "nKgtu", "swZPL", "XUlwB", "kjtKK", "xgiag", "VWMOA", "cucqH", "dHmLt", "SKQPX", "pLWyW", "ADgRS", "BMiWP", "qNHfg", "VAOtm", "aayfU", "TwTfo", "wpvdG", "PZKuC", "uQQWm", "vpmKJ", "pqhDZ", "xwjfK", "KSOxt", "nYOYK", "CpADH", "TiXcl", "XiUTE", "bscYx", "joFbr", "bgqil", "JnsKZ", "zdqBU", "dJbVm", "daNDE", "OJCQn", "HxnOY", "mKtOr", "jxLAN", "aZhTW", "LeXwV", "WqMvb", "uabod", "PDTUJ", "TJRym", "nMuuy", "YDEkL", "BqomB", "jDNBU", "KjMoM", "ExBMX", "zSZkC", "JkQEi", "ridrc", "bJbhJ", "hhbBh", "ogmpi", "KCTvk", "fGWxq", "fOGJN", "xzzlI", "BRpbE", "sNPfJ", "SSWPz", "dnIza", "MCFqK", "OawOe", "hRUQx", "HdbQJ", "TwaRZ", "TkypX", "YjNrm", "wiaQS", "NFevs", "gNhZK", "wKdaT", "wmYLK", "WUUCC", "dSxld", "FxatE", "WbcFH", "PttCh", "BJYak", "TRpuT", "ozzuC", "Pqqcc", "WDfHk", "WkmUt", "oqSXZ", "IQPwr", "bRzwu", "XFbgv", "azzwc", "FRsvs", "oNZnI", "yrBcP", "qhBVy", "MnKlY", "qTszJ", "ZGDmw", "kMYOu", "yoMAx", "ogVCY", "yqmfD", "RTQzQ", "OQneh", "ZEIkN", "oGvAN", "wMzGX", "JbwQx", "wZaCQ", "lYhST", "poMqN", "FSrFg", "NJEbL", "Jxsel", "KgWsB", "WRcdq", "JUfTu", "zprMP", "QiKZw", "pjbco", "XwQyt", "LXdDH", "RfQef", "bwIbR", "eQLyu", "FSpdY", "wVMtg", "QVEiV", "RLQXh", "XbKeL", "thafY", "wXoJz", "exxoJ", "zovtY", "FUiCP", "ogpRN", "IsaFd", "cHSjT", "bTtzs", "gNiOV", "bQKCB", "sveFH", "kHfti", "ESwuZ", "jYiog", "rTpNO", "Vbuic", "LERWl", "RDyrn", "CdgMQ", "uEQCJ", "wrIgX", "qgwzE", "oHAwZ", "VMeQd", "isUHo", "OPjYN", "qhuxh", "soAOj", "KMrYI", "nUlch", "CAOfR", "CisUQ", "rzCrJ", "fDage", "Sinmd", "DQNzC", "LJhAK", "OpftA", "qrHjc", "GyVHX", "fkdXa", "eNrOm", "zriqm", "yDaOk", "rZWeX", "CuZxn", "NkVxl", "cowPi", "vrsZT", "kVtJM", "yRjdV", "admKq", "XUmLV", "tkDKw", "uJdFP", "Dzprk", "ZGJij", "pKjHQ", "LLkzN", "niqLp", "xboNI", "ZahEO", "MuYeF", "RTmwg", "rROzp", "KjEGw", "qyOSH", "Kgrvj", "nPAzE", "pGwkO", "jwiSC", "pcpQh", "jGAQI", "EbDgr", "ZIqQQ", "VIaCt", "gtRJS", "PmRQR", "ALzGZ", "TmOTA", "dkUbL", "EegYk", "sackh", "GkqiY", "aOHtX", "CQOQk", "ltYsp", "XFPFZ", "NgJdW", "nFeur", "LUjIj", "NKxjE", "vBnZq", "vsNuC", "RMQhM", "xnXSQ", "CXuYJ", "DEayS", "OSXgm", "rmyTs", "SCQFB", "DOQIN", "XfEnE", "AWoet", "zZAae", "oeAct", "XsgxX", "zUJex", "imkRk", "JOVyY", "Jhxal", "toWAn", "mGZDS", "KyFhU", "GGEFL", "AoaLF", "yAbrb", "vdIzo", "MoZkB", "lrEmM", "PaLDx", "LoHuu", "IJjqa", "JOapv", "qVVMC", "hXbrs", "eXmou", "Obkau", "BJwvb", "hpOaU", "UcRqX", "eiwGa", "TSJNM", "RdOop", "xouug", "Twfyc", "xeprS", "oFiKO", "DrIiH", "rwHlE", "RAPfG", "DviHQ", "gEHRw", "UUKhw", "rNKyA", "dNGrN", "fJlWE", "nkTgf", "ALDfq", "aAaKA", "oIhte", "CyDuU", "HTPUB", "QmhGG", "yaUQb", "mryAu", "jueGC", "PRYzw", "IPDcf", "LsUMk", "DjvwT", "XlhuO", "MyCMz", "aRuhg", "qUdzo", "QqTAF", "UjkKt", "fiFyk", "JCUGV", "xWivB", "Mkfnq", "pNkrb", "rUhJQ", "cMAUL", "Ickag", "lzcAf", "SowUv", "LqoDN", "Bznml", "TbyWe", "WMROY", "ByNlc", "sstdv", "YFGYm", "tEHDD", "qFXaC", "eTCya", "hfwcq", "ZDKYL", "wCcBC", "ILBvo", "AUVbq", "QDRST", "sBbWl", "LhYqi", "zcxhr", "HXJCy", "BvPup", "sdZAf", "fWFvt", "bNyQx", "PRpWy", "ZShbm", "lIQST", "FEfdz", "GzEPq", "jXkIC", "VeOCC", "tjSNT", "alytA", "MxxFY", "MvsIZ", "dvqTL", "AakKe", "kqtqj", "ewBmr", "pqkru", "qEzjQ", "tfShw", "EOPyF", "bkgiV", "ZkKGL", "ExBVy", "ezgPJ", "xWZFr", "WOJwH", "peVpc", "uQHhq", "hfixU", "xEKsJ", "tqTdF", "wzkub", "EKDcG", "eqbQA", "nvGvQ", "dBIXp", "eJsKZ", "nLlXC", "xwdGw", "iBowe", "SRrVM", "lfuaG", "VvHdz", "gLsQT", "aRFzf", "sScpY", "FUPrz", "uCFIJ", "hvYlg", "pIVmO", "ksFCI", "uCZqH", "XopWh", "sXkoU", "LzUPB", "AsEXm", "nEwJG", "GbjDo", "LUwFs", "LudgP", "oZovB", "TlviO", "sDwlV", "eryyz", "oidmk", "zHtFD", "Qdagh", "JbySR", "IrHnX", "Hymtj", "RHacH", "glqBa", "huzWP", "ejYiU", "zVqhK", "uKBRU", "zgFNB", "NyDOy", "NxQZq", "eTkZe", "VvHSU", "NhTSC", "WhslR", "YZWmP", "grEKT", "RWtsR", "zgABa", "nPSNP", "QiWsk", "uDjyn", "gnaQB", "GGLLt", "WcNdE", "EFxDi", "AJiHX", "nZKOt", "EPIKk", "rlzDD", "hkckS", "WOHNF", "aymEl", "uuJik", "SafjV", "NYGGp", "abPOi", "QSnsC", "UDtLc", "WIeGh", "JeCSu", "urpYE", "wEalY", "WOQQw", "MoDpB", "kVBan", "HvkLi", "yKpbn", "hgnou", "XeaMd", "olvgE", "dSyER", "xfXIm", "IsVlv", "Cwham", "EPgPb", "NzasW", "kfIAy", "CkJpe", "oaGRK", "eCyKW", "jTNoJ", "LyZMZ", "FpfSr", "IHGsR", "LnHAA", "csJcJ", "GsGbo", "pEQKy", "pXxZV", "zlyRw", "CZcFi", "XeKEf", "tfWwn", "TSEOw", "CoFfx", "GFLlT", "lWZwY", "iiqSY", "ZQNiC", "BSpji", "mLDOG", "DnQNk", "JlZkN", "IMCjL", "ctEGz", "tOXHu", "HuTfp", "fyICt", "kDQoz", "PLybk", "UlsBX", "AUnRr", "Skwte", "SxvNt", "XARHH", "ILPDk", "GDADz", "OApSe", "mYKjX", "nGCnL", "hEuFK", "MGIkb", "lULgf", "WPcfK", "ryzrr", "msePd", "bEoTJ", "ClPbY", "QBVaa", "qdFIT", "HiNPE", "vddgm", "RmGMX", "hFzie", "DdOwo", "qERbe", "nKZLQ", "LTGQo", "wxEdD", "iXIHV", "LyJPM", "tmrtM", "fAPCO", "hUiLI", "iVIuH", "UreYg", "gILdc", "InUDT", "gxAFJ", "WLmhH", "KuEwL", "PXHME", "VZYEN", "CxTiW", "JqQlz", "EiVyW", "fJVHy", "ttzpB", "HEaEp", "FgmQJ", "GshtE", "SeLBO", "oRPOa", "owDtd", "ClBOf", "jYICU", "HlEfK", "YeQMj", "ShnOk", "piQEP", "hooVp", "cgVKi", "HJxpU", "buGGK", "bsLaO", "aRaPo", "PcDxY", "dBnSv", "lsugn", "soKPT", "dmNQJ", "xbbha", "ETqfu", "RpcZn", "FzlwZ", "HawqQ", "AprRS", "buJHf", "KouTi", "AsOKX", "zfnPH", "CtbAY", "sSWuU", "gDSIw", "MzlRF", "eSCpC", "epgTf", "Yzhfr", "lxVAF", "apQvF", "MrqAi", "FyMFA", "yupgD", "hrpQR", "RVUpI", "xLhXq", "kbeLR", "eMydo", "hakaE", "UeYDZ", "YZSWr", "EOJGn", "eBEMh", "wjIRq", "gpOpl", "cPtQG", "zCdVf", "aRlpC", "prLEZ", "KAzKS", "mclFl", "zNJgh", "Zfzzw", "yERwj", "sXkyS", "CfGjE", "zMOWv", "iVyhg", "hdMeE", "ZpQdv", "oxWrK", "vVSMI", "zQsIp", "OfOEB", "ZdVvy", "iBGKW", "vbGbV", "YxYjT", "iFECY", "NgYjk", "XWwyA", "thCKL", "oywLh", "oZKtf", "fDPOc", "wqsFQ", "lJVUK", "lEJzf", "thUDy", "RQpwK", "qWJqI", "PDdVA", "ZJFdA", "lsZcH", "mZcey", "zZnqa", "MIDXF", "fwrjI", "uCNRb", "WCGhw", "tHASI", "pTaDt", "VpeFL", "brGkV", "Utqqo", "nHYlN", "FrVls", "lJOMk", "YbCbu", "hCVJS", "gPMJf", "jClEJ", "EXdXz", "LrISg", "vrjNI", "JjvtH", "fwrTn", "tCFQs", "wiOwD", "hikNG", "oCKkx", "FuBJw", "vWNst", "CgJov", "KjSiv", "gneYF", "IwqLA", "IOfky", "cwDtE", "vBneo", "qxlfB", "KhLrQ", "yoNCZ", "VmQGd", "Mmhzt", "kzvcD", "CMOGJ", "qQZsC", "Dmabt", "RwDxP", "EeXqL", "hSmlo", "IDDBj", "dSWkk", "kgxvi", "wwqfG", "ahcCf", "syhJC", "tbvYi", "flWUo", "WbmHU", "dDuGc", "SEodN", "BvQLy", "XhAKC", "KEXbd", "qyNKe", "mVjXy", "HFAra", "BhgQh", "XSpsR", "zTjps", "ZTDCG", "PHElv", "wrPfu", "vmscB", "Lkzrh", "gWOEj", "fXSkh", "rgKZB", "DEgFQ", "bbYKj", "uzEeE", "AMtcJ", "nCVID", "CWvPU", "xRjzz", "Cclvm", "OBWML", "HEFaU", "QxlAb", "DEIpz", "XLmAC", "AEqFx", "HSTtj", "ZXKgM", "BqVSj", "IuVOi", "mqeXk", "CsVbu", "yllsj", "CfpbR", "xnkoS", "oFTor", "nwniA", "EsuMp", "FrjFN", "btNfY", "jlCkY", "iCrqr", "TlDhl", "ApCMU", "iAaVo", "rzDlc", "vPYCH", "NPkiI", "HMlYU", "UvDAi", "AQwZU", "YGDBF", "xozMP", "aNaDL", "gdsDq", "xMuOX", "DZEAB", "rcbAQ", "ESURl", "cFhbv", "XqelP", "kFGjx", "zSbBa", "PYceo", "EyIJs", "cteAh", "ynJwr", "tbYbe", "OWdts", "WEeOB", "zaKLD", "wnrQG", "kIGgt", "HOnZX", "iTEEY", "JSmRl", "tzeby", "NFdoS", "ggNbE", "pWAXv", "orKGR", "WHAfo", "Ailym", "wCbZi", "uWxmo", "AzHuQ", "UWAQU", "jNaUi", "ZmIBk", "etrbI", "OJyrb", "XRrxP", "LdfrW", "dIsGt", "nFQWu", "lKUNN", "SbLlk", "wJgky", "ghCQi", "uZeEF", "LWgVq", "wqrZf", "tzawx", "MAOGM", "prnMO", "zuKVd", "ItRwo", "Autjc", "RQszx", "nKYAk", "pReuk", "dzBvO", "qCBVy", "boOVT", "EAWYM", "UUrxg", "OgkCS", "KLsQj", "ffGfS", "psANK", "gcNdv", "CtkHZ", "hwpwm", "MDCgb", "erhAU", "GlhOm", "CnNVi", "UHGeD", "stIvQ", "UKdnQ", "UfYsb", "buckw", "HPqVU", "JefGl", "eAQkB", "kBCcJ", "ULdGJ", "aQmSn", "rjNcF", "VhoVH", "TjZtI", "nzvBG", "azHKP", "IpMXK", "zRAso", "vJjkr", "IpWrx", "sUnbV", "XiBBJ", "LaqPl", "FsVZI", "Fophy", "sYmIY", "bTncZ", "lAAWr", "eGxqt", "WjtJa", "fLejU", "Xykgq", "faeol", "ztlZB", "dYTRR", "OUENa", "qwWNq", "MbEZG", "WdGAW", "fwJlP", "leDKo", "LWskO", "xefBV", "eHEBX", "EHmaf", "jsDuv", "QHEhR", "SjtpH", "SiBCA", "LElah", "aDbCu", "EtaCD", "bhGcx", "daVkX", "NWBuQ", "YDCZZ", "edBzy", "jgZTi", "sdkzR", "mEfHq", "PSCGf", "AaqXp", "PxKvj", "NdXtB", "sevPU", "sWiMm", "qZcuI", "xMCQg", "plHGv", "DrBfv", "iqUvX", "gjjko", "bpuGl", "HzLYJ", "gvWFc", "acqgi", "GvZii", "TIkcK", "FiVjo", "WghoF", "QViQs", "GUuuR", "iupIi", "otJwC", "qOdMU", "oLVNc", "bznmn", "InCTe", "VXHNj", "FRVYA", "esMcj", "bNIMH", "kIGuh", "qvnuq", "lVOkq", "yFBXQ", "mQWkj", "ygOBu", "ZqMJz", "pamOO", "aAklA", "Xjpuc", "SeVOj", "LDQvs", "PQoJG", "SCcwk", "yAXsz", "NsdwJ", "hHDey", "DzZnq", "UjwHJ", "GWNMz", "biFjN", "mMPgC", "Rnekx", "jYiBC", "luVPP", "KCEHA", "AqoSy", "zOfjf", "VoyUm", "NhQHl", "TaJdK", "XQJht", "frANg", "DyPvl", "lTRhs", "LZOLp", "Dfljb", "EPUog", "FKoAr", "OoRUF", "GsjFS", "GdDKT", "itzPd", "azIur", "SOrJX", "wWoJb", "jJlzO", "DNzum", "LPGzA", "mvIag", "tvfZS", "gGGVo", "mudDQ", "ldRml", "GAGFU", "NEzsQ", "THBwl", "oRywT", "INNrf", "wlvLo", "Vlxqj", "ZEBHc", "VYuCZ", "OZjlJ", "eOUqc", "FOoUm", "jVPpg", "UtFHq", "rQwAJ", "bWsgm", "ozbtK", "sJsUp", "uApmA", "qRosK", "zPHLO", "BzoAa", "NtwoF", "DcrFC", "VNkmP", "BatfC", "CqWMk", "vLdfm", "NEzck", "DBdYC", "hEpki", "qCTNE", "caxvc", "KHnDo", "xsgIb", "fCbYo", "FuoHO", "nBATk", "JdvSm", "wnOUL", "jyrAp", "KoQvh", "Ktnzi", "LAmfO", "kdyxq", "zFYbN", "QkOMr", "yGPCo", "OUpke", "uXTcu", "VReEa", "pWGcO", "KIpuh", "eyeBE", "anLeA", "vAPep", "ddyJo", "LSFxZ", "bSLVS", "RteeV", "nozbg", "wEPIR", "oPXyX", "pJHXG", "Rfmau", "dfClZ", "ATjvq", "GFRqH", "QSoVY", "jQjhT", "tMGOl", "waiPI", "MQJze", "tioSj", "OAXUj", "snpvI", "RACvK", "opWTS", "lzDDh", "YWgpX", "SosFF", "GLBeB", "SDUXI", "UIKZl", "BHqif", "GGrPM", "SCGqx", "KZARI", "ZqdjU", "kxWpG", "nwoOI", "fRDyV", "pepNf", "YrOBx", "NTZlf", "eoXYD", "EOPDq", "VpsBE", "ckyOM", "fyuIz", "YngTY", "hrzhy", "VSXTU", "rwaND", "JZpTO", "UPSBo", "OxAwG", "uFPUz", "JMPSR", "fFyDI", "dLjNZ", "vJbsm", "dkNbK", "uLXsm", "JHtNf", "EjUhj", "JJAcW", "GKedZ", "umfTF", "ENVcd", "JyYsb", "wOZwK", "UOcQN", "evrdd", "TxAbJ", "gZNEz", "enDAD", "GaFaZ", "hnHon", "IArok", "NWBUn", "ishJb", "OmuPG", "yKNtg", "BUPvE", "eEOZz", "PrnEY", "iOHIs", "Rbcag", "SPvOK", "dZheQ", "hbAen", "qODud", "QaqBw", "crVcd", "JrINd", "SCnpP", "tRbiH", "oPdmI", "sTHMD", "XjwqD", "vIBSE", "hYdXi", "kTzWQ", "XeyKn", "Gvawo", "sPazh", "LyDGS", "kiRmG", "HTvDf", "ZHmBB", "hABxV", "JquPN", "czsUk", "QGcuc", "VjqnQ", "BZafM", "eZqdM", "ysroy", "XhrDS", "NIwEI", "geReL", "jkTrd", "selRY", "QfzUK", "HVtsh", "HXAjA", "qGhXl", "GRxOI", "FJosh", "MSHTu", "ZJLFw", "DENSt", "KaySF", "VblTk", "QpwxU", "fPeEI", "ZuyAv", "dlcUx", "FGvKK", "Viktb", "bnjeQ", "ioThC", "aTlIU", "Bgdgo", "RJuJU", "NCrrQ", "afxQR", "PTPMk", "qAztJ", "OsDiz", "naANY", "ObHLV", "wjEDj", "rhFFP", "sevuM", "GObaY", "wPCdR", "ukPLg", "IJRDF", "soNgY", "bDPlT", "eROAd", "WnFTf", "jIvnv", "ioYSh", "jaMmQ", "Ntgws", "hJGJK", "pDnea", "ItMeb", "ckCSK", "BmXLy", "hpiIq", "DaeVO", "hIWHM", "LLiEb", "YRBtS", "lelIz", "GlPIv", "SQlqF", "RvJIP", "WgGoD", "ihWOI", "wJkUs", "zWjXl", "iZEmY", "AafDi", "VsUPp", "zFvae", "PhgWy", "krYCo", "jRdFP", "PopJQ", "mtkMZ", "bAEpJ", "ugySo", "GGOhB", "UUqyh", "ZSbqt", "sdkRx", "rsYpH", "fBpKp", "vxdmj", "LesfZ", "HKmeR", "uPSXz", "auhUF", "skpam", "HOoJL", "zTfEJ", "ITSta", "mEVah", "vSLzL", "yBvmh", "LXZQr", "KeBVe", "gGFaW", "qkMec", "OoEzV", "wxpVc", "YEnXX", "wyKrI", "AZjan", "WGkQK", "GyYYP", "rKYxz", "uAJBW", "PzcKj", "JRUtU", "qDigo", "DIfJL", "IJHar", "MGRQD", "tYYZc", "KJwsw", "bRJcp", "ZgnUC", "zqRYS", "dbFHt", "asKqB", "xfvfw", "afMkT", "JZcGT", "Obige", "KhjwE", "gHmKg", "BLhZQ", "PYgAF", "YvuRj", "iTzlA", "oAZRW", "dinEN", "jCpjg", "rbEOw", "qEnNR", "mRtea", "QAedi", "YwkWS", "fSqsu", "WsriF", "ymxbh", "kbJOr", "RVhzg", "gbggG", "tIHPc", "QjNPM", "KnomE", "JGddz", "TxBHb", "cOwZt", "sRqnv", "xzdUt", "ERyPU", "IvGZD", "IYdnV", "mrHsR", "ghrkx", "kVExK", "AssnL", "EuXyI", "KOfjY", "qIgFF", "QivaX", "YCIdf", "gPrbs", "UWccv", "RQccZ", "aGshm", "jiiPG", "fXgWR", "lSljU", "ShigV", "cNSZm", "pweof", "rlDVI", "eHrQr", "urNwD", "KjclV", "UCACT", "eMYrz", "ywzTs", "QSVoS", "nxWoY", "bZRZL", "udPcK", "AwYiN", "FPSlG", "ALcNm", "RIDdX", "fSumK", "vjBca", "Gjwxb", "rnGGk", "UkDGy", "csPnl", "tksnF", "FtyWk", "mFDJj", "muTvK", "ypEMn", "YxtPN", "cKOvh", "LUajR", "PpMWu", "YMGwV", "RALbm", "DFBIY", "JPGQE", "CoFZE", "DjrXi", "DsdOt", "YUCgA", "MjJwy", "iPXRW", "aZeHz", "bGBYg", "DXceb", "EBqXx", "lJJJv", "yLPmq", "yBLxJ", "fwzAL", "CSnef", "fXDsV", "FpqDM", "ZXGeU", "SnTVu", "kSNsR", "KKJIk", "qGEEG", "ptaNZ", "KBRLv", "gkKzL", "JfFYB", "XIIkM", "oARcg", "WscQv", "tvUei", "QWBGS", "vXOum", "LJIpt", "qhXiD", "ZmxJb", "cFvEk", "JhXhj", "ClCSh", "PfWqg", "VVEsP", "JZXiL", "yfdos", "hCDjt", "ZWeNR", "yulXy", "FbQWg", "lDUrL", "WgSCj", "WBORG", "SYmXA", "Lyakd", "MPCoV", "ytaOl", "Jvkyv", "YMkNP", "bImMh", "bCbVZ", "VYrUq", "EapgJ", "LuLxP", "CFZZa", "WQsAe", "HzqzU", "wvIXO", "vEapn", "HFFPS", "IFOsp", "IZQOF", "Rfncq", "pNCyN", "vMecx", "zWKOg", "HzwVz", "hkDme", "HGnlg", "cyjcO", "xQdHf", "HIcLV", "uzIUf", "GOMEW", "fwoJk", "VgiYt", "iGQig", "PHYep", "zBFGN", "uJpRj", "ZgukG", "xilxE", "YYvMV", "SGisw", "uPrHT", "EZvtF", "madKj", "BhGtt", "hYxVZ", "cBXEH", "HoSeR", "JYffF", "aqMqZ", "NvyDW", "qkbHt", "HzrHN", "VIDFM", "rsfLm", "PQELZ", "EgmPe", "iPMlw", "UPsIz", "fsLrN", "PDDSk", "vKcTe", "cKilU", "KtRWl", "ItGhy", "tREwX", "SinpW", "Mwofy", "TTPxL", "VWsyK", "SvSta", "fnjHO", "giDpr", "qhbzL", "oUcsM", "IhZAm", "jTAZg", "BBZRB", "Hjxds", "lHEUD", "TJQev", "YBiMQ", "Jrjfy", "jQiSc", "xjfdA", "QpObV", "ESHkQ", "dwPzm", "OURff", "pniFZ", "JwEjf", "aJBcs", "BWxLK", "lobeP", "FSAEJ", "eWwmv", "OlEdB", "DUnHA", "LbNwE", "NePFs", "UJzjH", "hLOPg", "MKIUW", "gmpjp", "VyPlO", "MAYkz", "GgUFE", "fwXfV", "QRQXQ", "vbyqH", "yTixB", "NScDw", "vBHYy", "YfZFy", "vwqMi", "eWkgC", "EleSZ", "VRRuD", "cLQsC", "ENVjF", "jdUjb", "uNxMQ", "TGWOx", "OWyWD", "itCQA", "svzof", "sSGde", "CrVxg", "oSBOC", "dekZY", "UeJNd", "xygTw", "XXvEZ", "yhjpK", "uKclu", "lihJB", "Evqnw", "nPKLm", "YbHDS", "FhjLN", "dutVU", "qWKZM", "jkOed", "PMDYX", "YOePl", "lQxlG", "jTGui", "HJveT", "PVLnu", "UFAnd", "FoNCy", "CZsTR", "rnKmi", "zaiHX", "vXtGT", "uFOiO", "zXnKm", "phNpS", "ZdbzP", "ETUbw", "yMiMb", "VMske", "ndQBv", "iFrlw", "Bvoqu", "nECcd", "POgtc", "WKXcZ", "Uafce", "LwrtD", "ZnBop", "OCHuR", "WhWYP", "POuTr", "CYBgJ", "wAZwa", "iVthY", "IhVUv", "BbWbs", "AVvCF", "HpCus", "oykBb", "PBQDD", "CaVSD", "EyOgR", "hRhzk", "vsgWe", "cmnrk", "moyhV", "mOoFW", "UMabT", "Ykyfn", "ERvoP", "DInSu", "SLgCO", "OmuQE", "SEidm", "FJiKs", "vckfY", "fHOCd", "zDraj", "nPIFB", "EWaVK", "ZMmvS", "rsqvq", "mJKfA", "DorqB", "OfsJi", "bzJQc", "KyBMW", "xSdzi", "qrSoU", "jiycc", "flfpd", "xztVg", "Jflxm", "GduhY", "AvsHu", "vYbHu", "ANBly", "PUtCP", "iEehL", "EJvob", "cesGh", "VyQzz", "Ejbdg", "GJDZT", "genEq", "cXpal", "jxaZx", "FUdct", "PEwGE", "PKMbp", "jAyEy", "meBQn", "LRMPb", "WLGKy", "fixtL", "eyZfX", "OgXUJ", "nazPC", "ErpVp", "zMYQM", "STmkw", "bBSwM", "jZbEd", "HdaAv", "cTzYD", "FaSBB", "eNYDi", "XmLza", "aBxdT", "DoytH", "wuIvN", "QMZrC", "FXMjW", "WbFei", "kSsMt", "hprgz", "wWnTc", "wYrew", "XNbDy", "yocNC", "dZSRm", "DwFpt", "DCCrL", "KRcvA", "RTCXR", "VFcBg", "ApPzs", "BcOSv", "fpSwG", "jDuNV", "VJJEj", "qiuTa", "CHXeG", "DUyXq", "vEDAE", "JchKk", "PnItZ", "nxpXf", "Knmjy", "QxJaQ", "NRqsV", "zGkQJ", "zBHcG", "DBQah", "SYqli", "uqjZC", "JsrKZ", "nitYr", "tCLqv", "yPXCP", "ycqsi", "CvKCh", "SAiBD", "cjKTd", "cyQWj", "AAdAg", "Tbcvv", "jwunS", "NYLug", "ehxIF", "xCJQF", "Yqamv", "HylMc", "OhPRP", "LxceT", "NFmlO", "abedi", "KWRHV", "rnwDj", "EQBet", "Bwkjf", "dOuUo", "vzATH", "AkCUp", "xZKDZ", "SgVRB", "OuQbJ", "EvcOp", "VtsOo", "RJmqc", "nrqXh", "dNQIs", "ckgzN", "zuBAC", "CKkSZ", "YdPuO", "sVsrD", "jVtXz", "FzZBp", "idOFh", "atObC", "sbPZa", "ObQNK", "MKVeh", "WUxJU", "dNuUz", "kNjNu", "ZlSjQ", "UHRyS", "RJDKE", "bXPPX", "coEwo", "EANDN", "tAaNS", "cdUBy", "kvBeK", "vZLOp", "cGQNl", "yNnDU", "svwzq", "zXRjL", "GiMMf", "tpFwT", "qIoEB", "rDqKA", "pxxWa", "NuZOx", "WRBrc", "QbQXW", "MPhoF", "qYnJy", "hmgKC", "QUTdk", "LujDS", "deNFy", "IlEyK", "fArPp", "XSVWi", "JFtQv", "mFPzA", "FsiEu", "cFsxx", "AmIJa", "wSFqR", "rnlSc", "NSJNA", "UykVy", "NjOvF", "mPfMQ", "CWMer", "GfwrP", "YZjmw", "otRgJ", "mlSEg", "haBPb", "ISGiw", "OsTAp", "QHEIh", "sVaFU", "YVbVO", "FEZNH", "XQYkb", "cPIKo", "QNRKD", "UvakG", "DQcKh", "ekOJE", "MIjBG", "LOUCx", "HlCNe", "gdQUZ", "uQbMj", "zEXwB", "Uqtyi", "iBfjD", "hieNn", "TICKO", "vdVqo", "amqLt", "SFYtf", "wJsqx", "xSjhS", "KIjsi", "ssXVO", "wgSIW", "uFAXr", "uVbZw", "HxqRM", "bRBOC", "Scehe", "qoOnx", "fFzkA", "mkPwl", "rBvhx", "WdxCt", "HNRmZ", "RjqUD", "ZkBMf", "zBdNg", "MpMpv", "YICds", "ZstbQ", "UgIaF", "Yjaoo", "RVhJK", "TkjYd", "lDLdf", "HFoia", "EfDgo", "nXcas", "nStZM", "nZxVN", "jovYQ", "Orfgi", "HaJFa", "grBkb", "EURnP", "GAVyh", "OzJJy", "aMDcx", "ZnGoG", "tVJNQ", "kkhgn", "JnJfx", "unPxi", "nJUOM", "qNwDK", "XxwkK", "OTXKQ", "LHKom", "wEkWD", "vKtNF", "KSGSk", "QyQor", "SxEXe", "EbPAy", "PehIp", "rYpEt", "DVobD", "WDZwl", "jtSWB", "TUOOC", "XfOHx", "XzCrx", "IUtDs", "JEPxf", "wPlUm", "gNCjm", "FEnOe", "WqzEi", "aNJng", "fAwKV", "JmUui", "nZMbX", "LDXsO", "vsdfn", "QrqSU", "NHafW", "WJgKF", "QnHZJ", "ORRaP", "muIFK", "tlWgG", "eoLEE", "pDWql", "rlEKv", "vynCD", "rFNOZ", "aqErt", "ajRUY", "ZjXbN", "FhMWx", "VgFJR", "fGVnI", "NMrPY", "GdDvC", "BlXxO", "jxqgM", "MPlIl", "nOSca", "GPxWT", "hEaPU", "qYgrv", "KvYSv", "bCltD", "UoujQ", "HGkVs", "UvFVd", "cWTWA", "nHUNi", "VpeAS", "RsEjN", "FGfYr", "jytrB", "yrLvF", "tElnL", "MprOc", "qyHib", "aGhdP", "HkSkw", "ehUue", "OiMUj", "oXVWa", "WUnzP", "yuqZW", "PcYiP", "HXCQo", "BwzGH", "umwUL", "MqJUb", "RUxUA", "ToHZu", "UDmNz", "YqIxQ", "PwKCY", "Pomwz", "MIkqG", "JvsRd", "IFqqU", "bEUMR", "MclmY", "SjJbQ", "NJThL", "UiKyv", "ePMGv", "hTTZx", "DMKFX", "ZAAoR", "ryvuu", "UpCJH", "xSwUM", "AXodp", "tUjct", "chzLv", "pDnGy", "VhWFJ", "kFBOq", "ANvgD", "nVPVI", "GAiOT", "fJTHb", "CzBHs", "YuNRQ", "CTJzR", "OcdOl", "KHpcs", "vIYKZ", "yZGyr", "BWWBY", "ykGAb", "duSbP", "uoHJp", "BreUf", "wJxrU", "cGHqu", "kiGwC", "rMxwz", "vAqGX", "wLcvB", "CKMrP", "CvuPw", "QJEEf", "jaCbU", "UoVUG", "firss", "YqedG", "ylvRE", "OiENF", "Mrdhz", "fCMRt", "fTlBr", "lclzk", "xzOJi", "Tedpz", "YZVYb", "ClRGs", "nOyCD", "RkuhW", "HWWxO", "pmLXH", "BmVBJ", "BGszJ", "Cboaa", "iKGYS", "VfvQO", "bEoON", "xJJXW", "muozy", "juvdI", "YyOzW", "HMePQ", "yFpkR", "nvWaD", "HVbly", "hyNHe", "CNpYu", "glQSB", "vvwEl", "CXpmz", "sZMxJ", "JfvXX", "hpoAl", "oDdDf", "nXDHr", "qBqiE", "UlzWI", "bzmiZ", "siSET", "VADvK", "jLnXM", "AvvrP", "fgAJR", "HCttw", "jcRoo", "SqXnG", "hmbrw", "OODMt", "dAAAO", "mDeIF", "VfjTi", "sIySp", "yNRFb", "RlJXk", "GRMdC", "TMSrN", "YyhAq", "NMhRR", "xAYNQ", "LwjaB", "BnUwq", "PGdrw", "TCWRc", "ifxHG", "sgbpl", "pxSJQ", "MDudF", "hjWSn", "Gznuc", "WuuzD", "PLoXe", "RktPJ", "SWwwX", "xWvdd", "qPhMP", "SKGFL", "TXqTn", "mhTPL", "SLwbl", "YxmJU", "ROwZX", "CSjLU", "vPcMM", "vMuKp", "UPUZp", "ngkyg", "WntEe", "qEWas", "RBMjN", "zBsuB", "rgGQk", "Ndwku", "ymqmM", "xhSpZ", "CElHo", "HhTaD", "VbwMe", "gyeAW", "aULCp", "ENiby", "pMAqS", "ruSSg", "gVLhS", "ElqaF", "YDbTE", "dIEwx", "aZxdn", "InjhF", "AyylX", "AhTNN", "BIgck", "UvHRx", "QfqjY", "bDIva", "beaXg", "fxrdz", "AVXLL", "ULbBz", "NoGQU", "ZEwBH", "MCKQM", "bzxjx", "GDlJA", "JCCSi", "hYWbR", "IZDui", "DsziS", "nAFzk", "Utniq", "qcgfy", "QFUSx", "tqdFW", "zLKZD", "zYOCX", "JniBZ", "hCfRM", "jYmAi", "nYnak", "haIjS", "PbBtP", "KJKRv", "NDquu", "sNyma", "wPsxV", "cEzkq", "XgIvi", "aPovB", "abTyp", "BHwDl", "fDVXX", "XPFss", "GEOFn", "NawtP", "BDcfA", "XCXcB", "gcMgL", "pHpJH", "SaMgR", "hpmKc", "qaDoK", "jKSLx", "MOhFD", "EkFmq", "qXxBD", "XiNSE", "iMDgh", "szsCW", "VqotA", "AlYmn", "mCXJL", "Iuppn", "UJWnf", "jUsZZ", "wHwPc", "ouRSJ", "zLdme", "UHupq", "tDimw", "AfXYE", "EqAus", "ZSEop", "bWAFX", "eiKDt", "CMaau", "XTxLK", "xOfSi", "eooux", "jAZPQ", "NwLwc", "THCuS", "pehim", "lQpLs", "UIrCG", "hNVrK", "zOuvW", "SzIqK", "MmLQx", "zsYLd", "dcOAl", "TFnMw", "AceIK", "GdxKI", "vKjur", "opUyB", "CjsdP", "OefuF", "OpKyU", "ZMcwn", "KbCoO", "ChYel", "hNfql", "GikCe", "asipo", "JIPna", "gQTjO", "PMXWH", "XAjuv", "mPxgO", "ELPST", "topHH", "noxCV", "wlpJY", "buiSy", "fJldI", "LCtEp", "OGTwH", "TRwlw", "kHNBy", "WnZfz", "VPNlU", "EcpiN", "zqJyF", "pVxQy", "euKoo", "kIbJd", "nLYEt", "qhpeb", "gpoZU", "pGYtK", "ZMsoT", "VkUkn", "xtUjS", "pDbNM", "PvXUE", "WtazX", "TLKXf", "LcMqz", "xyAzW", "CfUDG", "lWiPk", "VQzNB", "JZqVR", "XBqgd", "vPxZl", "SLTWQ", "KhItY", "RnUqC", "qWEmT", "HleLb", "dsaPL", "Bgzlu", "KuDtY", "Qgqqy", "ZgsUs", "zLIkU", "CGkmf", "tZMay", "PJyNa", "BYNgx", "ZhmmZ", "dvfpL", "EZVhC", "TSmia", "qBKyO", "FjjCV", "HkwFC", "oOOXE", "OOnMh", "IxaQC", "Wqycw", "eICZC", "McNRm", "mqNLJ", "HGDTJ", "xVkcH", "YYhUs", "iamkq", "WApvn", "nPopy", "ePvkG", "PozSP", "bzluK", "GTmpV", "xMdsz", "lWFNW", "uXjlV", "MMtNb", "XGgDq", "JcnVx", "QBgrA", "GmXSq", "uqIMk", "CcWLS", "ckLOI", "NDnqA", "MiLEW", "EsPQr", "QWsVb", "wqKap", "iwpwX", "KLzlX", "Rqxyk", "SKknj", "vCOZD", "UrYFV", "zGnxY", "WDTuO", "obCtP", "QelfX", "MGdoe", "qcbgs", "Oftyk", "rfrxY", "XoiTK", "ckjHE", "mBaWy", "vpRFJ", "yIQVs", "tPwvr", "huOMR", "ZHPMe", "TWDbV", "VXWMd", "BKXej", "odfEN", "mowtR", "QOHHB", "EqvYU", "zWKSl", "PxIrv", "UAfNk", "FiAex", "xwUrh", "nFQlk", "kNKCa", "nmSsj", "nSvZp", "ReLlD", "AMfDd", "XIprQ", "RtMxi", "MGtfO", "CFgfE", "jRFlT", "gyfdd", "MTzuV", "pstmL", "nrJYE", "CfdIP", "QFqrA", "cDvif", "JaqSm", "GynXD", "mdWUB", "XQile", "jQJKf", "ohhFu", "gXOVZ", "BEYPp", "nqapk", "GVLHc", "oWYpc", "YaNVg", "OAeqi", "ODweQ", "KstqO", "KfXvI", "YHuUW", "VprBE", "lfDGq", "yEXDb", "DYwjw", "xodzc", "BckrB", "UlgKo", "SOpJa", "whGFE", "hSAcb", "qLRdK", "ceBgY", "CIcgM", "dCIpx", "wgVZl", "BrjLc", "ywhCa", "Tldwd", "EaiaF", "sTufh", "CKuUu", "JGWgB", "RWSjY", "CAiWP", "sJwnW", "LsQeX", "KDFsj", "anoTa", "YTLQV", "ojGGy", "IRJNd", "bvsxv", "LQUXV", "qsltK", "XtvhJ", "nRZmj", "KfnPW", "TzoNH", "mNrXk", "DvBJK", "kTdEz", "LGgEf", "GheXP", "WgriR", "gIJdW", "ErwGk", "HyEDX", "dHzlN", "QayLb", "hvdhU", "PeSRw", "NoZpP", "tXJJS", "blpdd", "bMIZO", "THUWT", "OUlOO", "Iweco", "ekOIV", "gKnaT", "CJcnA", "wRSnX", "lyiti", "feqzX", "rnuZL", "gnZIU", "UZrry", "dICOh", "cwbSL", "QPqVf", "XOtBS", "kQzgC", "gxKwL", "hemnF", "yRGCV", "fzyXd", "OhEgc", "zSagO", "MHESq", "XYRYd", "hJHvL", "CZDZQ", "xkOMK", "xZsVd", "SHbqF", "RmUGb", "WLsAZ", "yHCQD", "OFBGl", "rfrcW", "RhCWg", "AljbK", "ubUOy", "ihkCw", "yiJrA", "hPljr", "tSqOl", "FmSQl", "jwHQe", "Emtjg", "CRSKX", "HACgV", "JhsHc", "kKFnT", "MkjQE", "dLKoX", "DoPOV", "uPtVe", "XiSPq", "HfWmm", "wiiWx", "FhZaF", "NXOHF", "uwBxD", "cPJWA", "qAUhY", "VdIjR", "tDNxn", "JGgTe", "WBvzt", "BPvGc", "lbepn", "smxQA", "ipnTi", "nUetc", "HEzMs", "Bilhg", "NxRdq", "kekON", "RIyLc", "XTKkh", "ZvGBo", "YOTAP", "Tkalx", "AoaCz", "DfbmJ", "xGUNC", "BzAFA", "cuQht", "PWyZE", "Wmvyl", "KpojZ", "MPOwL", "ObtEY", "vjIjk", "fyCzG", "omKRD", "GNijW", "XoxuB", "CJFpE", "lSqcv", "cCaoV", "FtwME", "paqxc", "wmLuA", "MbYAq", "YiSjV", "kQnDz", "Gblej", "EnFgt", "pnUmD", "pQRUA", "qAZHc", "HVNQu", "pTVMR", "IiAoC", "TnSQU", "bnpsV", "MVamD", "CyvKQ", "YUFaT", "OQgKu", "fOrCh", "lWBCm", "vNmUY", "LJFSe", "AjVPh", "qmVCR", "aeroT", "crpzA", "SoxnG", "qKOYA", "EnqnE", "UZnKq", "vXEcE", "EYMlx", "QAKyq", "gJXvM", "pQFSl", "xlPVV", "SMvmM", "FEaPu", "zEbtg", "dVNWI", "vQxCA", "PYDiH", "fgGwa", "OltTl", "HmKXA", "IsRwW", "ANFOS", "GRusJ", "qzvFu", "yhxco", "DIDvV", "jfkWR", "vSnPT", "SVFyU", "wIojx", "cyTty", "rjhLv", "lWZvC", "qXFBz", "jocnw", "UxkGr", "KoeTO", "hRKxS", "JIggu", "gNqjk", "VgtYD", "DJLzq", "BDkgm", "FlJep", "iOCuU", "UyyOz", "SshGW", "Xpzki", "aEHtj", "vseRO", "VDCth", "PJqce", "KQiBx", "mGBJy", "MBygs", "vrdhf", "nXtTW", "CYCzP", "QaLNb", "gUkCm", "iaOZq", "jNVcE", "yIvTk", "isHIH", "CStwn", "pcWmx", "dwzeq", "EQKTK", "uUCeA", "iiiAJ", "xijlL", "uhCDG", "poITw", "gIlAO", "sswTK", "WMRhK", "SBPEY", "IHFXb", "JUmbZ", "VVHUD", "VmIUq", "LKmkD", "oBwat", "YgvPB", "AoFFn", "PfnYC", "xZhiD", "rmyEy", "QrvVF", "SwGKQ", "EiFqF", "WRcBk", "jGlnx", "IFbyJ", "lrasS", "xypUe", "gtMiu", "QZNet", "WPbxK", "dBWDD", "deYzI", "fcdoL", "iQozV", "OkwJC", "CdQYD", "gtlMA", "Aqewh", "VEubv", "GsyTm", "XQVBc", "duwzk", "qXfqz", "RAHCD", "qRXXS", "WUyxa", "FFtUw", "KxvyE", "vcPgs", "VmSmL", "DlvdO", "dPpgW", "ENfYC", "FKwfZ", "MATkm", "NgnDh", "QeLce", "uvbvx", "IVYva", "wFkCj", "cCoZM", "Wlkfd", "LImkO", "XLLxk", "SERzh", "NgkNC", "UEUco", "CwIkD", "NTpug", "GtErV", "rILMM", "GxsnL", "bhNUr", "KhPhM", "NOGcQ", "YuOlF", "FsdyZ", "jPxTH", "KLAqZ", "DCVzU", "vYPVF", "NbvDH", "Cwyex", "QGAdL", "LELUl", "wpKQj", "KHNaR", "PcKlT", "UiFPP", "aWrdD", "JBKVS", "KyQTU", "FRKAX", "KlQYV", "FcjnS", "eukUg", "lBfau", "SHoga", "DEPIL", "SMlwy", "NNGLq", "exGAN", "YfAvr", "cYaOt", "FjeDi", "AXrFb", "COwdk", "JurYr", "GPhgP", "JKcQS", "OdWQU", "GFtGQ", "TDkXt", "heQlc", "BvIbP", "XWXAH", "VWZvg", "yFJCV", "YejmA", "ZXYYs", "oZZsR", "tWXvY", "HNphM", "WurBk", "hSATq", "jFElg", "tRFRe", "NArTN", "vjrVi", "tGsXu", "iokxt", "nQOmt", "PDcVI", "zBnQG", "ObWlE", "jkJpq", "wLFTu", "LYaHH", "XkupU", "TnDQB", "XbNdt", "VWxun", "Xmron", "Ihiok", "WmsVF", "sfTqA", "PmvnM", "WJtXm", "sPlsN", "QtqWh", "lyeud", "cmHcb", "cHhem", "ksRvf", "TEnur", "Baiuf", "pMpvt", "krSNQ", "eGyLr", "BJMNR", "asjNK", "SxyJL", "CNtkp", "lSBJx", "tMYVH", "tueFR", "AFvEe", "DPTWU", "ojVeO", "DwPjF", "vlNsD", "QjivQ", "vWLpD", "iXVZv", "xymly", "augrh", "Ypzos", "krGlY", "hKrdL", "lLgyA", "vVLKc", "xaggH", "EyWrL", "lPaKo", "SbPrA", "hveet", "dgrLF", "cIpwF", "vTfNl", "hrjOp", "YNVch", "BCsns", "CAyyK", "aYEcM", "ctePJ", "ljXBZ", "uGYzT", "ELojT", "zmRSc", "jjCtq", "eWHzi", "nWrDi", "blqor", "IexGj", "AavLM", "EVIji", "iywIM", "ETEXW", "xDQLl", "hptlF", "uxnJr", "tPtRh", "FdGOB", "ZEAQi", "FgmZh", "yZlPj", "JjCxY", "WzkOp", "aAHOh", "hbvZQ", "KbjQq", "WwgVV", "ncgEt", "OjFVC", "yrUtm", "qWMbW", "SYmKS", "LyGfw", "hWYEK", "MwgRK", "Wjrnq", "CxLGy", "nkVAF", "CWtcM", "ROdpu", "AFlCF", "xvqRH", "RnmPj", "TPfmx", "PJUNp", "wbkqM", "xBPbl", "UkwkD", "HcMDp", "VqRUn", "kbhwi", "RXSRt", "MvrlG", "Sjnoz", "LoouE", "hftsD", "KnlAF", "JqKlM", "bxLsc", "nTwhg", "bvgEr", "pMZaG", "EzRua", "LNsfd", "UCrDQ", "XmEAX", "wifiB", "iWbnk", "FFjLj", "nLCQL", "GAvnx", "wUdRC", "bKcvR", "GXolu", "VIlAy", "pkVYi", "IPnLp", "CkCxN", "KcDVY", "TMsUQ", "UuRwQ", "VzKBB", "HFsIE", "xozxe", "FJFSk", "btMQH", "rLapI", "XiGHX", "WaUWQ", "cdxLF", "dLuNk", "VgARr", "IMTfn", "LBfVP", "okDxe", "HzOcB", "CNXJt", "azVdR", "gnnFu", "xdzpA", "LYHwd", "UHeuP", "Hwdhr", "kxUER", "kqnOL", "pcvGZ", "oWGiK", "ncOPk", "yjsYx", "nwBcB", "jdLQi", "IMZMP", "poHUh", "xIVyO", "OulQF", "VsLxC", "vPrOI", "GXAPt", "mXFjT", "xfGzF", "GfxnA", "SAWXJ", "daWGJ", "LINCD", "ZgaUJ", "rPoZK", "gVNhE", "JzMfF", "OPitE", "kwWTr", "ClaIK", "glcal", "TBCYW", "yjQnC", "KHDOv", "jMjcc", "yrxAh", "DkOXZ", "CWlPH", "MwAdh", "TrVBu", "dZYVI", "TWWVV", "hQPej", "UpanP", "sgLjy", "ifHXF", "Uqdjq", "jJsPk", "uetGb", "QuTNg", "IVlrU", "NcnYc", "TazgX", "rizuU", "YjgWb", "GIBVp", "vIhnU", "XBPpI", "Rwgdc", "lqfMW", "zJEit", "rOBZW", "cQMlK", "MUdjX", "AGJiC", "hhtrc", "zZOPE", "obOSj", "cTQnt", "vTopc", "UzaGi", "GRNnY", "PAGtF", "qzGTU", "TNPsX", "aUZsL", "dKkNz", "NMZTj", "iuGlq", "XmnXm", "aEijo", "luKDU", "awTDR", "GwolI", "HPrdC", "QpBfQ", "iZQUJ", "RPVma", "ugwJJ", "lfdHg", "uEbSQ", "NfXNX", "xqHTp", "eAwja", "JOCMe", "WKEoR", "uMWfV", "TibIJ", "nwiWC", "pBEQU", "fEvdn", "RwuWB", "KLKnB", "dHLzg", "IwEbV", "jfzpf", "DQbiu", "IvjcV", "sEnpi", "FXneh", "yYKAi", "peQjT", "feMnT", "gkSFD", "vrvCU", "NBKub", "SGjim", "bAhJs", "tZVBz", "pHUBc", "JAhUy", "mGSKN", "ACXfR", "nKShJ", "Jezmo", "UVOpY", "aWOZp", "BLbRF", "ghECx", "ZWFku", "OIDGE", "RaNuB", "MrWog", "wzlrI", "PSzpD", "gQPlH", "ZQiIV", "EPwAt", "uvXSL", "GEqTQ", "dSufR", "bnldH", "InRmo", "bNnfw", "nzQtM", "fWtUv", "gHVQl", "zmfzf", "tUADt", "jLXhh", "wVVwJ", "UALFK", "WDyDT", "homrG", "aavGm", "hzfGM", "kRZhB", "ZoVLC", "bSkdD", "IPmgy", "bOQkq", "aOGdr", "Ggmrq", "RTXFF", "qlCHw", "sKeGc", "VrKNN", "fbXsN", "JGbyA", "uEiCf", "hpHLu", "yoFDc", "VZyHR", "NPFLp", "COdIu", "JbezA", "boeDj", "OcWgW", "zXXpE", "psOmo", "qkmWU", "SeBNf", "kbNtg", "YZdsr", "SSqTL", "hVcnc", "kogpp", "ODtnu", "KQZzu", "ApTsj", "DdkKZ", "KxAKy", "vUAJt", "xxnEo", "xhQjo", "CKUgV", "DGuIy", "AMatj", "QfdNF", "HXMXk", "LGJRU", "jLMKm", "dOaDX", "BwTuu", "pvEOW", "LeOYN", "qKizu", "PFYXO", "vmGDz", "vFtSL", "tPdBs", "IBzGs", "XtyqC", "cLWQz", "ksPUX", "eYERN", "pBbBR", "YTluT", "TRDiM", "iMetS", "tTQSC", "bvxVf", "GBOfX", "TOZeq", "MJjOl", "jyXvI", "BckvT", "TUKSf", "vVYGJ", "ajaQv", "NkIOh", "JemQC", "KDYSy", "ZvZZk", "GPiGj", "vWJvm", "Nwfjz", "Cedgs", "mDsti", "VEIGo", "MIXHQ", "wdeja", "yjEII", "qraAd", "BWMGA", "Ksltg", "AHhOY", "LovTL", "oQCVr", "nQDjb", "Aqpzq", "RrcMt", "gDnmg", "YZDcH", "cVzKE", "YNSVL", "kEnqq", "kNdwF", "rXgAB", "jdWni", "qzvZO", "VflMH", "jZxwu", "jRDFc", "xyBLk", "zARez", "LXziJ", "TEawH", "DJXCi", "Rqevk", "sLeJc", "fnHUU", "XennG", "iDThE", "YHIxY", "yTDPm", "frqbN", "jvcxe", "klYao", "yxRAg", "ijzuk", "hiMGt", "qavDO", "XSIPp", "pfpIO", "DPUEn", "ULOKa", "aGkgw", "wjdAs", "Dkcvk", "hIxdb", "lnshL", "awbzw", "lawfr", "edvEO", "PEtHf", "uUydw", "wcgLq", "bLxvb", "QLPvT", "vjTtH", "JJSkA", "VLtZm", "IMBYl", "sMAMF", "kcrrn", "JXhOt", "byPcm", "cIwTs", "GQsDK", "tygpz", "UKOMc", "VtUSe", "cyNFy", "SNxGH", "iUeiW", "UWESW", "vHDIn", "cRyfq", "Iaguu", "nVopg", "HQsiI", "SHOCm", "gnKXX", "hRkaI", "RZACz", "gQkqn", "cgCFx", "dgjov", "suSLZ", "zZoiH", "QWIYD", "gnGMI", "eONnd", "dguzo", "vPSqd", "yFyfk", "VfGQX", "pSaFc", "CCtkI", "DJnuT", "AEApS", "IKPqa", "cMEXK", "KWmPe", "VFQqG", "tftrI", "nQpxy", "vOLDK", "fQffx", "pfXFS", "wivlO", "TDZjf", "JdATd", "Ppfca", "qKBYa", "ziUyc", "tsSor", "KlrQK", "QAfSp", "WakzJ", "JYJBT", "oOklr", "OZakJ", "IUtyz", "ezaJY", "HyfUD", "NEjog", "kyUBK", "WXorl", "vqvxs", "fefiw", "QNxnh", "GoxKC", "IqNCc", "gaLUN", "grCRG", "imOtg", "bkbXo", "UzxkN", "LFAiU", "biisK", "yLQPG", "YYreo", "jZjZW", "pZRGG", "JVGTE", "aMWPb", "dOzsV", "IqvJL", "CAHdS", "elqLp", "xMCQL", "HEhcq", "OUUUQ", "ZgckD", "aOOUf", "HlxsK", "tavBM", "XOMxz", "GodBg", "fAVat", "cFGCj", "GAfqG", "BJSWg", "btuMh", "VCbCU", "AAkAn", "smgpD", "Tfqtq", "OhYop", "wVxev", "fTltA", "fFFsS", "SeMSF", "EOYXX", "cRNXf", "eslVI", "DlmhR", "uicHs", "SdeDO", "oKlCD", "KSfVq", "qAbsi", "DBvFm", "mHOhx", "ZlzRk", "HkVEA", "zDWCN", "gikaX", "ZMgUh", "nLNhd", "LNLhM", "VxUea", "qRfmW", "iqazh", "GCjik", "QQKPN", "PspTj", "sFRgX", "cRrZS", "BXerS", "gChQn", "iEXlm", "sfMBG", "ZQcUR", "wMgLq", "yADmZ", "vqets", "QKhGN", "KYvfR", "cJduM", "jvrhR", "SOOuA", "VOGWu", "bTkQf", "lCMQc", "hukoy", "sMylB", "kmPTH", "TUChf", "tcbFL", "NCeek", "HYGUq", "lLING", "XyNJr", "SJtKO", "PhVCB", "zTMdl", "TRuwC", "DhYsT", "qGucB", "nUepw", "uxjWw", "CTZsj", "FWsTR", "kQIjy", "dJTFG", "ufzqw", "HxLpd", "CSbxM", "jJWnW", "VZCmD", "rjunY", "FSnVJ", "GBukF", "xLDTD", "dpwHU", "YTMUf", "olqwg", "MvaBX", "htnCn", "JnFAv", "xkZCj", "QtnNZ", "YuwjJ", "mlnhP", "FjqfV", "PcigP", "uPHBp", "tzMwG", "ubKAQ", "hdQBJ", "lILhq", "tiuPe", "nQWZt", "JkJHs", "EwWqS", "DlpbN", "jBExm", "VECJN", "jjQkk", "sVRtR", "KAiiD", "exOIO", "CZuab", "tZThp", "nXjPf", "nhvBM", "jaNrf", "HikAZ", "AAARI", "TKbdg", "zeBuL", "fMTRP", "xxPSw", "WiMXy", "hTHEP", "hNbHI", "uEWhH", "QzhbP", "MMaUi", "UdSGG", "TDpjR", "dHHPB", "VNTMg", "gynmj", "JfroV", "cINwa", "XltUD", "fBSIS", "ahjgl", "fllIE", "DjBmS", "TYVIM", "jwLec", "pCnev", "fGUNX", "UzCvq", "encTq", "OUMNZ", "aqbsr", "YlVPj", "uAQkd", "FdaCK", "jxEDX", "KBvvE", "jBnKt", "gGgxW", "VVvug", "Edmna", "XcwBb", "uGuLm", "zvdAG", "QGnyV", "HUxmB", "HqxQh", "NlZcM", "fPsQX", "SXACM", "qaWoV", "WARFw", "GYvMt", "OYYNs", "TaXbG", "nVmkV", "JesoG", "eyKon", "doasd", "qCYhs", "TwOTs", "vzmvB", "EjnKj", "jMcey", "ATnxU", "eDnqj", "FMhet", "wFsTM", "nanJK", "UnUVq", "cJvvk", "MEhHI", "uvRtn", "TApbm", "zvktq", "ogwki", "tMGUB", "OTBEV", "XurVp", "aVcXf", "jQJoM", "AoWnO", "xIPqn", "ayiVY", "XhPlc", "EqUTB", "LazDg", "Xbyel", "zwaAi", "CZiPC", "Djpvu", "VJAZe", "XPxHi", "sHkYk", "SyaAG", "ChxnV", "UAcff", "JvDFO", "YmztV", "QMKao", "bwKoq", "XfnXj", "YmHgR", "QUoGp", "QMFXd", "SRehX", "eGgcz", "ngotB", "WLglZ", "MgHkg", "GblTG", "vWNhr", "VATOU", "vPFMQ", "cPuLd", "bRiCr", "wQgoI", "aSgQb", "IOVBg", "zMQvB", "kZXtn", "RCaUu", "dJylv", "INDme", "oYTmO", "mQGcW", "jlweH", "IcfLl", "UskXT", "weScF", "wCRTn", "zjBwF", "qIDxl", "uUMfQ", "EFDBS", "paJDq", "PcpCU", "PwDkJ", "FqWmU", "blxiB", "KdnGS", "trsuJ", "xjMhf", "nALLr", "RBzcr", "gVSzB", "kHnYc", "tYPUx", "mvpta", "EVDnz", "MWNfw", "HENlJ", "gQOLJ", "mMSmy", "gLvjE", "ymOUq", "PuLzl", "Vfhud", "gsXVE", "Aoiuo", "MwVOq", "mWCKF", "hVPvL", "KNbBb", "SAmwz", "INUru", "EwQhR", "ODwaC", "KSJJd", "WyodN", "mljAT", "DWrYj", "YvwGa", "Qgzla", "DKhnP", "aRoGq", "xumFc", "jqngv", "xSuzT", "VXSjG", "NdKpk", "ErPxe", "wvWnl", "ESPNM", "rDFvI", "kkxyl", "pzSdR", "unDlo", "Nijyt", "XoMXg", "XBTEA", "DdAaB", "mPPsP", "cVhfF", "irjFz", "RxcLP", "aRcjC", "svkkZ", "ZLTuC", "MWbZE", "OZCwm", "pnhCc", "HQGMs", "wFhCi", "GSWaF", "nAVRH", "uBNup", "NZncg", "CUKTd", "Dwnfy", "xFXaN", "onhEo", "JXEfN", "eLgXL", "LFSMQ", "FBQbX", "wZqjz", "ViKAq", "ZRvVX", "BjKYZ", "FOQCW", "oCbPZ", "pibPn", "Elpgb", "hIrBr", "ldpOR", "rlyjR", "lxxQU", "Cfvrh", "HjBHy", "gPPPo", "dfTAN", "OlnsC", "SzAxy", "sNtrk", "JgLlx", "GyORt", "FJjic", "OlPIK", "KBVNh", "rseTQ", "eSbnj", "hRHKk", "dmvOp", "fKgEl", "gradc", "OIHwv", "ggOSt", "MyXgS", "KfdAV", "QYxrN", "UKMZb", "xOILS", "hZImr", "VurnZ", "dFdEf", "LlxEM", "yFPRa", "aqLIm", "gxFzg", "KoIqR", "YdJHN", "oBDRS", "oLtXE", "zuySw", "qNrtH", "gKonl", "NxdYH", "tXMeE", "wDRmp", "gRYzl", "pcYIW", "GObbq", "YkMEZ", "xkpbA", "bcTPQ", "RoLsH", "HOPrE", "uvvmX", "mLUcT", "yGzkT", "YhXtS", "yWVsS", "TsMko", "iCCuS", "lSdER", "bMtEN", "QyGac", "uQjda", "ZnplU", "RaEcG", "pwTur", "XmRrE", "HrLmt", "gaBzD", "eAFGQ", "OWkIl", "PnigR", "PMtJO", "fLFTJ", "zuiqw", "GNbvr", "vBpSI", "jPCjH", "SgiGp", "apEPC", "wGwWe", "dZAdE", "tcGQo", "IoeZC", "pOnjM", "dshfH", "AFOsD", "UEGai", "BXYTK", "RaKIM", "oEWjA", "ERSpn", "WPzcW", "icnIv", "UVIYc", "qLbem", "bBesP", "qxnpc", "cRmxe", "UiuzB", "maHkW", "keocn", "QCffE", "mRBvR", "JQIms", "yKcQM", "tKnDF", "RjoBA", "gtHcC", "mePda", "iwUYZ", "rtaiy", "VCwTm", "MbnPk", "yMnok", "KTTCx", "cyXNw", "IkNxK", "poHya", "NvpNJ", "CoQHB", "qnkSg", "jeqic", "sObDn", "ziHHQ", "HADlr", "lCVXS", "AvCeQ", "XDAvn", "dDfjm", "SCXKk", "zrKQk", "aOzYX", "PNbvI", "JjkRC", "tdipC", "zGAVl", "eyOzN", "zEnsE", "mnEWs", "TebKD", "JUtLC", "ulJHE", "RcWRj", "lUEBM", "nfNVd", "YYFWn", "KDVcV", "NTaif", "shAMq", "viqOb", "qukHq", "xVbJt", "hdmuZ", "fMQlk", "JNHBi", "GGqGN", "pUhMX", "dHHGA", "RVfzZ", "HBXPl", "SDCzB", "tPBgM", "iPTWa", "uppZK", "vcmfQ", "xzoqa", "xgsKm", "eeiFR", "JroRL", "UOwXO", "eoxZk", "sxrsd", "TbXMK", "gvnwf", "vpKGq", "bLhIO", "ZFHyK", "FcbmM", "XeKqx", "lOdvA", "LLUId", "ZFOSP", "YUCdE", "VZmLv", "fBXSs", "JFckV", "NUDDq", "mvbts", "QylFY", "jWwVR", "wvxcq", "wIIJr", "SBYcb", "ZYDVB", "bQGLf", "mkXpU", "LcbNR", "hregw", "KpKgv", "yYWlo", "BFluM", "OvPXf", "bombY", "nLynZ", "EsTxq", "rxpeB", "kXitz", "HIeLg", "xREbi", "CRmOI", "WGtNu", "BMcGG", "YZmUa", "ckoPM", "zHgUT", "OArQQ", "XUAxM", "dXSFG", "dQepG", "plKyt", "qcCdV", "BWMVr", "qzqhs", "sVAPI", "gWdvD", "NuHBJ", "EbJkS", "IIGWt", "OgrRl", "pUtqt", "UTpKA", "VxUxw", "GeNBy", "LblZk", "IVAxu", "niuXF", "MkjrT", "ySswV", "ADtaL", "yLesC", "HDfTp", "JZOiA", "kABSs", "sBJAv", "RHEog", "LOTZU", "cilli", "CEHrB", "COwrA", "hEZFT", "RklHL", "TVzte", "yJQKY", "JaZHs", "KXUZf", "iXMpv", "yPMIG", "WNfvC", "PcgFT", "orFfa", "dEnzn", "RCBIv", "MauAk", "DaHRp", "LGYJo", "iZvrL", "hmRZN", "JFMTM", "OakzG", "DCAEP", "SiHOu", "ADMZd", "igAPV", "Ozbht", "Obrqw", "uHoOg", "ghJYj", "IrzAj", "kurUV", "cMIIs", "JQYDn", "KMmLd", "Wroup", "dKpti", "MDhFO", "wKeNM", "vAHZM", "CDHLq", "OEZCt", "EchIc", "ViueX", "mXWAJ", "pjVVs", "oWWOu", "ndCLc", "LYwqL", "Txgep", "wCukD", "ODttv", "PmWSz", "CmQzF", "AVXaj", "IGzhj", "XBuBV", "OejSe", "PkORy", "akWPA", "mzpcz", "tITGC", "NKnYC", "bcvve", "vJwyI", "EKvNN", "GFQsc", "ZQNQn", "hbkxY", "AjmMP", "gYaqq", "fzmOL", "xussZ", "zmCkd", "FvmIS", "mFzmJ", "UecKj", "lbHTs", "cqOHX", "OMGTM", "MaeHw", "eWExk", "NcmHR", "xYjxt", "DUEpS", "IpfSA", "glffe", "FiOdo", "lrRgT", "dPhLc", "lezDh", "eKmRb", "IIgTz", "yZFiL", "wevwH", "ygUIn", "JRQVl", "ssHqE", "TiVBx", "YMUIe", "xJczN", "qCapn", "eULFM", "LEBRz", "qQAiS", "sSoNI", "hgNqn", "QVsat", "mmWhi", "qBXLD", "cThTi", "zhtkB", "FEcUg", "UiMmS", "KxUkl", "ZuyzJ", "XqImI", "MoAfm", "aavnz", "hOvCA", "okOzk", "UiIKL", "gBMGD", "FuJOn", "pRNuI", "AjOEN", "WqeyR", "oNGin", "CGZXf", "fZrrp", "ozFJH", "KHTXN", "RYriB", "vkclS", "AjwJo", "JDare", "bINgF", "SSXNk", "hTvca", "dHSuJ", "yctqB", "CNhZL", "RccsB", "cKFUr", "LmNvy", "tTiyl", "rQtXv", "ntbee", "XoFYV", "aiKiO", "iCHHO", "MVcun", "BkqTT", "QDHIN", "sZoAj", "iYyKG", "pMchT", "gLkwQ", "HoVFJ", "TLuqZ", "AlRdA", "TvPQA", "oeUXL", "AKOnh", "LBNfx", "aTKdQ", "VMLKt", "RAAiR", "nrpZa", "xbJXh", "YRrhu", "jQkok", "xnTrx", "eAZQz", "aXYiH", "NScWA", "GLDJL", "UGwaq", "lAwFB", "ifiYJ", "uQxIQ", "wRuSn", "mDWjG", "PjTvY", "BQVHf", "kNUdL", "fZOxA", "qwzIj", "BDTId", "wTBVt", "giWil", "VBTGU", "qIdbZ", "xJKxX", "tDCOG", "aiKzk", "HJpeL", "QDGNu", "sDeWj", "mDCDi", "qFuXI", "vJZpn", "qgoMm", "WcQaV", "HJVrq", "MKyqB", "gpPMO", "CgscA", "IBJUN", "HyGzp", "nJqmJ", "nmmmh", "dcnRq", "oKRUM", "kHslL", "CQOnV", "wmPKs", "bPthx", "VNboV", "bDypn", "duVsW", "WGnCn", "JQGGa", "tFTOV", "FlhGn", "JpyUW", "HjITf", "CArEP", "WGfuX", "kaSNA", "ckGDU", "WSwGG", "fBahT", "mNgzh", "lvEIU", "SvrQR", "xsVFU", "wjHXj", "lWajh", "EvInb", "AyYCn", "GCIVF", "FkbXQ", "KCDPV", "fiVdX", "EzYLK", "sXycd", "ddqXA", "CLKfx", "SLiso", "yWpGy", "CQeot", "iemPx", "McUxy", "BIpeC", "TyXQm", "JOFyR", "MBGXO", "GwyWA", "DhDtx", "Vrsbf", "SdBOF", "XUawR", "sShas", "nkYID", "TQwGh", "CSoYS", "eWCvF", "totUc", "xDYBs", "sEeyW", "AOmuM", "IVXiG", "uEQxW", "AatiF", "FOxfq", "xQEBq", "MdKyQ", "CLglx", "dBdSI", "lcXAd", "Jgtvb", "UnKrN", "FfVTh", "JjUHC", "NmWnf", "RGTKf", "KcFDJ", "oPpan", "SFHyC", "BPcoe", "gRJVO", "sCcxt", "EZlaS", "MuGbc", "sWoRS", "acNJb", "VLFUg", "cBoTe", "szjHg", "ntjqH", "zCPqv", "YanBg", "FVQlJ", "kPaHg", "KzsYu", "gYkDa", "Hkuub", "vauRw", "auwqQ", "SISuQ", "vOWvU", "htWlH", "vfcGG", "kgEyS", "oJPuU", "YBFhh", "pYcnR", "WVuyh", "qpfTx", "AqJvG", "mzyIg", "RImnU", "UgAVJ", "RJuvq", "tTKTY", "Lfpwh", "rjLqf", "OzuKj", "lHXCu", "xfInJ", "mHgiz", "GFxnF", "xOFNS", "TIyas", "tqSxk", "socPr", "bqBIu", "cOVNl", "ocfli", "QbQjx", "xsZdR", "VLsGv", "eDboz", "wgjXT", "tFTOQ", "pWpeu", "OkDEH", "vuQlX", "sYRiA", "FypJK", "mAWvN", "MOAHF", "CckJh", "rxRDV", "gZtqi", "JMVKV", "MXwxK", "ThqqC", "pEcpb", "QnwTR", "dAtFD", "oKzXs", "uiEgL", "hhrcl", "bdbDR", "GbFvj", "MBzpt", "aJMZl", "MtRlO", "gkSmD", "cPwDa", "DogdH", "LSUHj", "elLla", "LzImC", "DSoFI", "oFrmh", "Unlhg", "lUzvt", "wJRpH", "BavHP", "zwUOJ", "okdJo", "XSRbN", "igZAd", "WXdjV", "UCWDa", "pcFVu", "xhBFo", "AYshI", "PUrYL", "MqGej", "AscJn", "ZfpKJ", "OBuma", "rrlfY", "VHLKa", "ikfVM", "ZdiJM", "YQmPj", "cTLVV", "mmkFp", "SCmcT", "owpet", "yYqhU", "ofukt", "NeEcY", "aQJPq", "OvLdK", "vKRCw", "uPEsg", "OjnXm", "RFyiD", "afiKC", "zeagT", "lLuki", "yEHIe", "Gymey", "VpGyr", "yedjt", "BCOEc", "LuSYG", "nHJVq", "SqYif", "MKkAe", "Aelug", "HybPb", "wNICQ", "GvJNS", "qEvVn", "RmxQh", "iuqHS", "FHJbj", "wnIqS", "tXPos", "XdNtc", "atMGR", "OaXaa", "IaOkO", "CjaDc", "yzSvX", "dfiTf", "jvPEg", "dAOKC", "UeQze", "HXjDx", "AnBgQ", "XioHI", "hDXTw", "ytuXr", "wopxL", "ipDOI", "tzXct", "HXBPV", "FMmFY", "Hgxwf", "iOpgw", "IJTkB", "nHPVp", "TVBOb", "mBKAE", "OUIPG", "bLeph", "dVXrO", "nwXmh", "rSzqP", "BSEnD", "JJRpl", "YZsUw", "fTMWk", "xSRDz", "DMHgK", "Rmjey", "zFEdm", "brDYF", "ZAcXt", "rdquT", "Pigtz", "gcTpD", "wVunM", "VCaLl", "pATLF", "XJNVw", "NrsYa", "BnqYc", "PKHzW", "aWzlo", "XczPC", "YSbmO", "WbBcG", "TPcVM", "naydr", "WpupS", "AlGmJ", "UeUpF", "XdnPs", "lHnJH", "JWUKP", "ExSIJ", "rvHYD", "ESihX", "fxjjD", "xfVdl", "ECqgY", "tZeWz", "UnTiR", "IOOot", "fTvXG", "TgBcK", "tUEgF", "QHzhW", "hKrWK", "PdWSc", "bXxIe", "HtPGe", "DGrvX", "DPXcD", "yisii", "PMNmy", "kjHUn", "XxMlU", "QjyNC", "enxVU", "gVKht", "rwGjq", "ARrDn", "qVRQQ", "yqgvu", "CggTF", "LFamd", "WZGgN", "jzbTL", "gVxBC", "OcluX", "SBgvq", "Taywe", "NWgXD", "OWqQi", "ymZty", "oMgXJ", "VwtdX", "tyYmq", "uiweD", "SJxSd", "Xdvlp", "zVqBF", "lrspU", "fftXQ", "ISINO", "bQFnB", "qLhdF", "kzAFO", "zzQdF", "AePxD", "PNYrf", "MUruL", "tHbqm", "kNmIz", "GZQzQ", "ZtMFC", "SEOvQ", "LFLty", "BjbCk", "qmltz", "TFMYv", "HELPz", "ylzEG", "Oeiia", "vLmRA", "CrjCd", "pqqAm", "oDkhp", "jmSfH", "FYJqF", "TyZup", "OyNDP", "Qkytq", "wBZNm", "cKswe", "evThr", "GXPJP", "lSDYI", "veXEn", "miqFZ", "fkVCt", "QEPeR", "mSYtv", "WGQYD", "JTcrM", "CpDHA", "kPGWZ", "StvQj", "XYKZh", "plgWs", "QwwJn", "HUBHH", "ayWay", "kSzgG", "nXZeK", "PBWmK", "UUXnw", "RxEnw", "RfPPX", "cuvWu", "yMvue", "rGgCT", "FkRUv", "Hybza", "FHBmu", "jtfTS", "GokPO", "SXMfY", "QoMWx", "DuLQE", "rppEH", "vjddo", "NQWqK", "KvxbL", "sNzAs", "EFGRI", "yHhzh", "EVlIE", "DnKuA", "yTvCb", "UOMJJ", "lbHoS", "fSaxW", "FsMui", "ArdfV", "JHNOw", "slKsu", "gnENh", "lZspY", "RnzbD", "XaFlr", "kzFKL", "cKvTJ", "SHnNy", "fmByY", "tvaHo", "XSleN", "hmYUS", "zQHyh", "dUDrb", "tXsCl", "prNEW", "OgQJw", "nJRWX", "GFWZk", "vxkaV", "yxTYB", "WiXzU", "TaeDG", "agyyE", "cpSBM", "LtXNF", "YgeZt", "oBntJ", "UusvB", "GQHda", "uRlZP", "ZhWZL", "uZoLv", "knmdj", "lGFwG", "JMCWF", "txNBQ", "FPmfK", "WFPEt", "GkFGX", "airKz", "oCPKe", "HjKRY", "oRPqg", "CyBki", "pEqoe", "TbQrU", "ZCpSk", "xszAy", "vNQAo", "VLVvF", "gNsku", "rmnUi", "RGeqy", "wcEKQ", "UdLkR", "JdCPY", "kRIVI", "YrshO", "iBDEq", "zWXkN", "uHwAh", "cdWjC", "qqdLI", "ByjVT", "LlIga", "ZYOMQ", "jMlvD", "JkeSi", "nyhQB", "lxcOQ", "HbCqZ", "hJzDf", "zyYRg", "TwYmx", "ccido", "tBBRv", "BbzqU", "vlUQG", "OCYjw", "FLkpB", "jeuFU", "CVMty", "zBmxb", "WfjGk", "bIDps", "gCJPd", "IRexo", "nQheB", "nboBn", "DWpNB", "uFhTd", "KvvvQ", "wIsGy", "SPqsk", "LrKTj", "SCvkC", "ivhpH", "wBvrt", "uLPdE", "FTexP", "gIKzp", "abplQ", "iKJFE", "MFbRQ", "eXuvK", "VGMZt", "EQMzE", "tAqYC", "mHKZh", "HGrXA", "mLDAH", "dgWuZ", "bwFZd", "uHhby", "PJLkQ", "TvOnP", "pNwJc", "fOwVP", "kSftl", "sUlbv", "gdKof", "SMcHg", "DypNG", "WnsQT", "rZFRY", "PbttU", "pTXvF", "TmQCy", "XUAgE", "ikiMR", "LIPHO", "gsVPL", "WdsQA", "GYMOI", "YJJpA", "BKtch", "QhrgP", "yNuJk", "DaLrb", "rcLYa", "vdUri", "wMEIZ", "UXPsH", "ViHgN", "wnrUI", "FGWQj", "iLMxV", "KUxDU", "XGOxs", "VztqL", "jeKqI", "ZTjrk", "PPifA", "XljJj", "fDGnJ", "GgdtP", "lAuPd", "vLiEU", "ZJhrT", "Zaoce", "KbNDh", "zWJcX", "PVqEd", "zWicE", "RqMUn", "KOVaR", "evoHT", "ejmky", "nSgaM", "xdPfH", "rcqtX", "Trzfp", "ZTfDC", "wRHEk", "qqLrg", "Tizti", "mzeAr", "MdrKe", "ZOmXX", "MjsjZ", "zYKyp", "NyFze", "BdwEf", "utyPE", "oNFBS", "eYEJA", "ZlTaS", "bwTiY", "bHcCb", "pjzYF", "nKMeW", "zNZYD", "Rmlwh", "xPClO", "eMAiH", "BbrjK", "LwUVk", "AiCQx", "cLLaO", "nzVsb", "wTOON", "cijGT", "zwciE", "NRNyU", "AjaXM", "YvjIm", "lqxQu", "RSEjp", "uzGLh", "WzCob", "GRCGr", "skzNd", "AjQYa", "FcrTV", "XDKcK", "eRKWR", "UTgSY", "FTUqB", "SWOMn", "NpuNq", "JHpCw", "gLETU", "ZIJVD", "hLeQa", "YFPgd", "kGuOZ", "QyvaP", "GzMAq", "EiOks", "SFbDE", "blmRE", "mIuwY", "KYRqL", "nHjtP", "jQfjC", "UvwyM", "qgKvz", "drNdT", "OVIwu", "zHkUK", "ECLpm", "JetpG", "ylzFU", "hSJib", "WROIS", "qsFqB", "IUbLh", "YonAM", "iRmxV", "mrHuE", "cFiGK", "bNVjK", "KhfDK", "skEKX", "NZmvg", "BTaNd", "UViCh", "AvBQx", "FNEEr", "czrjQ", "hYfKf", "MDvpg", "EMdGM", "rUiYS", "ZLRFB", "blxRf", "IUUmj", "WkFwE", "Mfxbs", "uQpiw", "zDDaU", "TPGLf", "VsTkg", "ktiSC", "jPGzK", "UzVmx", "bEevj", "ygwnC", "yrzXe", "mtqil", "jnsPW", "LYNOr", "BmuGx", "gdJNu", "XPjBs", "wLkrz", "hoJGQ", "ckong", "BoPWB", "yIbZg", "cMRCb", "xfYML", "boIak", "ApZQO", "lIUAz", "UOTFf", "FSjRY", "HYTNV", "oOSNv", "mtlEJ", "haSub", "UlDjm", "RzLEU", "ilIjr", "Irsab", "QDRij", "XnhAr", "PzWXt", "DJbli", "gqgNI", "dZpwA", "tLoRB", "nxfIQ", "CWpbQ", "lEEGb", "fGoBS", "kMbLr", "XKLFA", "YAMVq", "ydUFF", "ZGWlt", "USSGF", "ofxVu", "WdHDu", "gmuUP", "taczS", "iwpBx", "MthjI", "NRCPE", "Cwfvf", "eIBsi", "XYEIB", "ObgCL", "vkKat", "yMbvF", "COzMh", "IMVww", "clqcW", "UzQqr", "OlpMz", "plcAd", "FBOGG", "nUbaj", "TYTWJ", "TCFXB", "PaMyK", "FLaaR", "lldgN", "iTBvk", "eHzjc", "xrpIC", "PdbBb", "SDYgs", "Xhkkg", "JLiNi", "hyLLu", "jnHBH", "nkIta", "MkFlQ", "Auzcb", "mYUnG", "UUteA", "shUQO", "msiXT", "uPhzk", "oaTyS", "LcSXX", "iizWv", "SaxBt", "DYjJm", "dnXtm", "jVLuR", "FPzgJ", "WjEvP", "huNEy", "yZNew", "LFMDh", "KIttR", "artdw", "nvIiF", "kdtCl", "QZZEW", "IrSdB", "TanIJ", "kZAPk", "sFEin", "pEZqo", "ZoWSb", "cTlEr", "GHFcf", "tLPKH", "PGGNy", "IJiIP", "BHptJ", "Wdosj", "ImIHL", "tEjzA", "mQgUg", "Oideh", "RyCPV", "CRPMB", "nugAi", "XSflY", "QHHIX", "YsQbV", "WhfWE", "BCIKq", "eXCgw", "ioInb", "cFdSk", "lKaxf", "JxtcB", "zTMBy", "wUavd", "MgSsM", "QHQkl", "kpEsZ", "kEuza", "DrPHi", "MuJmi", "JPnYL", "ktvuH", "vGnIk", "ZsMUH", "AyHEu", "vtcSP", "vWDbj", "LlvoK", "dtRzF", "xJPEg", "BYPNw", "hQXKf", "UfqsS", "CBPjA", "YnuxP", "nTgxA", "DqXzB", "dZvtl", "VgYTj", "BeKRX", "iOrdc", "AIkJy", "xtrIp", "XFAHS", "MScCs", "SNkPK", "xCFlk", "kQvGP", "TDFlm", "EwcxM", "cYxpE", "ioCKr", "Qsdge", "iibYA", "hsxHr", "Hklew", "MZSQS", "fiKRp", "ZcfMA", "jSPur", "itRzW", "JsFbD", "vgGws", "xfXoY", "ycdCb", "SjxSw", "YDZbM", "rNnXC", "svQtM", "rrtYM", "HfMDX", "iScdw", "xlpAT", "ufLsn", "IiPjp", "hKFVd", "vVaww", "wLNbR", "XIOyN", "YiqFE", "RhXOe", "LZpEN", "PiBgj", "yLMFg", "EMOgY", "JUCRz", "mfoWo", "lVESX", "FRung", "ZJqzt", "mJYVc", "tocMD", "WAJjL", "KmaVX", "HmrxF", "Dofzj", "lRyTf", "ZubAs", "ujPuH", "eNgpY", "RRmyI", "aSNMk", "gSATq", "tnowP", "tjBqF", "Yonsm", "vpeVa", "pfmMz", "pUFYk", "FFBSy", "qCaOp", "GlJlT", "DIhAf", "ngUwH", "hgVWQ", "oxwgU", "MdVxm", "htlfM", "LLmow", "vDfQO", "aCiow", "wjIom", "onJgo", "wXeTe", "NyqJJ", "TJLqq", "ZCwcC", "qfvqJ", "bHCAN", "RhFBr", "nKsml", "TGrdM", "vCdta", "fToGn", "xKAGm", "uMDOy", "SaBNx", "sTuBs", "FxDCs", "ykdFq", "ORzQK", "iVNFh", "mhGHh", "pmlUh", "XKXDs", "qWRuv", "khZJU", "lJUSY", "CASmp", "TYKqp", "NdLsn", "VrMxB", "hQkhw", "vxKrV", "dcCTi", "CoBel", "UiGYi", "XHNNY", "SiQku", "akDIw", "DSnQa", "GTDSQ", "IuAbD", "cneMg", "rVEIJ", "qOILR", "yQquL", "qEZEZ", "SWgWt", "mNjeJ", "REVmh", "bTYxb", "GLXqR", "KIKHm", "cdnCU", "NvWAj", "HzUSg", "JiuZu", "FcDqp", "YHjZN", "WBQiS", "kIMak", "gQkcK", "QJGWB", "cnqqc", "OhSVG", "mYqSK", "RSDGn", "oOMhG", "EHWxL", "lELld", "CIOhp", "DODZr", "PehCs", "VFLXc", "IFgho", "yGmUS", "pjZqW", "cnsaY", "oLjQH", "FHcYK", "Ekwfc", "LcSNk", "wmTYJ", "wCYiY", "kUZxW", "QTxOr", "sUcVT", "kjYZC", "BueKE", "dlUvZ", "ZbGOg", "PSxyj", "QwRtD", "qWgpM", "mLrUN", "BFufk", "PGljE", "Bhqpj", "HluIy", "IiokV", "tOaQE", "DZoXj", "QyXUq", "lXMBW", "Vsusl", "QiaUY", "ckEJX", "qtJzM", "EcAcF", "EDVoj", "fKyeH", "RlEoN", "jxFUf", "uCDrD", "SgJoD", "YefLP", "QqaSB", "sqdHF", "HZoyc", "SPoAl", "cbBEk", "FAPTR", "bakFG", "fpkwN", "SRERB", "LDhsv", "hKlsx", "gqzBg", "NOWNw", "RHpGY", "GAxOn", "assnj", "OcruS", "mVWAO", "SMqye", "srtUL", "hwcLo", "hsKHZ", "RgNfL", "lHhSl", "IXQFZ", "xhAYF", "VviJl", "KnGje", "GsmgZ", "srYEt", "HeJlw", "qQHSL", "fQSYC", "cOJky", "dDjDc", "LOrEM", "uUFvq", "uFVLQ", "cgOvl", "iILYZ", "Hunpy", "HlGii", "UbKwb", "dgMEI", "wxHPb", "jvdVz", "klnUS", "zalhx", "BwrjS", "TzkWn", "PaZWI", "EDZZp", "OHkMu", "FQOkz", "EaaDk", "zQHJg", "MkCne", "vqmiR", "mlySp", "SAaRr", "FPZxg", "gltRp", "NFrIE", "lWdza", "eFeip", "IoBYe", "jfrDR", "xotJG", "KHdma", "TOBTO", "REGfN", "jIRzD", "vdysZ", "fLtwB", "QdIne", "DESsE", "qXHGX", "vWEya", "rFoEe", "lNSKd", "BQWYe", "FWLHU", "yXTBB", "IAfyV", "eOmVU", "gUYAs", "rVHYi", "RComx", "ewWcj", "xhwqN", "uAOIU", "hdDAy", "lXndJ", "vdMSb", "SlMQA", "Fivqv", "EPQQG", "IhRiV", "RbdYe", "HKYRj", "UFRqP", "dgGBx", "Eqzew", "LyzxG", "fWWjt", "IWeRD", "AWPXf", "arshm", "cZclb", "AAOFE", "RPOts", "LLMeH", "RIcvq", "QdhYS", "LdAmc", "FtQoe", "YbrSX", "yoEkR", "iyZZq", "pETed", "WpvsM", "TUVAz", "uXDHb", "JHrTO", "DEJub", "kQHIC", "vuCCr", "fmnlX", "ZoKQO", "CujTy", "nxuSp", "GOxBk", "Nooov", "IRKjn", "unvGU", "ufrWw", "bSWPm", "PwpfO", "FIcYw", "hqLdS", "hmxpu", "BoVEq", "aAAKp", "qGsfn", "xuYQH", "Amvla", "DRVur", "qrvct", "ztXPo", "pEHQa", "NQvoj", "fJdZs", "gdznN", "eZYKh", "pScXb", "sSWrx", "WesJi", "oAlTM", "QuggZ", "ahjIB", "ZPCio", "mGTrr", "ZRXNs", "QvVJe", "lSoMv", "kNwie", "FQYrx", "gZRWN", "JtbVc", "cinPu", "LHXgK", "KLYRf", "ZyxAG", "nCeHE", "MWYwb", "QwyoB", "LZfHN", "sZleq", "GyzFo", "ksozH", "PFIeo", "JCfVH", "tvckW", "RfmPp", "IeWZs", "vUKLj", "uHfVg", "oQWWE", "HOJTA", "bndnZ", "EjZhP", "IqsEH", "vBzcS", "VZsEi", "zrwnC", "tCIMh", "Bhlgb", "cveIq", "VcKyO", "KBGYP", "BpMin", "rNMIP", "ZSTVV", "hrRVr", "uWmSX", "nUaCD", "SYlHy", "gsrJG", "oNJKW", "rhdgF", "bIbAA", "NFTbD", "sUbYv", "kwkzG", "SlCfa", "FdTrP", "NxFVf", "RexGA", "vWXgo", "cDZHe", "alRkn", "YosNL", "KaRBs", "vSiMk", "WPTZg", "WUZrc", "fKqKc", "jxOqo", "ogIkQ", "DkMUp", "ZzAKi", "VCEBu", "cGihN", "CCERU", "jpzcb", "EHmgn", "nHQCL", "WocBu", "rIKKx", "DOnKw", "USKrm", "QFoQp", "BVtnM", "VCXfg", "ggjjB", "UySAj", "eIanS", "fyjRX", "WsaWm", "xSMvr", "jKoLx", "Ssdew", "mYVXt", "qMekp", "HPMln", "QwpfG", "fXUtW", "tqpGT", "nUlUs", "OiSaI", "KBvud", "vfxEO", "lfSfi", "OgQPJ", "sytBs", "mByvv", "PjOcG", "WMKNo", "lgzAX", "zplnX", "aAXkW", "VaYgm", "qBnyW", "kGmSP", "aHpRt", "lDqUF", "lNCqK", "mLMUH", "JmqXk", "QgfFK", "Kibdb", "imOMP", "ADoKS", "qAZxz", "PgASd", "TDhIT", "XpmNy", "kOCFW", "rUPuC", "ITFAI", "Lndzd", "bTKBX", "BjdfW", "sbTEO", "hAkaA", "cfxIY", "IUTps", "sSUKl", "YYmqw", "eYnvD", "rPamD", "cdXmF", "RMjxN", "fdtID", "chCcf", "Ktpna", "VhYYT", "pTDCE", "lTANM", "GrDKN", "HSPpG", "xGINk", "uDxYt", "eNkxE", "gsXLY", "DeJEQ", "xdklG", "mWKTg", "SwRxP", "MppiN", "LKmDU", "sPwXG", "gwOeb", "vhSgz", "fNbyA", "Yomra", "lJIyx", "biZMy", "XQavg", "RdNTk", "OVotH", "nRKye", "klYgF", "PxIpF", "IVBZh", "vyEUm", "DJgaS", "XunKQ", "myvkb", "Xvpey", "hLWTO", "zJYqw", "XwBVZ", "uxUCQ", "qHODq", "vbwbf", "miSIa", "UFoYP", "iJxTd", "WGbmc", "SqgoQ", "ZHOVd", "yQbgG", "GBjXr", "JTbmB", "JXvVF", "LhRtF", "zyYOj", "JZmrb", "qKVUD", "xikSe", "FJTWb", "zWPEB", "RqVmw", "yFEXy", "QGoua", "ztCLe", "eqOqt", "IPUNV", "BlRFx", "jQBND", "ezsRb", "BkYEo", "XJIlS", "lpVTD", "vRsjs", "oiusD", "rhNay", "DIPmQ", "dClYo", "AVMYy", "YTZmX", "ZpHuW", "UinUs", "zhDvz", "zRUwN", "kHONS", "zbHPf", "EqZyN", "zipZm", "tVwIl", "YQYSS", "ZyaBI", "KxmHc", "OlvnO", "ZHcFx", "GtoYY", "kfkNd", "YpNOj", "tqvZI", "oRoEc", "orSDX", "xuncK", "PzHqr", "gjhZN", "CBKdf", "nUBdQ", "YZGij", "ZZPmt", "yNZiL", "ejmLm", "Odaqi", "fQChV", "cKHYB", "NUrTW", "TBNfO", "YhLAC", "FUMHO", "zqTkI", "VLOYy", "zIIPW", "lVZPU", "tRadw", "RRzQn", "Bbeji", "pMHNy", "OKIks", "dQbXv", "dTewJ", "BayQw", "PnPjd", "QyZAb", "UwikY", "zfRSg", "EvokX", "JTGRQ", "gIgON", "Ximtk", "lGSIs", "BDCDY", "YSEhL", "fMiff", "ywQqL", "LSfHb", "AojYe", "TcEls", "tdXqT", "xjqvZ", "gfwXJ", "IHZPO", "aGWBu", "BSWCC", "slgAt", "uGxIn", "mIYZu", "ZZBkq", "UABMs", "cPAQr", "MIzXi", "EUYdJ", "Yabcd", "BFrnU", "VNfFc", "sPCaJ", "trpmO", "tTXNm", "oBKrF", "ReRdY", "hisLE", "JywDx", "KXURH", "vptQj", "UkPVT", "drbIN", "qBMQS", "tWtgd", "JDjNr", "GdqDn", "nLtyC", "TeVqM", "BONsu", "zPTlg", "ZCNeU", "jHWGz", "kMMAV", "MgTlR", "QYjar", "watPf", "FbGOV", "xYeiU", "orryb", "uTVKT", "cIMnq", "agNJa", "ErTPl", "ckllK", "ESvEM", "WhbmM", "jQnTW", "btfdw", "QmaEs", "Rodgm", "Cjvsq", "IfYmB", "HtOYW", "yUJEA", "byVDP", "wFPoA", "fTlSy", "apVGK", "ANlnn", "kNuvG", "JLvNT", "JOzvs", "sFLap", "NyJOE", "jyZgW", "DKZgr", "FsqHp", "lMCXV", "JuzgT", "HnDqE", "EdCXa", "VpVUq", "hbhHo", "NDbLR", "BQgji", "mxGBs", "wTMNa", "RdIcr", "jsETg", "KYFLQ", "UZZNI", "HaHzQ", "UhtPZ", "nbsJc", "KKtFW", "beZTh", "LdFEm", "gpjRR", "OQsFO", "nwaLk", "wHnaN", "WryOd", "XxLqf", "ijmrM", "KeavA", "pYtoG", "EIhFM", "HwAaa", "WmZJc", "OcfYO", "tOMMz", "XdrkN", "ZotTK", "SOSeV", "jntZg", "bJMOl", "KlEXH", "cMOlu", "ugInR", "QWqbd", "qwfqO", "ALHFa", "BrFzP", "PFXYa", "oqHXw", "lcSGh", "TaPyN", "ofPNf", "wSNNI", "oMrFS", "OvCtW", "lhKkL", "jdXOf", "STMEn", "UOnxS", "VetGu", "jfgNw", "szBKS", "YjJuz", "tYcqn", "QsYXF", "AMosb", "Grhgu", "Rxzqy", "NmgXH", "MWLdB", "uwEJs", "GcmsQ", "JFPoE", "covEt", "IZFfE", "loUxa", "OEGSa", "dDkcc", "ksuDU", "VKJZg", "HKgLe", "vSXtN", "gZCNz", "oEJJD", "GcaJw", "xhJgc", "ofEAp", "mbJRU", "PcsNe", "EzzRG", "ixWwr", "YEtgm", "qOndN", "qzHeW", "MQlQZ", "mSNfU", "VlFUv", "HqWvu", "CYSPJ", "WdoMd", "bMlyH", "OWFJE", "dDkZn", "BHsgo", "gHNRO", "Vuooh", "oBNRq", "jZnNk", "SNOKj", "SyAsS", "uxchS", "tLlaZ", "GBUln", "KGvRH", "DUECh", "aLtzl", "KDTTn", "xfGpg", "IQIhO", "MGDhI", "cocoD", "JmYNL", "Ovkoq", "kMHTd", "IZoEO", "UjIKm", "eLfLq", "Hrdrs", "teirX", "GFKeB", "eHsYe", "gqAra", "uYXmt", "ayDjZ", "rROmU", "yhbdP", "RjyNQ", "WaCQD", "wUXaH", "opkXY", "ctjXd", "LvBJZ", "ijtFI", "CZboX", "yujSu", "WgTFL", "MAKTD", "bCqbi", "DjbEF", "UapAV", "zvRdg", "ovzKl", "YfSQm", "nYiNI", "IOhlg", "BrvaQ", "hrSfh", "AKdMd", "WqcSC", "GxQyQ", "hFdNB", "ipskF", "kwfOH", "IXZzh", "rlyjy", "cQDGS", "KNpef", "mJomn", "zyaRm", "KnIYW", "iDkKY", "gdDMx", "JdZOo", "DPyQa", "mwtxP", "LlUjI", "uiIiA", "zMmNF", "aQYBX", "tqGQb", "smRLz", "lrfkF", "ZwrNQ", "sPGZC", "cBBNG", "PusGL", "pYMsn", "rFeUR", "ZhUfe", "HBsCl", "ZQrXM", "aclib", "umCWS", "GFMVM", "ChTqH", "dbzjP", "nxtHX", "QoWli", "QytUh", "HGsJA", "TTkwx", "ZTwrZ", "cZkFO", "bbuGz", "nUsBy", "PLORQ", "fexxG", "knhyt", "xtJCd", "hCMki", "doWLZ", "JrMwI", "WIBzj", "dBgHV", "LoowB", "uJZcT", "eMbtb", "CXubQ", "hUaqg", "kSHRx", "EidGw", "tvAgs", "VdbKY", "WjIOo", "ZEsNd", "bwEii", "ffgfl", "IiQUv", "zOcHU", "Lgshz", "YLhXw", "xiDUv", "KveeI", "xBZsO", "adVvc", "bqfew", "qYcZS", "lgcrC", "JgRDv", "BeQqm", "YaCJt", "NVFyI", "qlMQj", "jXYhf", "WlfeE", "ZADjs", "pfYLZ", "aTTBA", "cvtMh", "xEGmh", "bLKFf", "ZmJFV", "pFUUE", "sFmoi", "tPCjx", "qbzHD", "dVIdq", "XrEqm", "uKZjc", "AJIUA", "aYjGZ", "sAOgL", "xWINq", "HHvtd", "ziDFA", "SVHrp", "lidxj", "HzZoR", "ouokO", "TTrnr", "TbNIT", "iSpjB", "rrBLG", "mqmUv", "NaEHv", "hMlfE", "FNeRw", "qUTra", "CKMBt", "jdWRk", "vksiv", "aqAtG", "EnTgx", "khcTr", "AEwyU", "lRsWN", "UukhJ", "NSlOG", "JoZUY", "yZuzy", "iIPFb", "qEAFD", "vlCFl", "ApIqP", "Thmpw", "YUJeU", "mrHhV", "BMXnI", "SvJNu", "lYxoC", "XDUzn", "ummyp", "vVXbR", "RaoWG", "LYxbv", "YEBit", "EkfXV", "dYAWl", "tnuRf", "wHFBU", "yDeQw", "ZcSDS", "ZHbDl", "Kuwvm", "uRHsK", "cdtRZ", "rRMvj", "aitgk", "YGJco", "CvvIq", "nkkpo", "Vzfzd", "FfsSq", "jFZHf", "mTwWr", "NENFd", "NCLSl", "WdRCI", "xykbt", "gYrrg", "MYkTv", "SjQCc", "IiJlg", "DVwNd", "IWgQW", "EvXvK", "qqbNI", "HGhOb", "NqBoy", "XKgsb", "RqNVV", "VlHhy", "rockS", "gXwMF", "NdJJs", "oYAuc", "nOIYD", "YNgpm", "xMUiV", "JlWMF", "XjFVL", "tTLfN", "xWUAA", "iDLoz", "kNkOb", "tEXnc", "MbKjr", "ASBPz", "MbaeA", "PlSDQ", "doOpf", "fjupE", "YvdlL", "AiqbE", "diSye", "hbIsP", "iNeUG", "BSmTe", "LMwlv", "AQBzQ", "nZNRE", "pQzOQ", "qvxRe", "zLmYP", "mkVEf", "AnZfX", "dXMoQ", "zQtgx", "TzyCr", "UQPxK", "iTtrF", "Higzv", "bCUpT", "aaPTV", "UnYaN", "qUgTa", "JvtSr", "eqrXT", "yvEbB", "MKIof", "alxeg", "gqayc", "QuujP", "ELoYm", "eQZAN", "DDZQA", "QKJlO", "EydWQ", "ooIwH", "wulHb", "CeORZ", "YTMrq", "EkApb", "Bhluc", "tFaPY", "Bozdi", "ElRbN", "eOCOr", "pITFQ", "ROPBW", "KGsFQ", "bgWeQ", "AhKNR", "kkrFd", "kSDot", "yhPNT", "LvVhj", "eKVZA", "RKtib", "GLUYE", "rkNtA", "DJLGU", "XIrYB", "AAcQc", "iezkg", "bLksR", "TCsEK", "VCIBm", "KAsTi", "hhEnF", "PYxHM", "WfGGI", "IpjrB", "dUtQp", "JKruh", "Bgsii", "ObFva", "zojGt", "MrQLt", "GDyfO", "GJKmR", "peqoL", "hdkdl", "yeTio", "PzOkd", "IcFyN", "kvslq", "HkZjk", "pvSPz", "AGGAg", "jITJY", "mrHFP", "bXdpP", "eyNWb", "lyCHr", "vEfKA", "AFINy", "jTrOz", "awunY", "NEIcC", "ZICQV", "QSCyI", "pcDHf", "aStMt", "gZvlP", "pcVTq", "sjHmd", "TIQDv", "TXqgT", "eCbhm", "FEVRM", "tBiaD", "nBEpZ", "JOVfX", "jTSxB", "KHJUS", "GzNbU", "TGxKX", "cYwdj", "UkKag", "MiQAV", "ocOxp", "DJdCW", "gcizE", "olVhH", "eammR", "BoZWf", "NBkJU", "AOELg", "SiImc", "OTufH", "LsYMx", "MSnEQ", "nFDTY", "KtktN", "XLUjS", "hvCSQ", "apUuO", "FqCau", "OnAWI", "mXmRO", "iuaGj", "XiQSo", "KWazp", "yxZgM", "LdWtI", "HPyRw", "AsSXU", "sexcI", "Vokni", "wvTfY", "dSuSR", "hcdTs", "fWDsH", "MhjTI", "YNqGq", "pbDIQ", "KgtmK", "KBOHw", "AwnDT", "eLewD", "QusBt", "cKBwS", "JXlJA", "sDbhS", "amBsl", "imWaC", "dFkgn", "mxvPG", "HbnCO", "hcxWq", "NURTb", "MxrFU", "LQQiF", "XEjAO", "agsKI", "nuIbo", "AFbzm", "jikny", "dENaz", "bklnE", "vsFfN", "YZlcA", "ZHytF", "MNBVW", "vsEMR", "UEmzr", "yLDpV", "ANCCt", "qFgRg", "QFmHZ", "tyLDd", "fmGED", "KMosj", "JcxUl", "pzMyN", "Xzzbw", "vcglx", "JKIhk", "fIamc", "Ketpe", "qmSZE", "GTkEJ", "mKVdW", "plKRh", "aYftk", "DgFdW", "AIDqB", "jOVGr", "pEMGD", "FGQhD", "gbkoo", "RUBhs", "JKyyD", "MbKZf", "opwvx", "BQRub", "ggaOV", "ycTzj", "SkOBe", "ysfmF", "EuXIX", "MQReb", "MsZjY", "RaNxc", "mZtxm", "TLRuW", "tiMnG", "LvzAg", "JJaQY", "OkvgE", "NKorG", "ZMhXG", "YktHA", "UxYiA", "Egxoc", "YWzgV", "Evalj", "yDpOI", "OPwQq", "XTLEa", "CsLVi", "LSNKD", "rOQeM", "SYmJf", "GSCNG", "QRHgv", "ugPvi", "nLwJk", "CAZgp", "EoAcW", "AYpPu", "Upruv", "PTnTY", "ctsKu", "hLlJa", "DXIBo", "JymGq", "QjGwn", "WFBUk", "pXCiU", "APHJd", "LipjW", "snBaq", "KSPiW", "rARfu", "ZCCop", "hAxAJ", "XHWhM", "FWMes", "YlqDq", "zxpAC", "mfvuy", "jAEYd", "kCcOD", "avDYd", "NZtlk", "TqFXR", "iwEPf", "AXofZ", "UUJzM", "OwNLh", "kmyhC", "EwRqN", "TwPjx", "SNnSH", "MMGeP", "avlMt", "MBkZO", "GLPrB", "hacsT", "LMpON", "ANNWy", "AMARR", "bykzV", "OUacI", "GQwFI", "MDGyL", "yIyGc", "ELahz", "fteua", "MZSwA", "apBCB", "dsrfu", "mIXMK", "ZaLmR", "fHCFz", "VnJfA", "vGgIz", "SAgSf", "yYraA", "LFpQg", "pYHEW", "NgucL", "hqFmU", "UzAIB", "XTnBC", "xjDkw", "Zxsqp", "hndYU", "OTcNs", "RqogI", "MJfmv", "kgWKX", "VTbxV", "bMhBi", "dZXyd", "mkMlE", "lhgsJ", "cjkky", "hFgFq", "nQSJE", "YXrVn", "adOFl", "JTsyn", "RKlzO", "BkDrW", "SWGHO", "QrSYM", "jxeSW", "ymLYb", "aMqUq", "xdFzS", "QqDdl", "FWPDF", "muaDI", "eThlZ", "kBsZd", "CgHyx", "HvxyV", "LVOhH", "OvXNt", "uJsoJ", "xhZsn", "BcQxw", "OAaDO", "QGyim", "FuRxT", "McHzo", "AntMY", "DhUdp", "byZuO", "qKdsT", "vQEWr", "oktNs", "BsFWU", "aPDuD", "KfBnZ", "gHQIA", "RBqtd", "VekBa", "ljBKe", "Lxpzr", "rxCWy", "GquNR", "ypFbd", "wYNRK", "wsFpe", "fdzkr", "cfPgo", "bOLLw", "HRNei", "KxYcm", "PGTod", "izzfg", "SBxNr", "NWXGU", "ppCwz", "YKJWg", "gXrxU", "OSPJE", "xXuJM", "uCSmW", "PehIa", "tCaeC", "PztbP", "BzCkX", "BHwqK", "mAbUU", "WbOfH", "OXWZf", "nXpZM", "sbYaw", "ejmdd", "pvaKv", "sGOtu", "AQOLs", "jslbI", "jvZvF", "ZSzgN", "alfvO", "hXgDR", "mqdTL", "fChQp", "csTYB", "spyqy", "xmRHl", "yOAQs", "VNYjv", "SFhqe", "MHFxn", "AXCaI", "lOAsK", "VPODe", "RIcDI", "aGksK", "AxLab", "MNMZG", "xyQna", "XymZy", "bjvLx", "VXZAw", "VIyAf", "IyDYk", "EFoJk", "cRFGp", "hzDpW", "TBQYR", "jOreH", "KuLYo", "mOdGV", "SdErE", "EkptK", "uTIEH", "LNpLJ", "Ksruj", "aUYNn", "KFGhy", "LMzni", "TgTcR", "SlQSg", "KLLjh", "JgDYe", "eDAkj", "NShRM", "bzOzl", "IPquB", "eWUpv", "HLwVj", "TDFCr", "TMuTi", "rXPAY", "oLxZB", "Jfssx", "XWkwN", "vhEih", "BblHO", "OBSgE", "pYwna", "oMuto", "aOnOD", "MzWsU", "ZXKyJ", "JwfqA", "BFFuJ", "WVTLP", "PfNZo", "scXhu", "QeoMl", "EfCnc", "nmPgU", "qrjii", "hgKNb", "mZgDg", "RqpIF", "CyUje", "PFzeA", "Ornei", "sIWvi", "oiVBU", "EPPNl", "QvFBZ", "iwxBR", "zFolP", "vFLaG", "KKFrp", "roYDX", "BfPaH", "OJQhM", "ViHWp", "hCQOj", "ESHsB", "fpBfW", "IomAT", "JBjfC", "xSNeq", "pJxlv", "aflzH", "RBmQT", "cpPhm", "yUcZu", "FsXuI", "YJZgf", "EShAU", "FnOEB", "iNcil", "Twrih", "UBPGr", "ykOUX", "Gksbe", "pUdxX", "zaBTr", "HovvW", "ZXbaw", "EgngP", "VytkB", "PNqII", "pGqYl", "tLNAo", "colyn", "JrNuE", "JnfBY", "MCYET", "oZGqH", "BKUno", "FwVzn", "HOpfW", "uWbbj", "hpdUV", "lvWQT", "Zchnq", "UUCto", "fRFoh", "VsqLR", "xytft", "vJEpk", "AYKzr", "UdpiO", "CJmpY", "ppgzc", "vxjeX", "bomlL", "rSipx", "HOmiA", "QVuUt", "UYAPT", "JOFAu", "DEfTL", "xqPoo", "uDGkV", "dBmRQ", "LIOmC", "Jqjbh", "mefnB", "qoxQf", "gQHQD", "letsJ", "lQcOR", "ACYeD", "Wlcjr", "dQphy", "eGqBC", "awmhv", "DiRez", "odXAt", "jPfht", "Chjct", "VbQOF", "iiivy", "fmTka", "PMIgO", "PRvdW", "Bpfzt", "CkNFf", "uQNIn", "QhjlP", "AICPe", "PtRae", "rUuQm", "Preif", "KIOoj", "CNXQK", "nCFwl", "FdAwc", "tPyHs", "WPkOK", "CdgUN", "iTeXl", "PPQsB", "RTdXz", "CTSSY", "mmnOy", "OvtCS", "HKoqf", "pSmZH", "SxuxH", "blrMx", "PoIug", "cSGyX", "obbyI", "GSujr", "TyVUR", "eugkX", "sQJDF", "zwlYq", "RDyWO", "GZqaL", "DRemD", "NLULY", "mBBga", "rZCrA", "FjYKC", "eZoBM", "IfnBT", "vzBYB", "DUGUj", "DjvtH", "UEjTF", "QoKOs", "bDLwz", "DiGdJ", "eIpVu", "VnatU", "vEKdM", "pOByC", "uAZnj", "mtBOZ", "PgrdR", "MycKB", "JNyPS", "nVDMJ", "RWKOT", "TRmUr", "CbfrJ", "KqlUB", "OVfjn", "lXHtl", "AglQT", "lFFFf", "KThSk", "NVSnT", "mLyVX", "djgQF", "dTQjO", "mmaIw", "YPqmQ", "GDxAx", "Feant", "UPKOg", "mNTvh", "WEYDo", "cnVmx", "mYhmC", "PxCWL", "FOEOM", "BWoAT", "ZTJxc", "IWRQz", "qLlks", "IZpfI", "gtrgj", "qEwWj", "nHugY", "ffjlb", "ejjuB", "LAiZC", "HuPIm", "Yubbs", "lnHyT", "iydDP", "oUEsx", "hJxKF", "hGJhx", "qxylt", "ehbWh", "Yigih", "UOqqM", "MsIjm", "uYOnp", "iLdHV", "PRAep", "OVGvb", "tnHqf", "Ieurt", "BCgBI", "IYfpy", "ZaEZy", "zhcFb", "OPlqj", "AcHni", "rAQbE", "TCuOt", "VzFDN", "zzIye", "AxXHJ", "OpiCy", "coFhi", "ftALg", "LWBnO", "YZgDo", "ojefi", "QXFiA", "MEtmt", "PQaMS", "QtGQG", "vFegR", "CQPzJ", "WPURT", "IZYhG", "EyCLM", "znRyo", "fnvzQ", "iEFJK", "fwDga", "dXsKP", "bgjDF", "imOxG", "pCWTs", "dloeI", "wSOXw", "TDmBy", "LLPru", "sVkjS", "NnrEV", "nAVtM", "JOeYc", "uzwlX", "LKFbn", "uribD", "reOMr", "aukph", "JZzoV", "ezIkQ", "HLuyb", "XezIM", "oXBJf", "XjMYC", "dvnet", "hawpC", "WcUzo", "MIgfj", "RFrYf", "cHPJb", "AfUtS", "UWAJX", "yXoxe", "vpLFn", "tObJz", "fGNmt", "StFXH", "gKTZc", "IUeve", "BYFVe", "MMzTJ", "fPiYK", "OkxyM", "wcRSI", "sjVMq", "jIYJT", "ggMDr", "DgJAG", "FvCXv", "XAkZd", "RnSJp", "ngluO", "oXalW", "UnQZr", "MGjSb", "jrTEb", "Lflia", "auaqf", "GODCU", "hRsZB", "EKMay", "rYkrC", "wZWGN", "Vgths", "MvxDY", "ShQGV", "xRZvc", "rwOmz", "JXWOx", "LsUmw", "Dnpfn", "VuChi", "eYaAB"]jiter-0.7.1/benches/true_array.json000064400000000000000000000011301046102023000154200ustar 00000000000000[true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true]jiter-0.7.1/benches/true_object.json000064400000000000000000000025561046102023000155650ustar 00000000000000{"k_0": true, "k_1": true, "k_2": true, "k_3": true, "k_4": true, "k_5": true, "k_6": true, "k_7": true, "k_8": true, "k_9": true, "k_10": true, "k_11": true, "k_12": true, "k_13": true, "k_14": true, "k_15": true, "k_16": true, "k_17": true, "k_18": true, "k_19": true, "k_20": true, "k_21": true, "k_22": true, "k_23": true, "k_24": true, "k_25": true, "k_26": true, "k_27": true, "k_28": true, "k_29": true, "k_30": true, "k_31": true, "k_32": true, "k_33": true, "k_34": true, "k_35": true, "k_36": true, "k_37": true, "k_38": true, "k_39": true, "k_40": true, "k_41": true, "k_42": true, "k_43": true, "k_44": true, "k_45": true, "k_46": true, "k_47": true, "k_48": true, "k_49": true, "k_50": true, "k_51": true, "k_52": true, "k_53": true, "k_54": true, "k_55": true, "k_56": true, "k_57": true, "k_58": true, "k_59": true, "k_60": true, "k_61": true, "k_62": true, "k_63": true, "k_64": true, "k_65": true, "k_66": true, "k_67": true, "k_68": true, "k_69": true, "k_70": true, "k_71": true, "k_72": true, "k_73": true, "k_74": true, "k_75": true, "k_76": true, "k_77": true, "k_78": true, "k_79": true, "k_80": true, "k_81": true, "k_82": true, "k_83": true, "k_84": true, "k_85": true, "k_86": true, "k_87": true, "k_88": true, "k_89": true, "k_90": true, "k_91": true, "k_92": true, "k_93": true, "k_94": true, "k_95": true, "k_96": true, "k_97": true, "k_98": true, "k_99": true}jiter-0.7.1/benches/unicode.json000064400000000000000000000005751046102023000147050ustar 00000000000000"Fast iterable JSON parser.\n\nDocumentation is available at £ [docs.rs/jiter](https://docs.rs/jiter).\n\njiter has three interfaces:\n* [`JsonValue`] an enum representing JSON data\n* [`Jiter`] an iterator over JSON data\n* [`python_parse`] which parses a JSON string into a Python object\n\n## JsonValue Example\n\nSee [the `JsonValue` docs][JsonValue] for more details.\n💩" jiter-0.7.1/benches/x100.json000064400000000000000000000001471046102023000137420ustar 00000000000000"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" jiter-0.7.1/build.rs000064400000000000000000000001251046102023000124110ustar 00000000000000fn main() { #[cfg(feature = "python")] pyo3_build_config::use_pyo3_cfgs(); } jiter-0.7.1/src/errors.rs000064400000000000000000000233611046102023000134240ustar 00000000000000/// Enum representing all possible errors in JSON syntax. /// /// Almost all of `JsonErrorType` is copied from [serde_json](https://github.com/serde-rs) so errors match /// those expected from `serde_json`. #[derive(Debug, PartialEq, Eq, Clone)] pub enum JsonErrorType { /// float value was found where an int was expected FloatExpectingInt, /// duplicate keys in an object DuplicateKey(String), /// happens when getting the `Decimal` type or constructing a decimal fails InternalError(String), /// NOTE: all errors from here on are copied from serde_json /// [src/error.rs](https://github.com/serde-rs/json/blob/v1.0.107/src/error.rs#L236) /// with `Io` and `Message` removed /// /// EOF while parsing a list. EofWhileParsingList, /// EOF while parsing an object. EofWhileParsingObject, /// EOF while parsing a string. EofWhileParsingString, /// EOF while parsing a JSON value. EofWhileParsingValue, /// Expected this character to be a `':'`. ExpectedColon, /// Expected this character to be either a `','` or a `']'`. ExpectedListCommaOrEnd, /// Expected this character to be either a `','` or a `'}'`. ExpectedObjectCommaOrEnd, /// Expected to parse either a `true`, `false`, or a `null`. ExpectedSomeIdent, /// Expected this character to start a JSON value. ExpectedSomeValue, /// Invalid hex escape code. InvalidEscape, /// Invalid number. InvalidNumber, /// Number is bigger than the maximum value of its type. NumberOutOfRange, /// Invalid unicode code point. InvalidUnicodeCodePoint, /// Control character found while parsing a string. ControlCharacterWhileParsingString, /// Object key is not a string. KeyMustBeAString, /// Lone leading surrogate in hex escape. LoneLeadingSurrogateInHexEscape, /// JSON has a comma after the last value in an array or map. TrailingComma, /// JSON has non-whitespace trailing characters after the value. TrailingCharacters, /// Unexpected end of hex escape. UnexpectedEndOfHexEscape, /// Encountered nesting of JSON maps and arrays more than 128 layers deep. RecursionLimitExceeded, } impl std::fmt::Display for JsonErrorType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // Messages for enum members copied from serde_json are unchanged match self { Self::FloatExpectingInt => f.write_str("float value was found where an int was expected"), Self::DuplicateKey(s) => write!(f, "Detected duplicate key {s:?}"), Self::InternalError(s) => write!(f, "Internal error: {s:?}"), Self::EofWhileParsingList => f.write_str("EOF while parsing a list"), Self::EofWhileParsingObject => f.write_str("EOF while parsing an object"), Self::EofWhileParsingString => f.write_str("EOF while parsing a string"), Self::EofWhileParsingValue => f.write_str("EOF while parsing a value"), Self::ExpectedColon => f.write_str("expected `:`"), Self::ExpectedListCommaOrEnd => f.write_str("expected `,` or `]`"), Self::ExpectedObjectCommaOrEnd => f.write_str("expected `,` or `}`"), Self::ExpectedSomeIdent => f.write_str("expected ident"), Self::ExpectedSomeValue => f.write_str("expected value"), Self::InvalidEscape => f.write_str("invalid escape"), Self::InvalidNumber => f.write_str("invalid number"), Self::NumberOutOfRange => f.write_str("number out of range"), Self::InvalidUnicodeCodePoint => f.write_str("invalid unicode code point"), Self::ControlCharacterWhileParsingString => { f.write_str("control character (\\u0000-\\u001F) found while parsing a string") } Self::KeyMustBeAString => f.write_str("key must be a string"), Self::LoneLeadingSurrogateInHexEscape => f.write_str("lone leading surrogate in hex escape"), Self::TrailingComma => f.write_str("trailing comma"), Self::TrailingCharacters => f.write_str("trailing characters"), Self::UnexpectedEndOfHexEscape => f.write_str("unexpected end of hex escape"), Self::RecursionLimitExceeded => f.write_str("recursion limit exceeded"), } } } pub type JsonResult = Result; /// Represents an error from parsing JSON #[derive(Debug, Clone, Eq, PartialEq)] pub struct JsonError { /// The type of error. pub error_type: JsonErrorType, /// The index in the data where the error occurred. pub index: usize, } impl JsonError { pub(crate) fn new(error_type: JsonErrorType, index: usize) -> Self { Self { error_type, index } } pub fn get_position(&self, json_data: &[u8]) -> LinePosition { LinePosition::find(json_data, self.index) } pub fn description(&self, json_data: &[u8]) -> String { let position = self.get_position(json_data); format!("{} at {}", self.error_type, position) } pub(crate) fn allowed_if_partial(&self) -> bool { matches!( self.error_type, JsonErrorType::EofWhileParsingList | JsonErrorType::EofWhileParsingObject | JsonErrorType::EofWhileParsingString | JsonErrorType::EofWhileParsingValue | JsonErrorType::ExpectedListCommaOrEnd | JsonErrorType::ExpectedObjectCommaOrEnd ) } } impl std::fmt::Display for JsonError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} at index {}", self.error_type, self.index) } } macro_rules! json_error { ($error_type:ident, $index:expr) => { crate::errors::JsonError::new(crate::errors::JsonErrorType::$error_type, $index) }; } pub(crate) use json_error; macro_rules! json_err { ($error_type:ident, $index:expr) => { Err(crate::errors::json_error!($error_type, $index)) }; } use crate::Jiter; pub(crate) use json_err; pub(crate) const DEFAULT_RECURSION_LIMIT: u8 = 200; /// Enum representing all JSON types. #[derive(Debug, Clone, Eq, PartialEq)] pub enum JsonType { Null, Bool, Int, Float, String, Array, Object, } impl std::fmt::Display for JsonType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Null => f.write_str("null"), Self::Bool => f.write_str("bool"), Self::Int => f.write_str("int"), Self::Float => f.write_str("float"), Self::String => f.write_str("string"), Self::Array => f.write_str("array"), Self::Object => f.write_str("object"), } } } /// Enum representing either a [JsonErrorType] or a WrongType error. #[derive(Debug, Clone, Eq, PartialEq)] pub enum JiterErrorType { JsonError(JsonErrorType), WrongType { expected: JsonType, actual: JsonType }, } impl std::fmt::Display for JiterErrorType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::JsonError(error_type) => write!(f, "{error_type}"), Self::WrongType { expected, actual } => { write!(f, "expected {expected} but found {actual}") } } } } /// An error from the Jiter iterator. #[derive(Debug, Clone, Eq, PartialEq)] pub struct JiterError { pub error_type: JiterErrorType, pub index: usize, } impl std::fmt::Display for JiterError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{} at index {}", self.error_type, self.index) } } impl JiterError { pub(crate) fn new(error_type: JiterErrorType, index: usize) -> Self { Self { error_type, index } } pub fn get_position(&self, jiter: &Jiter) -> LinePosition { jiter.error_position(self.index) } pub fn description(&self, jiter: &Jiter) -> String { let position = self.get_position(jiter); format!("{} at {}", self.error_type, position) } pub(crate) fn wrong_type(expected: JsonType, actual: JsonType, index: usize) -> Self { Self::new(JiterErrorType::WrongType { expected, actual }, index) } } impl From for JiterError { fn from(error: JsonError) -> Self { Self { error_type: JiterErrorType::JsonError(error.error_type), index: error.index, } } } /// Represents a line and column in a file or input string, used for both errors and value positions. #[derive(Debug, Clone, PartialEq, Eq)] pub struct LinePosition { /// Line number, starting at 1. pub line: usize, /// Column number, starting at 1. pub column: usize, } impl std::fmt::Display for LinePosition { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "line {} column {}", self.line, self.column) } } impl LinePosition { pub fn new(line: usize, column: usize) -> Self { Self { line, column } } /// Find the line and column of a byte index in a string. pub fn find(json_data: &[u8], find: usize) -> Self { let mut line = 1; let mut last_line_start = 0; let mut index = 0; while let Some(next) = json_data.get(index) { if *next == b'\n' { line += 1; last_line_start = index + 1; } if index == find { return Self { line, column: index + 1 - last_line_start, }; } index += 1; } Self { line, column: index.saturating_sub(last_line_start), } } pub fn short(&self) -> String { format!("{}:{}", self.line, self.column) } } jiter-0.7.1/src/jiter.rs000064400000000000000000000344251046102023000132300ustar 00000000000000use crate::errors::{json_error, JiterError, JsonType, LinePosition, DEFAULT_RECURSION_LIMIT}; use crate::number_decoder::{NumberAny, NumberFloat, NumberInt, NumberRange}; use crate::parse::{Parser, Peek}; use crate::string_decoder::{StringDecoder, StringDecoderRange, Tape}; use crate::value::{take_value_borrowed, take_value_owned, take_value_skip, JsonValue}; use crate::{JsonError, JsonErrorType, PartialMode}; pub type JiterResult = Result; /// A JSON iterator. #[derive(Debug)] pub struct Jiter<'j> { data: &'j [u8], parser: Parser<'j>, tape: Tape, allow_inf_nan: bool, allow_partial_strings: bool, } impl Clone for Jiter<'_> { /// Clone a `Jiter`. Like the default implementation, but a new empty `tape` is used. fn clone(&self) -> Self { Self { data: self.data, parser: self.parser.clone(), tape: Tape::default(), allow_inf_nan: self.allow_inf_nan, allow_partial_strings: self.allow_partial_strings, } } } impl<'j> Jiter<'j> { /// Constructs a new `Jiter`. /// /// # Arguments /// - `data`: The JSON data to be parsed. /// - `allow_inf_nan`: Whether to allow `NaN`, `Infinity` and `-Infinity` as numbers. pub fn new(data: &'j [u8]) -> Self { Self { data, parser: Parser::new(data), tape: Tape::default(), allow_inf_nan: false, allow_partial_strings: false, } } pub fn with_allow_inf_nan(mut self) -> Self { self.allow_inf_nan = true; self } pub fn with_allow_partial_strings(mut self) -> Self { self.allow_partial_strings = true; self } /// Get the current [LinePosition] of the parser. pub fn current_position(&self) -> LinePosition { self.parser.current_position() } /// Get the current index of the parser. pub fn current_index(&self) -> usize { self.parser.index } /// Get a slice of the underlying JSON data from `start` to `current_index`. pub fn slice_to_current(&self, start: usize) -> &'j [u8] { &self.data[start..self.current_index()] } /// Convert an error index to a [LinePosition]. /// /// # Arguments /// - `index`: The index of the error to find the position of. pub fn error_position(&self, index: usize) -> LinePosition { LinePosition::find(self.data, index) } /// Peek at the next JSON value without consuming it. pub fn peek(&mut self) -> JiterResult { self.parser.peek().map_err(Into::into) } /// Assuming the next value is `null`, consume it. Error if it is not `null`, or is invalid JSON. pub fn next_null(&mut self) -> JiterResult<()> { let peek = self.peek()?; match peek { Peek::Null => self.known_null(), _ => Err(self.wrong_type(JsonType::Null, peek)), } } /// Knowing the next value is `null`, consume it. pub fn known_null(&mut self) -> JiterResult<()> { self.parser.consume_null()?; Ok(()) } /// Assuming the next value is `true` or `false`, consume it. Error if it is not a boolean, or is invalid JSON. /// /// # Returns /// The boolean value. pub fn next_bool(&mut self) -> JiterResult { let peek = self.peek()?; self.known_bool(peek) } /// Knowing the next value is `true` or `false`, parse it. pub fn known_bool(&mut self, peek: Peek) -> JiterResult { match peek { Peek::True => { self.parser.consume_true()?; Ok(true) } Peek::False => { self.parser.consume_false()?; Ok(false) } _ => Err(self.wrong_type(JsonType::Bool, peek)), } } /// Assuming the next value is a number, consume it. Error if it is not a number, or is invalid JSON. /// /// # Returns /// A [NumberAny] representing the number. pub fn next_number(&mut self) -> JiterResult { let peek = self.peek()?; self.known_number(peek) } /// Knowing the next value is a number, parse it. pub fn known_number(&mut self, peek: Peek) -> JiterResult { self.parser .consume_number::(peek.into_inner(), self.allow_inf_nan) .map_err(|e| self.maybe_number_error(e, JsonType::Int, peek)) } /// Assuming the next value is an integer, consume it. Error if it is not an integer, or is invalid JSON. pub fn next_int(&mut self) -> JiterResult { let peek = self.peek()?; self.known_int(peek) } /// Knowing the next value is an integer, parse it. pub fn known_int(&mut self, peek: Peek) -> JiterResult { self.parser .consume_number::(peek.into_inner(), self.allow_inf_nan) .map_err(|e| { if e.error_type == JsonErrorType::FloatExpectingInt { JiterError::wrong_type(JsonType::Int, JsonType::Float, self.parser.index) } else { self.maybe_number_error(e, JsonType::Int, peek) } }) } /// Assuming the next value is a float, consume it. Error if it is not a float, or is invalid JSON. pub fn next_float(&mut self) -> JiterResult { let peek = self.peek()?; self.known_float(peek) } /// Knowing the next value is a float, parse it. pub fn known_float(&mut self, peek: Peek) -> JiterResult { self.parser .consume_number::(peek.into_inner(), self.allow_inf_nan) .map_err(|e| self.maybe_number_error(e, JsonType::Float, peek)) } /// Assuming the next value is a number, consume it and return bytes from the original JSON data. pub fn next_number_bytes(&mut self) -> JiterResult<&[u8]> { let peek = self.peek()?; self.known_number_bytes(peek) } /// Knowing the next value is a number, parse it and return bytes from the original JSON data. fn known_number_bytes(&mut self, peek: Peek) -> JiterResult<&[u8]> { match self .parser .consume_number::(peek.into_inner(), self.allow_inf_nan) { Ok(numbe_range) => Ok(&self.data[numbe_range.range]), Err(e) => Err(self.maybe_number_error(e, JsonType::Float, peek)), } } /// Assuming the next value is a string, consume it. Error if it is not a string, or is invalid JSON. pub fn next_str(&mut self) -> JiterResult<&str> { let peek = self.peek()?; match peek { Peek::String => self.known_str(), _ => Err(self.wrong_type(JsonType::String, peek)), } } /// Knowing the next value is a string, parse it. pub fn known_str(&mut self) -> JiterResult<&str> { match self .parser .consume_string::(&mut self.tape, self.allow_partial_strings) { Ok(output) => Ok(output.as_str()), Err(e) => Err(e.into()), } } /// Assuming the next value is a string, consume it and return bytes from the original JSON data. pub fn next_bytes(&mut self) -> JiterResult<&[u8]> { let peek = self.peek()?; match peek { Peek::String => self.known_bytes(), _ => Err(self.wrong_type(JsonType::String, peek)), } } /// Knowing the next value is a string, parse it and return bytes from the original JSON data. pub fn known_bytes(&mut self) -> JiterResult<&[u8]> { let range = self .parser .consume_string::(&mut self.tape, self.allow_partial_strings)?; Ok(&self.data[range]) } /// Parse the next JSON value and return it as a [JsonValue]. Error if it is invalid JSON. pub fn next_value(&mut self) -> JiterResult> { let peek = self.peek()?; self.known_value(peek) } /// Parse the next JSON value and return it as a [JsonValue]. Error if it is invalid JSON. /// /// # Arguments /// - `peek`: The [Peek] of the next JSON value. pub fn known_value(&mut self, peek: Peek) -> JiterResult> { take_value_borrowed( peek, &mut self.parser, &mut self.tape, DEFAULT_RECURSION_LIMIT, self.allow_inf_nan, PartialMode::Off, ) .map_err(Into::into) } /// Parse the next JSON value, but don't return it. /// This should be faster than returning the value, useful when you don't care about this value. /// Error if it is invalid JSON. /// /// *WARNING:* For performance reasons, this method does not check that strings would be valid UTF-8. pub fn next_skip(&mut self) -> JiterResult<()> { let peek = self.peek()?; self.known_skip(peek) } /// Parse the next JSON value, but don't return it. Error if it is invalid JSON. /// /// # Arguments /// - `peek`: The [Peek] of the next JSON value. pub fn known_skip(&mut self, peek: Peek) -> JiterResult<()> { take_value_skip( peek, &mut self.parser, &mut self.tape, DEFAULT_RECURSION_LIMIT, self.allow_inf_nan, ) .map_err(Into::into) } /// Parse the next JSON value and return it as a [JsonValue] with static lifetime. Error if it is invalid JSON. pub fn next_value_owned(&mut self) -> JiterResult> { let peek = self.peek()?; self.known_value_owned(peek) } /// Parse the next JSON value and return it as a [JsonValue] with static lifetime. Error if it is invalid JSON. /// /// # Arguments /// - `peek`: The [Peek] of the next JSON value. pub fn known_value_owned(&mut self, peek: Peek) -> JiterResult> { take_value_owned( peek, &mut self.parser, &mut self.tape, DEFAULT_RECURSION_LIMIT, self.allow_inf_nan, PartialMode::Off, ) .map_err(Into::into) } /// Assuming the next value is an array, peek at the first value. /// Error if it is not an array, or is invalid JSON. /// /// # Returns /// The `Some(peek)` of the first value in the array is not empty, `None` if it is empty. pub fn next_array(&mut self) -> JiterResult> { let peek = self.peek()?; match peek { Peek::Array => self.known_array(), _ => Err(self.wrong_type(JsonType::Array, peek)), } } /// Assuming the next value is an array, peat at the first value. pub fn known_array(&mut self) -> JiterResult> { self.parser.array_first().map_err(Into::into) } /// Peek at the next value in an array. pub fn array_step(&mut self) -> JiterResult> { self.parser.array_step().map_err(Into::into) } /// Assuming the next value is an object, consume the first key. /// Error if it is not an object, or is invalid JSON. /// /// # Returns /// The `Some(key)` of the first key in the object is not empty, `None` if it is empty. pub fn next_object(&mut self) -> JiterResult> { let peek = self.peek()?; match peek { Peek::Object => self.known_object(), _ => Err(self.wrong_type(JsonType::Object, peek)), } } /// Assuming the next value is an object, conssume the first key and return bytes from the original JSON data. pub fn known_object(&mut self) -> JiterResult> { let op_str = self.parser.object_first::(&mut self.tape)?; Ok(op_str.map(|s| s.as_str())) } /// Assuming the next value is an object, peek at the first key. pub fn next_object_bytes(&mut self) -> JiterResult> { let peek = self.peek()?; match peek { Peek::Object => { let op_range = self.parser.object_first::(&mut self.tape)?; Ok(op_range.map(|r| &self.data[r])) } _ => Err(self.wrong_type(JsonType::Object, peek)), } } /// Get the next key in an object, or `None` if there are no more keys. pub fn next_key(&mut self) -> JiterResult> { let strs = self.parser.object_step::(&mut self.tape)?; Ok(strs.map(|s| s.as_str())) } /// Get the next key in an object as bytes, or `None` if there are no more keys. pub fn next_key_bytes(&mut self) -> JiterResult> { let op_range = self.parser.object_step::(&mut self.tape)?; Ok(op_range.map(|r| &self.data[r])) } /// Finish parsing the JSON data. Error if there is more data to be parsed. pub fn finish(&mut self) -> JiterResult<()> { self.parser.finish().map_err(Into::into) } fn wrong_type(&self, expected: JsonType, peek: Peek) -> JiterError { match peek { Peek::True | Peek::False => JiterError::wrong_type(expected, JsonType::Bool, self.parser.index), Peek::Null => JiterError::wrong_type(expected, JsonType::Null, self.parser.index), Peek::String => JiterError::wrong_type(expected, JsonType::String, self.parser.index), Peek::Array => JiterError::wrong_type(expected, JsonType::Array, self.parser.index), Peek::Object => JiterError::wrong_type(expected, JsonType::Object, self.parser.index), _ if peek.is_num() => self.wrong_num(peek.into_inner(), expected), _ => json_error!(ExpectedSomeValue, self.parser.index).into(), } } fn wrong_num(&self, first: u8, expected: JsonType) -> JiterError { let mut parser2 = self.parser.clone(); let actual = match parser2.consume_number::(first, self.allow_inf_nan) { Ok(NumberAny::Int { .. }) => JsonType::Int, Ok(NumberAny::Float { .. }) => JsonType::Float, Err(e) => return e.into(), }; JiterError::wrong_type(expected, actual, self.parser.index) } fn maybe_number_error(&self, e: JsonError, expected: JsonType, peek: Peek) -> JiterError { if peek.is_num() { e.into() } else { self.wrong_type(expected, peek) } } } jiter-0.7.1/src/lazy_index_map.rs000064400000000000000000000112241046102023000151060ustar 00000000000000use std::borrow::{Borrow, Cow}; use std::fmt; use std::hash::Hash; use std::slice::Iter as SliceIter; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::OnceLock; use ahash::AHashMap; use smallvec::SmallVec; /// Like [IndexMap](https://docs.rs/indexmap/latest/indexmap/) but only builds the lookup map when it's needed. pub struct LazyIndexMap { vec: SmallVec<[(K, V); 8]>, map: OnceLock>, last_find: AtomicUsize, } impl Default for LazyIndexMap where K: Clone + fmt::Debug + Eq + Hash, V: fmt::Debug, { fn default() -> Self { Self::new() } } impl Clone for LazyIndexMap { fn clone(&self) -> Self { Self { vec: self.vec.clone(), map: self.map.clone(), last_find: AtomicUsize::new(0), } } } impl fmt::Debug for LazyIndexMap where K: Clone + fmt::Debug + Eq + Hash, V: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.iter_unique()).finish() } } // picked to be a good tradeoff after experimenting with `lazy_map_lookup` benchmark, should cover most models const HASHMAP_THRESHOLD: usize = 16; /// Like [IndexMap](https://docs.rs/indexmap/latest/indexmap/) but only builds the lookup map when it's needed. impl LazyIndexMap where K: Clone + fmt::Debug + Eq + Hash, V: fmt::Debug, { pub fn new() -> Self { Self { vec: SmallVec::new(), map: OnceLock::new(), last_find: AtomicUsize::new(0), } } pub fn insert(&mut self, key: K, value: V) { if let Some(map) = self.map.get_mut() { map.insert(key.clone(), self.vec.len()); } self.vec.push((key, value)); } pub fn len(&self) -> usize { self.get_map().len() } pub fn is_empty(&self) -> bool { self.vec.is_empty() } pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow + PartialEq, Q: Hash + Eq + ?Sized, { let vec_len = self.vec.len(); // if the vec is longer than the threshold, we use the hashmap for lookups if vec_len > HASHMAP_THRESHOLD { self.get_map().get(key).map(|&i| &self.vec[i].1) } else { // otherwise we find the value in the vec // we assume the most likely position for the match is at `last_find + 1` let first_try = self.last_find.load(Ordering::Relaxed) + 1; for i in first_try..first_try + vec_len { let index = i % vec_len; let (k, v) = &self.vec[index]; if k == key { self.last_find.store(index, Ordering::Relaxed); return Some(v); } } None } } pub fn keys(&self) -> impl Iterator { self.vec.iter().map(|(k, _)| k) } pub fn iter(&self) -> SliceIter<'_, (K, V)> { self.vec.iter() } pub fn iter_unique(&self) -> impl Iterator { IterUnique { vec: &self.vec, map: self.get_map(), index: 0, } } fn get_map(&self) -> &AHashMap { self.map.get_or_init(|| { self.vec .iter() .enumerate() .map(|(index, (key, _))| (key.clone(), index)) .collect() }) } } impl<'j> LazyIndexMap, crate::JsonValue<'j>> { pub(crate) fn to_static(&self) -> LazyIndexMap, crate::JsonValue<'static>> { LazyIndexMap { vec: self .vec .iter() .map(|(k, v)| (k.to_string().into(), v.to_static())) .collect(), map: OnceLock::new(), last_find: AtomicUsize::new(0), } } } impl PartialEq for LazyIndexMap { fn eq(&self, other: &Self) -> bool { self.vec == other.vec } } struct IterUnique<'a, K, V> { vec: &'a SmallVec<[(K, V); 8]>, map: &'a AHashMap, index: usize, } impl<'a, K: Hash + Eq, V> Iterator for IterUnique<'a, K, V> { type Item = (&'a K, &'a V); fn next(&mut self) -> Option { while self.index < self.vec.len() { let (k, v) = &self.vec[self.index]; if let Some(map_index) = self.map.get(k) { if *map_index == self.index { self.index += 1; return Some((k, v)); } } self.index += 1; } None } } jiter-0.7.1/src/lib.rs000064400000000000000000000026761046102023000126640ustar 00000000000000#![doc = include_str!("../README.md")] mod errors; mod jiter; mod lazy_index_map; mod number_decoder; mod parse; #[cfg(feature = "python")] mod py_lossless_float; #[cfg(feature = "python")] mod py_string_cache; #[cfg(feature = "python")] mod python; #[cfg(target_arch = "aarch64")] mod simd_aarch64; mod string_decoder; mod value; pub use errors::{JiterError, JiterErrorType, JsonError, JsonErrorType, JsonResult, JsonType, LinePosition}; pub use jiter::{Jiter, JiterResult}; pub use lazy_index_map::LazyIndexMap; pub use number_decoder::{NumberAny, NumberInt}; pub use parse::Peek; pub use value::{JsonArray, JsonObject, JsonValue}; #[cfg(feature = "python")] pub use py_lossless_float::{FloatMode, LosslessFloat}; #[cfg(feature = "python")] pub use py_string_cache::{cache_clear, cache_usage, cached_py_string, pystring_fast_new, StringCacheMode}; #[cfg(feature = "python")] pub use python::{map_json_error, PythonParse}; #[derive(Debug, Clone, Copy)] pub enum PartialMode { Off, On, TrailingStrings, } impl Default for PartialMode { fn default() -> Self { Self::Off } } impl From for PartialMode { fn from(mode: bool) -> Self { if mode { Self::On } else { Self::Off } } } impl PartialMode { pub fn is_active(self) -> bool { !matches!(self, Self::Off) } pub fn allow_trailing_str(self) -> bool { matches!(self, Self::TrailingStrings) } } jiter-0.7.1/src/number_decoder.rs000064400000000000000000000454601046102023000150710ustar 00000000000000#[cfg(feature = "num-bigint")] use num_bigint::BigInt; #[cfg(feature = "num-bigint")] use num_traits::cast::ToPrimitive; use std::ops::Range; use lexical_parse_float::{format as lexical_format, FromLexicalWithOptions, Options as ParseFloatOptions}; use crate::errors::{json_err, json_error, JsonError, JsonResult}; pub trait AbstractNumberDecoder { type Output; fn decode(data: &[u8], index: usize, first: u8, allow_inf_nan: bool) -> JsonResult<(Self::Output, usize)>; } /// A number that can be either an [i64] or a [BigInt](num_bigint::BigInt) #[derive(Debug, Clone, PartialEq)] pub enum NumberInt { Int(i64), #[cfg(feature = "num-bigint")] BigInt(BigInt), } impl From for f64 { fn from(num: NumberInt) -> Self { match num { NumberInt::Int(int) => int as f64, #[cfg(feature = "num-bigint")] NumberInt::BigInt(big_int) => big_int.to_f64().unwrap_or(f64::NAN), } } } impl TryFrom<&[u8]> for NumberInt { type Error = JsonError; fn try_from(value: &[u8]) -> Result { let first = *value.first().ok_or_else(|| json_error!(InvalidNumber, 0))?; let (int_parse, index) = IntParse::parse(value, 0, first)?; match int_parse { IntParse::Int(int) => { if index == value.len() { Ok(int) } else { json_err!(InvalidNumber, index) } } _ => json_err!(InvalidNumber, index), } } } impl AbstractNumberDecoder for NumberInt { type Output = NumberInt; fn decode(data: &[u8], index: usize, first: u8, _allow_inf_nan: bool) -> JsonResult<(Self::Output, usize)> { let (int_parse, index) = IntParse::parse(data, index, first)?; match int_parse { IntParse::Int(int) => Ok((int, index)), _ => json_err!(FloatExpectingInt, index), } } } pub struct NumberFloat; impl AbstractNumberDecoder for NumberFloat { type Output = f64; fn decode(data: &[u8], mut index: usize, first: u8, allow_inf_nan: bool) -> JsonResult<(Self::Output, usize)> { let start = index; let positive = match first { b'N' => return consume_nan(data, index, allow_inf_nan), b'-' => false, _ => true, }; if !positive { // we started with a minus sign, so the first digit is at index + 1 index += 1; }; let first2 = if positive { Some(&first) } else { data.get(index) }; if let Some(digit) = first2 { if INT_CHAR_MAP[*digit as usize] { const JSON: u128 = lexical_format::JSON; let options = ParseFloatOptions::new(); match f64::from_lexical_partial_with_options::(&data[start..], &options) { Ok((float, index)) => Ok((float, index + start)), Err(_) => { // it's impossible to work out the right error from LexicalError here, so we parse again // with NumberRange and use that error match NumberRange::decode(data, start, first, allow_inf_nan) { Err(e) => Err(e), // NumberRange should always raise an error if `parse_partial_with_options` // except for Infinity and -Infinity, which are handled above Ok(_) => unreachable!("NumberRange should always return an error"), } } } } else if digit == &b'I' { consume_inf_f64(data, index, positive, allow_inf_nan) } else { json_err!(InvalidNumber, index) } } else { json_err!(EofWhileParsingValue, index) } } } /// A number that can be either a [NumberInt] or an [f64] #[derive(Debug, Clone, PartialEq)] pub enum NumberAny { Int(NumberInt), Float(f64), } #[cfg(feature = "python")] impl pyo3::ToPyObject for NumberAny { fn to_object(&self, py: pyo3::Python<'_>) -> pyo3::PyObject { match self { Self::Int(NumberInt::Int(int)) => int.to_object(py), #[cfg(feature = "num-bigint")] Self::Int(NumberInt::BigInt(big_int)) => big_int.to_object(py), Self::Float(float) => float.to_object(py), } } } impl From for f64 { fn from(num: NumberAny) -> Self { match num { NumberAny::Int(int) => int.into(), NumberAny::Float(f) => f, } } } impl AbstractNumberDecoder for NumberAny { type Output = NumberAny; fn decode(data: &[u8], index: usize, first: u8, allow_inf_nan: bool) -> JsonResult<(Self::Output, usize)> { let start = index; let (int_parse, index) = IntParse::parse(data, index, first)?; match int_parse { IntParse::Int(int) => Ok((Self::Int(int), index)), IntParse::Float => { NumberFloat::decode(data, start, first, allow_inf_nan).map(|(f, index)| (Self::Float(f), index)) } IntParse::FloatInf(positive) => { consume_inf_f64(data, index, positive, allow_inf_nan).map(|(f, index)| (Self::Float(f), index)) } IntParse::FloatNaN => consume_nan(data, index, allow_inf_nan).map(|(f, index)| (Self::Float(f), index)), } } } fn consume_inf(data: &[u8], index: usize, positive: bool, allow_inf_nan: bool) -> JsonResult { if allow_inf_nan { crate::parse::consume_infinity(data, index) } else if positive { json_err!(ExpectedSomeValue, index) } else { json_err!(InvalidNumber, index) } } fn consume_inf_f64(data: &[u8], index: usize, positive: bool, allow_inf_nan: bool) -> JsonResult<(f64, usize)> { let end = consume_inf(data, index, positive, allow_inf_nan)?; if positive { Ok((f64::INFINITY, end)) } else { Ok((f64::NEG_INFINITY, end)) } } fn consume_nan(data: &[u8], index: usize, allow_inf_nan: bool) -> JsonResult<(f64, usize)> { if allow_inf_nan { let end = crate::parse::consume_nan(data, index)?; Ok((f64::NAN, end)) } else { json_err!(ExpectedSomeValue, index) } } #[derive(Debug)] pub(crate) enum IntParse { Int(NumberInt), Float, FloatInf(bool), FloatNaN, } impl IntParse { pub(crate) fn parse(data: &[u8], mut index: usize, first: u8) -> JsonResult<(Self, usize)> { let start = index; let positive = match first { b'N' => return Ok((Self::FloatNaN, index)), b'-' => false, _ => true, }; if !positive { // we started with a minus sign, so the first digit is at index + 1 index += 1; }; let first2 = if positive { Some(&first) } else { data.get(index) }; let first_value = match first2 { Some(b'0') => { index += 1; return match data.get(index) { Some(b'.') => Ok((Self::Float, index)), Some(b'e' | b'E') => Ok((Self::Float, index)), Some(digit) if digit.is_ascii_digit() => json_err!(InvalidNumber, index), _ => Ok((Self::Int(NumberInt::Int(0)), index)), }; } Some(b'I') => return Ok((Self::FloatInf(positive), index)), Some(digit) if (b'1'..=b'9').contains(digit) => (digit & 0x0f) as u64, Some(_) => return json_err!(InvalidNumber, index), None => return json_err!(EofWhileParsingValue, index), }; index += 1; let (chunk, new_index) = IntChunk::parse_small(data, index, first_value); let ongoing: u64 = match chunk { IntChunk::Ongoing(value) => value, IntChunk::Done(value) => { let mut value_i64 = value as i64; if !positive { value_i64 = -value_i64; } return Ok((Self::Int(NumberInt::Int(value_i64)), new_index)); } IntChunk::Float => return Ok((Self::Float, new_index)), }; // number is too big for i64, we need to use a BigInt, // or error out if num-bigint is not enabled #[cfg(not(feature = "num-bigint"))] { // silence unused variable warning let _ = (ongoing, start); return json_err!(NumberOutOfRange, index); } #[cfg(feature = "num-bigint")] { #[cfg(target_arch = "aarch64")] // in aarch64 we use a 128 bit registers - 16 bytes const ONGOING_CHUNK_MULTIPLIER: u64 = 10u64.pow(16); #[cfg(not(target_arch = "aarch64"))] // decode_int_chunk_fallback - we parse 18 bytes when the number is ongoing const ONGOING_CHUNK_MULTIPLIER: u64 = 10u64.pow(18); const POW_10: [u64; 18] = [ 10u64.pow(0), 10u64.pow(1), 10u64.pow(2), 10u64.pow(3), 10u64.pow(4), 10u64.pow(5), 10u64.pow(6), 10u64.pow(7), 10u64.pow(8), 10u64.pow(9), 10u64.pow(10), 10u64.pow(11), 10u64.pow(12), 10u64.pow(13), 10u64.pow(14), 10u64.pow(15), 10u64.pow(16), 10u64.pow(17), ]; let mut big_value: BigInt = ongoing.into(); index = new_index; loop { let (chunk, new_index) = IntChunk::parse_big(data, index); if (new_index - start) > 4300 { return json_err!(NumberOutOfRange, start + 4301); } match chunk { IntChunk::Ongoing(value) => { big_value *= ONGOING_CHUNK_MULTIPLIER; big_value += value; index = new_index; } IntChunk::Done(value) => { big_value *= POW_10[new_index - index]; big_value += value; if !positive { big_value = -big_value; } return Ok((Self::Int(NumberInt::BigInt(big_value)), new_index)); } IntChunk::Float => return Ok((Self::Float, new_index)), } } } } } pub(crate) enum IntChunk { Ongoing(u64), Done(u64), Float, } impl IntChunk { #[inline(always)] fn parse_small(data: &[u8], index: usize, value: u64) -> (Self, usize) { decode_int_chunk_fallback(data, index, value) } #[inline(always)] fn parse_big(data: &[u8], index: usize) -> (Self, usize) { // TODO x86_64: use simd #[cfg(target_arch = "aarch64")] { crate::simd_aarch64::decode_int_chunk(data, index) } #[cfg(not(target_arch = "aarch64"))] { decode_int_chunk_fallback(data, index, 0) } } } /// Turns out this is faster than fancy bit manipulation, see /// https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-integer/docs/Algorithm.md /// for some context #[inline(always)] pub(crate) fn decode_int_chunk_fallback(data: &[u8], mut index: usize, mut value: u64) -> (IntChunk, usize) { // i64::MAX = 9223372036854775807 (19 chars) - so 18 chars is always valid as an i64 for _ in 0..18 { if let Some(digit) = data.get(index) { if INT_CHAR_MAP[*digit as usize] { // we use wrapping add to avoid branching - we know the value cannot wrap value = value.wrapping_mul(10).wrapping_add((digit & 0x0f) as u64); index += 1; continue; } else if matches!(digit, b'.' | b'e' | b'E') { return (IntChunk::Float, index); } } return (IntChunk::Done(value), index); } (IntChunk::Ongoing(value), index) } pub(crate) static INT_CHAR_MAP: [bool; 256] = { const NU: bool = true; const __: bool = false; [ // 1 2 3 4 5 6 7 8 9 A B C D E F __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 0 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 1 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2 NU, NU, NU, NU, NU, NU, NU, NU, NU, NU, __, __, __, __, __, __, // 3 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 5 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F ] }; pub struct NumberRange { pub range: Range, // in some cfg configurations, this field is never read. #[allow(dead_code)] pub is_int: bool, } impl NumberRange { fn int(data: Range) -> Self { Self { range: data, is_int: true, } } fn float(data: Range) -> Self { Self { range: data, is_int: false, } } } impl AbstractNumberDecoder for NumberRange { type Output = Self; fn decode(data: &[u8], mut index: usize, first: u8, allow_inf_nan: bool) -> JsonResult<(Self::Output, usize)> { let start = index; let positive = match first { b'N' => { let (_, end) = consume_nan(data, index, allow_inf_nan)?; return Ok((Self::float(start..end), end)); } b'-' => false, _ => true, }; if !positive { // we started with a minus sign, so the first digit is at index + 1 index += 1; }; match data.get(index) { Some(b'0') => { // numbers start with zero must be floats, next char must be a dot index += 1; return match data.get(index) { Some(b'.') => { index += 1; let end = consume_decimal(data, index)?; Ok((Self::float(start..end), end)) } Some(b'e' | b'E') => { index += 1; let end = consume_exponential(data, index)?; Ok((Self::float(start..end), end)) } Some(digit) if digit.is_ascii_digit() => json_err!(InvalidNumber, index), _ => return Ok((Self::int(start..index), index)), }; } Some(b'I') => { let end = consume_inf(data, index, positive, allow_inf_nan)?; return Ok((Self::float(start..end), end)); } Some(digit) if (b'1'..=b'9').contains(digit) => (), Some(_) => return json_err!(InvalidNumber, index), None => return json_err!(EofWhileParsingValue, index), }; index += 1; for _ in 0..18 { if let Some(digit) = data.get(index) { if INT_CHAR_MAP[*digit as usize] { index += 1; continue; } else if matches!(digit, b'.') { index += 1; let end = consume_decimal(data, index)?; return Ok((Self::float(start..end), end)); } else if matches!(digit, b'e' | b'E') { index += 1; let end = consume_exponential(data, index)?; return Ok((Self::float(start..end), end)); } } return Ok((Self::int(start..index), index)); } loop { let (chunk, new_index) = IntChunk::parse_big(data, index); if (new_index - start) > 4300 { return json_err!(NumberOutOfRange, start + 4301); } #[allow(clippy::single_match_else)] match chunk { IntChunk::Ongoing(_) => { index = new_index; } IntChunk::Done(_) => return Ok((Self::int(start..new_index), new_index)), IntChunk::Float => { return match data.get(new_index) { Some(b'.') => { index = new_index + 1; let end = consume_decimal(data, index)?; Ok((Self::float(start..end), end)) } _ => { index = new_index + 1; let end = consume_exponential(data, index)?; Ok((Self::float(start..end), end)) } } } } } } } fn consume_exponential(data: &[u8], mut index: usize) -> JsonResult { match data.get(index) { Some(b'-' | b'+') => { index += 1; } Some(v) if v.is_ascii_digit() => (), Some(_) => return json_err!(InvalidNumber, index), None => return json_err!(EofWhileParsingValue, index), }; match data.get(index) { Some(v) if v.is_ascii_digit() => (), Some(_) => return json_err!(InvalidNumber, index), None => return json_err!(EofWhileParsingValue, index), }; index += 1; while let Some(next) = data.get(index) { match next { b'0'..=b'9' => (), _ => break, } index += 1; } Ok(index) } fn consume_decimal(data: &[u8], mut index: usize) -> JsonResult { match data.get(index) { Some(v) if v.is_ascii_digit() => (), Some(_) => return json_err!(InvalidNumber, index), None => return json_err!(EofWhileParsingValue, index), }; index += 1; while let Some(next) = data.get(index) { match next { b'0'..=b'9' => (), b'e' | b'E' => { index += 1; return consume_exponential(data, index); } _ => break, } index += 1; } Ok(index) } jiter-0.7.1/src/parse.rs000064400000000000000000000212151046102023000132160ustar 00000000000000use std::fmt; use std::ops::Range; use crate::errors::{json_err, JsonResult, LinePosition}; use crate::number_decoder::AbstractNumberDecoder; use crate::string_decoder::{AbstractStringDecoder, Tape}; #[derive(Copy, Clone, PartialEq, Eq)] pub struct Peek(u8); #[allow(non_upper_case_globals)] // while testing impl Peek { pub const Null: Self = Self(b'n'); pub const True: Self = Self(b't'); pub const False: Self = Self(b'f'); pub const Minus: Self = Self(b'-'); pub const Infinity: Self = Self(b'I'); pub const NaN: Self = Self(b'N'); pub const String: Self = Self(b'"'); pub const Array: Self = Self(b'['); pub const Object: Self = Self(b'{'); } impl fmt::Debug for Peek { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.0 { b'n' => write!(f, "Null"), b't' => write!(f, "True"), b'f' => write!(f, "False"), b'-' => write!(f, "Minus"), b'I' => write!(f, "Infinity"), b'N' => write!(f, "NaN"), b'"' => write!(f, "String"), b'[' => write!(f, "Array"), b'{' => write!(f, "Object"), _ => write!(f, "Peek({:?})", self.0 as char), } } } impl Peek { pub const fn new(next: u8) -> Self { Self(next) } pub const fn is_num(self) -> bool { self.0.is_ascii_digit() || matches!(self, Self::Minus | Self::Infinity | Self::NaN) } pub const fn into_inner(self) -> u8 { self.0 } } static TRUE_REST: [u8; 3] = [b'r', b'u', b'e']; static FALSE_REST: [u8; 4] = [b'a', b'l', b's', b'e']; static NULL_REST: [u8; 3] = [b'u', b'l', b'l']; static NAN_REST: [u8; 2] = [b'a', b'N']; static INFINITY_REST: [u8; 7] = [b'n', b'f', b'i', b'n', b'i', b't', b'y']; #[derive(Debug, Clone)] pub(crate) struct Parser<'j> { data: &'j [u8], pub index: usize, } impl<'j> Parser<'j> { pub fn new(data: &'j [u8]) -> Self { Self { data, index: 0 } } #[allow(dead_code)] pub fn slice(&self, range: Range) -> Option<&[u8]> { self.data.get(range) } pub fn current_position(&self) -> LinePosition { LinePosition::find(self.data, self.index) } pub fn peek(&mut self) -> JsonResult { if let Some(next) = self.eat_whitespace() { Ok(Peek::new(next)) } else { json_err!(EofWhileParsingValue, self.index) } } pub fn array_first(&mut self) -> JsonResult> { self.index += 1; if let Some(next) = self.eat_whitespace() { if next == b']' { self.index += 1; Ok(None) } else { Ok(Some(Peek::new(next))) } } else { json_err!(EofWhileParsingList, self.index) } } pub fn array_step(&mut self) -> JsonResult> { if let Some(next) = self.eat_whitespace() { match next { b',' => { self.index += 1; let next = self.array_peek()?; if next.is_none() { json_err!(TrailingComma, self.index) } else { Ok(next) } } b']' => { self.index += 1; Ok(None) } _ => { json_err!(ExpectedListCommaOrEnd, self.index) } } } else { json_err!(EofWhileParsingList, self.index) } } pub fn object_first<'t, D: AbstractStringDecoder<'t, 'j>>( &mut self, tape: &'t mut Tape, ) -> JsonResult> where 'j: 't, { self.index += 1; if let Some(next) = self.eat_whitespace() { match next { b'"' => self.object_key::(tape).map(Some), b'}' => { self.index += 1; Ok(None) } _ => json_err!(KeyMustBeAString, self.index), } } else { json_err!(EofWhileParsingObject, self.index) } } pub fn object_step<'t, D: AbstractStringDecoder<'t, 'j>>( &mut self, tape: &'t mut Tape, ) -> JsonResult> where 'j: 't, { if let Some(next) = self.eat_whitespace() { match next { b',' => { self.index += 1; match self.eat_whitespace() { Some(b'"') => self.object_key::(tape).map(Some), Some(b'}') => json_err!(TrailingComma, self.index), Some(_) => json_err!(KeyMustBeAString, self.index), None => json_err!(EofWhileParsingValue, self.index), } } b'}' => { self.index += 1; Ok(None) } _ => json_err!(ExpectedObjectCommaOrEnd, self.index), } } else { json_err!(EofWhileParsingObject, self.index) } } pub fn finish(&mut self) -> JsonResult<()> { if self.eat_whitespace().is_none() { Ok(()) } else { json_err!(TrailingCharacters, self.index) } } pub fn consume_true(&mut self) -> JsonResult<()> { self.consume_ident(TRUE_REST) } pub fn consume_false(&mut self) -> JsonResult<()> { self.consume_ident(FALSE_REST) } pub fn consume_null(&mut self) -> JsonResult<()> { self.consume_ident(NULL_REST) } pub fn consume_string<'t, D: AbstractStringDecoder<'t, 'j>>( &mut self, tape: &'t mut Tape, allow_partial: bool, ) -> JsonResult where 'j: 't, { let (output, index) = D::decode(self.data, self.index, tape, allow_partial)?; self.index = index; Ok(output) } pub fn consume_number( &mut self, first: u8, allow_inf_nan: bool, ) -> JsonResult { let (output, index) = D::decode(self.data, self.index, first, allow_inf_nan)?; self.index = index; Ok(output) } /// private method to get an object key, then consume the colon which should follow fn object_key<'t, D: AbstractStringDecoder<'t, 'j>>(&mut self, tape: &'t mut Tape) -> JsonResult where 'j: 't, { let (output, index) = D::decode(self.data, self.index, tape, false)?; self.index = index; if let Some(next) = self.eat_whitespace() { if next == b':' { self.index += 1; Ok(output) } else { json_err!(ExpectedColon, self.index) } } else { json_err!(EofWhileParsingObject, self.index) } } fn consume_ident(&mut self, expected: [u8; SIZE]) -> JsonResult<()> { self.index = consume_ident(self.data, self.index, expected)?; Ok(()) } fn array_peek(&mut self) -> JsonResult> { if let Some(next) = self.eat_whitespace() { match next { b']' => Ok(None), _ => Ok(Some(Peek::new(next))), } } else { json_err!(EofWhileParsingValue, self.index) } } fn eat_whitespace(&mut self) -> Option { while let Some(next) = self.data.get(self.index) { match next { b' ' | b'\r' | b'\t' | b'\n' => self.index += 1, _ => return Some(*next), } } None } } pub(crate) fn consume_infinity(data: &[u8], index: usize) -> JsonResult { consume_ident(data, index, INFINITY_REST) } pub(crate) fn consume_nan(data: &[u8], index: usize) -> JsonResult { consume_ident(data, index, NAN_REST) } fn consume_ident(data: &[u8], mut index: usize, expected: [u8; SIZE]) -> JsonResult { match data.get(index + 1..=index + SIZE) { Some(s) if s == expected => Ok(index + SIZE + 1), // TODO very sadly iterating over expected cause extra branches in the generated assembly // and is significantly slower than just returning an error _ => { index += 1; for c in &expected { match data.get(index) { Some(v) if v == c => index += 1, Some(_) => return json_err!(ExpectedSomeIdent, index), _ => break, } } json_err!(EofWhileParsingValue, index) } } } jiter-0.7.1/src/py_lossless_float.rs000064400000000000000000000051071046102023000156520ustar 00000000000000use pyo3::exceptions::{PyTypeError, PyValueError}; use pyo3::prelude::*; use pyo3::sync::GILOnceCell; use pyo3::types::PyType; use crate::Jiter; #[derive(Debug, Clone, Copy)] pub enum FloatMode { Float, Decimal, LosslessFloat, } impl Default for FloatMode { fn default() -> Self { Self::Float } } const FLOAT_ERROR: &str = "Invalid float mode, should be `'float'`, `'decimal'` or `'lossless-float'`"; impl<'py> FromPyObject<'py> for FloatMode { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { if let Ok(str_mode) = ob.extract::<&str>() { match str_mode { "float" => Ok(Self::Float), "decimal" => Ok(Self::Decimal), "lossless-float" => Ok(Self::LosslessFloat), _ => Err(PyValueError::new_err(FLOAT_ERROR)), } } else { Err(PyTypeError::new_err(FLOAT_ERROR)) } } } /// Represents a float from JSON, by holding the underlying bytes representing a float from JSON. #[derive(Debug, Clone)] #[pyclass(module = "jiter")] pub struct LosslessFloat(Vec); impl LosslessFloat { pub fn new_unchecked(raw: Vec) -> Self { Self(raw) } } #[pymethods] impl LosslessFloat { #[new] fn new(raw: Vec) -> PyResult { let s = Self(raw); // check the string is valid by calling `as_float` s.__float__()?; Ok(s) } fn as_decimal<'py>(&self, py: Python<'py>) -> PyResult> { let decimal = get_decimal_type(py)?; let float_str = self.__str__()?; decimal.call1((float_str,)) } fn __float__(&self) -> PyResult { let bytes = &self.0; let mut jiter = Jiter::new(bytes).with_allow_inf_nan(); let f = jiter .next_float() .map_err(|e| PyValueError::new_err(e.description(&jiter)))?; jiter .finish() .map_err(|e| PyValueError::new_err(e.description(&jiter)))?; Ok(f) } fn __bytes__(&self) -> &[u8] { &self.0 } fn __str__(&self) -> PyResult<&str> { std::str::from_utf8(&self.0).map_err(|_| PyValueError::new_err("Invalid UTF-8")) } fn __repr__(&self) -> PyResult { self.__str__().map(|s| format!("LosslessFloat({s})")) } } static DECIMAL_TYPE: GILOnceCell> = GILOnceCell::new(); pub fn get_decimal_type(py: Python) -> PyResult<&Bound<'_, PyType>> { DECIMAL_TYPE .get_or_try_init(py, || py.import_bound("decimal")?.getattr("Decimal")?.extract()) .map(|t| t.bind(py)) } jiter-0.7.1/src/py_string_cache.rs000064400000000000000000000165351046102023000152560ustar 00000000000000use std::cell::RefCell; use ahash::random_state::RandomState; use pyo3::exceptions::{PyTypeError, PyValueError}; use pyo3::prelude::*; use pyo3::sync::{GILOnceCell, GILProtected}; use pyo3::types::{PyBool, PyString}; #[derive(Debug, Clone, Copy)] pub enum StringCacheMode { All, Keys, None, } impl Default for StringCacheMode { fn default() -> Self { Self::All } } impl<'py> FromPyObject<'py> for StringCacheMode { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { if let Ok(bool_mode) = ob.downcast::() { Ok(bool_mode.is_true().into()) } else if let Ok(str_mode) = ob.extract::<&str>() { match str_mode { "all" => Ok(Self::All), "keys" => Ok(Self::Keys), "none" => Ok(Self::None), _ => Err(PyValueError::new_err( "Invalid string cache mode, should be `'all'`, '`keys`', `'none`' or a `bool`", )), } } else { Err(PyTypeError::new_err( "Invalid string cache mode, should be `'all'`, '`keys`', `'none`' or a `bool`", )) } } } impl From for StringCacheMode { fn from(mode: bool) -> Self { if mode { Self::All } else { Self::None } } } pub trait StringMaybeCache { fn get_key<'py>(py: Python<'py>, json_str: &str, ascii_only: bool) -> Bound<'py, PyString>; fn get_value<'py>(py: Python<'py>, json_str: &str, ascii_only: bool) -> Bound<'py, PyString> { Self::get_key(py, json_str, ascii_only) } } pub struct StringCacheAll; impl StringMaybeCache for StringCacheAll { fn get_key<'py>(py: Python<'py>, json_str: &str, ascii_only: bool) -> Bound<'py, PyString> { cached_py_string(py, json_str, ascii_only) } } pub struct StringCacheKeys; impl StringMaybeCache for StringCacheKeys { fn get_key<'py>(py: Python<'py>, json_str: &str, ascii_only: bool) -> Bound<'py, PyString> { cached_py_string(py, json_str, ascii_only) } fn get_value<'py>(py: Python<'py>, json_str: &str, ascii_only: bool) -> Bound<'py, PyString> { pystring_fast_new(py, json_str, ascii_only) } } pub struct StringNoCache; impl StringMaybeCache for StringNoCache { fn get_key<'py>(py: Python<'py>, json_str: &str, ascii_only: bool) -> Bound<'py, PyString> { pystring_fast_new(py, json_str, ascii_only) } } static STRING_CACHE: GILOnceCell>> = GILOnceCell::new(); macro_rules! get_string_cache { ($py:ident) => { STRING_CACHE .get_or_init($py, || GILProtected::new(RefCell::new(PyStringCache::default()))) .get($py) }; } pub fn cache_usage(py: Python) -> usize { get_string_cache!(py).borrow().usage() } pub fn cache_clear(py: Python) { get_string_cache!(py).borrow_mut().clear(); } pub fn cached_py_string<'py>(py: Python<'py>, s: &str, ascii_only: bool) -> Bound<'py, PyString> { // from tests, 0 and 1 character strings are faster not cached if (2..64).contains(&s.len()) { get_string_cache!(py).borrow_mut().get_or_insert(py, s, ascii_only) } else { pystring_fast_new(py, s, ascii_only) } } // capacity should be a power of 2 so the compiler can convert `%` to a right shift below // Using a smaller number here (e.g. 1024) seems to be faster in many cases than a larger number (like 65536) // and also avoids stack overflow risks const CAPACITY: usize = 16_384; type Entry = Option<(u64, Py)>; /// This is a Fully associative cache with LRU replacement policy. /// See https://en.wikipedia.org/wiki/Cache_placement_policies#Fully_associative_cache #[derive(Debug)] struct PyStringCache { entries: Box<[Entry; CAPACITY]>, hash_builder: RandomState, } const ARRAY_REPEAT_VALUE: Entry = None; impl Default for PyStringCache { fn default() -> Self { Self { entries: Box::new([ARRAY_REPEAT_VALUE; CAPACITY]), hash_builder: RandomState::default(), } } } impl PyStringCache { /// Lookup the cache for an entry with the given string. If it exists, return it. /// If it is not set or has a different string, insert it and return it. fn get_or_insert<'py>(&mut self, py: Python<'py>, s: &str, ascii_only: bool) -> Bound<'py, PyString> { let hash = self.hash_builder.hash_one(s); let hash_index = hash as usize % CAPACITY; let set_entry = |entry: &mut Entry| { let py_str = pystring_fast_new(py, s, ascii_only); *entry = Some((hash, py_str.to_owned().unbind())); py_str }; // we try up to 5 contiguous slots to find a match or an empty slot for index in hash_index..hash_index.wrapping_add(5) { if let Some(entry) = self.entries.get_mut(index) { if let Some((entry_hash, ref py_str_ob)) = entry { // to avoid a string comparison, we first compare the hashes if *entry_hash == hash { // if the hashes match, we compare the strings to be absolutely sure - as a hashmap would do if py_str_ob.bind(py).to_str().ok() == Some(s) { // the strings matched, return the cached string object return py_str_ob.bind(py).to_owned(); } } } else { // we got to an empty entry, use it return set_entry(entry); } } else { // we reached the end of entries, break break; } } // we tried all 5 slots (or got to the end of entries) without finding a match // or an empty slot, make this LRU by replacing the first entry let entry = self.entries.get_mut(hash_index).unwrap(); set_entry(entry) } /// get the number of entries in the cache that are set fn usage(&self) -> usize { self.entries.iter().filter(|e| e.is_some()).count() } /// clear the cache by resetting all entries to `None` fn clear(&mut self) { self.entries.fill_with(|| None); } } pub fn pystring_fast_new<'py>(py: Python<'py>, s: &str, ascii_only: bool) -> Bound<'py, PyString> { if ascii_only { unsafe { pystring_ascii_new(py, s) } } else { PyString::new_bound(py, s) } } /// Faster creation of PyString from an ASCII string, inspired by /// https://github.com/ijl/orjson/blob/3.10.0/src/str/create.rs#L41 #[cfg(all(not(PyPy), not(GraalPy)))] unsafe fn pystring_ascii_new<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyString> { let ptr = pyo3::ffi::PyUnicode_New(s.len() as isize, 127); // see https://github.com/pydantic/jiter/pull/72#discussion_r1545485907 debug_assert_eq!(pyo3::ffi::PyUnicode_KIND(ptr), pyo3::ffi::PyUnicode_1BYTE_KIND); let data_ptr = pyo3::ffi::PyUnicode_DATA(ptr).cast(); core::ptr::copy_nonoverlapping(s.as_ptr(), data_ptr, s.len()); core::ptr::write(data_ptr.add(s.len()), 0); Bound::from_owned_ptr(py, ptr).downcast_into_unchecked() } // ffi::PyUnicode_DATA seems to be broken for pypy, hence this, marked as unsafe to avoid warnings #[cfg(any(PyPy, GraalPy))] unsafe fn pystring_ascii_new<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyString> { PyString::new_bound(py, s) } jiter-0.7.1/src/python.rs000064400000000000000000000336531046102023000134360ustar 00000000000000use ahash::AHashSet; use std::marker::PhantomData; use pyo3::exceptions::{PyTypeError, PyValueError}; use pyo3::ffi; use pyo3::prelude::*; use pyo3::types::{PyBool, PyDict, PyList, PyString}; use pyo3::ToPyObject; use smallvec::SmallVec; use crate::errors::{json_err, json_error, JsonError, JsonResult, DEFAULT_RECURSION_LIMIT}; use crate::number_decoder::{AbstractNumberDecoder, NumberAny, NumberRange}; use crate::parse::{Parser, Peek}; use crate::py_lossless_float::{get_decimal_type, FloatMode}; use crate::py_string_cache::{StringCacheAll, StringCacheKeys, StringCacheMode, StringMaybeCache, StringNoCache}; use crate::string_decoder::{StringDecoder, Tape}; use crate::{JsonErrorType, LosslessFloat, PartialMode}; #[derive(Default)] #[allow(clippy::struct_excessive_bools)] pub struct PythonParse { /// Whether to allow `(-)Infinity` and `NaN` values. pub allow_inf_nan: bool, /// Whether to cache strings to avoid constructing new Python objects, pub cache_mode: StringCacheMode, /// Whether to allow partial JSON data. pub partial_mode: PartialMode, /// Whether to catch duplicate keys in objects. pub catch_duplicate_keys: bool, /// How to return floats: as a `float` (`'float'`), `Decimal` (`'decimal'`) or /// [`LosslessFloat`] (`'lossless-float'`) pub float_mode: FloatMode, } impl PythonParse { /// Parse a JSON value from a byte slice and return a Python object. /// /// # Arguments /// /// - `py`: [Python](https://docs.rs/pyo3/latest/pyo3/marker/struct.Python.html) marker token. /// - `json_data`: The JSON data to parse. /// this should have a significant improvement on performance but increases memory slightly. /// /// # Returns /// /// A [PyObject](https://docs.rs/pyo3/latest/pyo3/type.PyObject.html) representing the parsed JSON value. pub fn python_parse<'py>(self, py: Python<'py>, json_data: &[u8]) -> JsonResult> { macro_rules! ppp { ($string_cache:ident, $key_check:ident, $parse_number:ident) => { PythonParser::<$string_cache, $key_check, $parse_number>::parse( py, json_data, self.allow_inf_nan, self.partial_mode, ) }; } macro_rules! ppp_group { ($string_cache:ident) => { match (self.catch_duplicate_keys, self.float_mode) { (true, FloatMode::Float) => ppp!($string_cache, DuplicateKeyCheck, ParseNumberLossy), (true, FloatMode::Decimal) => ppp!($string_cache, DuplicateKeyCheck, ParseNumberDecimal), (true, FloatMode::LosslessFloat) => ppp!($string_cache, DuplicateKeyCheck, ParseNumberLossless), (false, FloatMode::Float) => ppp!($string_cache, NoopKeyCheck, ParseNumberLossy), (false, FloatMode::Decimal) => ppp!($string_cache, NoopKeyCheck, ParseNumberDecimal), (false, FloatMode::LosslessFloat) => ppp!($string_cache, NoopKeyCheck, ParseNumberLossless), } }; } match self.cache_mode { StringCacheMode::All => ppp_group!(StringCacheAll), StringCacheMode::Keys => ppp_group!(StringCacheKeys), StringCacheMode::None => ppp_group!(StringNoCache), } } } /// Map a `JsonError` to a `PyErr` which can be raised as an exception in Python as a `ValueError`. pub fn map_json_error(json_data: &[u8], json_error: &JsonError) -> PyErr { PyValueError::new_err(json_error.description(json_data)) } struct PythonParser<'j, StringCache, KeyCheck, ParseNumber> { _string_cache: PhantomData, _key_check: PhantomData, _parse_number: PhantomData, parser: Parser<'j>, tape: Tape, recursion_limit: u8, allow_inf_nan: bool, partial_mode: PartialMode, } impl<'j, StringCache: StringMaybeCache, KeyCheck: MaybeKeyCheck, ParseNumber: MaybeParseNumber> PythonParser<'j, StringCache, KeyCheck, ParseNumber> { fn parse<'py>( py: Python<'py>, json_data: &[u8], allow_inf_nan: bool, partial_mode: PartialMode, ) -> JsonResult> { let mut slf = PythonParser { _string_cache: PhantomData::, _key_check: PhantomData::, _parse_number: PhantomData::, parser: Parser::new(json_data), tape: Tape::default(), recursion_limit: DEFAULT_RECURSION_LIMIT, allow_inf_nan, partial_mode, }; let peek = slf.parser.peek()?; let v = slf.py_take_value(py, peek)?; if !slf.partial_mode.is_active() { slf.parser.finish()?; } Ok(v) } fn py_take_value<'py>(&mut self, py: Python<'py>, peek: Peek) -> JsonResult> { match peek { Peek::Null => { self.parser.consume_null()?; Ok(py.None().into_bound(py)) } Peek::True => { self.parser.consume_true()?; Ok(true.to_object(py).into_bound(py)) } Peek::False => { self.parser.consume_false()?; Ok(false.to_object(py).into_bound(py)) } Peek::String => { let s = self .parser .consume_string::(&mut self.tape, self.partial_mode.allow_trailing_str())?; Ok(StringCache::get_value(py, s.as_str(), s.ascii_only()).into_any()) } Peek::Array => { let peek_first = match self.parser.array_first() { Ok(Some(peek)) => peek, Err(e) if !self._allow_partial_err(&e) => return Err(e), Ok(None) | Err(_) => return Ok(PyList::empty_bound(py).into_any()), }; let mut vec: SmallVec<[Bound<'_, PyAny>; 8]> = SmallVec::with_capacity(8); if let Err(e) = self._parse_array(py, peek_first, &mut vec) { if !self._allow_partial_err(&e) { return Err(e); } } Ok(PyList::new_bound(py, vec).into_any()) } Peek::Object => { let dict = PyDict::new_bound(py); if let Err(e) = self._parse_object(py, &dict) { if !self._allow_partial_err(&e) { return Err(e); } } Ok(dict.into_any()) } _ => ParseNumber::parse_number(py, &mut self.parser, peek, self.allow_inf_nan), } } fn _parse_array<'py>( &mut self, py: Python<'py>, peek_first: Peek, vec: &mut SmallVec<[Bound<'py, PyAny>; 8]>, ) -> JsonResult<()> { let v = self._check_take_value(py, peek_first)?; vec.push(v); while let Some(peek) = self.parser.array_step()? { let v = self._check_take_value(py, peek)?; vec.push(v); } Ok(()) } fn _parse_object<'py>(&mut self, py: Python<'py>, dict: &Bound<'py, PyDict>) -> JsonResult<()> { let set_item = |key: Bound<'py, PyString>, value: Bound<'py, PyAny>| { let r = unsafe { ffi::PyDict_SetItem(dict.as_ptr(), key.as_ptr(), value.as_ptr()) }; // AFAIK this shouldn't happen since the key will always be a string which is hashable // we panic here rather than returning a result and using `?` below as it's up to 14% faster // presumably because there are fewer branches assert_ne!(r, -1, "PyDict_SetItem failed"); }; let mut check_keys = KeyCheck::default(); if let Some(first_key) = self.parser.object_first::(&mut self.tape)? { let first_key_s = first_key.as_str(); check_keys.check(first_key_s, self.parser.index)?; let first_key = StringCache::get_key(py, first_key_s, first_key.ascii_only()); let peek = self.parser.peek()?; let first_value = self._check_take_value(py, peek)?; set_item(first_key, first_value); while let Some(key) = self.parser.object_step::(&mut self.tape)? { let key_s = key.as_str(); check_keys.check(key_s, self.parser.index)?; let key = StringCache::get_key(py, key_s, key.ascii_only()); let peek = self.parser.peek()?; let value = self._check_take_value(py, peek)?; set_item(key, value); } } Ok(()) } fn _allow_partial_err(&self, e: &JsonError) -> bool { if self.partial_mode.is_active() { e.allowed_if_partial() } else { false } } fn _check_take_value<'py>(&mut self, py: Python<'py>, peek: Peek) -> JsonResult> { self.recursion_limit = match self.recursion_limit.checked_sub(1) { Some(limit) => limit, None => return json_err!(RecursionLimitExceeded, self.parser.index), }; let r = self.py_take_value(py, peek); self.recursion_limit += 1; r } } const PARTIAL_ERROR: &str = "Invalid partial mode, should be `'off'`, `'on'`, `'trailing-strings'` or a `bool`"; impl<'py> FromPyObject<'py> for PartialMode { fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult { if let Ok(bool_mode) = ob.downcast::() { Ok(bool_mode.is_true().into()) } else if let Ok(str_mode) = ob.extract::<&str>() { match str_mode { "off" => Ok(Self::Off), "on" => Ok(Self::On), "trailing-strings" => Ok(Self::TrailingStrings), _ => Err(PyValueError::new_err(PARTIAL_ERROR)), } } else { Err(PyTypeError::new_err(PARTIAL_ERROR)) } } } trait MaybeKeyCheck: Default { fn check(&mut self, key: &str, index: usize) -> JsonResult<()>; } #[derive(Default)] struct NoopKeyCheck; impl MaybeKeyCheck for NoopKeyCheck { fn check(&mut self, _key: &str, _index: usize) -> JsonResult<()> { Ok(()) } } #[derive(Default)] struct DuplicateKeyCheck(AHashSet); impl MaybeKeyCheck for DuplicateKeyCheck { fn check(&mut self, key: &str, index: usize) -> JsonResult<()> { if self.0.insert(key.to_owned()) { Ok(()) } else { Err(JsonError::new(JsonErrorType::DuplicateKey(key.to_owned()), index)) } } } trait MaybeParseNumber { fn parse_number<'py>( py: Python<'py>, parser: &mut Parser, peek: Peek, allow_inf_nan: bool, ) -> JsonResult>; } struct ParseNumberLossy; impl MaybeParseNumber for ParseNumberLossy { fn parse_number<'py>( py: Python<'py>, parser: &mut Parser, peek: Peek, allow_inf_nan: bool, ) -> JsonResult> { match parser.consume_number::(peek.into_inner(), allow_inf_nan) { Ok(number) => Ok(number.to_object(py).into_bound(py)), Err(e) => { if !peek.is_num() { Err(json_error!(ExpectedSomeValue, parser.index)) } else { Err(e) } } } } } struct ParseNumberLossless; impl MaybeParseNumber for ParseNumberLossless { fn parse_number<'py>( py: Python<'py>, parser: &mut Parser, peek: Peek, allow_inf_nan: bool, ) -> JsonResult> { match parser.consume_number::(peek.into_inner(), allow_inf_nan) { Ok(number_range) => { let bytes = parser.slice(number_range.range).unwrap(); let obj = if number_range.is_int { NumberAny::decode(bytes, 0, peek.into_inner(), allow_inf_nan)? .0 .to_object(py) } else { LosslessFloat::new_unchecked(bytes.to_vec()).into_py(py) }; Ok(obj.into_bound(py)) } Err(e) => { if !peek.is_num() { Err(json_error!(ExpectedSomeValue, parser.index)) } else { Err(e) } } } } } struct ParseNumberDecimal; impl MaybeParseNumber for ParseNumberDecimal { fn parse_number<'py>( py: Python<'py>, parser: &mut Parser, peek: Peek, allow_inf_nan: bool, ) -> JsonResult> { match parser.consume_number::(peek.into_inner(), allow_inf_nan) { Ok(number_range) => { let bytes = parser.slice(number_range.range).unwrap(); if number_range.is_int { let obj = NumberAny::decode(bytes, 0, peek.into_inner(), allow_inf_nan)? .0 .to_object(py); Ok(obj.into_bound(py)) } else { let decimal_type = get_decimal_type(py) .map_err(|e| JsonError::new(JsonErrorType::InternalError(e.to_string()), parser.index))?; // SAFETY: NumberRange::decode has already confirmed that bytes are a valid JSON number, // and therefore valid str let float_str = unsafe { std::str::from_utf8_unchecked(bytes) }; decimal_type .call1((float_str,)) .map_err(|e| JsonError::new(JsonErrorType::InternalError(e.to_string()), parser.index)) } } Err(e) => { if !peek.is_num() { Err(json_error!(ExpectedSomeValue, parser.index)) } else { Err(e) } } } } } jiter-0.7.1/src/simd_aarch64.rs000064400000000000000000000230471046102023000143550ustar 00000000000000use std::mem::transmute; #[rustfmt::skip] use std::arch::aarch64::{ uint8x16_t, uint16x8_t, uint32x4_t, uint64x2_t, uint8x8_t, uint16x4_t, uint32x2_t, uint64x1_t, // 16 byte methods vld1q_u8 as simd_load_16, vcgtq_u8 as simd_gt_16, vcltq_u8 as simd_lt_16, vorrq_u8 as simd_or_16, vceqq_u8 as simd_eq_16, vextq_u8 as combine_vecs_16, vsubq_u8 as simd_sub_16, vmulq_u8 as simd_mul_16, vpaddlq_u8 as simd_add_16, vmulq_u16 as simd_mul_u16_8, vpaddlq_u16 as simd_add_u16_8, vmulq_u32 as simd_mul_u32_4, vpaddlq_u32 as simd_add_u32_4, // 8 byte methods vget_low_u8 as simd_get_low, vext_u8 as combine_vecs_8, vsub_u8 as simd_sub_8, vmul_u8 as simd_mul_8, vpaddl_u8 as simd_add_8, vmul_u16 as simd_mul_u16_4, vpaddl_u16 as simd_add_u16_4, vmul_u32 as simd_mul_u32_2, vpaddl_u32 as simd_add_u32_2, }; use crate::JsonResult; use crate::number_decoder::{decode_int_chunk_fallback, IntChunk}; use crate::string_decoder::StringChunk; type SimdVecu8_16 = uint8x16_t; type SimdVecu16_8 = uint16x8_t; type SimdVecu32_4 = uint32x4_t; type SimdVecu64_2 = uint64x2_t; type SimdVecu8_8 = uint8x8_t; type SimdVecu16_4 = uint16x4_t; type SimdVecu32_2 = uint32x2_t; type SimdVecu64_1 = uint64x1_t; const SIMD_STEP: usize = 16; macro_rules! simd_const { ($array:expr) => { unsafe { transmute($array) } }; } const ZERO_DIGIT_U8_8: SimdVecu8_8 = simd_const!([b'0'; 8]); const ZERO_VAL_U8_8: SimdVecu8_8 = simd_const!([0u8; 8]); const ALT_MUL_U8_8: SimdVecu8_8 = simd_const!([10u8, 1u8, 10u8, 1u8, 10u8, 1u8, 10u8, 1u8]); const ALT_MUL_U16_4: SimdVecu16_4 = simd_const!([100u16, 1u16, 100u16, 1u16]); const ALT_MUL_U32_2: SimdVecu32_2 = simd_const!([10000u32, 1u32]); const ZERO_DIGIT_16: SimdVecu8_16 = simd_const!([b'0'; 16]); const NINE_DIGIT_16: SimdVecu8_16 = simd_const!([b'9'; 16]); const ZERO_VAL_U8_16: SimdVecu8_16 = simd_const!([0u8; 16]); const ALT_MUL_U8_16: SimdVecu8_16 = simd_const!([10u8, 1u8, 10u8, 1u8, 10u8, 1u8, 10u8, 1u8, 10u8, 1u8, 10u8, 1u8, 10u8, 1u8, 10u8, 1u8]); const ALT_MUL_U16_8: SimdVecu16_8 = simd_const!([100u16, 1u16, 100u16, 1u16, 100u16, 1u16, 100u16, 1u16]); const ALT_MUL_U32_4: SimdVecu32_4 = simd_const!([10000u32, 1u32, 10000u32, 1u32]); #[inline(always)] pub(crate) fn decode_int_chunk(data: &[u8], index: usize) -> (IntChunk, usize) { if let Some(byte_chunk) = data.get(index..index + SIMD_STEP) { let byte_vec = load_slice(byte_chunk); let digit_mask = get_digit_mask(byte_vec); if is_zero(digit_mask) { // all lanes are digits, parse the full vector let value = unsafe { full_calc(byte_vec, 16) }; (IntChunk::Ongoing(value), index + SIMD_STEP) } else { // some lanes are not digits, transmute to a pair of u64 and find the first non-digit let last_digit = find_end(digit_mask); let index = index + last_digit as usize; if next_is_float(data, index) { (IntChunk::Float, index) } else if last_digit <= 8 { // none-digit in the first 8 bytes let value = unsafe { first_half_calc(byte_vec, last_digit) }; (IntChunk::Done(value), index) } else { // none-digit in the last 8 bytes let value = unsafe { full_calc(byte_vec, last_digit) }; (IntChunk::Done(value), index) } } } else { // we got near the end of the string, fall back to the slow path decode_int_chunk_fallback(data, index, 0) } } #[rustfmt::skip] fn get_digit_mask(byte_vec: SimdVecu8_16) -> SimdVecu8_16 { unsafe { simd_or_16( simd_lt_16(byte_vec, ZERO_DIGIT_16), simd_gt_16(byte_vec, NINE_DIGIT_16), ) } } unsafe fn first_half_calc(byte_vec: SimdVecu8_16, last_digit: u32) -> u64 { let small_byte_vec = simd_get_low(byte_vec); // subtract ascii '0' from every byte to get the digit values let digits: SimdVecu8_8 = simd_sub_8(small_byte_vec, ZERO_DIGIT_U8_8); let digits = match last_digit { 0 => return 0, 1 => { let t: [u8; 8] = transmute(digits); return t[0] as u64; } 2 => combine_vecs_8::<2>(ZERO_VAL_U8_8, digits), 3 => combine_vecs_8::<3>(ZERO_VAL_U8_8, digits), 4 => combine_vecs_8::<4>(ZERO_VAL_U8_8, digits), 5 => combine_vecs_8::<5>(ZERO_VAL_U8_8, digits), 6 => combine_vecs_8::<6>(ZERO_VAL_U8_8, digits), 7 => combine_vecs_8::<7>(ZERO_VAL_U8_8, digits), 8 => digits, _ => unreachable!("last_digit should be less than 8"), }; // multiple every other digit by 10 let x: SimdVecu8_8 = simd_mul_8(digits, ALT_MUL_U8_8); // add the value together and combine the 8x8-bit lanes into 4x16-bit lanes let x: SimdVecu16_4 = simd_add_8(x); // multiple every other digit by 100 let x: SimdVecu16_4 = simd_mul_u16_4(x, ALT_MUL_U16_4); // add the value together and combine the 4x16-bit lanes into 2x32-bit lanes let x: SimdVecu32_2 = simd_add_u16_4(x); // multiple the first value 10000 let x: SimdVecu32_2 = simd_mul_u32_2(x, ALT_MUL_U32_2); // add the value together and combine the 2x32-bit lanes into 1x64-bit lane let x: SimdVecu64_1 = simd_add_u32_2(x); // transmute the 64-bit lane into a u64 transmute(x) } unsafe fn full_calc(byte_vec: SimdVecu8_16, last_digit: u32) -> u64 { // subtract ascii '0' from every byte to get the digit values let digits: SimdVecu8_16 = simd_sub_16(byte_vec, ZERO_DIGIT_16); let digits = match last_digit { 9 => combine_vecs_16::<9>(ZERO_VAL_U8_16, digits), 10 => combine_vecs_16::<10>(ZERO_VAL_U8_16, digits), 11 => combine_vecs_16::<11>(ZERO_VAL_U8_16, digits), 12 => combine_vecs_16::<12>(ZERO_VAL_U8_16, digits), 13 => combine_vecs_16::<13>(ZERO_VAL_U8_16, digits), 14 => combine_vecs_16::<14>(ZERO_VAL_U8_16, digits), 15 => combine_vecs_16::<15>(ZERO_VAL_U8_16, digits), 16 => digits, _ => unreachable!("last_digit should be between 9 and 16"), }; // multiple every other digit by 10 let x: SimdVecu8_16 = simd_mul_16(digits, ALT_MUL_U8_16); // add the value together and combine the 16x8-bit lanes into 8x16-bit lanes let x: SimdVecu16_8 = simd_add_16(x); // multiple every other digit by 100 let x: SimdVecu16_8 = simd_mul_u16_8(x, ALT_MUL_U16_8); // add the value together and combine the 8x16-bit lanes into 4x32-bit lanes let x: SimdVecu32_4 = simd_add_u16_8(x); // multiple every other digit by 10000 let x: SimdVecu32_4 = simd_mul_u32_4(x, ALT_MUL_U32_4); // add the value together and combine the 4x32-bit lanes into 2x64-bit lane let x: SimdVecu64_2 = simd_add_u32_4(x); // transmute the 2x64-bit lane into an array; let t: [u64; 2] = transmute(x); // since the data started out as digits, it's safe to assume the result fits in a u64 t[0].wrapping_mul(100_000_000).wrapping_add(t[1]) } fn next_is_float(data: &[u8], index: usize) -> bool { let next = unsafe { data.get_unchecked(index) }; matches!(next, b'.' | b'e' | b'E') } const QUOTE_16: SimdVecu8_16 = simd_const!([b'"'; 16]); const BACKSLASH_16: SimdVecu8_16 = simd_const!([b'\\'; 16]); // values below 32 are control characters const CONTROL_16: SimdVecu8_16 = simd_const!([32u8; 16]); const ASCII_MAX_16: SimdVecu8_16 = simd_const!([127u8; 16]); #[inline(always)] pub(crate) fn decode_string_chunk( data: &[u8], mut index: usize, mut ascii_only: bool, allow_partial: bool, ) -> JsonResult<(StringChunk, bool, usize)> { while let Some(byte_chunk) = data.get(index..index + SIMD_STEP) { let byte_vec = load_slice(byte_chunk); let ascii_mask = string_ascii_mask(byte_vec); if is_zero(ascii_mask) { // this chunk is just ascii, continue to the next chunk index += SIMD_STEP; } else { // this chunk contains either a stop character or a non-ascii character let a: [u8; 16] = unsafe { transmute(byte_vec) }; #[allow(clippy::redundant_else)] if let Some(r) = StringChunk::decode_array(a, &mut index, ascii_only) { return r; } else { ascii_only = false; } } } // we got near the end of the string, fall back to the slow path StringChunk::decode_fallback(data, index, ascii_only, allow_partial) } #[rustfmt::skip] /// returns a mask where any non-zero byte means we don't have a simple ascii character, either /// quote, backslash, control character, or non-ascii (above 127) fn string_ascii_mask(byte_vec: SimdVecu8_16) -> SimdVecu8_16 { unsafe { simd_or_16( simd_eq_16(byte_vec, QUOTE_16), simd_or_16( simd_eq_16(byte_vec, BACKSLASH_16), simd_or_16( simd_gt_16(byte_vec, ASCII_MAX_16), simd_lt_16(byte_vec, CONTROL_16), ) ) ) } } fn find_end(digit_mask: SimdVecu8_16) -> u32 { let t: [u64; 2] = unsafe { transmute(digit_mask) }; if t[0] != 0 { // non-digit in the first 8 bytes t[0].trailing_zeros() / 8 } else { t[1].trailing_zeros() / 8 + 8 } } /// return true if all bytes are zero fn is_zero(vec: SimdVecu8_16) -> bool { let t: [u64; 2] = unsafe { transmute(vec) }; t[0] == 0 && t[1] == 0 } fn load_slice(bytes: &[u8]) -> SimdVecu8_16 { debug_assert_eq!(bytes.len(), 16); unsafe { simd_load_16(bytes.as_ptr()) } } jiter-0.7.1/src/string_decoder.rs000064400000000000000000000343721046102023000151070ustar 00000000000000use std::borrow::Cow; use std::ops::Range; use std::str::{from_utf8, from_utf8_unchecked}; use crate::errors::{json_err, json_error, JsonResult}; pub type Tape = Vec; /// `'t` is the lifetime of the tape (reusable buffer), `'j` is the lifetime of the JSON data itself /// data must outlive tape, so if you return data with the lifetime of tape, /// a slice of data the original JSON data is okay too pub trait AbstractStringDecoder<'t, 'j> where 'j: 't, { type Output: std::fmt::Debug; fn decode( data: &'j [u8], index: usize, tape: &'t mut Tape, allow_partial: bool, ) -> JsonResult<(Self::Output, usize)>; } pub struct StringDecoder; #[derive(Debug)] pub enum StringOutput<'t, 'j> where 'j: 't, { Tape(&'t str, bool), Data(&'j str, bool), } impl From> for String { fn from(val: StringOutput) -> Self { match val { StringOutput::Tape(s, _) => s.to_owned(), StringOutput::Data(s, _) => s.to_owned(), } } } impl<'t, 'j> From> for Cow<'j, str> { fn from(val: StringOutput<'t, 'j>) -> Self { match val { StringOutput::Tape(s, _) => s.to_owned().into(), StringOutput::Data(s, _) => s.into(), } } } impl<'t, 'j> StringOutput<'t, 'j> { pub fn as_str(&self) -> &'t str { match self { Self::Tape(s, _) => s, Self::Data(s, _) => s, } } pub fn ascii_only(&self) -> bool { match self { Self::Tape(_, ascii_only) => *ascii_only, Self::Data(_, ascii_only) => *ascii_only, } } } impl<'t, 'j> AbstractStringDecoder<'t, 'j> for StringDecoder where 'j: 't, { type Output = StringOutput<'t, 'j>; fn decode( data: &'j [u8], index: usize, tape: &'t mut Tape, allow_partial: bool, ) -> JsonResult<(Self::Output, usize)> { let start = index + 1; match decode_chunk(data, start, true, allow_partial)? { (StringChunk::StringEnd, ascii_only, index) => { let s = to_str(&data[start..index], ascii_only, start)?; Ok((StringOutput::Data(s, ascii_only), index + 1)) } (StringChunk::Backslash, ascii_only, index) => { decode_to_tape(data, index, tape, start, ascii_only, allow_partial) } } } } fn decode_to_tape<'t, 'j>( data: &'j [u8], mut index: usize, tape: &'t mut Tape, start: usize, mut ascii_only: bool, allow_partial: bool, ) -> JsonResult<(StringOutput<'t, 'j>, usize)> { tape.clear(); let mut chunk_start = start; loop { // on_backslash tape.extend_from_slice(&data[chunk_start..index]); index += 1; if let Some(next_inner) = data.get(index) { match next_inner { b'"' | b'\\' | b'/' => tape.push(*next_inner), b'b' => tape.push(b'\x08'), b'f' => tape.push(b'\x0C'), b'n' => tape.push(b'\n'), b'r' => tape.push(b'\r'), b't' => tape.push(b'\t'), b'u' => { let (c, new_index) = parse_escape(data, index)?; ascii_only = false; index = new_index; tape.extend_from_slice(c.encode_utf8(&mut [0_u8; 4]).as_bytes()); } _ => return json_err!(InvalidEscape, index), } index += 1; } else { return json_err!(EofWhileParsingString, index); } match decode_chunk(data, index, ascii_only, allow_partial)? { (StringChunk::StringEnd, ascii_only, new_index) => { tape.extend_from_slice(&data[index..new_index]); index = new_index + 1; let s = to_str(tape, ascii_only, start)?; return Ok((StringOutput::Tape(s, ascii_only), index)); } (StringChunk::Backslash, ascii_only_new, index_new) => { ascii_only = ascii_only_new; chunk_start = index; index = index_new; } } } } #[inline(always)] pub(crate) fn decode_chunk( data: &[u8], index: usize, ascii_only: bool, allow_partial: bool, ) -> JsonResult<(StringChunk, bool, usize)> { // TODO x86_64: use simd #[cfg(target_arch = "aarch64")] { crate::simd_aarch64::decode_string_chunk(data, index, ascii_only, allow_partial) } #[cfg(not(target_arch = "aarch64"))] { StringChunk::decode_fallback(data, index, ascii_only, allow_partial) } } pub(crate) enum StringChunk { StringEnd, Backslash, } impl StringChunk { #[inline(always)] pub fn decode_fallback( data: &[u8], mut index: usize, mut ascii_only: bool, allow_partial: bool, ) -> JsonResult<(Self, bool, usize)> { while let Some(next) = data.get(index) { if !JSON_ASCII[*next as usize] { match &CHAR_TYPE[*next as usize] { CharType::Quote => return Ok((Self::StringEnd, ascii_only, index)), CharType::Backslash => return Ok((Self::Backslash, ascii_only, index)), CharType::ControlChar => return json_err!(ControlCharacterWhileParsingString, index), CharType::Other => { ascii_only = false; } } } index += 1; } if allow_partial { Ok((Self::StringEnd, ascii_only, index)) } else { json_err!(EofWhileParsingString, index) } } /// decode an array (generally from SIMD) return the result of the chunk, or none if the non-ascii character /// is just > \x7F (127) #[inline(always)] #[allow(dead_code)] pub fn decode_array( data: [u8; T], index: &mut usize, ascii_only: bool, ) -> Option> { for u8_char in data { if !JSON_ASCII[u8_char as usize] { return match &CHAR_TYPE[u8_char as usize] { CharType::Quote => Some(Ok((Self::StringEnd, ascii_only, *index))), CharType::Backslash => Some(Ok((Self::Backslash, ascii_only, *index))), CharType::ControlChar => Some(json_err!(ControlCharacterWhileParsingString, *index)), CharType::Other => { *index += 1; None } }; } *index += 1; } unreachable!("error decoding SIMD string chunk") } } // taken serde-rs/json but altered // https://github.com/serde-rs/json/blob/ebaf61709aba7a3f2429a5d95a694514f180f565/src/read.rs#L787-L811 // this helps the fast path by telling us if something is ascii or not, it also simplifies // CharType below by only requiring 4 options in that enum static JSON_ASCII: [bool; 256] = { const CT: bool = false; // control character \x00..=\x1F const QU: bool = false; // quote \x22 const BS: bool = false; // backslash \x5C const __: bool = true; // simple ascii const HI: bool = false; // > \x7F (127) [ // 1 2 3 4 5 6 7 8 9 A B C D E F CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 0 CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 1 __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4 __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7 HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, // 8 HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, // 9 HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, // A HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, // B HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, // C HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, // D HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, // E HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, HI, // F ] }; enum CharType { // control character \x00..=\x1F ControlChar, // quote \x22 Quote, // backslash \x5C Backslash, // all other characters. In reality this will only be > \x7F (127) after the JSON_ASCII check Other, } // Lookup table of bytes that must be escaped. A value of true at index i means // that byte i requires an escape sequence in the input. static CHAR_TYPE: [CharType; 256] = { const CT: CharType = CharType::ControlChar; const QU: CharType = CharType::Quote; const BS: CharType = CharType::Backslash; const __: CharType = CharType::Other; [ // 1 2 3 4 5 6 7 8 9 A B C D E F CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 0 CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, // 1 __, __, QU, __, __, __, __, __, __, __, __, __, __, __, __, __, // 2 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 3 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 4 __, __, __, __, __, __, __, __, __, __, __, __, BS, __, __, __, // 5 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 6 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 7 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 8 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // 9 __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // A __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // B __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // C __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // D __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // E __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, // F ] }; fn to_str(bytes: &[u8], ascii_only: bool, start: usize) -> JsonResult<&str> { if ascii_only { // safety: in this case we've already confirmed that all characters are ascii, we can safely // transmute from bytes to str Ok(unsafe { from_utf8_unchecked(bytes) }) } else { from_utf8(bytes).map_err(|e| json_error!(InvalidUnicodeCodePoint, start + e.valid_up_to() + 1)) } } /// Taken approximately from https://github.com/serde-rs/json/blob/v1.0.107/src/read.rs#L872-L945 fn parse_escape(data: &[u8], index: usize) -> JsonResult<(char, usize)> { let (n, index) = parse_u4(data, index)?; match n { 0xDC00..=0xDFFF => json_err!(LoneLeadingSurrogateInHexEscape, index), 0xD800..=0xDBFF => match data.get(index + 1..index + 3) { Some(slice) if slice == b"\\u" => { let (n2, index) = parse_u4(data, index + 2)?; if !(0xDC00..=0xDFFF).contains(&n2) { return json_err!(LoneLeadingSurrogateInHexEscape, index); } let n2 = (((n - 0xD800) as u32) << 10 | (n2 - 0xDC00) as u32) + 0x1_0000; match char::from_u32(n2) { Some(c) => Ok((c, index)), None => json_err!(EofWhileParsingString, index), } } Some(slice) if slice.starts_with(b"\\") => json_err!(UnexpectedEndOfHexEscape, index + 2), Some(_) => json_err!(UnexpectedEndOfHexEscape, index + 1), None => match data.get(index + 1) { Some(b'\\') | None => json_err!(EofWhileParsingString, data.len()), Some(_) => json_err!(UnexpectedEndOfHexEscape, index + 1), }, }, _ => match char::from_u32(n as u32) { Some(c) => Ok((c, index)), None => json_err!(InvalidEscape, index), }, } } fn parse_u4(data: &[u8], mut index: usize) -> JsonResult<(u16, usize)> { let mut n = 0; let u4 = data .get(index + 1..index + 5) .ok_or_else(|| json_error!(EofWhileParsingString, data.len()))?; for c in u4 { index += 1; let hex = match c { b'0'..=b'9' => (c & 0x0f) as u16, b'a'..=b'f' => (c - b'a' + 10) as u16, b'A'..=b'F' => (c - b'A' + 10) as u16, _ => return json_err!(InvalidEscape, index), }; n = (n << 4) + hex; } Ok((n, index)) } /// A string decoder that returns the range of the string. /// /// *WARNING:* For performance reasons, this decoder does not check that the string would be valid UTF-8. pub struct StringDecoderRange; impl<'t, 'j> AbstractStringDecoder<'t, 'j> for StringDecoderRange where 'j: 't, { type Output = Range; fn decode( data: &'j [u8], mut index: usize, _tape: &'t mut Tape, allow_partial: bool, ) -> JsonResult<(Self::Output, usize)> { index += 1; let start = index; loop { index = match decode_chunk(data, index, true, allow_partial)? { (StringChunk::StringEnd, _, index) => { let r = start..index; return Ok((r, index + 1)); } (StringChunk::Backslash, _, index) => index, }; index += 1; if let Some(next_inner) = data.get(index) { match next_inner { // these escapes are easy to validate b'"' | b'\\' | b'/' | b'b' | b'f' | b'n' | b'r' | b't' => (), b'u' => { let (_, new_index) = parse_escape(data, index)?; index = new_index; } _ => return json_err!(InvalidEscape, index), } index += 1; } else { return json_err!(EofWhileParsingString, index); } } } } jiter-0.7.1/src/value.rs000064400000000000000000000652651046102023000132350ustar 00000000000000use std::borrow::Cow; use std::sync::Arc; #[cfg(feature = "num-bigint")] use num_bigint::BigInt; use smallvec::SmallVec; use crate::errors::{json_error, JsonError, JsonResult, DEFAULT_RECURSION_LIMIT}; use crate::lazy_index_map::LazyIndexMap; use crate::number_decoder::{NumberAny, NumberInt, NumberRange}; use crate::parse::{Parser, Peek}; use crate::string_decoder::{StringDecoder, StringDecoderRange, StringOutput, Tape}; use crate::PartialMode; /// Enum representing a JSON value. #[derive(Clone, Debug, PartialEq)] pub enum JsonValue<'s> { Null, Bool(bool), Int(i64), #[cfg(feature = "num-bigint")] BigInt(BigInt), Float(f64), Str(Cow<'s, str>), Array(JsonArray<'s>), Object(JsonObject<'s>), } pub type JsonArray<'s> = Arc; 8]>>; pub type JsonObject<'s> = Arc, JsonValue<'s>>>; #[cfg(feature = "python")] impl pyo3::ToPyObject for JsonValue<'_> { fn to_object(&self, py: pyo3::Python<'_>) -> pyo3::PyObject { use pyo3::prelude::*; match self { Self::Null => py.None().to_object(py), Self::Bool(b) => b.to_object(py), Self::Int(i) => i.to_object(py), #[cfg(feature = "num-bigint")] Self::BigInt(b) => b.to_object(py), Self::Float(f) => f.to_object(py), Self::Str(s) => s.to_object(py), Self::Array(v) => pyo3::types::PyList::new_bound(py, v.iter().map(|v| v.to_object(py))).to_object(py), Self::Object(o) => { let dict = pyo3::types::PyDict::new_bound(py); for (k, v) in o.iter() { dict.set_item(k, v.to_object(py)).unwrap(); } dict.to_object(py) } } } } impl<'j> JsonValue<'j> { /// Parse a JSON enum from a byte slice, returning a borrowed version of the enum - e.g. strings can be /// references into the original byte slice. pub fn parse(data: &'j [u8], allow_inf_nan: bool) -> Result { Self::parse_with_config(data, allow_inf_nan, PartialMode::Off) } pub fn parse_with_config( data: &'j [u8], allow_inf_nan: bool, allow_partial: PartialMode, ) -> Result { let mut parser = Parser::new(data); let mut tape = Tape::default(); let peek = parser.peek()?; let v = take_value_borrowed( peek, &mut parser, &mut tape, DEFAULT_RECURSION_LIMIT, allow_inf_nan, allow_partial, )?; if !allow_partial.is_active() { parser.finish()?; } Ok(v) } /// Convert a borrowed JSON enum into an owned JSON enum. pub fn into_static(self) -> JsonValue<'static> { value_static(self) } /// Copy a borrowed JSON enum into an owned JSON enum. pub fn to_static(&self) -> JsonValue<'static> { value_static(self.clone()) } } fn value_static(v: JsonValue<'_>) -> JsonValue<'static> { match v { JsonValue::Null => JsonValue::Null, JsonValue::Bool(b) => JsonValue::Bool(b), JsonValue::Int(i) => JsonValue::Int(i), #[cfg(feature = "num-bigint")] JsonValue::BigInt(b) => JsonValue::BigInt(b), JsonValue::Float(f) => JsonValue::Float(f), JsonValue::Str(s) => JsonValue::Str(s.into_owned().into()), JsonValue::Array(v) => JsonValue::Array(Arc::new(v.iter().map(JsonValue::to_static).collect::>())), JsonValue::Object(o) => JsonValue::Object(Arc::new(o.to_static())), } } impl JsonValue<'static> { /// Parse a JSON enum from a byte slice, returning an owned version of the enum. pub fn parse_owned(data: &[u8], allow_inf_nan: bool, allow_partial: PartialMode) -> Result { let mut parser = Parser::new(data); let mut tape = Tape::default(); let peek = parser.peek()?; let v = take_value_owned( peek, &mut parser, &mut tape, DEFAULT_RECURSION_LIMIT, allow_inf_nan, allow_partial, )?; parser.finish()?; Ok(v) } } pub(crate) fn take_value_borrowed<'j>( peek: Peek, parser: &mut Parser<'j>, tape: &mut Tape, recursion_limit: u8, allow_inf_nan: bool, allow_partial: PartialMode, ) -> JsonResult> { take_value( peek, parser, tape, recursion_limit, allow_inf_nan, allow_partial, &|s: StringOutput<'_, 'j>| s.into(), ) } pub(crate) fn take_value_owned<'j>( peek: Peek, parser: &mut Parser<'j>, tape: &mut Tape, recursion_limit: u8, allow_inf_nan: bool, allow_partial: PartialMode, ) -> JsonResult> { take_value( peek, parser, tape, recursion_limit, allow_inf_nan, allow_partial, &|s: StringOutput<'_, 'j>| Into::::into(s).into(), ) } fn take_value<'j, 's>( peek: Peek, parser: &mut Parser<'j>, tape: &mut Tape, recursion_limit: u8, allow_inf_nan: bool, allow_partial: PartialMode, create_cow: &impl Fn(StringOutput<'_, 'j>) -> Cow<'s, str>, ) -> JsonResult> { let partial_active = allow_partial.is_active(); match peek { Peek::True => { parser.consume_true()?; Ok(JsonValue::Bool(true)) } Peek::False => { parser.consume_false()?; Ok(JsonValue::Bool(false)) } Peek::Null => { parser.consume_null()?; Ok(JsonValue::Null) } Peek::String => { let s: StringOutput<'_, 'j> = parser.consume_string::(tape, allow_partial.allow_trailing_str())?; Ok(JsonValue::Str(create_cow(s))) } Peek::Array => { let array = Arc::new(SmallVec::new()); let peek_first = match parser.array_first() { Ok(Some(peek)) => peek, Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), Ok(None) | Err(_) => return Ok(JsonValue::Array(array)), }; take_value_recursive( peek_first, RecursedValue::Array(array), parser, tape, recursion_limit, allow_inf_nan, allow_partial, create_cow, ) } Peek::Object => { // same for objects let object = Arc::new(LazyIndexMap::new()); let first_key = match parser.object_first::(tape) { Ok(Some(first_key)) => first_key, Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => return Ok(JsonValue::Object(object)), }; let first_key = create_cow(first_key); match parser.peek() { Ok(peek) => take_value_recursive( peek, RecursedValue::Object { partial: object, next_key: first_key, }, parser, tape, recursion_limit, allow_inf_nan, allow_partial, create_cow, ), Err(e) if !(partial_active && e.allowed_if_partial()) => Err(e), _ => Ok(JsonValue::Object(object)), } } _ => { let n = parser.consume_number::(peek.into_inner(), allow_inf_nan); match n { Ok(NumberAny::Int(NumberInt::Int(int))) => Ok(JsonValue::Int(int)), #[cfg(feature = "num-bigint")] Ok(NumberAny::Int(NumberInt::BigInt(big_int))) => Ok(JsonValue::BigInt(big_int)), Ok(NumberAny::Float(float)) => Ok(JsonValue::Float(float)), Err(e) => { if !peek.is_num() { Err(json_error!(ExpectedSomeValue, parser.index)) } else { Err(e) } } } } } } enum RecursedValue<'s> { Array(JsonArray<'s>), Object { partial: JsonObject<'s>, next_key: Cow<'s, str>, }, } #[inline(never)] // this is an iterative algo called only from take_value, no point in inlining #[allow(clippy::too_many_lines)] // FIXME? #[allow(clippy::too_many_arguments)] fn take_value_recursive<'j, 's>( mut peek: Peek, mut current_recursion: RecursedValue<'s>, parser: &mut Parser<'j>, tape: &mut Tape, recursion_limit: u8, allow_inf_nan: bool, allow_partial: PartialMode, create_cow: &impl Fn(StringOutput<'_, 'j>) -> Cow<'s, str>, ) -> JsonResult> { let recursion_limit: usize = recursion_limit.into(); let mut recursion_stack: SmallVec<[RecursedValue; 8]> = SmallVec::new(); let partial_active = allow_partial.is_active(); macro_rules! push_recursion { ($next_peek:expr, $value:expr) => { peek = $next_peek; recursion_stack.push(std::mem::replace(&mut current_recursion, $value)); if recursion_stack.len() >= recursion_limit { return Err(json_error!(RecursionLimitExceeded, parser.index)); } }; } 'recursion: loop { let mut value = match &mut current_recursion { RecursedValue::Array(array) => { let array = Arc::get_mut(array).expect("sole writer"); loop { let result = match peek { Peek::True => parser.consume_true().map(|()| JsonValue::Bool(true)), Peek::False => parser.consume_false().map(|()| JsonValue::Bool(false)), Peek::Null => parser.consume_null().map(|()| JsonValue::Null), Peek::String => parser .consume_string::(tape, allow_partial.allow_trailing_str()) .map(|s| JsonValue::Str(create_cow(s))), Peek::Array => { let array = Arc::new(SmallVec::new()); match parser.array_first() { Ok(Some(first_peek)) => { push_recursion!(first_peek, RecursedValue::Array(array)); // immediately jump to process the first value in the array continue 'recursion; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }; Ok(JsonValue::Array(array)) } Peek::Object => { let object = Arc::new(LazyIndexMap::new()); match parser.object_first::(tape) { Ok(Some(first_key)) => match parser.peek() { Ok(peek) => { push_recursion!( peek, RecursedValue::Object { partial: object, next_key: create_cow(first_key) } ); continue 'recursion; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }, Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }; Ok(JsonValue::Object(object)) } _ => parser .consume_number::(peek.into_inner(), allow_inf_nan) .map_err(|e| { if !peek.is_num() { json_error!(ExpectedSomeValue, parser.index) } else { e } }) .map(|n| match n { NumberAny::Int(NumberInt::Int(int)) => JsonValue::Int(int), #[cfg(feature = "num-bigint")] NumberAny::Int(NumberInt::BigInt(big_int)) => JsonValue::BigInt(big_int), NumberAny::Float(float) => JsonValue::Float(float), }), }; let array = match result { Ok(value) => { // now try to advance position in the current array match parser.array_step() { Ok(Some(next_peek)) => { array.push(value); peek = next_peek; // array continuing continue; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }; let RecursedValue::Array(mut array) = current_recursion else { unreachable!("known to be in array recursion"); }; Arc::get_mut(&mut array).expect("sole writer to value").push(value); array } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => { let RecursedValue::Array(array) = current_recursion else { unreachable!("known to be in array recursion"); }; array } }; break JsonValue::Array(array); } } RecursedValue::Object { partial, next_key } => { let partial = Arc::get_mut(partial).expect("sole writer"); loop { let result = match peek { Peek::True => parser.consume_true().map(|()| JsonValue::Bool(true)), Peek::False => parser.consume_false().map(|()| JsonValue::Bool(false)), Peek::Null => parser.consume_null().map(|()| JsonValue::Null), Peek::String => parser .consume_string::(tape, allow_partial.allow_trailing_str()) .map(|s| JsonValue::Str(create_cow(s))), Peek::Array => { let array = Arc::new(SmallVec::new()); match parser.array_first() { Ok(Some(first_peek)) => { push_recursion!(first_peek, RecursedValue::Array(array)); // immediately jump to process the first value in the array continue 'recursion; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }; Ok(JsonValue::Array(array)) } Peek::Object => { let object = Arc::new(LazyIndexMap::new()); match parser.object_first::(tape) { Ok(Some(first_key)) => match parser.peek() { Ok(peek) => { push_recursion!( peek, RecursedValue::Object { partial: object, next_key: create_cow(first_key) } ); continue 'recursion; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }, Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }; Ok(JsonValue::Object(object)) } _ => parser .consume_number::(peek.into_inner(), allow_inf_nan) .map_err(|e| { if !peek.is_num() { json_error!(ExpectedSomeValue, parser.index) } else { e } }) .map(|n| match n { NumberAny::Int(NumberInt::Int(int)) => JsonValue::Int(int), #[cfg(feature = "num-bigint")] NumberAny::Int(NumberInt::BigInt(big_int)) => JsonValue::BigInt(big_int), NumberAny::Float(float) => JsonValue::Float(float), }), }; let object = match result { Ok(value) => { // now try to advance position in the current object match parser.object_step::(tape) { Ok(Some(yet_another_key)) => { match parser.peek() { Ok(next_peek) => { // object continuing partial.insert( std::mem::replace(next_key, create_cow(yet_another_key)), value, ); peek = next_peek; continue; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), } let RecursedValue::Object { mut partial, next_key } = current_recursion else { unreachable!("known to be in object recursion"); }; Arc::get_mut(&mut partial).expect("sole writer").insert(next_key, value); partial } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => { let RecursedValue::Object { partial, .. } = current_recursion else { unreachable!("known to be in object recursion"); }; partial } }; break JsonValue::Object(object); } } }; // current array or object has finished; // try to pop and continue with the parent peek = loop { if let Some(next_recursion) = recursion_stack.pop() { current_recursion = next_recursion; } else { return Ok(value); } value = match current_recursion { RecursedValue::Array(mut array) => { Arc::get_mut(&mut array).expect("sole writer").push(value); match parser.array_step() { Ok(Some(next_peek)) => { current_recursion = RecursedValue::Array(array); break next_peek; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), } JsonValue::Array(array) } RecursedValue::Object { mut partial, next_key } => { Arc::get_mut(&mut partial).expect("sole writer").insert(next_key, value); match parser.object_step::(tape) { Ok(Some(next_key)) => match parser.peek() { Ok(next_peek) => { current_recursion = RecursedValue::Object { partial, next_key: create_cow(next_key), }; break next_peek; } Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), }, Err(e) if !(partial_active && e.allowed_if_partial()) => return Err(e), _ => (), } JsonValue::Object(partial) } } }; } } /// like `take_value`, but nothing is returned, should be faster than `take_value`, useful when you don't care /// about the value, but just want to consume it pub(crate) fn take_value_skip( peek: Peek, parser: &mut Parser, tape: &mut Tape, recursion_limit: u8, allow_inf_nan: bool, ) -> JsonResult<()> { match peek { Peek::True => parser.consume_true(), Peek::False => parser.consume_false(), Peek::Null => parser.consume_null(), Peek::String => parser.consume_string::(tape, false).map(drop), Peek::Array => { if let Some(next_peek) = parser.array_first()? { take_value_skip_recursive(next_peek, ARRAY, parser, tape, recursion_limit, allow_inf_nan) } else { Ok(()) } } Peek::Object => { if parser.object_first::(tape)?.is_some() { take_value_skip_recursive(parser.peek()?, OBJECT, parser, tape, recursion_limit, allow_inf_nan) } else { Ok(()) } } _ => parser .consume_number::(peek.into_inner(), allow_inf_nan) .map(drop) .map_err(|e| { if !peek.is_num() { json_error!(ExpectedSomeValue, parser.index) } else { e } }), } } const ARRAY: bool = false; const OBJECT: bool = true; #[inline(never)] // this is an iterative algo called only from take_value_skip, no point in inlining fn take_value_skip_recursive( mut peek: Peek, mut current_recursion: bool, parser: &mut Parser, tape: &mut Tape, recursion_limit: u8, allow_inf_nan: bool, ) -> JsonResult<()> { let mut recursion_stack = bitvec::bitarr![0; 256]; let recursion_limit: usize = recursion_limit.into(); let mut current_recursion_depth = 0; macro_rules! push_recursion { ($next_peek:expr, $value:expr) => { peek = $next_peek; recursion_stack.set( current_recursion_depth, std::mem::replace(&mut current_recursion, $value), ); current_recursion_depth += 1; if current_recursion_depth >= recursion_limit { return Err(json_error!(RecursionLimitExceeded, parser.index)); } }; } loop { match peek { Peek::True => parser.consume_true()?, Peek::False => parser.consume_false()?, Peek::Null => parser.consume_null()?, Peek::String => { parser.consume_string::(tape, false)?; } Peek::Array => { if let Some(next_peek) = parser.array_first()? { push_recursion!(next_peek, ARRAY); // immediately jump to process the first value in the array continue; } } Peek::Object => { if parser.object_first::(tape)?.is_some() { push_recursion!(parser.peek()?, OBJECT); // immediately jump to process the first value in the object continue; } } _ => { parser .consume_number::(peek.into_inner(), allow_inf_nan) .map_err(|e| { if !peek.is_num() { json_error!(ExpectedSomeValue, parser.index) } else { e } })?; } }; // now try to advance position in the current array or object peek = loop { match current_recursion { ARRAY => { if let Some(next_peek) = parser.array_step()? { break next_peek; } } OBJECT => { if parser.object_step::(tape)?.is_some() { break parser.peek()?; } } } current_recursion_depth = match current_recursion_depth.checked_sub(1) { Some(r) => r, // no recursion left, we are done None => return Ok(()), }; current_recursion = recursion_stack[current_recursion_depth]; }; } } jiter-0.7.1/tests/main.rs000064400000000000000000001702771046102023000134200ustar 00000000000000use std::borrow::Cow; use std::fs::File; use std::io::Read; use std::iter; use std::str::FromStr; use std::sync::Arc; use num_bigint::BigInt; use smallvec::smallvec; use jiter::{ Jiter, JiterErrorType, JiterResult, JsonErrorType, JsonType, JsonValue, LazyIndexMap, LinePosition, NumberAny, NumberInt, PartialMode, Peek, }; fn json_vec(jiter: &mut Jiter, peek: Option) -> JiterResult> { let mut v = Vec::new(); let peek = match peek { Some(peek) => peek, None => jiter.peek()?, }; let position = jiter.current_position().short(); match peek { Peek::True => { jiter.known_bool(peek)?; v.push(format!("true @ {position}")); } Peek::False => { jiter.known_bool(peek)?; v.push(format!("false @ {position}")); } Peek::Null => { jiter.known_null()?; v.push(format!("null @ {position}")); } Peek::String => { let str = jiter.known_str()?; v.push(format!("String({str}) @ {position}")); } Peek::Array => { v.push(format!("[ @ {position}")); if let Some(peek) = jiter.known_array()? { let el_vec = json_vec(jiter, Some(peek))?; v.extend(el_vec); while let Some(peek) = jiter.array_step()? { let el_vec = json_vec(jiter, Some(peek))?; v.extend(el_vec); } } v.push("]".to_string()); } Peek::Object => { v.push(format!("{{ @ {position}")); if let Some(key) = jiter.known_object()? { v.push(format!("Key({key})")); let value_vec = json_vec(jiter, None)?; v.extend(value_vec); while let Some(key) = jiter.next_key()? { v.push(format!("Key({key}")); let value_vec = json_vec(jiter, None)?; v.extend(value_vec); } } v.push("}".to_string()); } _ => { let s = display_number(peek, jiter)?; v.push(s); } }; Ok(v) } fn display_number(peek: Peek, jiter: &mut Jiter) -> JiterResult { let position = jiter.current_position().short(); let number = jiter.known_number(peek)?; let s = match number { NumberAny::Int(NumberInt::Int(int)) => { format!("Int({int}) @ {position}") } NumberAny::Int(NumberInt::BigInt(big_int)) => { format!("BigInt({big_int}) @ {position}") } NumberAny::Float(float) => { format!("Float({float}) @ {position}") } }; Ok(s) } macro_rules! single_expect_ok_or_error { ($name:ident, ok, $json:literal, $expected:expr) => { paste::item! { #[allow(non_snake_case)] #[test] fn [< single_element_ok__ $name >]() { let mut jiter = Jiter::new($json.as_bytes()).with_allow_inf_nan(); let elements = json_vec(&mut jiter, None).unwrap().join(", "); assert_eq!(elements, $expected); jiter.finish().unwrap(); } } }; ($name:ident, err, $json:literal, $expected_error:literal) => { paste::item! { #[allow(non_snake_case)] #[test] fn [< single_element_xerror__ $name >]() { let mut jiter = Jiter::new($json.as_bytes()).with_allow_inf_nan(); let result = json_vec(&mut jiter, None); let first_value = match result { Ok(v) => v, Err(e) => { let position = jiter.error_position(e.index); // no wrong type errors, so unwrap the json error let error_type = match e.error_type { JiterErrorType::JsonError(ref e) => e, _ => panic!("unexpected error type: {:?}", e.error_type), }; let actual_error = format!("{:?} @ {}", error_type, position.short()); assert_eq!(actual_error, $expected_error); let full_error = format!("{} at {}", e.error_type, position); let serde_err = serde_json::from_str::($json).unwrap_err(); assert_eq!(full_error, serde_err.to_string()); return }, }; let result = jiter.finish(); match result { Ok(_) => panic!("unexpectedly valid at finish: {:?} -> {:?}", $json, first_value), Err(e) => { // to check to_string works, and for coverage e.to_string(); let position = jiter.error_position(e.index); // no wrong type errors, so unwrap the json error let error_type = match e.error_type { JiterErrorType::JsonError(e) => e, _ => panic!("unexpected error type: {:?}", e.error_type), }; let actual_error = format!("{:?} @ {}", error_type, position.short()); assert_eq!(actual_error, $expected_error); return }, } } } }; } macro_rules! single_tests { ($($name:ident: $ok_or_err:ident => $input:literal, $expected:literal;)*) => { $( single_expect_ok_or_error!($name, $ok_or_err, $input, $expected); )* } } single_tests! { string: ok => r#""foobar""#, "String(foobar) @ 1:1"; int_pos: ok => "1234", "Int(1234) @ 1:1"; int_zero: ok => "0", "Int(0) @ 1:1"; int_zero_space: ok => "0 ", "Int(0) @ 1:1"; int_neg: ok => "-1234", "Int(-1234) @ 1:1"; big_int: ok => "92233720368547758070", "BigInt(92233720368547758070) @ 1:1"; big_int_neg: ok => "-92233720368547758070", "BigInt(-92233720368547758070) @ 1:1"; big_int2: ok => "99999999999999999999999999999999999999999999999999", "BigInt(99999999999999999999999999999999999999999999999999) @ 1:1"; float_pos: ok => "12.34", "Float(12.34) @ 1:1"; float_neg: ok => "-12.34", "Float(-12.34) @ 1:1"; float_exp: ok => "2.2e10", "Float(22000000000) @ 1:1"; float_simple_exp: ok => "20e10", "Float(200000000000) @ 1:1"; float_exp_pos: ok => "2.2e+10", "Float(22000000000) @ 1:1"; float_exp_neg: ok => "2.2e-2", "Float(0.022) @ 1:1"; float_exp_zero: ok => "0.000e123", "Float(0) @ 1:1"; float_exp_massive1: ok => "2e2147483647", "Float(inf) @ 1:1"; float_exp_massive2: ok => "2e2147483648", "Float(inf) @ 1:1"; float_exp_massive3: ok => "2e2147483646", "Float(inf) @ 1:1"; float_exp_massive4: ok => "2e2147483646", "Float(inf) @ 1:1"; float_exp_massive5: ok => "18446744073709551615000.0", "Float(18446744073709552000000) @ 1:1"; float_exp_massive6: ok => "0.0E667", "Float(0) @ 1:1"; float_exp_tiny0: ok => "2e-2147483647", "Float(0) @ 1:1"; float_exp_tiny1: ok => "2e-2147483648", "Float(0) @ 1:1"; float_exp_tiny2: ok => "2e-2147483646", "Float(0) @ 1:1"; float_exp_tiny3: ok => "8e-7766666666", "Float(0) @ 1:1"; float_exp_tiny4: ok => "200.08e-76200000102", "Float(0) @ 1:1"; float_exp_tiny5: ok => "0e459", "Float(0) @ 1:1"; null: ok => "null", "null @ 1:1"; v_true: ok => "true", "true @ 1:1"; v_false: ok => "false", "false @ 1:1"; nan: ok => "NaN", "Float(NaN) @ 1:1"; infinity: ok => "Infinity", "Float(inf) @ 1:1"; neg_infinity: ok => "-Infinity", "Float(-inf) @ 1:1"; offset_true: ok => " true", "true @ 1:3"; empty: err => "", "EofWhileParsingValue @ 1:0"; string_unclosed: err => r#""foobar"#, "EofWhileParsingString @ 1:7"; bad_int_neg: err => "-", "EofWhileParsingValue @ 1:1"; bad_true1: err => "truX", "ExpectedSomeIdent @ 1:4"; bad_true2: err => "tru", "EofWhileParsingValue @ 1:3"; bad_true3: err => "trX", "ExpectedSomeIdent @ 1:3"; bad_false1: err => "falsX", "ExpectedSomeIdent @ 1:5"; bad_false2: err => "fals", "EofWhileParsingValue @ 1:4"; bad_null1: err => "nulX", "ExpectedSomeIdent @ 1:4"; bad_null2: err => "nul", "EofWhileParsingValue @ 1:3"; object_trailing_comma: err => r#"{"foo": "bar",}"#, "TrailingComma @ 1:15"; array_trailing_comma: err => r#"[1, 2,]"#, "TrailingComma @ 1:7"; array_wrong_char_after_comma: err => r#"[1, 2,;"#, "ExpectedSomeValue @ 1:7"; array_end_after_comma: err => "[9,", "EofWhileParsingValue @ 1:3"; object_wrong_char: err => r#"{"foo":42;"#, "ExpectedObjectCommaOrEnd @ 1:10"; object_wrong_char_after_comma: err => r#"{"foo":42,;"#, "KeyMustBeAString @ 1:11"; object_end_after_comma: err => r#"{"x": 9,"#, "EofWhileParsingValue @ 1:8"; object_end_after_colon: err => r#"{"":"#, "EofWhileParsingValue @ 1:4"; eof_while_parsing_object: err => r#"{"foo": 1"#, "EofWhileParsingObject @ 1:9"; expected_colon: err => r#"{"foo"1"#, "ExpectedColon @ 1:7"; array_bool: ok => "[true, false]", "[ @ 1:1, true @ 1:2, false @ 1:8, ]"; object_string: ok => r#"{"foo": "ba"}"#, "{ @ 1:1, Key(foo), String(ba) @ 1:9, }"; object_null: ok => r#"{"foo": null}"#, "{ @ 1:1, Key(foo), null @ 1:9, }"; object_bool_compact: ok => r#"{"foo":true}"#, "{ @ 1:1, Key(foo), true @ 1:8, }"; deep_array: ok => r#"[["Not too deep"]]"#, "[ @ 1:1, [ @ 1:2, String(Not too deep) @ 1:3, ], ]"; object_key_int: err => r#"{4: 4}"#, "KeyMustBeAString @ 1:2"; array_no_close: err => r#"["#, "EofWhileParsingList @ 1:1"; array_double_close: err => "[1]]", "TrailingCharacters @ 1:4"; invalid_float_e_end: err => "0E", "EofWhileParsingValue @ 1:2"; invalid_float_dot_end: err => "0.", "EofWhileParsingValue @ 1:2"; invalid_float_bracket: err => "2E[", "InvalidNumber @ 1:3"; trailing_char: err => "2z", "TrailingCharacters @ 1:2"; invalid_number_newline: err => "-\n", "InvalidNumber @ 2:0"; double_zero: err => "00", "InvalidNumber @ 1:2"; double_zero_one: err => "001", "InvalidNumber @ 1:2"; first_line: err => "[1 x]", "ExpectedListCommaOrEnd @ 1:4"; second_line: err => "[1\nx]", "ExpectedListCommaOrEnd @ 2:1"; floats_error: err => "06", "InvalidNumber @ 1:2"; unexpect_value: err => "[\u{16}\u{8}", "ExpectedSomeValue @ 1:2"; unexpect_value_xx: err => "xx", "ExpectedSomeValue @ 1:1"; } #[test] fn invalid_string_controls() { let json = "\"123\x08\x0c\n\r\t\""; let b = json.as_bytes(); let mut jiter = Jiter::new(b); let e = jiter.next_str().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ControlCharacterWhileParsingString) ); assert_eq!(e.index, 4); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 5)); assert_eq!( e.to_string(), "control character (\\u0000-\\u001F) found while parsing a string at index 4" ); } #[test] fn json_parse_str() { let json = r#" "foobar" "#; let data = json.as_bytes(); let mut jiter = Jiter::new(data); let peek = jiter.peek().unwrap(); assert_eq!(peek, Peek::String); assert_eq!(jiter.current_position(), LinePosition::new(1, 2)); let result_string = jiter.known_str().unwrap(); assert_eq!(result_string, "foobar"); jiter.finish().unwrap(); } macro_rules! string_tests { ($($name:ident: $json:literal => $expected:expr;)*) => { $( paste::item! { #[test] fn [< string_parsing_ $name >]() { let data = $json.as_bytes(); let mut jiter = Jiter::new(data); let str = jiter.next_str().unwrap(); assert_eq!(str, $expected); jiter.finish().unwrap(); } } )* } } string_tests! { simple: r#" "foobar" "# => "foobar"; newline: r#" "foo\nbar" "# => "foo\nbar"; pound_sign: r#" "\u00a3" "# => "£"; double_quote: r#" "\"" "# => r#"""#; backslash: r#""\\""# => r"\"; controls: "\"\\b\\f\\n\\r\\t\"" => "\u{8}\u{c}\n\r\t"; controls_python: "\"\\b\\f\\n\\r\\t\"" => "\x08\x0c\n\r\t"; // python notation for the same thing } macro_rules! string_test_errors { ($($name:ident: $json:literal => $expected_error:literal;)*) => { $( paste::item! { #[test] fn [< string_parsing_errors_ $name >]() { let data = $json.as_bytes(); let mut jiter = Jiter::new(data); match jiter.next_str() { Ok(t) => panic!("unexpectedly valid: {:?} -> {:?}", $json, t), Err(e) => { // to check to_string works, and for coverage e.to_string(); let error_type = match e.error_type { JiterErrorType::JsonError(e) => e, _ => panic!("unexpected error type: {:?}", e.error_type), }; let position = jiter.error_position(e.index); let actual_error = format!("{:?} @ {} - {}", error_type, e.index, position.short()); assert_eq!(actual_error, $expected_error); } } } } )* } } string_test_errors! { u4_unclosed: r#""\uxx"# => "EofWhileParsingString @ 5 - 1:5"; u4_unclosed2: r#""\udBdd"# => "EofWhileParsingString @ 7 - 1:7"; line_leading_surrogate: r#""\uddBd""# => "LoneLeadingSurrogateInHexEscape @ 6 - 1:7"; // needs the long tail so SIMD is used to parse the string line_leading_surrogate_tail: r#""\uddBd" "# => "LoneLeadingSurrogateInHexEscape @ 6 - 1:7"; unexpected_hex_escape1: r#""\udBd8x"# => "UnexpectedEndOfHexEscape @ 7 - 1:8"; unexpected_hex_escape2: r#""\udBd8xx"# => "UnexpectedEndOfHexEscape @ 7 - 1:8"; unexpected_hex_escape3: "\"un\\uDBBB\0" => "UnexpectedEndOfHexEscape @ 9 - 1:10"; unexpected_hex_escape4: r#""\ud8e0\e"# => "UnexpectedEndOfHexEscape @ 8 - 1:9"; newline_in_string: "\"\n" => "ControlCharacterWhileParsingString @ 1 - 2:0"; invalid_escape: r#" "\u12xx" "# => "InvalidEscape @ 6 - 1:7"; } #[test] fn invalid_unicode_code() { let json = vec![34, 92, 34, 206, 44, 163, 34]; // dbg!(json.iter().map(|b| *b as char).collect::>()); let mut jiter = Jiter::new(&json); let e = jiter.next_str().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::InvalidUnicodeCodePoint) ); assert_eq!(e.index, 3); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 4)); } #[test] fn invalid_control() { let json = vec![34, 206, 34]; // dbg!(json.iter().map(|b| *b as char).collect::>()); let mut jiter = Jiter::new(&json); let e = jiter.next_str().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::InvalidUnicodeCodePoint) ); assert_eq!(e.index, 2); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 3)); } #[test] fn utf8_range() { for c in 0u8..255u8 { let json = vec![34, c, 34]; // dbg!(c, json.iter().map(|b| *b as char).collect::>()); let jiter_result = JsonValue::parse(&json, false); match serde_json::from_slice::(&json) { Ok(serde_s) => { let jiter_value = jiter_result.unwrap(); assert_eq!(jiter_value, JsonValue::Str(serde_s.into())); } Err(serde_err) => { let jiter_err = jiter_result.unwrap_err(); let position = jiter_err.get_position(&json); let full_error = format!("{} at {position}", jiter_err.error_type); assert_eq!(full_error, serde_err.to_string()); } } } } #[test] fn utf8_range_long() { for c in 0u8..255u8 { let mut json = vec![b'"', b':', c]; json.extend(iter::repeat(b' ').take(20)); json.push(b'"'); // dbg!(c, json.iter().map(|b| *b as char).collect::>()); let jiter_result = JsonValue::parse(&json, false); match serde_json::from_slice::(&json) { Ok(serde_s) => { let jiter_value = jiter_result.unwrap(); assert_eq!(jiter_value, JsonValue::Str(serde_s.into())); } Err(serde_err) => { let jiter_err = jiter_result.unwrap_err(); // just compare the start of the error - https://github.com/serde-rs/json/issues/1110 assert!(serde_err.to_string().starts_with(&jiter_err.error_type.to_string())); } } } } #[test] fn nan_disallowed() { let json = r#"[NaN]"#; let mut jiter = Jiter::new(json.as_bytes()); assert_eq!(jiter.next_array().unwrap().unwrap(), Peek::NaN); let e = jiter.next_number().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); assert_eq!(e.index, 1); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 2)); } #[test] fn inf_disallowed() { let json = r#"[Infinity]"#; let mut jiter = Jiter::new(json.as_bytes()); assert_eq!(jiter.next_array().unwrap().unwrap(), Peek::Infinity); let e = jiter.next_number().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); assert_eq!(e.index, 1); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 2)); } #[test] fn inf_neg_disallowed() { let json = r#"[-Infinity]"#; let mut jiter = Jiter::new(json.as_bytes()); assert_eq!(jiter.next_array().unwrap().unwrap(), Peek::Minus); let e = jiter.next_number().unwrap_err(); assert_eq!(e.error_type, JiterErrorType::JsonError(JsonErrorType::InvalidNumber)); assert_eq!(e.index, 2); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 3)); } #[test] fn num_after() { let json = r#"2:"#; // `:` is 58, directly after 9 let mut jiter = Jiter::new(json.as_bytes()); let num = jiter.next_number().unwrap(); assert_eq!(num, NumberAny::Int(NumberInt::Int(2))); let e = jiter.finish().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::TrailingCharacters) ); assert_eq!(e.index, 1); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 2)); } #[test] fn num_before() { let json = r#"2/"#; // `/` is 47, directly before 0 let mut jiter = Jiter::new(json.as_bytes()); let num = jiter.next_number().unwrap(); assert_eq!(num, NumberAny::Int(NumberInt::Int(2))); let e = jiter.finish().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::TrailingCharacters) ); assert_eq!(e.index, 1); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 2)); } #[test] fn nan_disallowed_wrong_type() { let json = r#"[NaN]"#; let mut jiter = Jiter::new(json.as_bytes()); assert_eq!(jiter.next_array().unwrap().unwrap(), Peek::NaN); let e = jiter.next_str().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); assert_eq!(e.index, 1); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 2)); } #[test] fn value_allow_nan_inf() { let json = r#"[1, NaN, Infinity, -Infinity]"#; let value = JsonValue::parse(json.as_bytes(), true).unwrap(); let expected = JsonValue::Array(Arc::new(smallvec![ JsonValue::Int(1), JsonValue::Float(f64::NAN), JsonValue::Float(f64::INFINITY), JsonValue::Float(f64::NEG_INFINITY) ])); // compare debug since `f64::NAN != f64::NAN` assert_eq!(format!("{:?}", value), format!("{:?}", expected)); } #[test] fn value_disallow_nan() { let json = r#"[1, NaN]"#; let err = JsonValue::parse(json.as_bytes(), false).unwrap_err(); assert_eq!(err.error_type, JsonErrorType::ExpectedSomeValue); assert_eq!(err.description(json.as_bytes()), "expected value at line 1 column 5"); } #[test] fn key_str() { let json = r#"{"foo": "bar"}"#; let mut jiter = Jiter::new(json.as_bytes()); assert_eq!(jiter.next_object().unwrap().unwrap(), "foo"); assert_eq!(jiter.next_str().unwrap(), "bar"); assert!(jiter.next_key().unwrap().is_none()); jiter.finish().unwrap(); } #[test] fn key_bytes() { let json = r#"{"foo": "bar"}"#.as_bytes(); let mut jiter = Jiter::new(json); assert_eq!(jiter.next_object_bytes().unwrap().unwrap(), b"foo"); assert_eq!(jiter.next_bytes().unwrap(), *b"bar"); assert!(jiter.next_key().unwrap().is_none()); jiter.finish().unwrap(); } macro_rules! test_position { ($($name:ident: $data:literal, $find:literal, $expected:expr;)*) => { $( paste::item! { #[test] fn [< test_position_ $name >]() { assert_eq!(LinePosition::find($data, $find), $expected); } } )* } } test_position! { empty_zero: b"", 0, LinePosition::new(1, 0); empty_one: b"", 1, LinePosition::new(1, 0); first_line_zero: b"123456", 0, LinePosition::new(1, 1); first_line_first: b"123456", 1, LinePosition::new(1, 2); first_line_3rd: b"123456", 3, LinePosition::new(1, 4); first_line_5th: b"123456", 5, LinePosition::new(1, 6); first_line_last: b"123456", 6, LinePosition::new(1, 6); first_line_after: b"123456", 7, LinePosition::new(1, 6); second_line0: b"123456\n789", 6, LinePosition::new(2, 0); second_line1: b"123456\n789", 7, LinePosition::new(2, 1); second_line2: b"123456\n789", 8, LinePosition::new(2, 2); } #[test] fn parse_tiny_float() { let v = JsonValue::parse(b"8e-7766666666", false).unwrap(); assert_eq!(v, JsonValue::Float(0.0)); } #[test] fn parse_zero_float() { let v = JsonValue::parse(b"0.1234", false).unwrap(); match v { JsonValue::Float(v) => assert!((0.1234 - v).abs() < 1e-6), other => panic!("unexpected value: {other:?}"), }; } #[test] fn parse_zero_exp_float() { let v = JsonValue::parse(b"0.12e3", false).unwrap(); match v { JsonValue::Float(v) => assert!((120.0 - v).abs() < 1e-3), other => panic!("unexpected value: {other:?}"), }; } #[test] fn bad_lower_value_in_string() { let bytes: Vec = vec![34, 27, 32, 34]; let e = JsonValue::parse(&bytes, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::ControlCharacterWhileParsingString); assert_eq!(e.index, 1); assert_eq!(e.get_position(&bytes), LinePosition::new(1, 2)); } #[test] fn bad_high_order_string() { let bytes: Vec = vec![34, 32, 32, 210, 34]; let e = JsonValue::parse(&bytes, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::InvalidUnicodeCodePoint); assert_eq!(e.index, 4); assert_eq!(e.description(&bytes), "invalid unicode code point at line 1 column 5") } #[test] fn bad_high_order_string_tail() { // needs the long tail so SIMD is used to parse the string let mut bytes: Vec = vec![34, 32, 32, 210, 34]; bytes.extend(vec![b' '; 100]); // dbg!(json.iter().map(|b| *b as char).collect::>()); let e = JsonValue::parse(&bytes, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::InvalidUnicodeCodePoint); assert_eq!(e.index, 4); assert_eq!(e.description(&bytes), "invalid unicode code point at line 1 column 5") } #[test] fn invalid_escape_position() { // from fuzzing on #130 let bytes = br#""con(\u0trol character (\u000.00"#; let e = JsonValue::parse(bytes, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::InvalidEscape); assert_eq!(e.index, 8); assert_eq!(e.description(bytes), "invalid escape at line 1 column 9") } #[test] fn simd_string_sizes() { for i in 0..100 { let mut json = vec![b'"']; json.extend(iter::repeat(b'a').take(i)); json.push(b'"'); json.extend(iter::repeat(b' ').take(40)); let value = JsonValue::parse(&json, false).unwrap(); let s = match value { JsonValue::Str(s) => s, _ => panic!("unexpected value {value:?}"), }; assert_eq!(s.len(), i); assert!(s.as_bytes().iter().all(|&b| b == b'a')); } } #[test] fn udb_string() { let bytes: Vec = vec![34, 92, 117, 100, 66, 100, 100, 92, 117, 100, 70, 100, 100, 34]; let v = JsonValue::parse(&bytes, false).unwrap(); match v { JsonValue::Str(s) => assert_eq!(s.as_bytes(), [244, 135, 159, 157]), _ => panic!("unexpected value {v:?}"), } } #[test] fn json_value_object() { let json = r#"{"foo": "bar", "spam": [1, null, true]}"#; let v = JsonValue::parse(json.as_bytes(), false).unwrap(); let mut expected = LazyIndexMap::new(); expected.insert("foo".into(), JsonValue::Str("bar".into())); expected.insert( "spam".into(), JsonValue::Array(Arc::new(smallvec![ JsonValue::Int(1), JsonValue::Null, JsonValue::Bool(true) ])), ); assert_eq!(v, JsonValue::Object(Arc::new(expected))); } #[test] fn json_value_string() { let json = r#"["foo", "\u00a3", "\""]"#; let v = JsonValue::parse(json.as_bytes(), false).unwrap(); let expected = JsonValue::Array(Arc::new(smallvec![ JsonValue::Str("foo".into()), JsonValue::Str("£".into()), JsonValue::Str("\"".into()) ])); assert_eq!(v, expected); } #[test] fn parse_array_3() { let json = r#"[1 , null, true]"#; let v = JsonValue::parse(json.as_bytes(), false).unwrap(); assert_eq!( v, JsonValue::Array(Arc::new(smallvec![ JsonValue::Int(1), JsonValue::Null, JsonValue::Bool(true) ])) ); } #[test] fn parse_array_empty() { let json = r#"[ ]"#; let v = JsonValue::parse(json.as_bytes(), false).unwrap(); assert_eq!(v, JsonValue::Array(Arc::new(smallvec![]))); } #[test] fn repeat_trailing_array() { let json = b"[1]]"; let e = JsonValue::parse(json, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::TrailingCharacters); assert_eq!(e.get_position(json), LinePosition::new(1, 4)); } #[test] fn parse_value_nested() { let json = r#"[1, 2, [3, 4], 5, 6]"#; let v = JsonValue::parse(json.as_bytes(), false).unwrap(); assert_eq!( v, JsonValue::Array(Arc::new(smallvec![ JsonValue::Int(1), JsonValue::Int(2), JsonValue::Array(Arc::new(smallvec![JsonValue::Int(3), JsonValue::Int(4)])), JsonValue::Int(5), JsonValue::Int(6), ]),) ) } #[test] fn test_array_trailing() { let json = br#"[1, 2,]"#; let e = JsonValue::parse(json, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::TrailingComma); assert_eq!(e.get_position(json), LinePosition::new(1, 7)); assert_eq!(e.description(json), "trailing comma at line 1 column 7"); } fn read_file(path: &str) -> String { let mut file = File::open(path).unwrap(); let mut contents = String::new(); file.read_to_string(&mut contents).unwrap(); contents } #[test] fn pass1_to_value() { let json = read_file("./benches/pass1.json"); let json_data = json.as_bytes(); let v = JsonValue::parse(json_data, false).unwrap(); let array = match v { JsonValue::Array(array) => array, v => panic!("expected array, not {:?}", v), }; assert_eq!(array.len(), 20); assert_eq!(array[0], JsonValue::Str("JSON Test Pattern pass1".into())); } #[test] fn pass1_skip() { let json = read_file("./benches/pass1.json"); let json_data = json.as_bytes(); let mut jiter = Jiter::new(json_data); jiter.next_skip().unwrap(); jiter.finish().unwrap(); } #[test] fn escaped_string() { let json_data = br#""" \u0022 %22 0x22 034 """#; // let json_data = br#" "\n" "#; let v = JsonValue::parse(json_data, false).unwrap(); let s = match v { JsonValue::Str(s) => s, v => panic!("expected array, not {:?}", v), }; dbg!(s); // assert_eq!(s, r#"" " %22 0x22 034 ""#); } #[test] fn jiter_object() { let mut jiter = Jiter::new(br#"{"foo": "bar", "spam": [ 1, -2, "x"]}"#); assert_eq!(jiter.next_object().unwrap(), Some("foo")); assert_eq!(jiter.next_str().unwrap(), "bar"); assert_eq!(jiter.next_key().unwrap(), Some("spam")); assert_eq!(jiter.next_array().unwrap().unwrap().into_inner(), b'1'); assert_eq!(jiter.next_int().unwrap(), NumberInt::Int(1)); assert_eq!(jiter.array_step().unwrap(), Some(Peek::Minus)); assert_eq!(jiter.next_int().unwrap(), NumberInt::Int(-2)); assert_eq!(jiter.array_step().unwrap(), Some(Peek::String)); assert_eq!(jiter.next_bytes().unwrap(), b"x"); assert!(jiter.array_step().unwrap().is_none()); assert_eq!(jiter.next_key().unwrap(), None); jiter.finish().unwrap(); } #[test] fn jiter_inf() { let mut jiter = Jiter::new(b"[Infinity, -Infinity, NaN]").with_allow_inf_nan(); assert_eq!(jiter.next_array().unwrap(), Some(Peek::Infinity)); assert_eq!(jiter.next_float().unwrap(), f64::INFINITY); assert_eq!(jiter.array_step().unwrap(), Some(Peek::Minus)); assert_eq!(jiter.next_float().unwrap(), f64::NEG_INFINITY); assert_eq!(jiter.array_step().unwrap(), Some(Peek::NaN)); assert_eq!(jiter.next_float().unwrap().to_string(), "NaN"); assert_eq!(jiter.array_step().unwrap(), None); jiter.finish().unwrap(); } #[test] fn jiter_bool() { let mut jiter = Jiter::new(b"[true, false, null]"); assert_eq!(jiter.next_array().unwrap(), Some(Peek::True)); assert_eq!(jiter.next_bool().unwrap(), true); assert_eq!(jiter.array_step().unwrap(), Some(Peek::False)); assert_eq!(jiter.next_bool().unwrap(), false); assert_eq!(jiter.array_step().unwrap(), Some(Peek::Null)); jiter.next_null().unwrap(); assert_eq!(jiter.array_step().unwrap(), None); jiter.finish().unwrap(); } #[test] fn jiter_bytes() { let mut jiter = Jiter::new(br#"{"foo": "bar", "new-line": "\\n"}"#); assert_eq!(jiter.next_object_bytes().unwrap().unwrap(), b"foo"); assert_eq!(jiter.next_bytes().unwrap(), b"bar"); assert_eq!(jiter.next_key_bytes().unwrap().unwrap(), b"new-line"); assert_eq!(jiter.next_bytes().unwrap(), br#"\\n"#); assert_eq!(jiter.next_key_bytes().unwrap(), None); jiter.finish().unwrap(); } #[test] fn jiter_number() { let mut jiter = Jiter::new(br#" [1, 2.2, 3, 4.1, 5.67]"#); assert_eq!(jiter.next_array().unwrap().unwrap().into_inner(), b'1'); assert_eq!(jiter.next_int().unwrap(), NumberInt::Int(1)); assert_eq!(jiter.array_step().unwrap().unwrap().into_inner(), b'2'); assert_eq!(jiter.next_float().unwrap(), 2.2); assert_eq!(jiter.array_step().unwrap().unwrap().into_inner(), b'3'); let n = jiter.next_number().unwrap(); assert_eq!(n, NumberAny::Int(NumberInt::Int(3))); let n_float: f64 = n.into(); assert_eq!(n_float, 3.0); assert_eq!(jiter.array_step().unwrap().unwrap().into_inner(), b'4'); assert_eq!(jiter.next_number().unwrap(), NumberAny::Float(4.1)); assert_eq!(jiter.array_step().unwrap().unwrap().into_inner(), b'5'); assert_eq!(jiter.next_number_bytes().unwrap(), b"5.67"); assert_eq!(jiter.array_step().unwrap(), None); jiter.finish().unwrap(); } #[test] fn jiter_bytes_u_escape() { let mut jiter = Jiter::new(br#"{"foo": "xx \u00a3"}"#); assert_eq!(jiter.next_object_bytes().unwrap().unwrap(), b"foo"); assert_eq!(jiter.next_bytes().unwrap(), b"xx \\u00a3"); assert_eq!(jiter.next_key_bytes().unwrap(), None); jiter.finish().unwrap(); } #[test] fn jiter_empty_array() { let mut jiter = Jiter::new(b"[]"); assert_eq!(jiter.next_array().unwrap(), None); jiter.finish().unwrap(); } #[test] fn jiter_trailing_bracket() { let mut jiter = Jiter::new(b"[1]]"); assert_eq!(jiter.next_array().unwrap().unwrap().into_inner(), b'1'); assert_eq!(jiter.next_int().unwrap(), NumberInt::Int(1)); assert!(jiter.array_step().unwrap().is_none()); let e = jiter.finish().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::TrailingCharacters) ); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 4)); } #[test] fn jiter_wrong_type() { let mut jiter = Jiter::new(b" 123"); let e = jiter.next_str().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::WrongType { expected: JsonType::String, actual: JsonType::Int } ); assert_eq!(e.index, 1); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 2)); assert_eq!(e.to_string(), "expected string but found int at index 1"); assert_eq!( e.description(&jiter), "expected string but found int at line 1 column 2" ); } #[test] fn test_crazy_massive_int() { let mut s = "5".to_string(); s.push_str(&"0".repeat(500)); s.push_str("E-6666"); let mut jiter = Jiter::new(s.as_bytes()); assert_eq!(jiter.next_float().unwrap(), 0.0); jiter.finish().unwrap(); } #[test] fn unique_iter_object() { let value = JsonValue::parse(br#" {"x": 1, "x": 2} "#, false).unwrap(); if let JsonValue::Object(obj) = value { assert_eq!(obj.len(), 1); let mut unique = obj.iter_unique(); let first = unique.next().unwrap(); assert_eq!(first.0, "x"); assert_eq!(first.1, &JsonValue::Int(2)); assert!(unique.next().is_none()); } else { panic!("expected object"); } } #[test] fn unique_iter_object_repeat() { let value = JsonValue::parse(br#" {"x": 1, "x": 1} "#, false).unwrap(); if let JsonValue::Object(obj) = value { assert_eq!(obj.len(), 1); let mut unique = obj.iter_unique(); let first = unique.next().unwrap(); assert_eq!(first.0, "x"); assert_eq!(first.1, &JsonValue::Int(1)); assert!(unique.next().is_none()); } else { panic!("expected object"); } } #[test] fn test_recursion_limit() { let json = (0..2000).map(|_| "[").collect::(); let bytes = json.as_bytes(); let e = JsonValue::parse(bytes, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::RecursionLimitExceeded); assert_eq!(e.index, 201); assert_eq!(e.description(bytes), "recursion limit exceeded at line 1 column 202"); } #[test] fn test_recursion_limit_incr() { let json = (0..2000).map(|_| "[1]".to_string()).collect::>().join(", "); let json = format!("[{}]", json); let bytes = json.as_bytes(); let value = JsonValue::parse(bytes, false).unwrap(); match value { JsonValue::Array(v) => { assert_eq!(v.len(), 2000); } _ => panic!("expected array"), } } #[test] fn test_recursion_limit_skip_array() { let json = (0..2000).map(|_| "[ ").collect::(); let bytes = json.as_bytes(); let mut jiter = Jiter::new(bytes); let e = jiter.next_skip().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::RecursionLimitExceeded) ); let expected_index = JsonValue::parse(bytes, false).unwrap_err().index; assert_eq!(e.index, expected_index); assert_eq!( e.description(&jiter), format!("recursion limit exceeded at line 1 column {}", expected_index + 1) ); } #[test] fn test_recursion_limit_skip_object() { let json = (0..2000).map(|_| "{\"a\": ").collect::(); let bytes = json.as_bytes(); let mut jiter = Jiter::new(bytes); let e = jiter.next_skip().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::RecursionLimitExceeded) ); let expected_index = JsonValue::parse(bytes, false).unwrap_err().index; assert_eq!(e.index, expected_index); assert_eq!( e.description(&jiter), format!("recursion limit exceeded at line 1 column {}", expected_index + 1) ); } macro_rules! number_bytes { ($($name:ident: $json:literal => $expected:expr;)*) => { $( paste::item! { #[test] fn [< $name >]() { let mut jiter = Jiter::new($json); let bytes = jiter.next_number_bytes().unwrap(); assert_eq!(bytes, $expected); } } )* } } number_bytes! { number_bytes_int: b" 123 " => b"123"; number_bytes_float: b" 123.456 " => b"123.456"; number_bytes_zero_float: b" 0.456 " => b"0.456"; number_bytes_zero: b" 0" => b"0"; number_bytes_exp: b" 123e4 " => b"123e4"; number_bytes_exp_neg: b" 123e-4 " => b"123e-4"; number_bytes_exp_pos: b" 123e+4 " => b"123e+4"; number_bytes_exp_decimal: b" 123.456e4 " => b"123.456e4"; } #[test] fn test_4300_int() { let json = (0..4300).map(|_| "9".to_string()).collect::>().join(""); let bytes = json.as_bytes(); let value = JsonValue::parse(bytes, false).unwrap(); let expected_big_int = BigInt::from_str(&json).unwrap(); match value { JsonValue::BigInt(v) => { assert_eq!(v, expected_big_int); } _ => panic!("expected array, got {:?}", value), } } #[test] fn test_big_int_errs() { for json in [ &[b'9'; 4302][..], &[b'9'; 5900][..], // If the check is only done at the end, this will hang &[b'9'; 10usize.pow(7)][..], ] { let e = JsonValue::parse(json, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::NumberOutOfRange); assert_eq!(e.index, 4301); assert_eq!(e.description(json), "number out of range at line 1 column 4302"); } } #[test] fn lazy_index_map_pretty() { let mut map: LazyIndexMap, JsonValue<'_>> = LazyIndexMap::new(); assert!(map.is_empty()); map.insert("foo".into(), JsonValue::Str("bar".into())); assert!(!map.is_empty()); map.insert("spam".into(), JsonValue::Null); assert_eq!(format!("{map:?}"), r#"{"foo": Str("bar"), "spam": Null}"#); let keys = map.keys().collect::>(); assert_eq!(keys, vec!["foo", "spam"]); } #[test] fn lazy_index_map_small_get() { let mut map: LazyIndexMap, JsonValue<'_>> = LazyIndexMap::new(); map.insert("foo".into(), JsonValue::Str("bar".into())); map.insert("spam".into(), JsonValue::Null); assert_eq!(map.get("foo"), Some(&JsonValue::Str("bar".into()))); assert_eq!(map.get("spam"), Some(&JsonValue::Null)); assert_eq!(map.get("spam"), Some(&JsonValue::Null)); assert_eq!(map.get("foo"), Some(&JsonValue::Str("bar".into()))); assert_eq!(map.get("other"), None); } #[test] fn lazy_index_map_big_get() { let mut map: LazyIndexMap, JsonValue<'_>> = LazyIndexMap::new(); for i in 0..25 { let key = i.to_string().into(); map.insert(key, JsonValue::Int(i)); } assert_eq!(map.get("0"), Some(&JsonValue::Int(0))); assert_eq!(map.get("10"), Some(&JsonValue::Int(10))); assert_eq!(map.get("22"), Some(&JsonValue::Int(22))); assert_eq!(map.get("other"), None); } #[test] fn lazy_index_map_clone() { let mut map: LazyIndexMap, JsonValue<'_>> = LazyIndexMap::default(); map.insert("foo".into(), JsonValue::Str("bar".into())); map.insert("spam".into(), JsonValue::Null); assert_eq!(map.get("foo"), Some(&JsonValue::Str("bar".into()))); assert_eq!(map.get("spam"), Some(&JsonValue::Null)); assert_eq!(map.get("spam"), Some(&JsonValue::Null)); assert_eq!(map.get("foo"), Some(&JsonValue::Str("bar".into()))); assert_eq!(map.get("other"), None); let map2 = map.clone(); assert_eq!(map2.get("foo"), Some(&JsonValue::Str("bar".into()))); assert_eq!(map2.get("spam"), Some(&JsonValue::Null)); assert_eq!(map2.get("spam"), Some(&JsonValue::Null)); assert_eq!(map2.get("foo"), Some(&JsonValue::Str("bar".into()))); assert_eq!(map2.get("other"), None); } #[test] fn readme_jiter() { let json_data = r#" { "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] }"#; let mut jiter = Jiter::new(json_data.as_bytes()); assert_eq!(jiter.next_object().unwrap(), Some("name")); assert_eq!(jiter.next_str().unwrap(), "John Doe"); assert_eq!(jiter.next_key().unwrap(), Some("age")); assert_eq!(jiter.next_int().unwrap(), NumberInt::Int(43)); assert_eq!(jiter.next_key().unwrap(), Some("phones")); assert_eq!(jiter.next_array().unwrap(), Some(Peek::String)); // we know the next value is a string as we just asserted so assert_eq!(jiter.known_str().unwrap(), "+44 1234567"); assert_eq!(jiter.array_step().unwrap(), Some(Peek::String)); // same again assert_eq!(jiter.known_str().unwrap(), "+44 2345678"); // next we'll get `None` from `array_step` as the array is finished assert_eq!(jiter.array_step().unwrap(), None); // and `None` from `next_key` as the object is finished assert_eq!(jiter.next_key().unwrap(), None); // and we check there's nothing else in the input jiter.finish().unwrap(); } #[test] fn jiter_clone() { let json = r#"[1, 2]"#; let mut jiter1 = Jiter::new(json.as_bytes()); assert_eq!(jiter1.next_array().unwrap().unwrap().into_inner(), b'1'); let n = jiter1.next_number().unwrap(); assert_eq!(n, NumberAny::Int(NumberInt::Int(1))); let mut jiter2 = jiter1.clone(); assert_eq!(jiter1.array_step().unwrap().unwrap().into_inner(), b'2'); let n = jiter1.next_number().unwrap(); assert_eq!(n, NumberAny::Int(NumberInt::Int(2))); assert_eq!(jiter2.array_step().unwrap().unwrap().into_inner(), b'2'); let n = jiter2.next_number().unwrap(); assert_eq!(n, NumberAny::Int(NumberInt::Int(2))); assert_eq!(jiter1.array_step().unwrap(), None); assert_eq!(jiter2.array_step().unwrap(), None); jiter1.finish().unwrap(); jiter2.finish().unwrap(); } #[test] fn jiter_invalid_value() { let mut jiter = Jiter::new(b" bar"); let e = jiter.next_value().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); assert_eq!(e.index, 1); assert_eq!(jiter.error_position(e.index), LinePosition::new(1, 2)); } #[test] fn jiter_wrong_types() { macro_rules! expect_wrong_type_inner { ($actual:path, $input:expr, $method: ident, $expected:path) => { let mut jiter = Jiter::new($input); let result = jiter.$method(); if $actual == $expected || matches!(($actual, $expected), (JsonType::Int, JsonType::Float)) { // Type matches, or int input to float assert!(result.is_ok()); } else { let e = result.unwrap_err(); assert_eq!( e.error_type, JiterErrorType::WrongType { expected: $expected, actual: $actual, } ); } }; } macro_rules! expect_wrong_type { ($method:ident, $expected:path) => { expect_wrong_type_inner!(JsonType::Array, b"[]", $method, $expected); expect_wrong_type_inner!(JsonType::Bool, b"true", $method, $expected); expect_wrong_type_inner!(JsonType::Int, b"123", $method, $expected); expect_wrong_type_inner!(JsonType::Float, b"123.123", $method, $expected); expect_wrong_type_inner!(JsonType::Null, b"null", $method, $expected); expect_wrong_type_inner!(JsonType::Object, b"{}", $method, $expected); expect_wrong_type_inner!(JsonType::String, b"\"hello\"", $method, $expected); }; } expect_wrong_type!(next_array, JsonType::Array); expect_wrong_type!(next_bool, JsonType::Bool); expect_wrong_type!(next_bytes, JsonType::String); expect_wrong_type!(next_null, JsonType::Null); expect_wrong_type!(next_object, JsonType::Object); expect_wrong_type!(next_object_bytes, JsonType::Object); expect_wrong_type!(next_str, JsonType::String); expect_wrong_type!(next_int, JsonType::Int); expect_wrong_type!(next_float, JsonType::Float); } #[test] fn peek_debug() { assert_eq!(format!("{:?}", Peek::True), "True"); assert_eq!(format!("{:?}", Peek::False), "False"); assert_eq!(format!("{:?}", Peek::new(b'4')), "Peek('4')"); } #[test] fn jiter_invalid_numbers() { let mut jiter = Jiter::new(b" -a"); let peek = jiter.peek().unwrap(); let e = jiter.known_int(peek).unwrap_err(); assert_eq!(e.error_type, JiterErrorType::JsonError(JsonErrorType::InvalidNumber)); let e = jiter.known_float(peek).unwrap_err(); assert_eq!(e.error_type, JiterErrorType::JsonError(JsonErrorType::InvalidNumber)); let e = jiter.known_number(peek).unwrap_err(); assert_eq!(e.error_type, JiterErrorType::JsonError(JsonErrorType::InvalidNumber)); let e = jiter.next_number_bytes().unwrap_err(); assert_eq!(e.error_type, JiterErrorType::JsonError(JsonErrorType::InvalidNumber)); } #[test] fn jiter_invalid_numbers_expected_some_value() { let mut jiter = Jiter::new(b" bar"); let peek = jiter.peek().unwrap(); let e = jiter.known_int(peek).unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); let e = jiter.known_float(peek).unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); let e = jiter.known_number(peek).unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); let e = jiter.next_number_bytes().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); } fn value_owned() -> JsonValue<'static> { let s = r#" { "int": 1, "const": true, "float": 1.2, "array": [1, false, null]}"#.to_string(); JsonValue::parse_owned(s.as_bytes(), false, PartialMode::Off).unwrap() } #[test] fn test_owned_value() { let value = value_owned(); let obj = match value { JsonValue::Object(obj) => obj, _ => panic!("expected object"), }; assert_eq!(obj.get("int").unwrap(), &JsonValue::Int(1)); assert_eq!(obj.get("const").unwrap(), &JsonValue::Bool(true)); assert_eq!(obj.get("float").unwrap(), &JsonValue::Float(1.2)); let array = match obj.get("array").unwrap() { JsonValue::Array(array) => array, _ => panic!("expected array"), }; assert_eq!( array, &Arc::new(smallvec![JsonValue::Int(1), JsonValue::Bool(false), JsonValue::Null]) ); } fn value_into_static() -> JsonValue<'static> { let s = r#"{ "big_int": 92233720368547758070, "const": true, "float": 1.2, "array": [1, false, null, "x"]}"# .to_string(); let jiter = JsonValue::parse(s.as_bytes(), false).unwrap(); jiter.into_static() } #[test] fn test_into_static() { let value = crate::value_into_static(); let obj = match value { JsonValue::Object(obj) => obj, _ => panic!("expected object"), }; let expected_big_int = BigInt::from_str("92233720368547758070").unwrap(); assert_eq!(obj.get("big_int").unwrap(), &JsonValue::BigInt(expected_big_int)); assert_eq!(obj.get("const").unwrap(), &JsonValue::Bool(true)); assert_eq!(obj.get("float").unwrap(), &JsonValue::Float(1.2)); let array = match obj.get("array").unwrap() { JsonValue::Array(array) => array, _ => panic!("expected array"), }; assert_eq!( array, &Arc::new(smallvec![ JsonValue::Int(1), JsonValue::Bool(false), JsonValue::Null, JsonValue::Str("x".into()) ]) ); } #[test] fn jiter_next_value_borrowed() { let mut jiter = Jiter::new(br#" "v" "#); let v = jiter.next_value().unwrap(); let s = match v { JsonValue::Str(s) => s, _ => panic!("expected string"), }; assert_eq!(s, "v"); assert!(matches!(s, Cow::Borrowed(_))); } #[test] fn jiter_next_value_owned() { let mut jiter = Jiter::new(br#" "v" "#); let v = jiter.next_value_owned().unwrap(); let s = match v { JsonValue::Str(s) => s, _ => panic!("expected string"), }; assert_eq!(s, "v"); assert!(matches!(s, Cow::Owned(_))); } #[test] fn i64_max() { let json = "9223372036854775807"; assert_eq!(i64::MAX.to_string(), json); let v = JsonValue::parse(json.as_bytes(), false).unwrap(); match v { JsonValue::Int(v) => assert_eq!(v, i64::MAX), JsonValue::BigInt(v) => assert_eq!(v, i64::MAX.into()), _ => panic!("expected int"), } } #[test] fn test_all_int_lengths() { for int_size in 1..100 { let json = "9".repeat(int_size); let v = JsonValue::parse(json.as_bytes(), false).unwrap(); match v { JsonValue::Int(v) => assert_eq!(v.to_string(), json), JsonValue::BigInt(v) => assert_eq!(v.to_string(), json), _ => panic!("expected int"), } } } #[test] fn test_number_int_try_from_bytes() { let n: NumberInt = b"123".as_ref().try_into().unwrap(); assert_eq!(n, NumberInt::Int(123)); let n: NumberInt = b"0".as_ref().try_into().unwrap(); assert_eq!(n, NumberInt::Int(0)); let twenty_nines = "9".repeat(29); let n: NumberInt = twenty_nines.as_bytes().try_into().unwrap(); match n { NumberInt::BigInt(v) => assert_eq!(v.to_string(), twenty_nines), _ => panic!("expected big int"), } let e = NumberInt::try_from(b"x23".as_ref()).unwrap_err(); assert_eq!(e.to_string(), "invalid number at index 0"); let e = NumberInt::try_from(b"".as_ref()).unwrap_err(); assert_eq!(e.to_string(), "invalid number at index 0"); let e = NumberInt::try_from(b"2x3".as_ref()).unwrap_err(); assert_eq!(e.to_string(), "invalid number at index 1"); let e = NumberInt::try_from(b"123 ".as_ref()).unwrap_err(); assert_eq!(e.to_string(), "invalid number at index 3"); let e = NumberInt::try_from(b"123.1".as_ref()).unwrap_err(); assert_eq!(e.to_string(), "invalid number at index 3"); let e = NumberInt::try_from(b"0123".as_ref()).unwrap_err(); assert_eq!(e.to_string(), "invalid number at index 1"); let too_long = "9".repeat(4309); let e = NumberInt::try_from(too_long.as_bytes()).unwrap_err(); assert_eq!(e.to_string(), "number out of range at index 4301"); } #[test] fn jiter_skip_whole_object() { let mut jiter = Jiter::new(br#"{"x": 1}"#); jiter.next_skip().unwrap(); jiter.finish().unwrap(); } #[test] fn jiter_skip_in_object() { let mut jiter = Jiter::new( br#" { "is_bool": true, "is_int": 123, "is_float": 123.456, "is_str": "x", "is_array": [0, 1, 2, 3, "4", [], {}], "is_object": {"x": 1, "y": ["2"], "z": {}}, "last": 123 } "#, ); assert_eq!(jiter.next_object(), Ok(Some("is_bool"))); jiter.next_skip().unwrap(); assert_eq!(jiter.next_key(), Ok(Some("is_int"))); jiter.next_skip().unwrap(); assert_eq!(jiter.next_key(), Ok(Some("is_float"))); jiter.next_skip().unwrap(); assert_eq!(jiter.next_key(), Ok(Some("is_str"))); jiter.next_skip().unwrap(); assert_eq!(jiter.next_key(), Ok(Some("is_array"))); let peek = jiter.peek().unwrap(); let start = jiter.current_index(); jiter.known_skip(peek).unwrap(); let array_slice = jiter.slice_to_current(start); assert_eq!(array_slice, br#"[0, 1, 2, 3, "4", [], {}]"#); assert_eq!(jiter.next_key(), Ok(Some("is_object"))); jiter.next_skip().unwrap(); assert_eq!(jiter.next_key(), Ok(Some("last"))); assert_eq!(jiter.next_int(), Ok(NumberInt::Int(123))); assert_eq!(jiter.next_key().unwrap(), None); jiter.finish().unwrap(); } #[test] fn jiter_skip_in_array() { let mut jiter = Jiter::new( br#" [ true, false, null, NaN, Infinity, -Infinity, 123, 234.566, 345e45, "", "\u00a3", "\"", "last item" ] "#, ) .with_allow_inf_nan(); assert_eq!(jiter.next_array(), Ok(Some(Peek::True))); jiter.known_skip(Peek::True).unwrap(); // true assert_eq!(jiter.array_step(), Ok(Some(Peek::False))); jiter.known_skip(Peek::False).unwrap(); // false assert_eq!(jiter.array_step(), Ok(Some(Peek::Null))); jiter.known_skip(Peek::Null).unwrap(); // null assert_eq!(jiter.array_step(), Ok(Some(Peek::NaN))); jiter.known_skip(Peek::NaN).unwrap(); // NaN assert_eq!(jiter.array_step(), Ok(Some(Peek::Infinity))); jiter.known_skip(Peek::Infinity).unwrap(); // Infinity assert_eq!(jiter.array_step(), Ok(Some(Peek::Minus))); jiter.known_skip(Peek::Minus).unwrap(); // -Infinity assert_eq!(jiter.array_step(), Ok(Some(Peek::new(b'1')))); jiter.known_skip(Peek::new(b'1')).unwrap(); // 123 assert_eq!(jiter.array_step(), Ok(Some(Peek::new(b'2')))); jiter.known_skip(Peek::new(b'2')).unwrap(); // 234.566 assert_eq!(jiter.array_step(), Ok(Some(Peek::new(b'3')))); jiter.known_skip(Peek::new(b'3')).unwrap(); // 345e45 assert_eq!(jiter.array_step(), Ok(Some(Peek::String))); jiter.known_skip(Peek::String).unwrap(); // "" assert_eq!(jiter.array_step(), Ok(Some(Peek::String))); jiter.known_skip(Peek::String).unwrap(); // "\u00a3" assert_eq!(jiter.array_step(), Ok(Some(Peek::String))); jiter.known_skip(Peek::String).unwrap(); // "\"" assert_eq!(jiter.array_step(), Ok(Some(Peek::String))); assert_eq!(jiter.known_str(), Ok("last item")); assert_eq!(jiter.array_step(), Ok(None)); jiter.finish().unwrap(); } #[test] fn jiter_skip_backslash_strings() { let mut jiter = Jiter::new(br#" ["\"", "\n", "\t", "\u00a3", "\\"] "#); jiter.next_skip().unwrap(); jiter.finish().unwrap(); } #[test] fn jiter_skip_invalid_ident() { let mut jiter = Jiter::new(br#"trUe"#).with_allow_inf_nan(); let e = jiter.next_skip().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeIdent) ); } #[test] fn jiter_skip_invalid_string() { let mut jiter = Jiter::new(br#" "foo "#).with_allow_inf_nan(); let e = jiter.next_skip().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::EofWhileParsingString) ); } #[test] fn jiter_skip_invalid_int() { let mut jiter = Jiter::new(br#"01"#); let e = jiter.next_skip().unwrap_err(); assert_eq!(e.error_type, JiterErrorType::JsonError(JsonErrorType::InvalidNumber)); } #[test] fn jiter_skip_invalid_object() { let mut jiter = Jiter::new(br#"{{"#); let e = jiter.next_skip().unwrap_err(); assert_eq!(e.error_type, JiterErrorType::JsonError(JsonErrorType::KeyMustBeAString)); } #[test] fn jiter_skip_invalid_string_u() { let mut jiter = Jiter::new(br#" "\uddBd" "#); let e = jiter.next_skip().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::LoneLeadingSurrogateInHexEscape) ); } #[test] fn jiter_skip_invalid_nan() { let mut jiter = Jiter::new(b"NaN"); let e = jiter.next_skip().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::ExpectedSomeValue) ); } #[test] fn jiter_skip_invalid_string_high() { let json = vec![34, 92, 34, 206, 44, 163, 34]; let mut jiter = Jiter::new(&json); // NOTE this would raise an error with next_value etc, but next_skip does not check UTF-8 jiter.next_skip().unwrap(); jiter.finish().unwrap(); } #[test] fn jiter_skip_invalid_long_float() { let mut jiter = Jiter::new(br#"2121515572557277572557277e"#); let e = jiter.next_skip().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::EofWhileParsingValue) ); } #[test] fn jiter_value_invalid_long_float() { let e = JsonValue::parse(br#"2121515572557277572557277e"#, false).unwrap_err(); assert_eq!(e.error_type, JsonErrorType::EofWhileParsingValue); } #[test] fn jiter_partial_string() { let mut jiter = Jiter::new(br#"["foo"#).with_allow_partial_strings(); assert_eq!(jiter.next_array().unwrap(), Some(Peek::String)); assert_eq!(jiter.next_str().unwrap(), "foo"); let e = jiter.array_step().unwrap_err(); assert_eq!( e.error_type, JiterErrorType::JsonError(JsonErrorType::EofWhileParsingList) ); } #[test] fn test_unicode_roundtrip() { // '"中文"' let json_bytes = b"\"\\u4e2d\\u6587\""; let value = JsonValue::parse(json_bytes, false).unwrap(); let cow = match value { JsonValue::Str(s) => s, _ => panic!("expected string"), }; assert_eq!(cow, "中文"); assert!(matches!(cow, Cow::Owned(_))); } #[test] fn test_value_partial_array_on() { let json_bytes = br#"["string", true, null, 1, "foo"#; let value = JsonValue::parse_with_config(json_bytes, false, PartialMode::On).unwrap(); assert_eq!( value, JsonValue::Array(Arc::new(smallvec![ JsonValue::Str("string".into()), JsonValue::Bool(true), JsonValue::Null, JsonValue::Int(1), ])) ); // test all position in the string for i in 1..json_bytes.len() { let partial_json = &json_bytes[..i]; let value = JsonValue::parse_with_config(partial_json, false, PartialMode::On).unwrap(); assert!(matches!(value, JsonValue::Array(_))); } } #[test] fn test_value_partial_array_trailing_strings() { let json_bytes = br#"["string", true, null, 1, "foo"#; let value = JsonValue::parse_with_config(json_bytes, false, PartialMode::TrailingStrings).unwrap(); assert_eq!( value, JsonValue::Array(Arc::new(smallvec![ JsonValue::Str("string".into()), JsonValue::Bool(true), JsonValue::Null, JsonValue::Int(1), JsonValue::Str("foo".into()), ])) ); // test all position in the string for i in 1..json_bytes.len() { let partial_json = &json_bytes[..i]; let value = JsonValue::parse_with_config(partial_json, false, PartialMode::TrailingStrings).unwrap(); assert!(matches!(value, JsonValue::Array(_))); } } #[test] fn test_value_partial_object() { let json_bytes = br#"{"a": "value", "b": true, "c": false, "d": null, "e": 1, "f": 2.22, "g": ["#; let value = JsonValue::parse_with_config(json_bytes, false, PartialMode::TrailingStrings).unwrap(); let obj = match value { JsonValue::Object(obj) => obj, _ => panic!("expected object"), }; assert_eq!(obj.len(), 7); let pairs = obj.iter().collect::>(); assert_eq!(pairs[0].clone(), (Cow::Borrowed("a"), JsonValue::Str("value".into()))); assert_eq!(pairs[1].clone(), (Cow::Borrowed("b"), JsonValue::Bool(true))); assert_eq!(pairs[2].clone(), (Cow::Borrowed("c"), JsonValue::Bool(false))); assert_eq!(pairs[3].clone(), (Cow::Borrowed("d"), JsonValue::Null)); assert_eq!(pairs[4].clone(), (Cow::Borrowed("e"), JsonValue::Int(1))); assert_eq!(pairs[5].clone(), (Cow::Borrowed("f"), JsonValue::Float(2.22))); assert_eq!( pairs[6].clone(), (Cow::Borrowed("g"), JsonValue::Array(Arc::new(smallvec![]))) ); // test all position in the string for i in 1..json_bytes.len() { let partial_json = &json_bytes[..i]; let value = JsonValue::parse_with_config(partial_json, false, PartialMode::TrailingStrings).unwrap(); assert!(matches!(value, JsonValue::Object(_))); } } #[test] fn test_partial_pass1() { let json = read_file("./benches/pass1.json"); let json_bytes = json.as_bytes(); // test all position in the string for i in 1..json_bytes.len() { let partial_json = &json_bytes[..i]; let value = JsonValue::parse_with_config(partial_json, false, PartialMode::TrailingStrings).unwrap(); assert!(matches!(value, JsonValue::Array(_))); } } #[test] fn test_partial_medium_response() { let json = read_file("./benches/medium_response.json"); let json_bytes = json.as_bytes(); // test all position in the string for i in 1..json_bytes.len() { let partial_json = &json_bytes[..i]; let value = JsonValue::parse_with_config(partial_json, false, PartialMode::TrailingStrings).unwrap(); assert!(matches!(value, JsonValue::Object(_))); } } jiter-0.7.1/tests/python.rs000064400000000000000000000055051046102023000140040ustar 00000000000000use pyo3::prelude::*; use pyo3::types::PyString; use jiter::{pystring_fast_new, JsonValue, PythonParse, StringCacheMode}; #[test] fn test_to_py_object_numeric() { let value = JsonValue::parse( br#" { "int": 1, "bigint": 123456789012345678901234567890, "float": 1.2} "#, false, ) .unwrap(); Python::with_gil(|py| { let python_value = value.to_object(py); let string = python_value.bind(py).to_string(); assert_eq!( string, "{'int': 1, 'bigint': 123456789012345678901234567890, 'float': 1.2}" ); }) } #[test] fn test_to_py_object_other() { let value = JsonValue::parse( br#"["string", "\u00a3", true, false, null, NaN, Infinity, -Infinity]"#, true, ) .unwrap(); Python::with_gil(|py| { let python_value = value.to_object(py); let string = python_value.bind(py).to_string(); assert_eq!(string, "['string', '£', True, False, None, nan, inf, -inf]"); }) } #[test] fn test_cache_into() { Python::with_gil(|py| { let c: StringCacheMode = true.to_object(py).extract(py).unwrap(); assert!(matches!(c, StringCacheMode::All)); let c: StringCacheMode = false.to_object(py).extract(py).unwrap(); assert!(matches!(c, StringCacheMode::None)); let c: StringCacheMode = PyString::new_bound(py, "all").extract().unwrap(); assert!(matches!(c, StringCacheMode::All)); let c: StringCacheMode = PyString::new_bound(py, "keys").extract().unwrap(); assert!(matches!(c, StringCacheMode::Keys)); let c: StringCacheMode = PyString::new_bound(py, "none").extract().unwrap(); assert!(matches!(c, StringCacheMode::None)); let e = PyString::new_bound(py, "wrong") .extract::() .unwrap_err(); assert_eq!( e.to_string(), "ValueError: Invalid string cache mode, should be `'all'`, '`keys`', `'none`' or a `bool`" ); let e = 123.to_object(py).extract::(py).unwrap_err(); assert_eq!( e.to_string(), "TypeError: Invalid string cache mode, should be `'all'`, '`keys`', `'none`' or a `bool`" ); }) } #[test] fn test_pystring_fast_new_non_ascii() { let json = "£100 💩"; Python::with_gil(|py| { let s = pystring_fast_new(py, json, false); assert_eq!(s.to_string(), "£100 💩"); }) } #[test] fn test_pystring_fast_new_ascii() { let json = "100abc"; Python::with_gil(|py| { let s = pystring_fast_new(py, json, true); assert_eq!(s.to_string(), "100abc"); }) } #[test] fn test_python_parse_default() { Python::with_gil(|py| { let v = PythonParse::default().python_parse(py, b"[123]").unwrap(); assert_eq!(v.to_string(), "[123]"); }) }