[{"data":1,"prerenderedAt":18022},["ShallowReactive",2],{"post-gridsome-mise-a-jour-du-blog":3,"related-gridsome-mise-a-jour-du-blog":1707},{"id":4,"title":5,"author":6,"body":7,"category":1672,"categorySlug":1673,"date":1674,"description":1675,"excerpt":1676,"extension":194,"location":1697,"meta":1698,"navigation":216,"path":1699,"published":216,"seo":1700,"slug":1701,"stem":1702,"tags":1703,"timeToRead":288,"__hash__":1706},"posts\u002Fposts\u002FLogiciels\u002F2021-03-02-gridsome-mise-a-jour-du-blog.md","Mise à jour du blog vers gridsome","Ulrich Vandenhekke",{"type":8,"value":9,"toc":1663},"minimark",[10,27,42,45,48,68,71,76,79,82,112,115,119,122,150,153,156,186,189,224,227,292,295,364,368,375,383,386,494,512,580,583,623,630,703,706,765,774,777,844,847,930,933,937,940,943,946,949,959,962,969,1253,1262,1266,1269,1272,1283,1286,1316,1319,1322,1325,1333,1342,1351,1359,1362,1372,1558,1561,1614,1617,1621,1624,1635,1659],[11,12,13,14,19,20,26],"p",{},"J'avais migré en Janvier 2013 mon ",[15,16,18],"a",{"href":17},"\u002Fpages\u002Fmigration-to-pelican","blog vers Pelican"," en venant de\n",[15,21,25],{"href":22,"rel":23},"https:\u002F\u002Ffr.dotclear.org\u002F",[24],"nofollow","Dotclear",". Pelican est un générateur de site statique en Python. J'avais\nalors dû faire l'impasse sur les commentaires mais au bénéfice d'un site performant et avec une\nsurface d'attaque plus faible.",[11,28,29,30,35,36,41],{},"Plus tard, en décembre 2016, j'avais changé le thème pour ",[15,31,34],{"href":32,"rel":33},"https:\u002F\u002Fgithub.com\u002Falexandrevicenzi\u002FFlex",[24],"alexandrevicenzi\u002FFlex",".\nAujoud'hui je vais vous montrer la migration de mon blog vers ",[15,37,40],{"href":38,"rel":39},"https:\u002F\u002Fgridsome.org\u002F",[24],"Gridsome",".",[11,43,44],{},"Je reste sur un générateur de site statique car, j'aime l'idée d'un site à la fois rapide et\nimmuable tant que je ne décide pas de modifier le contenu mon blog. Alors pourquoi changer de Pelican\nvers Gridsome ?",[11,46,47],{},"Gridsome est un générateur de site statique écrit en Javascript. Il a la particularité de pouvoir générer\ndes pages depuis des fichiers au format Markdown mais aussi depuis des CMS Headless, ou de n'importe\nquelles autres API et ce grace à une API commune en GraphQL.",[11,49,50,51,62,63,41],{},"En plus de générer le site statique au format HTML, Gridsome fonctionne comme une SPA",[52,53,54],"sup",{},[15,55,61],{"href":56,"ariaDescribedBy":57,"dataFootnoteRef":59,"id":60},"#user-content-fn-1",[58],"footnote-label","","user-content-fnref-1","1",". Dans une SPA\nles pages sont générées côté client et sont mises à jour lors d'appel API pour récupérer les données. Ainsi\nseul le contenu modifié est rafraichit. Le framework Gridsome se base sur ",[15,64,67],{"href":65,"rel":66},"https:\u002F\u002Ffr.vuejs.org\u002F",[24],"Vue.Js",[11,69,70],{},"Ce qui m'a plus dans Gridsome, c'est l'utilisation de Vue.JS pour générer les pages statiques, mais aussi\nl'utilisation de GraphQL pour requêter le contenu des pages d'une même et unique façon.",[72,73,75],"h2",{"id":74},"alternatives","Alternatives",[11,77,78],{},"Lors de la migration de mon blog, je voulais une technologie basée sur Vue.Js, car c'est un framework que\nj'apprécie. Mais le plus important, c'est que j'avais besoin de changement (pour le plaisir quoi ;)).",[11,80,81],{},"Les générateurs de site statique en Vue.Js sont :",[83,84,85,93,100,107],"ul",{},[86,87,88],"li",{},[15,89,92],{"href":90,"rel":91},"https:\u002F\u002Fvuepress.vuejs.org\u002F",[24],"VuePress",[86,94,95],{},[15,96,99],{"href":97,"rel":98},"https:\u002F\u002Ffr.nuxtjs.org\u002F",[24],"Nuxt.js",[86,101,102],{},[15,103,106],{"href":104,"rel":105},"https:\u002F\u002Fsaber.land\u002F",[24],"Saber",[86,108,109],{},[15,110,40],{"href":38,"rel":111},[24],[11,113,114],{},"Je vous laisse regarder et vous faire votre avis sur les différents framework. J'ai surtout testé VuePress mais\nj'ai changé pour Gridsome quand j'ai vu la simplicité d'implémentation.",[72,116,118],{"id":117},"début-de-limplémentation","Début de l'implémentation",[11,120,121],{},"Je voulais changer de technologie, mais j'aimais bien le thème Pelican que j'utilisais. Je n'avais donc pas\nenvie de le changer. Je me suis imposé également les contraintes suivantes:",[83,123,124,127,138,141,144,147],{},[86,125,126],{},"Je ne voulais pas changer les différents chemins d'accès au site (tant que faire se peut).",[86,128,129,130],{},"Je voulais garder les fonctionnalités suivantes:\n",[83,131,132,135],{},[86,133,134],{},"Sitemap",[86,136,137],{},"Atom",[86,139,140],{},"J'avais des billets écrits en Markdown mais aussi 3 pages que je ne voulais pas réécrire en HTML",[86,142,143],{},"Garder le même thème",[86,145,146],{},"Avoir une page par catégorie et une page avec toutes les catégories",[86,148,149],{},"Avoir une page par tag et une page avec tous les tags",[11,151,152],{},"Je commence donc à initialiser un projet de zéro avec mes différents billets de blog, les pages (contact,\nanciens-projets, et contact) et les fichiers statiques (les images, les zips, ...).",[11,154,155],{},"J'ai du retravailler les différents billets de blog au format Markdown:",[83,157,158,161,179],{},[86,159,160],{},"J'ai dû déplacer les différents attributs du fichier pour les placer dans un frontmatter au format YAML.",[86,162,163,164,168,169,172,173,41,176,178],{},"Les fichiers ont un nom qui porte de l'information. Ainsi, le dossier dans lequel se trouve le fichier\nconstitue le nom de la catégorie, et le nom du fichier porte la date de publication et le ",[165,166,167],"code",{},"slug"," (utilisé\npour le chemin dans l'URL).",[170,171],"br",{},"Par exemple, avec le fichier: ",[165,174,175],{},"Logiciels\u002F2009-02-15_debian-lenny-est-sortie.md",[170,177],{},"Avec le changement de paradigme de Gridsome, j'ai dû intégrer ces différentes informations dans le frontmatter.",[86,180,181,182,185],{},"J'ai également du retravailler les emplacements de fichiers qui étaient préfixés dans Pelican\nde ",[165,183,184],{},"|static|\u002Fpublic\u002F...",". Dans Gridsome, il n'y pas de syntaxe particulière, juste le nom du fichier absolu.",[11,187,188],{},"Avant j'avais:",[190,191,195],"pre",{"className":192,"code":193,"language":194,"meta":59,"style":59},"language-md shiki shiki-themes one-dark-pro","Title: Debian Lenny est sortie\nTags: debian, kde\n\n![Logo](|static|\u002Fpublic\u002FLogiciels\u002Fdebian-lenny-est-sortie\u002Fdebian-logo.png)\n","md",[165,196,197,205,211,218],{"__ignoreMap":59},[198,199,202],"span",{"class":200,"line":201},"line",1,[198,203,204],{},"Title: Debian Lenny est sortie\n",[198,206,208],{"class":200,"line":207},2,[198,209,210],{},"Tags: debian, kde\n",[198,212,214],{"class":200,"line":213},3,[198,215,217],{"emptyLinePlaceholder":216},true,"\n",[198,219,221],{"class":200,"line":220},4,[198,222,223],{},"![Logo](|static|\u002Fpublic\u002FLogiciels\u002Fdebian-lenny-est-sortie\u002Fdebian-logo.png)\n",[11,225,226],{},"et j'ai corrigé cela en",[190,228,230],{"className":192,"code":229,"language":194,"meta":59,"style":59},"---\ntitle: Debian Lenny est sortie\ndate: 2009-02-15\ntags:\n  - debian\n  - kde\npublished: True\ncategory: Logiciels\n---\n\n![Logo](\u002FLogiciels\u002Fdebian-lenny-est-sortie\u002Fdebian-logo.png)\n",[165,231,232,237,242,247,252,258,264,270,276,281,286],{"__ignoreMap":59},[198,233,234],{"class":200,"line":201},[198,235,236],{},"---\n",[198,238,239],{"class":200,"line":207},[198,240,241],{},"title: Debian Lenny est sortie\n",[198,243,244],{"class":200,"line":213},[198,245,246],{},"date: 2009-02-15\n",[198,248,249],{"class":200,"line":220},[198,250,251],{},"tags:\n",[198,253,255],{"class":200,"line":254},5,[198,256,257],{},"  - debian\n",[198,259,261],{"class":200,"line":260},6,[198,262,263],{},"  - kde\n",[198,265,267],{"class":200,"line":266},7,[198,268,269],{},"published: True\n",[198,271,273],{"class":200,"line":272},8,[198,274,275],{},"category: Logiciels\n",[198,277,279],{"class":200,"line":278},9,[198,280,236],{},[198,282,284],{"class":200,"line":283},10,[198,285,217],{"emptyLinePlaceholder":216},[198,287,289],{"class":200,"line":288},11,[198,290,291],{},"![Logo](\u002FLogiciels\u002Fdebian-lenny-est-sortie\u002Fdebian-logo.png)\n",[11,293,294],{},"Afin de pouvoir reprendre mes fichiers au format markdown sans trop de modification, j'ai également installé les\nplugins remark suivants (ce sur quoi Gridsome se base pour transformer le Markdown en HTML) :",[83,296,297,303,337,352,358],{},[86,298,299,302],{},[165,300,301],{},"@gridsome\u002Fremark-prismjs",": pour effectuer une coloration syntaxique.",[86,304,305,308,309],{},[165,306,307],{},"remark-inline-links",": pour pouvoir gérer les liens inclus (qui sont ensuite reportés en bas du fichier)",[190,310,312],{"className":192,"code":311,"language":194,"meta":59,"style":59},"[foo], [foo][], [bar][foo].\n\n![foo], ![foo][], ![bar][foo].\n\n[foo]: http:\u002F\u002Fexample.com \"Example Domain\"\n",[165,313,314,319,323,328,332],{"__ignoreMap":59},[198,315,316],{"class":200,"line":201},[198,317,318],{},"[foo], [foo][], [bar][foo].\n",[198,320,321],{"class":200,"line":207},[198,322,217],{"emptyLinePlaceholder":216},[198,324,325],{"class":200,"line":213},[198,326,327],{},"![foo], ![foo][], ![bar][foo].\n",[198,329,330],{"class":200,"line":220},[198,331,217],{"emptyLinePlaceholder":216},[198,333,334],{"class":200,"line":254},[198,335,336],{},"[foo]: http:\u002F\u002Fexample.com \"Example Domain\"\n",[86,338,339,342,343],{},[165,340,341],{},"remark-attr",": pour pouvoir ajouter des attributs à une image ou à un objet.",[190,344,346],{"className":192,"code":345,"language":194,"meta":59,"style":59},"![alt](img){attrs} \u002F ![alt](img){ height=50 }\n",[165,347,348],{"__ignoreMap":59},[198,349,350],{"class":200,"line":201},[198,351,345],{},[86,353,354,357],{},[165,355,356],{},"remark-toc",": pour pouvoir ajouter un sommaire à certain billet.",[86,359,360,363],{},[165,361,362],{},"remark-footnotes",": pour pouvoir ajouter les footnotes.",[72,365,367],{"id":366},"création-du-thème","Création du thème",[11,369,370,371,374],{},"Le thème Pelican de mon blog est basé sur ",[15,372,34],{"href":32,"rel":373},[24],".\nJ'ai donc créé un thème gridsome en reprenant le style du thème précédent mais en convertissant les templates\nen Vue.Js.",[11,376,377,378,41],{},"J'ai donc créé ce thème que j'ai mis à disposition ici : ",[15,379,382],{"href":380,"rel":381},"https:\u002F\u002Fgithub.com\u002Fphoenix741\u002Fgridsome-flex-markdown-starter",[24],"phoenix741\u002Fgridsome-flex-markdown-starter",[11,384,385],{},"Voici la configuration de gridsome que j'ai implémenté pour reconstruire le thème du blog:",[190,387,391],{"className":388,"code":389,"language":390,"meta":59,"style":59},"language-js shiki shiki-themes one-dark-pro","  plugins: [\n    {\n      use: \"@gridsome\u002Fsource-filesystem\",\n      options: {\n        baseDir: \"content\u002Fposts\",\n        path: \"**\u002F*.md\",\n        typeName: \"Post\",\n        refs: {\n          tags: {\n            typeName: \"Tag\",\n            create: true,\n          },\n          category: {\n            typeName: \"Category\",\n            create: true,\n          },\n        },\n      },\n    },\n","js",[165,392,393,398,403,408,413,418,423,428,433,438,443,448,454,460,466,471,476,482,488],{"__ignoreMap":59},[198,394,395],{"class":200,"line":201},[198,396,397],{},"  plugins: [\n",[198,399,400],{"class":200,"line":207},[198,401,402],{},"    {\n",[198,404,405],{"class":200,"line":213},[198,406,407],{},"      use: \"@gridsome\u002Fsource-filesystem\",\n",[198,409,410],{"class":200,"line":220},[198,411,412],{},"      options: {\n",[198,414,415],{"class":200,"line":254},[198,416,417],{},"        baseDir: \"content\u002Fposts\",\n",[198,419,420],{"class":200,"line":260},[198,421,422],{},"        path: \"**\u002F*.md\",\n",[198,424,425],{"class":200,"line":266},[198,426,427],{},"        typeName: \"Post\",\n",[198,429,430],{"class":200,"line":272},[198,431,432],{},"        refs: {\n",[198,434,435],{"class":200,"line":278},[198,436,437],{},"          tags: {\n",[198,439,440],{"class":200,"line":283},[198,441,442],{},"            typeName: \"Tag\",\n",[198,444,445],{"class":200,"line":288},[198,446,447],{},"            create: true,\n",[198,449,451],{"class":200,"line":450},12,[198,452,453],{},"          },\n",[198,455,457],{"class":200,"line":456},13,[198,458,459],{},"          category: {\n",[198,461,463],{"class":200,"line":462},14,[198,464,465],{},"            typeName: \"Category\",\n",[198,467,469],{"class":200,"line":468},15,[198,470,447],{},[198,472,474],{"class":200,"line":473},16,[198,475,453],{},[198,477,479],{"class":200,"line":478},17,[198,480,481],{},"        },\n",[198,483,485],{"class":200,"line":484},18,[198,486,487],{},"      },\n",[198,489,491],{"class":200,"line":490},19,[198,492,493],{},"    },\n",[11,495,496,497,500,501,504,505,508,509,41],{},"Pour commencer, on utilise le module ",[165,498,499],{},"@gridsome\u002Fsource-filesystem"," pour lire le contenu du dossier\n",[165,502,503],{},"content\u002Fposts\u002F**\u002F*.md",". On définit au plugin comment on créé les ",[165,506,507],{},"Tag"," et les ",[165,510,511],{},"Category",[190,513,515],{"className":388,"code":514,"language":390,"meta":59,"style":59},"    {\n      use: \"@microflash\u002Fgridsome-plugin-feed\",\n      options: {\n        contentTypes: [\"Post\"],\n        rss: {\n          enabled: true,\n          output: \"\u002Ffeed.xml\",\n        },\n        atom: {\n          enabled: true,\n          output: \"\u002Ffeed.atom\",\n        },\n      },\n    },\n",[165,516,517,521,526,530,535,540,545,550,554,559,563,568,572,576],{"__ignoreMap":59},[198,518,519],{"class":200,"line":201},[198,520,402],{},[198,522,523],{"class":200,"line":207},[198,524,525],{},"      use: \"@microflash\u002Fgridsome-plugin-feed\",\n",[198,527,528],{"class":200,"line":213},[198,529,412],{},[198,531,532],{"class":200,"line":220},[198,533,534],{},"        contentTypes: [\"Post\"],\n",[198,536,537],{"class":200,"line":254},[198,538,539],{},"        rss: {\n",[198,541,542],{"class":200,"line":260},[198,543,544],{},"          enabled: true,\n",[198,546,547],{"class":200,"line":266},[198,548,549],{},"          output: \"\u002Ffeed.xml\",\n",[198,551,552],{"class":200,"line":272},[198,553,481],{},[198,555,556],{"class":200,"line":278},[198,557,558],{},"        atom: {\n",[198,560,561],{"class":200,"line":283},[198,562,544],{},[198,564,565],{"class":200,"line":288},[198,566,567],{},"          output: \"\u002Ffeed.atom\",\n",[198,569,570],{"class":200,"line":450},[198,571,481],{},[198,573,574],{"class":200,"line":456},[198,575,487],{},[198,577,578],{"class":200,"line":462},[198,579,493],{},[11,581,582],{},"Ensuite on crée un flux RSS et un flux ATOM avec ces posts, afin que les lecteurs qui utilisent\nencore un lecteur de flux, ou les programmes qui s'abonnent directement à mon site fonctionnent encore.",[190,584,586],{"className":388,"code":585,"language":390,"meta":59,"style":59},"    {\n      use: \"@gridsome\u002Fsource-filesystem\",\n      options: {\n        baseDir: \"content\u002Fpages\",\n        path: \"*.md\",\n        typeName: \"BlogPage\",\n      },\n    },\n",[165,587,588,592,596,600,605,610,615,619],{"__ignoreMap":59},[198,589,590],{"class":200,"line":201},[198,591,402],{},[198,593,594],{"class":200,"line":207},[198,595,407],{},[198,597,598],{"class":200,"line":213},[198,599,412],{},[198,601,602],{"class":200,"line":220},[198,603,604],{},"        baseDir: \"content\u002Fpages\",\n",[198,606,607],{"class":200,"line":254},[198,608,609],{},"        path: \"*.md\",\n",[198,611,612],{"class":200,"line":260},[198,613,614],{},"        typeName: \"BlogPage\",\n",[198,616,617],{"class":200,"line":266},[198,618,487],{},[198,620,621],{"class":200,"line":272},[198,622,493],{},[11,624,625,626,629],{},"On recommence avec les pages du site, que l'on type comme ",[165,627,628],{},"BlogPage",". Ces pages ne seront\npas accessibles via des catégories ou des pages. Il faudra faire des liens directement vers les\npages depuis un menu.",[190,631,633],{"className":388,"code":632,"language":390,"meta":59,"style":59},"    {\n      use: \"@gridsome\u002Fplugin-sitemap\",\n      options: {\n        config: {\n          \"\u002Fpost\u002F*\": {\n            changefreq: \"weekly\",\n            priority: 0.5,\n          },\n          \"\u002Fpage\u002F*\": {\n            changefreq: \"monthly\",\n            priority: 0.7,\n          },\n        },\n      },\n    },\n",[165,634,635,639,644,648,653,658,663,668,672,677,682,687,691,695,699],{"__ignoreMap":59},[198,636,637],{"class":200,"line":201},[198,638,402],{},[198,640,641],{"class":200,"line":207},[198,642,643],{},"      use: \"@gridsome\u002Fplugin-sitemap\",\n",[198,645,646],{"class":200,"line":213},[198,647,412],{},[198,649,650],{"class":200,"line":220},[198,651,652],{},"        config: {\n",[198,654,655],{"class":200,"line":254},[198,656,657],{},"          \"\u002Fpost\u002F*\": {\n",[198,659,660],{"class":200,"line":260},[198,661,662],{},"            changefreq: \"weekly\",\n",[198,664,665],{"class":200,"line":266},[198,666,667],{},"            priority: 0.5,\n",[198,669,670],{"class":200,"line":272},[198,671,453],{},[198,673,674],{"class":200,"line":278},[198,675,676],{},"          \"\u002Fpage\u002F*\": {\n",[198,678,679],{"class":200,"line":283},[198,680,681],{},"            changefreq: \"monthly\",\n",[198,683,684],{"class":200,"line":288},[198,685,686],{},"            priority: 0.7,\n",[198,688,689],{"class":200,"line":450},[198,690,453],{},[198,692,693],{"class":200,"line":456},[198,694,481],{},[198,696,697],{"class":200,"line":462},[198,698,487],{},[198,700,701],{"class":200,"line":468},[198,702,493],{},[11,704,705],{},"Après, on définit un sitemap qui pourra être utilisé par les moteurs de recherches.",[190,707,709],{"className":388,"code":708,"language":390,"meta":59,"style":59},"  ],\n  templates: {\n    Post: (obj) => {\n      return (\n        \"\u002Fpost\u002F\" + obj.fileInfo.name.replace(\u002F^\\d{4}-\\d{2}-\\d{2}[_\\-]\u002F, \"\")\n      );\n    },\n    BlogPage: \"\u002Fpages\u002F:fileInfo__name\",\n    Tag: \"\u002Ftag\u002F:id\",\n    Category: \"\u002Fcategory\u002F:title\",\n  },\n",[165,710,711,716,721,726,731,736,741,745,750,755,760],{"__ignoreMap":59},[198,712,713],{"class":200,"line":201},[198,714,715],{},"  ],\n",[198,717,718],{"class":200,"line":207},[198,719,720],{},"  templates: {\n",[198,722,723],{"class":200,"line":213},[198,724,725],{},"    Post: (obj) => {\n",[198,727,728],{"class":200,"line":220},[198,729,730],{},"      return (\n",[198,732,733],{"class":200,"line":254},[198,734,735],{},"        \"\u002Fpost\u002F\" + obj.fileInfo.name.replace(\u002F^\\d{4}-\\d{2}-\\d{2}[_\\-]\u002F, \"\")\n",[198,737,738],{"class":200,"line":260},[198,739,740],{},"      );\n",[198,742,743],{"class":200,"line":266},[198,744,493],{},[198,746,747],{"class":200,"line":272},[198,748,749],{},"    BlogPage: \"\u002Fpages\u002F:fileInfo__name\",\n",[198,751,752],{"class":200,"line":278},[198,753,754],{},"    Tag: \"\u002Ftag\u002F:id\",\n",[198,756,757],{"class":200,"line":283},[198,758,759],{},"    Category: \"\u002Fcategory\u002F:title\",\n",[198,761,762],{"class":200,"line":288},[198,763,764],{},"  },\n",[11,766,767,768,770,771,773],{},"On définit les différentes chemins d'accès pour nos billets, nos pages, nos ",[165,769,507],{},",\net nos ",[165,772,511],{},". Comme je ne souhaite pas changer les adresses de mes billets sur mon site,\nj'ai défini les adresses sur les mêmes chemins que mon blog sous Pelican.",[11,775,776],{},"Comme les noms des fichiers des billets portent la date et le nom du billet, pour retrouver\nle nom du chemin d'origine, je supprime la date pour la génération du chemin.",[190,778,780],{"className":388,"code":779,"language":390,"meta":59,"style":59},"  transformers: {\n    remark: {\n      plugins: [\n        [\"@gridsome\u002Fremark-prismjs\", { showLineNumbers: true }],\n        \"remark-inline-links\",\n        [\"remark-toc\", { heading: \"sommaire\" }],\n        \"remark-attr\",\n      ],\n      config: {\n        footnotes: true,\n      },\n    },\n  },\n",[165,781,782,787,792,797,802,807,812,817,822,827,832,836,840],{"__ignoreMap":59},[198,783,784],{"class":200,"line":201},[198,785,786],{},"  transformers: {\n",[198,788,789],{"class":200,"line":207},[198,790,791],{},"    remark: {\n",[198,793,794],{"class":200,"line":213},[198,795,796],{},"      plugins: [\n",[198,798,799],{"class":200,"line":220},[198,800,801],{},"        [\"@gridsome\u002Fremark-prismjs\", { showLineNumbers: true }],\n",[198,803,804],{"class":200,"line":254},[198,805,806],{},"        \"remark-inline-links\",\n",[198,808,809],{"class":200,"line":260},[198,810,811],{},"        [\"remark-toc\", { heading: \"sommaire\" }],\n",[198,813,814],{"class":200,"line":266},[198,815,816],{},"        \"remark-attr\",\n",[198,818,819],{"class":200,"line":272},[198,820,821],{},"      ],\n",[198,823,824],{"class":200,"line":278},[198,825,826],{},"      config: {\n",[198,828,829],{"class":200,"line":283},[198,830,831],{},"        footnotes: true,\n",[198,833,834],{"class":200,"line":288},[198,835,487],{},[198,837,838],{"class":200,"line":450},[198,839,493],{},[198,841,842],{"class":200,"line":456},[198,843,764],{},[11,845,846],{},"Enfin, je définis les différents plugins dont j'ai besoin pour que mes différents billets\nfonctionnent correctement.",[190,848,850],{"className":388,"code":849,"language":390,"meta":59,"style":59},"  permalinks: {\n    trailingSlash: \"false\",\n    slugify: {\n      use: \"@sindresorhus\u002Fslugify\",\n      options: {\n        decamelize: false,\n      },\n    },\n  },\n  css: {\n    loaderOptions: {\n      less: {\n        \u002F\u002F options here will be passed to less-loader\n      },\n    },\n  },\n};\n",[165,851,852,857,862,867,872,876,881,885,889,893,898,903,908,913,917,921,925],{"__ignoreMap":59},[198,853,854],{"class":200,"line":201},[198,855,856],{},"  permalinks: {\n",[198,858,859],{"class":200,"line":207},[198,860,861],{},"    trailingSlash: \"false\",\n",[198,863,864],{"class":200,"line":213},[198,865,866],{},"    slugify: {\n",[198,868,869],{"class":200,"line":220},[198,870,871],{},"      use: \"@sindresorhus\u002Fslugify\",\n",[198,873,874],{"class":200,"line":254},[198,875,412],{},[198,877,878],{"class":200,"line":260},[198,879,880],{},"        decamelize: false,\n",[198,882,883],{"class":200,"line":266},[198,884,487],{},[198,886,887],{"class":200,"line":272},[198,888,493],{},[198,890,891],{"class":200,"line":278},[198,892,764],{},[198,894,895],{"class":200,"line":283},[198,896,897],{},"  css: {\n",[198,899,900],{"class":200,"line":288},[198,901,902],{},"    loaderOptions: {\n",[198,904,905],{"class":200,"line":450},[198,906,907],{},"      less: {\n",[198,909,910],{"class":200,"line":456},[198,911,912],{},"        \u002F\u002F options here will be passed to less-loader\n",[198,914,915],{"class":200,"line":462},[198,916,487],{},[198,918,919],{"class":200,"line":468},[198,920,493],{},[198,922,923],{"class":200,"line":473},[198,924,764],{},[198,926,927],{"class":200,"line":478},[198,928,929],{},"};\n",[11,931,932],{},"Je termine par modifier la manière dont Gridsome transforme les adresses, toujours pour\nque les chemins de mon blog ne changent pas.",[72,934,936],{"id":935},"développement-des-pages","Développement des pages",[11,938,939],{},"Viens ensuite l'écriture des différentes pages, composants et layout pour définir notre thème.\nLe plus compliqué, c'est que le résumé (excerpt) fourni par Gridsome supprime le rendu HTML et\nles retours chariots.",[11,941,942],{},"Je voulais que sur la page principale de mon application, je puisse générer un résumé de chaque\nbillet avec le texte et le rendu original du billet.",[11,944,945],{},"Pour cela malheureusement Gridsome ne fournit pas une manière simple de générer un résumé. Je vais\nvous présenter mon implémentation afin d'avoir un résumé au format Markdown.",[11,947,948],{},"Ma première version a été de créer à partir de contenu HTML le résumé dans un composant vue dédié.\nLors de la génération des pages statiques, le résultat était comme attendu. Par contre lors du\nchangement des pages (en mode SPA), le billet intégral du blog est chargé, pour être tronqué dynamiquement. Ce\nqui est long et pas performant quand cela arrive sur 10 billets à la suite. J'ai donc modifié le système pour\ngénérer les pages côté serveur.",[11,950,951,952,955,956,958],{},"Pour cela j'ai donc modifié le fichier ",[165,953,954],{},"gridsome.server.js",". Le problème, c'est que Gridsome ne permet\npas d'appeler un transformer (remark) directement, et ne permet pas de convertir un text en markdown (autrement\nqu'en passant par le plugin ",[165,957,499],{},").",[11,960,961],{},"J'ai donc dû implémenter l'appel à remark (et les différents plugins) directement dans la partie\nserveur manuellement.",[11,963,964,965,968],{},"Une fois le fichier HTML obtenu, j'appelle une librairie dédiée ",[165,966,967],{},"truncatise"," afin de réduire le contenu\nà quelques paragraphes (4).",[190,970,972],{"className":388,"code":971,"language":390,"meta":59,"style":59},"const truncatise = require(\"truncatise\");\n\nconst remark = require(\"remark\");\nconst html = require(\"remark-html\");\n\nconst remarkPrism = require(\"@gridsome\u002Fremark-prismjs\");\nconst remarkInlineLinks = require(\"remark-inline-links\");\nconst remarkToc = require(\"remark-toc\");\nconst remarkAttr = require(\"remark-attr\");\nconst remarkFN = require(\"remark-footnotes\");\n\nmodule.exports = function(api) {\n  api.loadSource(({ addSchemaResolvers }) => {\n    addSchemaResolvers({\n      Post: {\n        excerpt: {\n          type: \"String\",\n          async resolve(obj) {\n            return new Promise((resolve, reject) => {\n              remark()\n                \u002F\u002F Appel des différents plugins utilisé coté config.\n                .use(remarkPrism)\n                .use(remarkInlineLinks)\n                .use(remarkToc, { heading: \"sommaire\" })\n                .use(remarkAttr)\n                .use(remarkFN)\n                \u002F\u002F Génération HTML\n                .use(html)\n                .process(obj.content, function(err, file) {\n                  if (err) {\n                    return reject(err);\n                  }\n\n                  \u002F\u002F On tronque en ne gardant que les 4 premiers paragraphes\n                  resolve(\n                    truncatise(String(file), {\n                      TruncateLength: 4,\n                      TruncateBy: \"paragraphs\",\n                      Strict: false,\n                      StripHTML: false,\n                      Suffix: \" ...\",\n                    })\n                  );\n                });\n            });\n          },\n        },\n      },\n    });\n  });\n};\n",[165,973,974,979,983,988,993,997,1002,1007,1012,1017,1022,1026,1031,1036,1041,1046,1051,1056,1061,1066,1072,1078,1084,1090,1096,1102,1108,1114,1120,1126,1132,1138,1144,1149,1155,1161,1167,1173,1179,1185,1191,1197,1203,1209,1215,1221,1226,1231,1236,1242,1248],{"__ignoreMap":59},[198,975,976],{"class":200,"line":201},[198,977,978],{},"const truncatise = require(\"truncatise\");\n",[198,980,981],{"class":200,"line":207},[198,982,217],{"emptyLinePlaceholder":216},[198,984,985],{"class":200,"line":213},[198,986,987],{},"const remark = require(\"remark\");\n",[198,989,990],{"class":200,"line":220},[198,991,992],{},"const html = require(\"remark-html\");\n",[198,994,995],{"class":200,"line":254},[198,996,217],{"emptyLinePlaceholder":216},[198,998,999],{"class":200,"line":260},[198,1000,1001],{},"const remarkPrism = require(\"@gridsome\u002Fremark-prismjs\");\n",[198,1003,1004],{"class":200,"line":266},[198,1005,1006],{},"const remarkInlineLinks = require(\"remark-inline-links\");\n",[198,1008,1009],{"class":200,"line":272},[198,1010,1011],{},"const remarkToc = require(\"remark-toc\");\n",[198,1013,1014],{"class":200,"line":278},[198,1015,1016],{},"const remarkAttr = require(\"remark-attr\");\n",[198,1018,1019],{"class":200,"line":283},[198,1020,1021],{},"const remarkFN = require(\"remark-footnotes\");\n",[198,1023,1024],{"class":200,"line":288},[198,1025,217],{"emptyLinePlaceholder":216},[198,1027,1028],{"class":200,"line":450},[198,1029,1030],{},"module.exports = function(api) {\n",[198,1032,1033],{"class":200,"line":456},[198,1034,1035],{},"  api.loadSource(({ addSchemaResolvers }) => {\n",[198,1037,1038],{"class":200,"line":462},[198,1039,1040],{},"    addSchemaResolvers({\n",[198,1042,1043],{"class":200,"line":468},[198,1044,1045],{},"      Post: {\n",[198,1047,1048],{"class":200,"line":473},[198,1049,1050],{},"        excerpt: {\n",[198,1052,1053],{"class":200,"line":478},[198,1054,1055],{},"          type: \"String\",\n",[198,1057,1058],{"class":200,"line":484},[198,1059,1060],{},"          async resolve(obj) {\n",[198,1062,1063],{"class":200,"line":490},[198,1064,1065],{},"            return new Promise((resolve, reject) => {\n",[198,1067,1069],{"class":200,"line":1068},20,[198,1070,1071],{},"              remark()\n",[198,1073,1075],{"class":200,"line":1074},21,[198,1076,1077],{},"                \u002F\u002F Appel des différents plugins utilisé coté config.\n",[198,1079,1081],{"class":200,"line":1080},22,[198,1082,1083],{},"                .use(remarkPrism)\n",[198,1085,1087],{"class":200,"line":1086},23,[198,1088,1089],{},"                .use(remarkInlineLinks)\n",[198,1091,1093],{"class":200,"line":1092},24,[198,1094,1095],{},"                .use(remarkToc, { heading: \"sommaire\" })\n",[198,1097,1099],{"class":200,"line":1098},25,[198,1100,1101],{},"                .use(remarkAttr)\n",[198,1103,1105],{"class":200,"line":1104},26,[198,1106,1107],{},"                .use(remarkFN)\n",[198,1109,1111],{"class":200,"line":1110},27,[198,1112,1113],{},"                \u002F\u002F Génération HTML\n",[198,1115,1117],{"class":200,"line":1116},28,[198,1118,1119],{},"                .use(html)\n",[198,1121,1123],{"class":200,"line":1122},29,[198,1124,1125],{},"                .process(obj.content, function(err, file) {\n",[198,1127,1129],{"class":200,"line":1128},30,[198,1130,1131],{},"                  if (err) {\n",[198,1133,1135],{"class":200,"line":1134},31,[198,1136,1137],{},"                    return reject(err);\n",[198,1139,1141],{"class":200,"line":1140},32,[198,1142,1143],{},"                  }\n",[198,1145,1147],{"class":200,"line":1146},33,[198,1148,217],{"emptyLinePlaceholder":216},[198,1150,1152],{"class":200,"line":1151},34,[198,1153,1154],{},"                  \u002F\u002F On tronque en ne gardant que les 4 premiers paragraphes\n",[198,1156,1158],{"class":200,"line":1157},35,[198,1159,1160],{},"                  resolve(\n",[198,1162,1164],{"class":200,"line":1163},36,[198,1165,1166],{},"                    truncatise(String(file), {\n",[198,1168,1170],{"class":200,"line":1169},37,[198,1171,1172],{},"                      TruncateLength: 4,\n",[198,1174,1176],{"class":200,"line":1175},38,[198,1177,1178],{},"                      TruncateBy: \"paragraphs\",\n",[198,1180,1182],{"class":200,"line":1181},39,[198,1183,1184],{},"                      Strict: false,\n",[198,1186,1188],{"class":200,"line":1187},40,[198,1189,1190],{},"                      StripHTML: false,\n",[198,1192,1194],{"class":200,"line":1193},41,[198,1195,1196],{},"                      Suffix: \" ...\",\n",[198,1198,1200],{"class":200,"line":1199},42,[198,1201,1202],{},"                    })\n",[198,1204,1206],{"class":200,"line":1205},43,[198,1207,1208],{},"                  );\n",[198,1210,1212],{"class":200,"line":1211},44,[198,1213,1214],{},"                });\n",[198,1216,1218],{"class":200,"line":1217},45,[198,1219,1220],{},"            });\n",[198,1222,1224],{"class":200,"line":1223},46,[198,1225,453],{},[198,1227,1229],{"class":200,"line":1228},47,[198,1230,481],{},[198,1232,1234],{"class":200,"line":1233},48,[198,1235,487],{},[198,1237,1239],{"class":200,"line":1238},49,[198,1240,1241],{},"    });\n",[198,1243,1245],{"class":200,"line":1244},50,[198,1246,1247],{},"  });\n",[198,1249,1251],{"class":200,"line":1250},51,[198,1252,929],{},[11,1254,1255,1256,1258,1259,958],{},"C'est ainsi que j'ai converti mon blog vers le framework ",[165,1257,40],{},". Je vous passe tous les\ndétails (vu que le thème est disponible sur Github sur ",[15,1260,382],{"href":380,"rel":1261},[24],[72,1263,1265],{"id":1264},"ajout-dun-système-de-commentaire","Ajout d'un système de commentaire",[11,1267,1268],{},"Ce qu'il manquait sur mon blog précédent c'était un système de commentaires. J'ai donc ajouté\nce système de commentaires à mon blog.",[11,1270,1271],{},"Je ne souhaitais pas ajouter n'importe quel système de commentaires. J'ai donc regardé\nce que je pouvais ajouter sur un site statique. On va retrouver les systèmes de commentaires\nnon libres, et faciles à implémenter (et pas forcément très compatible RGPD).",[83,1273,1274,1277,1280],{},[86,1275,1276],{},"Disqus",[86,1278,1279],{},"Facebook comments",[86,1281,1282],{},"...",[11,1284,1285],{},"De mon coté je me suis dirigé vers les systèmes de commentaires libres:",[83,1287,1288,1295,1302,1309],{},[86,1289,1290],{},[15,1291,1294],{"href":1292,"rel":1293},"https:\u002F\u002Fvssue.js.org\u002F",[24],"Vssue",[86,1296,1297],{},[15,1298,1301],{"href":1299,"rel":1300},"https:\u002F\u002Fgithub.com\u002Fimsun\u002Fgitment",[24],"Gitment",[86,1303,1304],{},[15,1305,1308],{"href":1306,"rel":1307},"https:\u002F\u002Futteranc.es\u002F",[24],"Utterances",[86,1310,1311],{},[15,1312,1315],{"href":1313,"rel":1314},"https:\u002F\u002Fgithub.com\u002Fumputun\u002Fremark42",[24],"Remark42",[11,1317,1318],{},"Remark42 nécessite l'installation d'un programme sur mon serveur. Je l'ai testé mais j'ai été à quelques\nproblème lors de l'intégration avec Gridsome.",[11,1320,1321],{},"Vssue, Gitment et Utterances sont intéressants car ils permettent d'ajouter un système de commentaires\nse basant sur le système de ticketing de Github. Github n'est en lui même pas OpenSource mais les frameworks\nci-dessus le sont.",[11,1323,1324],{},"Je considère que la plupart des personnes lisant mon blog ont un compte Github. Mais n'hésitez pas à commenter\nsi ce n'est pas le cas ;).",[11,1326,1327,1328,41],{},"Vssue était mon système préféré, beau, simple compatible avec Gitea (que j'utilise pour mes sources), Gitlab,\net avec Github également. Mais dû aux limitations de Github et Gitea, il m'était nécessaire de fournir mon\n",[15,1329,1332],{"href":1330,"rel":1331},"https:\u002F\u002Fvssue.js.org\u002Fguide\u002Fgithub.html",[24],"ClientSecret OAuth2",[11,1334,1335,1336,1341],{},"Je n'ai pas apprécié cette idée mais j'ai tout de même voulu tester. Là je me suis rendu compte qu'il\ny avait des problèmes CORS. Le composant passe par ",[15,1337,1340],{"href":1338,"rel":1339},"https:\u002F\u002Fgithub.com\u002FRob--W\u002Fcors-anywhere",[24],"CORS Anywhere"," mais\nce dernier ne peut être utilisé que pour le développement. Ce qui signifie que je dois installer un proxy équivalent\nsur mon serveur. J'ai donc regardé pour autre chose.",[11,1343,1344,1345,1350],{},"J'ai alors testé Utterances. Le problème est que cette librairie n'est pas compatible avec les\napplications de type SPA. On peut voir d'ailleurs quelques commentaires sur le ticket ",[15,1346,1349],{"href":1347,"rel":1348},"https:\u002F\u002Fgithub.com\u002Futterance\u002Futterances\u002Fissues\u002F231",[24],"Github #231","\nde personnes ayant tenté de faire une version du client pour Vue.Js.",[11,1352,1353,1354,958],{},"Je me suis donc inspiré d'un composant Vue.JS écrit par quelqu'un d'autre (dans le 1er commentaire) pour inclure\nce système sur mon site.\nCe composant a dû être légèrement adapté pour fonctionner (je vous invite à regarder\n",[15,1355,1358],{"href":1356,"rel":1357},"https:\u002F\u002Fgithub.com\u002Fphoenix741\u002Fgridsome-flex-markdown-starter\u002Fblob\u002Fmain\u002Fsrc\u002Fcomponents\u002FGithubComponent.vue",[24],"GithubComponent.vue",[11,1360,1361],{},"Comme le plugin utilise directement l'objet window, il ne peut fonctionner avec le mode SSR (Server Side Rendering) de\nVue.Js. J'ai dû donc désactiver le mode commentaires pour le côté SSR (la génération). Ce n'est pas déconnant car\nde toutes façon les commentaires sont gérés sur Github.",[11,1363,1364,1365,1368,1369,41],{},"Voici comment on fait avec Gridsome. On commence par encadrer le bloc qui ne doit pas faire partie de la génération\ncôté serveur (et qui est donc ",[165,1366,1367],{},"Client Only","). Ce bloc contient notre composant ",[165,1370,1371],{},"GithubComponent",[190,1373,1377],{"className":1374,"code":1375,"language":1376,"meta":59,"style":59},"language-html shiki shiki-themes one-dark-pro","\u003Carticle>\n  ...\n  \u003CClientOnly>\n    \u003Cdiv class=\"commentswrap\">\n      \u003Cdiv id=\"comments\">\n        \u003CGithubComponent\n          :title=\"$page.post.title\"\n          :repo=\"$page.metadata.utterances.repo\"\n          :pathname=\"this.$route.path\"\n          :url=\"url\"\n          :issueTerm=\"$page.metadata.utterances.issueTerm\"\n          :label=\"$page.metadata.utterances.label\"\n        >\u003C\u002FGithubComponent>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  \u003C\u002FClientOnly>\n\u003C\u002Farticle>\n","html",[165,1378,1379,1392,1397,1407,1428,1445,1453,1463,1473,1483,1493,1503,1513,1522,1531,1540,1549],{"__ignoreMap":59},[198,1380,1381,1385,1389],{"class":200,"line":201},[198,1382,1384],{"class":1383},"sn6KH","\u003C",[198,1386,1388],{"class":1387},"sVyAn","article",[198,1390,1391],{"class":1383},">\n",[198,1393,1394],{"class":200,"line":207},[198,1395,1396],{"class":1383},"  ...\n",[198,1398,1399,1402,1405],{"class":200,"line":213},[198,1400,1401],{"class":1383},"  \u003C",[198,1403,1404],{"class":1387},"ClientOnly",[198,1406,1391],{"class":1383},[198,1408,1409,1412,1415,1419,1422,1426],{"class":200,"line":220},[198,1410,1411],{"class":1383},"    \u003C",[198,1413,1414],{"class":1387},"div",[198,1416,1418],{"class":1417},"sVC51"," class",[198,1420,1421],{"class":1383},"=",[198,1423,1425],{"class":1424},"subq3","\"commentswrap\"",[198,1427,1391],{"class":1383},[198,1429,1430,1433,1435,1438,1440,1443],{"class":200,"line":254},[198,1431,1432],{"class":1383},"      \u003C",[198,1434,1414],{"class":1387},[198,1436,1437],{"class":1417}," id",[198,1439,1421],{"class":1383},[198,1441,1442],{"class":1424},"\"comments\"",[198,1444,1391],{"class":1383},[198,1446,1447,1450],{"class":200,"line":260},[198,1448,1449],{"class":1383},"        \u003C",[198,1451,1452],{"class":1387},"GithubComponent\n",[198,1454,1455,1458,1460],{"class":200,"line":266},[198,1456,1457],{"class":1417},"          :title",[198,1459,1421],{"class":1383},[198,1461,1462],{"class":1424},"\"$page.post.title\"\n",[198,1464,1465,1468,1470],{"class":200,"line":272},[198,1466,1467],{"class":1417},"          :repo",[198,1469,1421],{"class":1383},[198,1471,1472],{"class":1424},"\"$page.metadata.utterances.repo\"\n",[198,1474,1475,1478,1480],{"class":200,"line":278},[198,1476,1477],{"class":1417},"          :pathname",[198,1479,1421],{"class":1383},[198,1481,1482],{"class":1424},"\"this.$route.path\"\n",[198,1484,1485,1488,1490],{"class":200,"line":283},[198,1486,1487],{"class":1417},"          :url",[198,1489,1421],{"class":1383},[198,1491,1492],{"class":1424},"\"url\"\n",[198,1494,1495,1498,1500],{"class":200,"line":288},[198,1496,1497],{"class":1417},"          :issueTerm",[198,1499,1421],{"class":1383},[198,1501,1502],{"class":1424},"\"$page.metadata.utterances.issueTerm\"\n",[198,1504,1505,1508,1510],{"class":200,"line":450},[198,1506,1507],{"class":1417},"          :label",[198,1509,1421],{"class":1383},[198,1511,1512],{"class":1424},"\"$page.metadata.utterances.label\"\n",[198,1514,1515,1518,1520],{"class":200,"line":456},[198,1516,1517],{"class":1383},"        >\u003C\u002F",[198,1519,1371],{"class":1387},[198,1521,1391],{"class":1383},[198,1523,1524,1527,1529],{"class":200,"line":462},[198,1525,1526],{"class":1383},"      \u003C\u002F",[198,1528,1414],{"class":1387},[198,1530,1391],{"class":1383},[198,1532,1533,1536,1538],{"class":200,"line":468},[198,1534,1535],{"class":1383},"    \u003C\u002F",[198,1537,1414],{"class":1387},[198,1539,1391],{"class":1383},[198,1541,1542,1545,1547],{"class":200,"line":473},[198,1543,1544],{"class":1383},"  \u003C\u002F",[198,1546,1404],{"class":1387},[198,1548,1391],{"class":1383},[198,1550,1551,1554,1556],{"class":200,"line":478},[198,1552,1553],{"class":1383},"\u003C\u002F",[198,1555,1388],{"class":1387},[198,1557,1391],{"class":1383},[11,1559,1560],{},"Enfin on charge le composant dynamiquement dans la partie Javascript.",[190,1562,1564],{"className":388,"code":1563,"language":390,"meta":59,"style":59},"export default {\n  components: {\n    PostHeaderTitle,\n    GithubComponent: () =>\n      import(\"..\u002Fcomponents\u002FGithubComponent\")\n        .then((m) => m.default)\n        .catch(),\n  },\n  ...\n}\n",[165,1565,1566,1571,1576,1581,1586,1591,1596,1601,1605,1609],{"__ignoreMap":59},[198,1567,1568],{"class":200,"line":201},[198,1569,1570],{},"export default {\n",[198,1572,1573],{"class":200,"line":207},[198,1574,1575],{},"  components: {\n",[198,1577,1578],{"class":200,"line":213},[198,1579,1580],{},"    PostHeaderTitle,\n",[198,1582,1583],{"class":200,"line":220},[198,1584,1585],{},"    GithubComponent: () =>\n",[198,1587,1588],{"class":200,"line":254},[198,1589,1590],{},"      import(\"..\u002Fcomponents\u002FGithubComponent\")\n",[198,1592,1593],{"class":200,"line":260},[198,1594,1595],{},"        .then((m) => m.default)\n",[198,1597,1598],{"class":200,"line":266},[198,1599,1600],{},"        .catch(),\n",[198,1602,1603],{"class":200,"line":272},[198,1604,764],{},[198,1606,1607],{"class":200,"line":278},[198,1608,1396],{},[198,1610,1611],{"class":200,"line":283},[198,1612,1613],{},"}\n",[11,1615,1616],{},"Ces deux opérations permettent d'exclure cette partie lors de la génération des pages statique, mais de\nl'ajouter dynamiquement après le chargement de la page coté client.",[72,1618,1620],{"id":1619},"conclusion","Conclusion",[11,1622,1623],{},"Voici donc comment j'ai mis en place la version Vue.JS de mon blog. N'hésitez pas à m'envoyer un mail\nou lâcher un commentaire.",[11,1625,1626,1627,1630,1631,41],{},"Vous pouvez retrouver le kit de démarrage que j'ai fait pour mon blog sur github: ",[15,1628,382],{"href":380,"rel":1629},[24],". Vous pouvez également consulter l'intégration d'utterances sur un site\nen vue ici: ",[15,1632,1634],{"href":1356,"rel":1633},[24],"phoenix741\u002Fgridsome-flex-markdown-starter:GithubComponent.vue",[1636,1637,1640,1645],"section",{"className":1638,"dataFootnotes":59},[1639],"footnotes",[72,1641,1644],{"className":1642,"id":58},[1643],"sr-only","Footnotes",[1646,1647,1648],"ol",{},[86,1649,1651,1652],{"id":1650},"user-content-fn-1","Single Page Application ",[15,1653,1658],{"href":1654,"ariaLabel":1655,"className":1656,"dataFootnoteBackref":59},"#user-content-fnref-1","Back to reference 1",[1657],"data-footnote-backref","↩",[1660,1661,1662],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}",{"title":59,"searchDepth":207,"depth":207,"links":1664},[1665,1666,1667,1668,1669,1670,1671],{"id":74,"depth":207,"text":75},{"id":117,"depth":207,"text":118},{"id":366,"depth":207,"text":367},{"id":935,"depth":207,"text":936},{"id":1264,"depth":207,"text":1265},{"id":1619,"depth":207,"text":1620},{"id":58,"depth":207,"text":1644},"Logiciels","logiciels","2021-03-02","J'avais migré en Janvier 2013 mon blog vers Pelican en venant de\nDotclear. Pelican est un générateur de site statique en Python. J'avais\nalors dû faire l'impasse sur les commentaires mais au bénéfice d'un site performant et avec une\nsurface d'attaque plus faible.",{"type":8,"value":1677},[1678,1685,1693,1695],[11,1679,13,1680,19,1682,26],{},[15,1681,18],{"href":17},[15,1683,25],{"href":22,"rel":1684},[24],[11,1686,29,1687,35,1690,41],{},[15,1688,34],{"href":32,"rel":1689},[24],[15,1691,40],{"href":38,"rel":1692},[24],[11,1694,44],{},[11,1696,47],{},"Lille, France",{"planet":216},"\u002Fpost\u002Fgridsome-mise-a-jour-du-blog",{"title":5,"description":1675},"gridsome-mise-a-jour-du-blog","posts\u002FLogiciels\u002F2021-03-02-gridsome-mise-a-jour-du-blog",[1704,1705],"dedie","javascript","92imksbvFvyNB9g-BgsuOp-f1qDd_PCUcic_SG3Gf2o",[1708,3277,4277,4943,6329,10527],{"id":1709,"title":1710,"author":6,"body":1711,"category":1672,"categorySlug":1673,"date":3248,"description":59,"excerpt":3249,"extension":194,"location":1697,"meta":3267,"navigation":216,"path":3268,"published":216,"seo":3269,"slug":3270,"stem":3271,"tags":3272,"timeToRead":456,"__hash__":3276},"posts\u002Fposts\u002FLogiciels\u002F2014-03-19-monlivretdemesse-fr.md","Mon livret de messe - Site de génération de livrets au format PDF",{"type":8,"value":1712,"toc":3228},[1713,1718,1721,1730,1738,1741,1780,1795,1799,1802,1805,1808,1816,1819,1822,1825,1828,1831,1834,1842,1845,1856,1859,1868,1872,1878,1882,1885,1896,1899,1902,1905,1908,1916,1919,2166,2169,2638,2641,2647,2651,2654,2657,2661,2664,2667,2671,2678,2682,2692,2696,2699,2703,2715,2718,2722,2725,2728,2732,2739,2742,2855,2858,2861,2869,2872,2876,2882,2885,2888,2899,2903,2906,2913,2916,2930,2934,2941,2949,2957,2960,2964,2970,2973,2976,3055,3058,3061,3064,3142,3145,3216,3219,3222,3225],[1714,1715,1717],"h3",{"id":1716},"mon-livret-de-messe-générateur-de-pdf","Mon livret de messe - Générateur de PDF",[11,1719,1720],{},"Bonjour,",[11,1722,1723,1724,1729],{},"Ce petit billet pour vous parler d'un site que j'ai développé pour ma femme et dont l'adresse est\n",[15,1725,1728],{"href":1726,"rel":1727},"http:\u002F\u002Fmonlivretdemesse.fr\u002F",[24],"http:\u002F\u002Fmonlivretdemesse.fr",". Ce projet que je développe depuis\nplusieurs années, a été mis à jours récément. Je profite de cette mise à jours pour vous parler de\nce projet fonctionnellement mais aussi techniquement.",[11,1731,1732,1737],{},[15,1733,1736],{"href":1734,"rel":1735},"http:\u002F\u002Fmonlivretdemessse.fr",[24],"Monlivretdemesse.FR"," est un site permettant aux utilisateurs allant\nse marier de générer leur livret de messe au format PDF afin de l'imprimer directement chez eux.\nLes pages du livret ainsi générées sont alors ordonnées de telle manière qu'il suffit de faire une\nimpression recto\u002Fverso puis de plier les feuilles pour avoir son livret. Je me suis chargé\ndu développement de ce site, pendant que ma femme se charge du contenu (donc le contenu des textes,\ndes images, mais aussi et surtout le thème de chaque produit, leur format).",[11,1739,1740],{},"La nouvelle version sortie le 11 mars 2014 permet également la création d'autres types de produits\nafin de générer des",[83,1742,1743,1750,1763,1770,1777],{},[86,1744,1745],{},[15,1746,1749],{"href":1747,"rel":1748},"http:\u002F\u002Fmonlivretdemesse.fr\u002Ffr\u002Fcategory\u002Fbapteme",[24],"livrets de messe de baptêmes",[86,1751,1752,1757,1758],{},[15,1753,1756],{"href":1754,"rel":1755},"http:\u002F\u002Fmonlivretdemesse.fr\u002Ffr\u002Fcategory\u002Ffaire-part-mariage",[24],"faire-parts de mariage",",\n",[15,1759,1762],{"href":1760,"rel":1761},"http:\u002F\u002Fmonlivretdemesse.fr\u002Ffr\u002Fcategory\u002Ffaire-part-bapteme",[24],"de baptêmes",[86,1764,1765],{},[15,1766,1769],{"href":1767,"rel":1768},"http:\u002F\u002Fmonlivretdemesse.fr\u002Ffr\u002Fcategory\u002Fmenus-mariage",[24],"menus pour la soirée",[86,1771,1772],{},[15,1773,1776],{"href":1774,"rel":1775},"http:\u002F\u002Fmonlivretdemesse.fr\u002Ffr\u002Fcategory\u002Fmarque-places",[24],"des marques places",[86,1778,1779],{},"et bien d'autres...",[11,1781,1782,1783,1788,1789,1794],{},"Le site a été écrit à l'aide du framework Symfony2 et utilise la bibliothèque\n",[15,1784,1787],{"href":1785,"rel":1786},"http:\u002F\u002Fwww.tcpdf.org\u002F",[24],"TCPDF"," afin de générer les fichiers PDF. Les données sont stockées dans une\nbase de données ",[15,1790,1793],{"href":1791,"rel":1792},"http:\u002F\u002Fwww.mongodb.org\u002F",[24],"MongoDB",". Parmi les données on peut compter les données\nproduits, utilisateurs, mais aussi le cache des PDF générés enregistrés en tant que fichier dans\nGridFS (et ceci afin qu'un livret qui n'a pas été modifié ne soit pas re-généré).",[1714,1796,1798],{"id":1797},"symfony2","Symfony2",[11,1800,1801],{},"Symfony 2 est un framework PHP permettant le développement de sites Internet. Il est livré par\ndéfaut avec un ORM: Doctrine qui permet de faire correspondre à une structure de base de données des\nclasses PHP qui seront automatiquement hydratées.",[11,1803,1804],{},"Le développement PHP s'en retrouve presque agréable (je préfère les langages compilés en règle\ngénérale). Le framework est de la même trempe que le Framework Python Django.",[11,1806,1807],{},"Ce dernier m'a d'ailleurs tenté (bien qu'interpreté aussi), mais une lecture rapide de la\ndocumentation m'a donné l'impression d'être un peu moins pratique à utiliser que Symfony2. Peut-être\ncar je ne fais pas de Python.",[11,1809,1810,1811,1815],{},"Pour mon prochain projet j'étudierai l'utilisation de symfony2 vs ruby on rails vs django vs\nnode.js. Mais je ne suis pas sûr qu'au final l'utilisation d'une des technos précédentes m'apporte\nbeaucoup plus par rapport à ce que sait déjà faire un framework comme symfony2. L'avantage d'un tel\nframework réside aussi dans le nombre de ",[1812,1813,1814],"em",{},"bundle"," et de librairie utilisables à l'extérieur.",[11,1817,1818],{},"Par rapport à la distribution de base de symfony2 j'ai remplacé la version Doctrine ORM par Doctrine\nODM. Ce qui me permet de me connecter à une base de données MongoDB.",[1714,1820,1793],{"id":1821},"mongodb",[11,1823,1824],{},"Mon projet d'abord basé sur une base MySQL a été basculé sur une base de données NoSQL nommée\nMongoDB.",[11,1826,1827],{},"La raison n'est pas technique (je n'ai pas besoin de replication, de sharding, ...., pas assez de\nvisiteurs). J'avais juste envie de tester cette base de données sur mon projet. De plus l'aspect\norienté document est agréable au développement.",[11,1829,1830],{},"En effet, au lieu de stocker les informations dans différentes tables et de tenter d'y accéder à\nl'aide de jointure ou de requête multiple, dans on MongoDB on stocke un document dans un format\nbinaire du JSON (le BSON).",[11,1832,1833],{},"Un panier stocké en base pourra avoir la forme :",[190,1835,1840],{"className":1836,"code":1838,"language":1839},[1837],"language-text","{\n  \"_id\": ObjectId(\"......................\"),\n  \"expiration_updated_at\": ISODate(\"2014-03-17T21:00:34.0Z\"),\n  \"lines\": [\n    {\n      \"product\": {\n        \"product\": \"marque-place-baroque-dore\",\n        \"product_name\": \"Marque-place baroque doré\",\n        \"variant\": \"dore-gris\",\n        \"variant_name\": \"Doré\\\u002FGris\",\n        \"amount\": 7.9\n      },\n      \"custom\": ObjectId(\"....................\")\n    }\n  ],\n  \"lines_count\": NumberInt(1)\n}\n","text",[165,1841,1838],{"__ignoreMap":59},[11,1843,1844],{},"On retrouve dans un seul document les informations liées au panier et les informations concernant\nchaque ligne. La dénormalisation n'étant pas un problème, on rappelera alors ici le nom du produit,\net le nombre de lignes que l'on pourrait retrouver autrement mais qui permettra un affichage plus\nrapide de cette manière.",[11,1846,1847,1848,1851,1852,1855],{},"Par exemple, sur la page d'acceuil où on affiche le nombre de produit dans le panier, il nous\nsuffira de requêter ",[1812,1849,1850],{},"lines_count"," sans toucher à l'attribute ",[1812,1853,1854],{},"lines",". Ensuite lors de l'affichage\ndu panier, on récupérera les lignes et les informations du panier en une seule requête et sans\njointure.",[11,1857,1858],{},"Ainsi pour des entités avec forte relation, qu'on ne récupère jamais les unes sans les autres, une\nseule requête permet de récupérer toutes les informations. Par exemple, dans une base relationnelle,\non aura l'habitude de stocker l'entête du panier dans une table, et les lignes dans une autre table.\nAvec Mongo, si je veux récupérer le panier en une requête, je récupère aussi les lignes. Cela\nimplique par contre de ne pouvoir requêter facilement sur les lignes du panier indépendamment de\nleur entête.",[11,1860,1861,1862,1867],{},"Le seul problème que j'ai actuellement avec l'ODM Doctrine est que la mise à jour du panier se fait\nen plusieurs requêtes alors qu'il serait préférable de le faire en une seule pour des questions\nd'atomicité. Ce point fait d'ailleurs l'objet du ticket\n",[15,1863,1866],{"href":1864,"rel":1865},"https:\u002F\u002Fgithub.com\u002Fdoctrine\u002Fmongodb-odm\u002Fissues\u002F437",[24],"437"," du Github du projet.",[1714,1869,1871],{"id":1870},"les-différents-modules-du-site","Les différents modules du site",[11,1873,1874,1875,1877],{},"Dans cette section je vais vous parler rapidement des différents ",[1812,1876,1814],{}," que j'ai créé pour le site.",[72,1879,1881],{"id":1880},"le-cms","Le CMS",[11,1883,1884],{},"Afin de faciliter l'édition des pages de contenu (Mention légales, Documentation, FAQ) sans toucher\nau code. J'ai écrit un mini CMS. Le but est de stocker dans la base de données les différentes pages\ndu projet, ainsi que les images associées aux pages.",[11,1886,1887,1888,1890,1891,1895],{},"Pour cela j'ai un ",[1812,1889,1814],{}," nommé CMS qui utilise la notion d'édition inline de CKEditor. J'ai écris\nmon propre ",[1892,1893,1894],"strong",{},"Explorer de media"," qui permet de récupérer et ajouter dans cette même base des\nfichiers à attacher aux différentes pages.",[11,1897,1898],{},"L'adresse de la page est alors décomposée pour récupérer la clé de la page. Une page dont l'adresse\nsera \u002Fpage\u002Fprout aura comme clé en base \u002Fprout. Pour un utilisateur non administrateur (ou anonyme),\nsi la page est trouvée, elle est affichée telle quelle et si elle n'est pas trouvée, une page 404\nest affichée.",[11,1900,1901],{},"En mode administrateur si la page existe, elle est ouverte en mode édition inline pour CKEditor. Si\nla page n'existe pas, elle est ouverte en mode création et en mode inline avec CKEditor. Il est\nainsi super facile pour un administrateur de créer de nouvelles pages.",[11,1903,1904],{},"La partie media permet d'ajouter dans un GridFS dedié les images, et fichiers attachés.",[11,1906,1907],{},"Le module est du coup assez simple, deux documents",[83,1909,1910,1913],{},[86,1911,1912],{},"Page",[86,1914,1915],{},"Media",[11,1917,1918],{},"Le document Page ressemble à ceci:",[190,1920,1924],{"className":1921,"code":1922,"language":1923,"meta":59,"style":59},"language-php shiki shiki-themes one-dark-pro","\u002F**\n  * Page\n  *\n  * @MongoDB\\Document(collection=\"cms_page\")\n  *\u002F\nclass Page {\n    \u002F**\n      * @var string\n      *\n      * @MongoDB\\Id(strategy=\"CUSTOM\", options={\"class\"=\"\\Shadoware\\CMSBundle\\Generator\\PageSlugGenerator\"})\n      *\u002F\n    private $slug;\n\n    \u002F**\n      * @var string\n      *\n      * @MongoDB\\String\n      *\u002F\n    private $name;\n\n    \u002F**\n      * @var string\n      *\n      * @MongoDB\\String\n      *\u002F\n    private $title;\n\n    \u002F**\n      * @var string\n      *\n      * @MongoDB\\String\n      *\u002F\n    private $content;\n\n    \u002F**\n      * @var string $lang\n      *\n      * @MongoDB\\String\n      *\u002F\n    private $lang;\n}\n","php",[165,1925,1926,1932,1937,1942,1947,1952,1965,1970,1983,1988,1993,1998,2009,2013,2017,2025,2029,2034,2038,2047,2051,2055,2063,2067,2071,2075,2084,2088,2092,2100,2104,2108,2112,2121,2125,2129,2141,2145,2149,2153,2162],{"__ignoreMap":59},[198,1927,1928],{"class":200,"line":201},[198,1929,1931],{"class":1930},"sV9Aq","\u002F**\n",[198,1933,1934],{"class":200,"line":207},[198,1935,1936],{"class":1930},"  * Page\n",[198,1938,1939],{"class":200,"line":213},[198,1940,1941],{"class":1930},"  *\n",[198,1943,1944],{"class":200,"line":220},[198,1945,1946],{"class":1930},"  * @MongoDB\\Document(collection=\"cms_page\")\n",[198,1948,1949],{"class":200,"line":254},[198,1950,1951],{"class":1930},"  *\u002F\n",[198,1953,1954,1958,1962],{"class":200,"line":260},[198,1955,1957],{"class":1956},"seHd6","class",[198,1959,1961],{"class":1960},"sU0A5"," Page",[198,1963,1964],{"class":1383}," {\n",[198,1966,1967],{"class":200,"line":266},[198,1968,1969],{"class":1930},"    \u002F**\n",[198,1971,1972,1975,1979],{"class":200,"line":272},[198,1973,1974],{"class":1930},"      * ",[198,1976,1978],{"class":1977},"shdRp","@var",[198,1980,1982],{"class":1981},"sKU4T"," string\n",[198,1984,1985],{"class":200,"line":278},[198,1986,1987],{"class":1930},"      *\n",[198,1989,1990],{"class":200,"line":283},[198,1991,1992],{"class":1930},"      * @MongoDB\\Id(strategy=\"CUSTOM\", options={\"class\"=\"\\Shadoware\\CMSBundle\\Generator\\PageSlugGenerator\"})\n",[198,1994,1995],{"class":200,"line":288},[198,1996,1997],{"class":1930},"      *\u002F\n",[198,1999,2000,2003,2006],{"class":200,"line":450},[198,2001,2002],{"class":1956},"    private",[198,2004,2005],{"class":1387}," $slug",[198,2007,2008],{"class":1383},";\n",[198,2010,2011],{"class":200,"line":456},[198,2012,217],{"emptyLinePlaceholder":216},[198,2014,2015],{"class":200,"line":462},[198,2016,1969],{"class":1930},[198,2018,2019,2021,2023],{"class":200,"line":468},[198,2020,1974],{"class":1930},[198,2022,1978],{"class":1977},[198,2024,1982],{"class":1981},[198,2026,2027],{"class":200,"line":473},[198,2028,1987],{"class":1930},[198,2030,2031],{"class":200,"line":478},[198,2032,2033],{"class":1930},"      * @MongoDB\\String\n",[198,2035,2036],{"class":200,"line":484},[198,2037,1997],{"class":1930},[198,2039,2040,2042,2045],{"class":200,"line":490},[198,2041,2002],{"class":1956},[198,2043,2044],{"class":1387}," $name",[198,2046,2008],{"class":1383},[198,2048,2049],{"class":200,"line":1068},[198,2050,217],{"emptyLinePlaceholder":216},[198,2052,2053],{"class":200,"line":1074},[198,2054,1969],{"class":1930},[198,2056,2057,2059,2061],{"class":200,"line":1080},[198,2058,1974],{"class":1930},[198,2060,1978],{"class":1977},[198,2062,1982],{"class":1981},[198,2064,2065],{"class":200,"line":1086},[198,2066,1987],{"class":1930},[198,2068,2069],{"class":200,"line":1092},[198,2070,2033],{"class":1930},[198,2072,2073],{"class":200,"line":1098},[198,2074,1997],{"class":1930},[198,2076,2077,2079,2082],{"class":200,"line":1104},[198,2078,2002],{"class":1956},[198,2080,2081],{"class":1387}," $title",[198,2083,2008],{"class":1383},[198,2085,2086],{"class":200,"line":1110},[198,2087,217],{"emptyLinePlaceholder":216},[198,2089,2090],{"class":200,"line":1116},[198,2091,1969],{"class":1930},[198,2093,2094,2096,2098],{"class":200,"line":1122},[198,2095,1974],{"class":1930},[198,2097,1978],{"class":1977},[198,2099,1982],{"class":1981},[198,2101,2102],{"class":200,"line":1128},[198,2103,1987],{"class":1930},[198,2105,2106],{"class":200,"line":1134},[198,2107,2033],{"class":1930},[198,2109,2110],{"class":200,"line":1140},[198,2111,1997],{"class":1930},[198,2113,2114,2116,2119],{"class":200,"line":1146},[198,2115,2002],{"class":1956},[198,2117,2118],{"class":1387}," $content",[198,2120,2008],{"class":1383},[198,2122,2123],{"class":200,"line":1151},[198,2124,217],{"emptyLinePlaceholder":216},[198,2126,2127],{"class":200,"line":1157},[198,2128,1969],{"class":1930},[198,2130,2131,2133,2135,2138],{"class":200,"line":1163},[198,2132,1974],{"class":1930},[198,2134,1978],{"class":1977},[198,2136,2137],{"class":1981}," string",[198,2139,2140],{"class":1930}," $lang\n",[198,2142,2143],{"class":200,"line":1169},[198,2144,1987],{"class":1930},[198,2146,2147],{"class":200,"line":1175},[198,2148,2033],{"class":1930},[198,2150,2151],{"class":200,"line":1181},[198,2152,1997],{"class":1930},[198,2154,2155,2157,2160],{"class":200,"line":1187},[198,2156,2002],{"class":1956},[198,2158,2159],{"class":1387}," $lang",[198,2161,2008],{"class":1383},[198,2163,2164],{"class":200,"line":1193},[198,2165,1613],{"class":1383},[11,2167,2168],{},"Le controlleur est assez simple :",[190,2170,2172],{"className":1921,"code":2171,"language":1923,"meta":59,"style":59},"\u002F**\n  * @Route(\"\u002Fpage\u002F{slug}\", requirements={\"slug\" = \".+\"})\n  * @Template()\n  *\u002F\npublic function indexAction($slug) {\n    $dm = $this->get('doctrine_mongodb')->getManager();\n\n    $page = $dm->getRepository(\"CMSBundle:Page\")->find($slug);\n    if ($page == null) {\n        if ($this->get('security.context')->isGranted('ROLE_ADMIN')) {\n            $page = new Page();\n            $page->setTitle(\"Titre de la page\");\n            $page->setSlug($slug);\n            $page->setName(\"Nom\");\n            $page->setContent(\"Contenue de la page\");\n        } else {\n            throw $this->createNotFoundException(\"Page not found\");\n        }\n    }\n\n    $request = $this->getRequest();\n    if ($request->getMethod() == \"POST\" && $page != null) {\n        $page->setName($request->get('name'));\n        $page->setTitle($request->get('title'));\n        $page->setContent($request->get('content'));\n\n        $dm->persist($page);\n        $dm->flush();\n    }\n\n    return array('page' => $page);\n}\n",[165,2173,2174,2178,2183,2188,2192,2213,2245,2249,2281,2300,2332,2346,2362,2377,2393,2409,2419,2438,2443,2448,2452,2468,2504,2529,2552,2575,2579,2595,2606,2610,2614,2634],{"__ignoreMap":59},[198,2175,2176],{"class":200,"line":201},[198,2177,1931],{"class":1930},[198,2179,2180],{"class":200,"line":207},[198,2181,2182],{"class":1930},"  * @Route(\"\u002Fpage\u002F{slug}\", requirements={\"slug\" = \".+\"})\n",[198,2184,2185],{"class":200,"line":213},[198,2186,2187],{"class":1930},"  * @Template()\n",[198,2189,2190],{"class":200,"line":220},[198,2191,1951],{"class":1930},[198,2193,2194,2197,2200,2204,2207,2210],{"class":200,"line":254},[198,2195,2196],{"class":1956},"public",[198,2198,2199],{"class":1956}," function",[198,2201,2203],{"class":2202},"sVbv2"," indexAction",[198,2205,2206],{"class":1383},"(",[198,2208,2209],{"class":1387},"$slug",[198,2211,2212],{"class":1383},") {\n",[198,2214,2215,2218,2222,2225,2228,2231,2233,2236,2239,2242],{"class":200,"line":260},[198,2216,2217],{"class":1387},"    $dm",[198,2219,2221],{"class":2220},"sjrmR"," =",[198,2223,2224],{"class":1960}," $this",[198,2226,2227],{"class":1383},"->",[198,2229,2230],{"class":2202},"get",[198,2232,2206],{"class":1383},[198,2234,2235],{"class":1424},"'doctrine_mongodb'",[198,2237,2238],{"class":1383},")->",[198,2240,2241],{"class":2202},"getManager",[198,2243,2244],{"class":1383},"();\n",[198,2246,2247],{"class":200,"line":266},[198,2248,217],{"emptyLinePlaceholder":216},[198,2250,2251,2254,2256,2259,2261,2264,2266,2269,2271,2274,2276,2278],{"class":200,"line":272},[198,2252,2253],{"class":1387},"    $page",[198,2255,2221],{"class":2220},[198,2257,2258],{"class":1387}," $dm",[198,2260,2227],{"class":1383},[198,2262,2263],{"class":2202},"getRepository",[198,2265,2206],{"class":1383},[198,2267,2268],{"class":1424},"\"CMSBundle:Page\"",[198,2270,2238],{"class":1383},[198,2272,2273],{"class":2202},"find",[198,2275,2206],{"class":1383},[198,2277,2209],{"class":1387},[198,2279,2280],{"class":1383},");\n",[198,2282,2283,2286,2289,2292,2295,2298],{"class":200,"line":278},[198,2284,2285],{"class":1956},"    if",[198,2287,2288],{"class":1383}," (",[198,2290,2291],{"class":1387},"$page",[198,2293,2294],{"class":2220}," ==",[198,2296,2297],{"class":1417}," null",[198,2299,2212],{"class":1383},[198,2301,2302,2305,2307,2310,2312,2314,2316,2319,2321,2324,2326,2329],{"class":200,"line":283},[198,2303,2304],{"class":1956},"        if",[198,2306,2288],{"class":1383},[198,2308,2309],{"class":1960},"$this",[198,2311,2227],{"class":1383},[198,2313,2230],{"class":2202},[198,2315,2206],{"class":1383},[198,2317,2318],{"class":1424},"'security.context'",[198,2320,2238],{"class":1383},[198,2322,2323],{"class":2202},"isGranted",[198,2325,2206],{"class":1383},[198,2327,2328],{"class":1424},"'ROLE_ADMIN'",[198,2330,2331],{"class":1383},")) {\n",[198,2333,2334,2337,2339,2342,2344],{"class":200,"line":288},[198,2335,2336],{"class":1387},"            $page",[198,2338,2221],{"class":2220},[198,2340,2341],{"class":1956}," new",[198,2343,1961],{"class":1960},[198,2345,2244],{"class":1383},[198,2347,2348,2350,2352,2355,2357,2360],{"class":200,"line":450},[198,2349,2336],{"class":1387},[198,2351,2227],{"class":1383},[198,2353,2354],{"class":2202},"setTitle",[198,2356,2206],{"class":1383},[198,2358,2359],{"class":1424},"\"Titre de la page\"",[198,2361,2280],{"class":1383},[198,2363,2364,2366,2368,2371,2373,2375],{"class":200,"line":456},[198,2365,2336],{"class":1387},[198,2367,2227],{"class":1383},[198,2369,2370],{"class":2202},"setSlug",[198,2372,2206],{"class":1383},[198,2374,2209],{"class":1387},[198,2376,2280],{"class":1383},[198,2378,2379,2381,2383,2386,2388,2391],{"class":200,"line":462},[198,2380,2336],{"class":1387},[198,2382,2227],{"class":1383},[198,2384,2385],{"class":2202},"setName",[198,2387,2206],{"class":1383},[198,2389,2390],{"class":1424},"\"Nom\"",[198,2392,2280],{"class":1383},[198,2394,2395,2397,2399,2402,2404,2407],{"class":200,"line":468},[198,2396,2336],{"class":1387},[198,2398,2227],{"class":1383},[198,2400,2401],{"class":2202},"setContent",[198,2403,2206],{"class":1383},[198,2405,2406],{"class":1424},"\"Contenue de la page\"",[198,2408,2280],{"class":1383},[198,2410,2411,2414,2417],{"class":200,"line":473},[198,2412,2413],{"class":1383},"        } ",[198,2415,2416],{"class":1956},"else",[198,2418,1964],{"class":1383},[198,2420,2421,2424,2426,2428,2431,2433,2436],{"class":200,"line":478},[198,2422,2423],{"class":1956},"            throw",[198,2425,2224],{"class":1960},[198,2427,2227],{"class":1383},[198,2429,2430],{"class":2202},"createNotFoundException",[198,2432,2206],{"class":1383},[198,2434,2435],{"class":1424},"\"Page not found\"",[198,2437,2280],{"class":1383},[198,2439,2440],{"class":200,"line":484},[198,2441,2442],{"class":1383},"        }\n",[198,2444,2445],{"class":200,"line":490},[198,2446,2447],{"class":1383},"    }\n",[198,2449,2450],{"class":200,"line":1068},[198,2451,217],{"emptyLinePlaceholder":216},[198,2453,2454,2457,2459,2461,2463,2466],{"class":200,"line":1074},[198,2455,2456],{"class":1387},"    $request",[198,2458,2221],{"class":2220},[198,2460,2224],{"class":1960},[198,2462,2227],{"class":1383},[198,2464,2465],{"class":2202},"getRequest",[198,2467,2244],{"class":1383},[198,2469,2470,2472,2474,2477,2479,2482,2485,2488,2491,2494,2497,2500,2502],{"class":200,"line":1080},[198,2471,2285],{"class":1956},[198,2473,2288],{"class":1383},[198,2475,2476],{"class":1387},"$request",[198,2478,2227],{"class":1383},[198,2480,2481],{"class":2202},"getMethod",[198,2483,2484],{"class":1383},"() ",[198,2486,2487],{"class":2220},"==",[198,2489,2490],{"class":1424}," \"POST\"",[198,2492,2493],{"class":2220}," &&",[198,2495,2496],{"class":1387}," $page",[198,2498,2499],{"class":2220}," !=",[198,2501,2297],{"class":1417},[198,2503,2212],{"class":1383},[198,2505,2506,2509,2511,2513,2515,2517,2519,2521,2523,2526],{"class":200,"line":1086},[198,2507,2508],{"class":1387},"        $page",[198,2510,2227],{"class":1383},[198,2512,2385],{"class":2202},[198,2514,2206],{"class":1383},[198,2516,2476],{"class":1387},[198,2518,2227],{"class":1383},[198,2520,2230],{"class":2202},[198,2522,2206],{"class":1383},[198,2524,2525],{"class":1424},"'name'",[198,2527,2528],{"class":1383},"));\n",[198,2530,2531,2533,2535,2537,2539,2541,2543,2545,2547,2550],{"class":200,"line":1092},[198,2532,2508],{"class":1387},[198,2534,2227],{"class":1383},[198,2536,2354],{"class":2202},[198,2538,2206],{"class":1383},[198,2540,2476],{"class":1387},[198,2542,2227],{"class":1383},[198,2544,2230],{"class":2202},[198,2546,2206],{"class":1383},[198,2548,2549],{"class":1424},"'title'",[198,2551,2528],{"class":1383},[198,2553,2554,2556,2558,2560,2562,2564,2566,2568,2570,2573],{"class":200,"line":1098},[198,2555,2508],{"class":1387},[198,2557,2227],{"class":1383},[198,2559,2401],{"class":2202},[198,2561,2206],{"class":1383},[198,2563,2476],{"class":1387},[198,2565,2227],{"class":1383},[198,2567,2230],{"class":2202},[198,2569,2206],{"class":1383},[198,2571,2572],{"class":1424},"'content'",[198,2574,2528],{"class":1383},[198,2576,2577],{"class":200,"line":1104},[198,2578,217],{"emptyLinePlaceholder":216},[198,2580,2581,2584,2586,2589,2591,2593],{"class":200,"line":1110},[198,2582,2583],{"class":1387},"        $dm",[198,2585,2227],{"class":1383},[198,2587,2588],{"class":2202},"persist",[198,2590,2206],{"class":1383},[198,2592,2291],{"class":1387},[198,2594,2280],{"class":1383},[198,2596,2597,2599,2601,2604],{"class":200,"line":1116},[198,2598,2583],{"class":1387},[198,2600,2227],{"class":1383},[198,2602,2603],{"class":2202},"flush",[198,2605,2244],{"class":1383},[198,2607,2608],{"class":200,"line":1122},[198,2609,2447],{"class":1383},[198,2611,2612],{"class":200,"line":1128},[198,2613,217],{"emptyLinePlaceholder":216},[198,2615,2616,2619,2622,2624,2627,2630,2632],{"class":200,"line":1134},[198,2617,2618],{"class":1956},"    return",[198,2620,2621],{"class":2220}," array",[198,2623,2206],{"class":1383},[198,2625,2626],{"class":1424},"'page'",[198,2628,2629],{"class":1383}," => ",[198,2631,2291],{"class":1387},[198,2633,2280],{"class":1383},[198,2635,2636],{"class":200,"line":1140},[198,2637,1613],{"class":1383},[11,2639,2640],{},"Et enfin la vue Twig contient les références à CKEditor et l'activation du contenu modifiable inliné\npour les projets. Pour l'instant le module est fortement lié à l'application existante. J'ai dans\nl'espoir d'avoir assez de temps un jour pour externaliser ce module afin de pouvoir le partager à\nplus de monde.",[11,2642,2643,2644,2646],{},"Si vous avez envie d'avoir plus d'information sur ce ",[1812,2645,1814],{}," n'hesitez pas à me contacter et je\nvous réponderez avec joie.",[72,2648,2650],{"id":2649},"les-produits","Les produits",[11,2652,2653],{},"La partie produits et beaucoup plus liée à l'activité du site. Les produits contiennent pour chaque\ncolori, un modèle dans lequel sont définis la position des différentes informations qui seront par\nla suite saisies par l'utilisateur. Ma femme peut ainsi, après avoir préparé son modèle le\npersonnaliser sur le site.",[11,2655,2656],{},"Un document de type produit personnalisé permet ensuite de spécialiser le produit en y ajoutant les\ninformations saisies par l'utilisateur. C'est ce produit final qui est ensuite acheté par\nl'utilisateur.",[72,2658,2660],{"id":2659},"les-paiements","Les paiements",[11,2662,2663],{},"La partie paiement contient la gestion du panier, de la facturation et le lien avec le site Paypal.\nEn effet on utilise l'API de paypal pour effectuer les paiements car nous n'avions pas l'envie de\ngérer pour ce site un système de paiement onéreux et complexe. Paypal prélève un pourcentage de la\ntransaction, et permet le paiement par carte bancaire des utilisateurs anonymes, ce qui nous\nconvient.",[11,2665,2666],{},"Au niveau du panier, certaines informations sont enregistrées, comme le nombre de lignes dans le\npanier, ainsi que le nom du produit et le nom du coloris choisis afin de faciliter le requêtage et\nl'affichage.",[72,2668,2670],{"id":2669},"la-gestion-des-utilisateurs","La gestion des utilisateurs",[11,2672,2673,2674,2677],{},"La gestion des utilisateurs passent par ",[1812,2675,2676],{},"FOS\u002FUserBundle",". Quelques personnalisations ont été\najoutées à ce module afin de correspondre au thème du site et aussi pour ajouter quelques\ninformations.",[72,2679,2681],{"id":2680},"le-site","Le site",[11,2683,2684,2685,2688,2689,2691],{},"Ajoute les ",[1812,2686,2687],{},"CSS"," et ",[1812,2690,1705],{}," personnalisés du site. Le theme a été acheté à une époque sur un\nsite proposant des templates, mais à depuis été customizé et adapté pour notre utilisation.",[72,2693,2695],{"id":2694},"ladmin","L'admin",[11,2697,2698],{},"L'interface d'administration permet à femme et à moi d'accéder aux différents produit, d'en créer de\nnouveau, de les modifiers. L'interface se base sur un thème bootstrape et reste assez simple. Seul\nl'utilisateur avec le role d'administrateur peut accéder à cette page.",[72,2700,2702],{"id":2701},"dans-lavenir","Dans l'avenir",[11,2704,2705,2706,2709,2710,2714],{},"Le découpage actuel ne me plaît pas forcément. En effet, je charge des ",[1812,2707,2708],{},"bundles"," propres à l'admin\nsur le site alors que ces derniers pourraient être chargés uniquement dans le cadre de l'admin et\ninversement. Je pense qu'appliquer une architecture comme celle décrite ici:\n",[15,2711,2712],{"href":2712,"rel":2713},"http:\u002F\u002Fjolicode.com\u002Fblog\u002Fmultiple-applications-with-symfony2",[24],",\npourrait être une bonne idée pour mieux découper l'application.",[11,2716,2717],{},"Dans le même style, la partie CMS actuelle est liée au site, et j'aimerais la découpler du site pour\npouvoir l'utiliser assez facilement dans d'autres projets.",[1714,2719,2721],{"id":2720},"mes-contributions","Mes contributions",[11,2723,2724],{},"Lors du développement de mon projet, j'ai eu besoin de certaines fonctionnalités que je n'ai pas\ntrouvées dans les bundles existants ou qui ne me convenaient pas. Je vous présente ici différents\nprojets que j'ai développé pour pallier à ces manques, sachant que pour l'instant ceux-ci ne sont\npas parfaits et voir même, la documentation peut laisser à désirer (quand aux tests unitaires ils\nsont dans le néant).",[11,2726,2727],{},"Si vous souhaiter aider ou contribuer, n'hésitez pas.",[72,2729,2731],{"id":2730},"collectionbundle","CollectionBundle",[11,2733,2734,2735],{},"Lien: ",[15,2736,2731],{"href":2737,"rel":2738},"http:\u002F\u002Fhg.shadoware.org\u002FSoftware\u002FSymfony2Bundle\u002FCollectionBundle",[24],[11,2740,2741],{},"Dans symfony, il est possible d'ajouter dans un formulaire un type collection pour permettre à un\nutilisateur de saisir une collection de sous-éléments (jointure de type OneToMany):",[190,2743,2745],{"className":1921,"code":2744,"language":1923,"meta":59,"style":59},"$builder->add('emails', 'collection', array(\n    \u002F\u002F chaque item du tableau sera un champ « email »\n    'type'   => 'email',\n    \u002F\u002F ces options sont passées à chaque type « email »\n    'options'  => array(\n        'required'  => false,\n        'attr'      => array('class' => 'email-box')\n    ),\n));\n",[165,2746,2747,2776,2781,2794,2799,2811,2823,2846,2851],{"__ignoreMap":59},[198,2748,2749,2752,2754,2757,2759,2762,2765,2768,2770,2773],{"class":200,"line":201},[198,2750,2751],{"class":1387},"$builder",[198,2753,2227],{"class":1383},[198,2755,2756],{"class":2202},"add",[198,2758,2206],{"class":1383},[198,2760,2761],{"class":1424},"'emails'",[198,2763,2764],{"class":1383},", ",[198,2766,2767],{"class":1424},"'collection'",[198,2769,2764],{"class":1383},[198,2771,2772],{"class":2220},"array",[198,2774,2775],{"class":1383},"(\n",[198,2777,2778],{"class":200,"line":207},[198,2779,2780],{"class":1930},"    \u002F\u002F chaque item du tableau sera un champ « email »\n",[198,2782,2783,2786,2789,2792],{"class":200,"line":213},[198,2784,2785],{"class":1424},"    'type'",[198,2787,2788],{"class":1383},"   => ",[198,2790,2791],{"class":1424},"'email'",[198,2793,1757],{"class":1383},[198,2795,2796],{"class":200,"line":220},[198,2797,2798],{"class":1930},"    \u002F\u002F ces options sont passées à chaque type « email »\n",[198,2800,2801,2804,2807,2809],{"class":200,"line":254},[198,2802,2803],{"class":1424},"    'options'",[198,2805,2806],{"class":1383},"  => ",[198,2808,2772],{"class":2220},[198,2810,2775],{"class":1383},[198,2812,2813,2816,2818,2821],{"class":200,"line":260},[198,2814,2815],{"class":1424},"        'required'",[198,2817,2806],{"class":1383},[198,2819,2820],{"class":1417},"false",[198,2822,1757],{"class":1383},[198,2824,2825,2828,2831,2833,2835,2838,2840,2843],{"class":200,"line":266},[198,2826,2827],{"class":1424},"        'attr'",[198,2829,2830],{"class":1383},"      => ",[198,2832,2772],{"class":2220},[198,2834,2206],{"class":1383},[198,2836,2837],{"class":1424},"'class'",[198,2839,2629],{"class":1383},[198,2841,2842],{"class":1424},"'email-box'",[198,2844,2845],{"class":1383},")\n",[198,2847,2848],{"class":200,"line":272},[198,2849,2850],{"class":1383},"    ),\n",[198,2852,2853],{"class":200,"line":278},[198,2854,2528],{"class":1383},[11,2856,2857],{},"Le problème c'est que dans les formulaires symfony2 il n'est pas possible de gérer des formulaires\ndifférents suivant le sous-type de l'objet (gestion de l'héritage dans l'ORM).",[11,2859,2860],{},"CollectionBundle propose deux nouveaux types :",[83,2862,2863,2866],{},[86,2864,2865],{},"Un type permettant de gérer pour chaque classe fille, un formulaire différent.",[86,2867,2868],{},"Un type permettant de gérer des collections de taille fixe : Exemple toujours 5 éléments, quel\nque soit le nombre d'éléments rééls en base.",[11,2870,2871],{},"Ce bundle est actuellement utilisé uniquement dans la partie admin du site.",[72,2873,2875],{"id":2874},"doctrinemigrationodmbundle","DoctrineMigrationODMBundle",[11,2877,2734,2878],{},[15,2879,2875],{"href":2880,"rel":2881},"http:\u002F\u002Fhg.shadoware.org\u002FSoftware\u002FSymfony2Bundle\u002Fdoctrine-migrations-bundle",[24],[11,2883,2884],{},"Pour l'ORM Doctrine, il existe DoctrineMigrationBundle qui permet de faire des migrations de schéma,\nmais il n'existait pas d'équivalent pour l'ODM gérant MongoDB.",[11,2886,2887],{},"Même si MongoDB est schemaless, et que les données peuvent être migrées à l'execution, je ressens le\nbesoin d'avoir la possiblité d'exécuter des scripts lors des changements de version, pour :",[83,2889,2890,2893,2896],{},[86,2891,2892],{},"ajouter de nouvelles données (nécessaires) dans des tables (car on requête sur ces données).",[86,2894,2895],{},"renommage de collection, suite à gros refactoring.",[86,2897,2898],{},"voir autre",[72,2900,2902],{"id":2901},"fpdi-et-fpdf_tpl","FPDI et FPDF_TPL",[11,2904,2905],{},"Pour la génération des PDF, je génère une première version où chaque page est un élément différent,\npuis je me sers de FPDI pour associer les différentes pages sur une même page (avec la mention\nSPECIMEN ou pas).",[11,2907,2908,2909,2912],{},"Afin d'avoir accès à FPDI je me suis créé les dépôts suivants qui fonctionnent avec ceux de\n",[1812,2910,2911],{},"tecnick.com\u002Ftcpdf"," pour les utilisateurs de TCPDF.",[11,2914,2915],{},"Liens:",[83,2917,2918,2924],{},[86,2919,2920],{},[15,2921,2922],{"href":2922,"rel":2923},"http:\u002F\u002Fhg.shadoware.org\u002FSoftware\u002FSymfony2Bundle\u002Ffpdi",[24],[86,2925,2926],{},[15,2927,2928],{"href":2928,"rel":2929},"http:\u002F\u002Fhg.shadoware.org\u002FSoftware\u002FSymfony2Bundle\u002Ffpdf_tpl",[24],[72,2931,2933],{"id":2932},"imageresizerbundle","ImageResizerBundle",[11,2935,2936,2937],{},"Lien : ",[15,2938,2933],{"href":2939,"rel":2940},"http:\u002F\u002Fhg.shadoware.org\u002FSoftware\u002FSymfony2Bundle\u002FImageResizerBundle",[24],[11,2942,2943,2944,2948],{},"Dérivé de\n",[15,2945,2946],{"href":2946,"rel":2947},"https:\u002F\u002Fgithub.com\u002Fnresni\u002FImageResizerBundle",[24],", ce\nbundle ajoute",[83,2950,2951,2954],{},[86,2952,2953],{},"des caches supplémentaires",[86,2955,2956],{},"fournit une URL sur la valeur du cache directement (et de générer le cache lors de l'appel de la\ncommande twig). Cette dernière permet de cacher un peu l'URL utilisée pour accéder à l'image\nd'origine. On ne peut accéder alors qu'à l'URL finale. Comme les ids des images sont des ObjectId,\nil n'est pas possible de retrouver par le nom l'URL de l'image d'origine.",[11,2958,2959],{},"Cette extension est utilisée par toute l'application pour l'affichage de toutes les miniatures.",[72,2961,2963],{"id":2962},"piwikbundle","PiwikBundle",[11,2965,2936,2966],{},[15,2967,2963],{"href":2968,"rel":2969},"http:\u002F\u002Fhg.shadoware.org\u002FSoftware\u002FSymfony2Bundle\u002FPiwikBundle",[24],[11,2971,2972],{},"Ce plugin a été créé afin de pouvoir ajouter la gestion de Piwik dans Symfony2. Les commandes PIWIK\npeuvent être passées au travers d'un service ou au travers de commandes TWIG. Ce plugin gère\négalement la notion d'e-commerce de PIWIK.",[11,2974,2975],{},"Une fois le plugin installé (via composer), il faut l'activer à l'aide de la configuration suivante:",[190,2977,2981],{"className":2978,"code":2979,"language":2980,"meta":59,"style":59},"language-yaml shiki shiki-themes one-dark-pro","shadoware_piwik:\n  base_url: http:\u002F\u002Fmonpiwik.monsite # URL de base du serveur PIWIK\n  id_site: 1 # N° du site dans PIWIK\n  hidePiwik: false # Indique s'il faut cacher le tracker par un controlleur interne.\n  tokenId: abcedfghijkmn123456789 # Le token id de l'utilisateur (pour le cas où on cache piwik)\n  heartbeat: ~ # Permet de définir quelques attributs activant la fonctionnalité de heatbeat de piwik.\n","yaml",[165,2982,2983,2991,3005,3017,3029,3042],{"__ignoreMap":59},[198,2984,2985,2988],{"class":200,"line":201},[198,2986,2987],{"class":1387},"shadoware_piwik",[198,2989,2990],{"class":1383},":\n",[198,2992,2993,2996,2999,3002],{"class":200,"line":207},[198,2994,2995],{"class":1387},"  base_url",[198,2997,2998],{"class":1383},": ",[198,3000,3001],{"class":1424},"http:\u002F\u002Fmonpiwik.monsite",[198,3003,3004],{"class":1930}," # URL de base du serveur PIWIK\n",[198,3006,3007,3010,3012,3014],{"class":200,"line":213},[198,3008,3009],{"class":1387},"  id_site",[198,3011,2998],{"class":1383},[198,3013,61],{"class":1417},[198,3015,3016],{"class":1930}," # N° du site dans PIWIK\n",[198,3018,3019,3022,3024,3026],{"class":200,"line":220},[198,3020,3021],{"class":1387},"  hidePiwik",[198,3023,2998],{"class":1383},[198,3025,2820],{"class":1417},[198,3027,3028],{"class":1930}," # Indique s'il faut cacher le tracker par un controlleur interne.\n",[198,3030,3031,3034,3036,3039],{"class":200,"line":254},[198,3032,3033],{"class":1387},"  tokenId",[198,3035,2998],{"class":1383},[198,3037,3038],{"class":1424},"abcedfghijkmn123456789",[198,3040,3041],{"class":1930}," # Le token id de l'utilisateur (pour le cas où on cache piwik)\n",[198,3043,3044,3047,3049,3052],{"class":200,"line":260},[198,3045,3046],{"class":1387},"  heartbeat",[198,3048,2998],{"class":1383},[198,3050,3051],{"class":1417},"~",[198,3053,3054],{"class":1930}," # Permet de définir quelques attributs activant la fonctionnalité de heatbeat de piwik.\n",[11,3056,3057],{},"Une fois la configuration faite, le plugin ajoutera juste avant chaque balise  l'appel à\npiwik (en utilisant la méthode asynchrone). Si la page ne contient pas de balise  ou si elle\nconstitue une page de redirection, les informations seront déportées à l'affichage suivant.",[11,3059,3060],{},"Cette dernière fonctionnalité permet par exemple d'ajouter des éléménts au panier e-commerce piwik\nlors des pages de redirection, et de traiter son affichage dès que possible. Cela a par contre comme\nlimitation de ne pas gérer les conflits.",[11,3062,3063],{},"L'utilisation depuis un controlleur se fait grâce à l'utilisation du service:",[190,3065,3067],{"className":1921,"code":3066,"language":1923,"meta":59,"style":59},"$this->container->get('shadoware_piwik.service')->addEcommerceItem($productId, $productName, $category, $amount);\n$this->container->get('shadoware_piwik.service')->trackEcommerceCartUpdate($totalAmount);\n",[165,3068,3069,3114],{"__ignoreMap":59},[198,3070,3071,3073,3075,3078,3080,3082,3084,3087,3089,3092,3094,3097,3099,3102,3104,3107,3109,3112],{"class":200,"line":201},[198,3072,2309],{"class":1960},[198,3074,2227],{"class":1383},[198,3076,3077],{"class":1387},"container",[198,3079,2227],{"class":1383},[198,3081,2230],{"class":2202},[198,3083,2206],{"class":1383},[198,3085,3086],{"class":1424},"'shadoware_piwik.service'",[198,3088,2238],{"class":1383},[198,3090,3091],{"class":2202},"addEcommerceItem",[198,3093,2206],{"class":1383},[198,3095,3096],{"class":1387},"$productId",[198,3098,2764],{"class":1383},[198,3100,3101],{"class":1387},"$productName",[198,3103,2764],{"class":1383},[198,3105,3106],{"class":1387},"$category",[198,3108,2764],{"class":1383},[198,3110,3111],{"class":1387},"$amount",[198,3113,2280],{"class":1383},[198,3115,3116,3118,3120,3122,3124,3126,3128,3130,3132,3135,3137,3140],{"class":200,"line":207},[198,3117,2309],{"class":1960},[198,3119,2227],{"class":1383},[198,3121,3077],{"class":1387},[198,3123,2227],{"class":1383},[198,3125,2230],{"class":2202},[198,3127,2206],{"class":1383},[198,3129,3086],{"class":1424},[198,3131,2238],{"class":1383},[198,3133,3134],{"class":2202},"trackEcommerceCartUpdate",[198,3136,2206],{"class":1383},[198,3138,3139],{"class":1387},"$totalAmount",[198,3141,2280],{"class":1383},[11,3143,3144],{},"L'utilisation depuis une page twig se fait à l'aide des commandes twig. Par exemple dans la page\ntwig de base:",[190,3146,3150],{"className":3147,"code":3148,"language":3149,"meta":59,"style":59},"language-twig shiki shiki-themes one-dark-pro","\u003Ctitle>{{ 'title' | trans }} - {% block title %}{{ 'menu.home' | trans }}{% endblock %}\u003C\u002Ftitle>\n{{ setPiwikPageName(block('title')) }}\n","twig",[165,3151,3152,3202],{"__ignoreMap":59},[198,3153,3154,3156,3159,3162,3164,3167,3170,3173,3176,3179,3182,3185,3187,3189,3192,3195,3198,3200],{"class":200,"line":201},[198,3155,1384],{"class":1383},[198,3157,3158],{"class":1387},"title",[198,3160,3161],{"class":1383},">{{ ",[198,3163,2549],{"class":1424},[198,3165,3166],{"class":1383}," | ",[198,3168,3169],{"class":1387},"trans",[198,3171,3172],{"class":1383}," }} - {% ",[198,3174,3175],{"class":1956},"block",[198,3177,3178],{"class":1387}," title",[198,3180,3181],{"class":1383}," %}{{ ",[198,3183,3184],{"class":1424},"'menu.home'",[198,3186,3166],{"class":1383},[198,3188,3169],{"class":1387},[198,3190,3191],{"class":1383}," }}{% ",[198,3193,3194],{"class":1956},"endblock",[198,3196,3197],{"class":1383}," %}\u003C\u002F",[198,3199,3158],{"class":1387},[198,3201,1391],{"class":1383},[198,3203,3204,3207,3209,3211,3213],{"class":200,"line":207},[198,3205,3206],{"class":1383},"{{ setPiwikPageName(",[198,3208,3175],{"class":2220},[198,3210,2206],{"class":1383},[198,3212,2549],{"class":1424},[198,3214,3215],{"class":1383},")) }}\n",[3217,3218,1620],"h1",{"id":1619},[11,3220,3221],{},"Bon voilà j'espère vous avoir fait découvrir le site ainsi que quelques nouveaux plugins\nintéressant.",[11,3223,3224],{},"A bientôt,",[1660,3226,3227],{},"html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sU0A5, html code.shiki .sU0A5{--shiki-default:#E5C07B}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .shdRp, html code.shiki .shdRp{--shiki-default:#C678DD;--shiki-default-font-style:italic}html pre.shiki code .sKU4T, html code.shiki .sKU4T{--shiki-default:#E5C07B;--shiki-default-font-style:italic}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}",{"title":59,"searchDepth":207,"depth":207,"links":3229},[3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3243,3244,3245,3246,3247],{"id":1716,"depth":213,"text":1717},{"id":1797,"depth":213,"text":1798},{"id":1821,"depth":213,"text":1793},{"id":1870,"depth":213,"text":1871},{"id":1880,"depth":207,"text":1881},{"id":2649,"depth":207,"text":2650},{"id":2659,"depth":207,"text":2660},{"id":2669,"depth":207,"text":2670},{"id":2680,"depth":207,"text":2681},{"id":2694,"depth":207,"text":2695},{"id":2701,"depth":207,"text":2702,"children":3241},[3242],{"id":2720,"depth":213,"text":2721},{"id":2730,"depth":207,"text":2731},{"id":2874,"depth":207,"text":2875},{"id":2901,"depth":207,"text":2902},{"id":2932,"depth":207,"text":2933},{"id":2962,"depth":207,"text":2963},"2014-03-19",{"type":8,"value":3250},[3251,3253,3255,3260,3265],[1714,3252,1717],{"id":1716},[11,3254,1720],{},[11,3256,1723,3257,1729],{},[15,3258,1728],{"href":1726,"rel":3259},[24],[11,3261,3262,1737],{},[15,3263,1736],{"href":1734,"rel":3264},[24],[11,3266,1740],{},{},"\u002Fpost\u002Fmonlivretdemesse-fr",{"title":1710,"description":59},"monlivretdemesse-fr","posts\u002FLogiciels\u002F2014-03-19-monlivretdemesse-fr",[1704,3273,3274,3275],"livrets","mariage","bapteme","CLzxUTrMi7D7_9aacVnIiqCI2iUc0MClvm1Kv0yZXCA",{"id":3278,"title":3279,"author":6,"body":3280,"category":1672,"categorySlug":1673,"date":4259,"description":3284,"excerpt":4260,"extension":194,"location":1697,"meta":4270,"navigation":216,"path":4271,"published":216,"seo":4272,"slug":4273,"stem":4274,"tags":4275,"timeToRead":272,"__hash__":4276},"posts\u002Fposts\u002FLogiciels\u002F2013-01-12-migration-to-pelican.md","Passage du site sous Pelican",{"type":8,"value":3281,"toc":4245},[3282,3285,3288,3291,3294,3298,3301,3304,3307,3310,3313,3316,3327,3330,3347,3350,3354,3357,3360,3363,3367,3370,3373,3377,3387,3394,3397,3400,3404,3411,3418,3422,3431,3434,3467,3470,3473,3490,3493,3496,3500,3503,3513,3516,3625,3628,3688,3691,3796,3813,3817,3824,3827,3846,3852,3858,3862,3865,3872,4029,4032,4035,4041,4045,4048,4051,4054,4057,4102,4112,4116,4119,4143,4153,4223,4226,4242],[11,3283,3284],{},"Bonjour à tous,",[11,3286,3287],{},"Cela fait bien longtemps que je n'ai rien écrit sur ce site. Et pour\ncause, je suis bien occupé 😄.",[11,3289,3290],{},"J'ai quand même pris un peu de temps récemment pour passer entièrement mon\nsite sous Pelican.",[11,3292,3293],{},"C'est mon cadeau de Noël de Geek ;).",[72,3295,3297],{"id":3296},"quest-ce-que-pelican","Qu'est-ce que Pelican ?",[11,3299,3300],{},"Pelican est un gestionnaire de blog statique.",[11,3302,3303],{},"Qu'est-ce que ça veut dire ?",[11,3305,3306],{},"Cela signifie que je vais écrire mes billets avec mon éditeur de texte\npréféré (kwrite), au format Markdown (ou restructuredText), et que je\ngénère mon blog au format HTML avant publication. (De la même manière que\nl'on compilerait un programme).",[11,3308,3309],{},"Le serveur n'a alors besoin de servir que des fichiers statiques, il n'y\na donc pas de surplus de mémoire, ou de délai dû à la nécessité de\ngénérer les pages.",[11,3311,3312],{},"Les pages n'étant pas modifiées tous les jours, il n'y a de toute façon\npas d'intérêt de générer les pages à chaque accès.",[11,3314,3315],{},"Les avantages indéniables sont les suivants :",[83,3317,3318,3321,3324],{},[86,3319,3320],{},"Pas de base de données, pas de page générée à la volée : donc pas de\ntemps de latence. La page est servie dés qu'elle est demandée. De plus\nil existe un plugin permettant de générer les pages au format pré-zippé,\nce qui fait un traitement de moins sur le serveur.",[86,3322,3323],{},"Pas de faille de sécurité dû à un script mal paramétré.",[86,3325,3326],{},"Je peux gérer mes billets sous un gestionnaire de version (exemple\nMercurial).",[11,3328,3329],{},"Par contre les inconvénients sont :",[83,3331,3332,3341,3344],{},[86,3333,3334,3335,3340],{},"Plus de commentaire direct sur le blog (sauf à utiliser des plateformes\ntel que ",[15,3336,3339],{"href":3337,"rel":3338},"http:\u002F\u002Fdisqus.com\u002F",[24],"disqus",")",[86,3342,3343],{},"Je dois installer le générateur de blog sur la\u002Fles machines que je\nsouhaite utiliser pour générer le blog.",[86,3345,3346],{},"Je dois ensuite utiliser SCP pour transférer mon blog.",[11,3348,3349],{},"Pour les deux derniers points, ils sont de mon choix. D'autres installent\nces outils sur le serveur, ils peuvent donc générer leur page directement\nà partir du serveur.",[72,3351,3353],{"id":3352},"les-implications","Les implications",[11,3355,3356],{},"Les conséquences pour ce blog sont donc : plus de commentaire (jusqu'à\nnouvel ordre). Vous pouvez toujours m'envoyer un mail, pour poser une\nquestion, je l'ajouterai manuellement en tant que commentaire.",[11,3358,3359],{},"Je garde tout de même les anciens commentaires, qui peuvent contenir\nparfois quelques informations utiles.",[11,3361,3362],{},"J'ai également profité de ce petit changement pour faire un petit\nnettoyage et j'ai supprimé tous les billets d'humeur, pour ne garder que\nles articles réellement intéressant.",[72,3364,3366],{"id":3365},"comment-sest-déroulé-la-conversion","Comment s'est déroulé la conversion ?",[11,3368,3369],{},"Dans cette partie, je vais décrire le déroulement de la conversion du\nblog.",[11,3371,3372],{},"Cette conversion comprend les articles, les commentaires et le thème.",[1714,3374,3376],{"id":3375},"exportation-des-billets-provenant-de-dotclear","Exportation des billets provenant de dotclear",[11,3378,3379,3380,3382,3383,3386],{},"Il a d'abord fallu exporter les billets depuis le site sous\n",[1812,3381,25],{},". Sous Dotclear, dans la partie administration, il est possible\nd'utiliser le plugin ",[165,3384,3385],{},"Import\u002FExport"," pour exporter le site dans un fichier\ntexte.",[11,3388,3389],{},[3390,3391],"img",{"alt":3392,"src":3393},"Export","\u002FLogiciels\u002Fmigration\u002Fdotclear_export.png",[11,3395,3396],{},"Le fichier texte se présente alors comme un mixte entre un fichier INI et\nun ensemble de fichier CSV. Il contient, les catégories, les articles, et\nles commentaires.",[11,3398,3399],{},"Ce fichier peut alors être utilisé avec l'outil d'import de pelican pour\nrécupérer les différents billets.",[1714,3401,3403],{"id":3402},"création-dun-environnement-pour-pelican","Création d'un environnement pour pelican",[11,3405,3406,3407,3410],{},"La création de l'environnement se fait comme décrit sur le ",[198,3408,3409],{},"site de\npelican",". Je ne vais donc pas le décrire une fois de plus.",[11,3412,3413,3414,3417],{},"Une fois installé, les billets sont à placer dans le dossier ",[165,3415,3416],{},"content",".\nLes fichiers générés par l'import seront donc placés dans ce dossier.",[1714,3419,3421],{"id":3420},"importation-des-billets-au-format-markdown","Importation des billets au format Markdown",[11,3423,3424,3425,3430],{},"L'import est décrit dans la ",[15,3426,3429],{"href":3427,"rel":3428},"http:\u002F\u002Fdocs.getpelican.com\u002Fen\u002Flatest\u002Fimporter.html",[24],"documentation de pelican",". Après différents\ntests, l'import au format Markdown a été celui qui a donné de meilleurs\nrésultats.",[11,3432,3433],{},"Voici donc la commande qui m'a permis de réaliser cet import :",[190,3435,3439],{"className":3436,"code":3437,"language":3438,"meta":59,"style":59},"language-bash shiki shiki-themes one-dark-pro","pelican-import --dotclear -m markdown --dir-cat 2012-12-11-shadoware-backup.txt -o content\n","bash",[165,3440,3441],{"__ignoreMap":59},[198,3442,3443,3446,3449,3452,3455,3458,3461,3464],{"class":200,"line":201},[198,3444,3445],{"class":2202},"pelican-import",[198,3447,3448],{"class":1417}," --dotclear",[198,3450,3451],{"class":1417}," -m",[198,3453,3454],{"class":1424}," markdown",[198,3456,3457],{"class":1417}," --dir-cat",[198,3459,3460],{"class":1424}," 2012-12-11-shadoware-backup.txt",[198,3462,3463],{"class":1417}," -o",[198,3465,3466],{"class":1424}," content\n",[11,3468,3469],{},"Cela m'a généré une liste de 65 fichiers : 1 par billet. Parmi ces\nbillets, j'ai fait le tri, et j'ai supprimé les billets d'humeur. J'ai\najouté également un tag indiquant l'état de draft sur quelques billets qui\nsont en cours d'écriture et que je n'ai pas encore eu le temps de\nterminer et de publier.",[11,3471,3472],{},"Puis j'ai effectué une passe sur chaque billet, pour",[83,3474,3475,3478,3481,3484,3487],{},[86,3476,3477],{},"reprendre les parties de code (coloration syntaxique),",[86,3479,3480],{},"reprendre les tableaux,",[86,3482,3483],{},"reprendre les tags (qui n'ont pas été importés),",[86,3485,3486],{},"corriger les dates (la date était celle de création du poste, et non\ncelle de publication),",[86,3488,3489],{},"modification des catégories.",[11,3491,3492],{},"Sous dotclear, j'avais fait plusieurs niveaux de catégories, alors que\nsous pelican, il n'y a qu'un seul niveau de catégorie. J'ai donc dû mettre\nà plat les différentes catégories.",[11,3494,3495],{},"Pour les tableaux, ces derniers étaient repris directement au format HTML,\nils étaient donc exploitables directement. J'ai préféré refaire les\ntableaux au format Markdown.",[1714,3497,3499],{"id":3498},"ajustement-du-fichier-de-configuration","Ajustement du fichier de configuration",[11,3501,3502],{},"Viennent ensuite les ajustements faits dans le fichier de configuration,\npour que les URL des articles sous dotclear soient les plus proches\npossibles des nouvelles URL.",[11,3504,3505,3506,3509,3510,41],{},"Pour cela, j'ai choisi d'avoir les mêmes adresses que sur le site dotclear\nsuivies de ",[165,3507,3508],{},".html"," ou de ",[165,3511,3512],{},".xml",[11,3514,3515],{},"Dans le fichier, j'ai positionné les variables pelicanconf.py",[190,3517,3521],{"className":3518,"code":3519,"language":3520,"meta":59,"style":59},"language-python shiki shiki-themes one-dark-pro","ARTICLE_URL = 'post\u002F{slug}.html'\nARTICLE_SAVE_AS = 'post\u002F{slug}.html'\nAUTHOR_SAVE_AS = False\n\nFEED_DOMAIN = SITEURL\nFEED_ALL_ATOM = 'feed\u002Fatom.xml'\nCATEGORY_FEED_ATOM = 'feed\u002Fcategory\u002F%s\u002Fatom.xml'\nTAG_FEED_ATOM = 'feed\u002Ftags\u002F%s\u002Fatom.xml'\nTRANSLATION_FEED_ATOM = False\n","python",[165,3522,3523,3539,3552,3562,3566,3576,3586,3602,3616],{"__ignoreMap":59},[198,3524,3525,3528,3530,3533,3536],{"class":200,"line":201},[198,3526,3527],{"class":1417},"ARTICLE_URL",[198,3529,2221],{"class":2220},[198,3531,3532],{"class":1424}," 'post\u002F",[198,3534,3535],{"class":1417},"{slug}",[198,3537,3538],{"class":1424},".html'\n",[198,3540,3541,3544,3546,3548,3550],{"class":200,"line":207},[198,3542,3543],{"class":1417},"ARTICLE_SAVE_AS",[198,3545,2221],{"class":2220},[198,3547,3532],{"class":1424},[198,3549,3535],{"class":1417},[198,3551,3538],{"class":1424},[198,3553,3554,3557,3559],{"class":200,"line":213},[198,3555,3556],{"class":1417},"AUTHOR_SAVE_AS",[198,3558,2221],{"class":2220},[198,3560,3561],{"class":1417}," False\n",[198,3563,3564],{"class":200,"line":220},[198,3565,217],{"emptyLinePlaceholder":216},[198,3567,3568,3571,3573],{"class":200,"line":254},[198,3569,3570],{"class":1417},"FEED_DOMAIN",[198,3572,2221],{"class":2220},[198,3574,3575],{"class":1417}," SITEURL\n",[198,3577,3578,3581,3583],{"class":200,"line":260},[198,3579,3580],{"class":1417},"FEED_ALL_ATOM",[198,3582,2221],{"class":2220},[198,3584,3585],{"class":1424}," 'feed\u002Fatom.xml'\n",[198,3587,3588,3591,3593,3596,3599],{"class":200,"line":266},[198,3589,3590],{"class":1417},"CATEGORY_FEED_ATOM",[198,3592,2221],{"class":2220},[198,3594,3595],{"class":1424}," 'feed\u002Fcategory\u002F",[198,3597,3598],{"class":1417},"%s",[198,3600,3601],{"class":1424},"\u002Fatom.xml'\n",[198,3603,3604,3607,3609,3612,3614],{"class":200,"line":272},[198,3605,3606],{"class":1417},"TAG_FEED_ATOM",[198,3608,2221],{"class":2220},[198,3610,3611],{"class":1424}," 'feed\u002Ftags\u002F",[198,3613,3598],{"class":1417},[198,3615,3601],{"class":1424},[198,3617,3618,3621,3623],{"class":200,"line":278},[198,3619,3620],{"class":1417},"TRANSLATION_FEED_ATOM",[198,3622,2221],{"class":2220},[198,3624,3561],{"class":1417},[11,3626,3627],{},"Dans le fichier, j'ai positionné les variables publishconf.py",[190,3629,3631],{"className":3518,"code":3630,"language":3520,"meta":59,"style":59},"ARTICLE_URL = 'post\u002F{slug}'\nPAGE_URL = 'pages\u002F{slug}'\nCATEGORY_URL = 'category\u002F{slug}'\nTAG_URL = 'tag\u002F{slug}'\n",[165,3632,3633,3646,3660,3674],{"__ignoreMap":59},[198,3634,3635,3637,3639,3641,3643],{"class":200,"line":201},[198,3636,3527],{"class":1417},[198,3638,2221],{"class":2220},[198,3640,3532],{"class":1424},[198,3642,3535],{"class":1417},[198,3644,3645],{"class":1424},"'\n",[198,3647,3648,3651,3653,3656,3658],{"class":200,"line":207},[198,3649,3650],{"class":1417},"PAGE_URL",[198,3652,2221],{"class":2220},[198,3654,3655],{"class":1424}," 'pages\u002F",[198,3657,3535],{"class":1417},[198,3659,3645],{"class":1424},[198,3661,3662,3665,3667,3670,3672],{"class":200,"line":213},[198,3663,3664],{"class":1417},"CATEGORY_URL",[198,3666,2221],{"class":2220},[198,3668,3669],{"class":1424}," 'category\u002F",[198,3671,3535],{"class":1417},[198,3673,3645],{"class":1424},[198,3675,3676,3679,3681,3684,3686],{"class":200,"line":220},[198,3677,3678],{"class":1417},"TAG_URL",[198,3680,2221],{"class":2220},[198,3682,3683],{"class":1424}," 'tag\u002F",[198,3685,3535],{"class":1417},[198,3687,3645],{"class":1424},[11,3689,3690],{},"Du coté de nginx, le serveur d'application, j'ai ajouté les lignes\nsuivantes :",[190,3692,3696],{"className":3693,"code":3694,"language":3695,"meta":59,"style":59},"language-nginx shiki shiki-themes one-dark-pro","rewrite ^\u002Fdotclear\u002Findex.php\u002Fpost\u002F\\d+\u002F\\d+\u002F\\d+\u002F\\d+-(.*)$ \u002Fpost\u002F$1 permanent;\nrewrite ^\u002Fpost\u002F\\d+\u002F\\d+\u002F\\d+\u002F\\d+-(.*)$ \u002Fpost\u002F$1 permanent;\nrewrite ^\u002Fpost\u002F\\d+\u002F\\d+\u002F\\d+\u002F(.*)$ \u002Fpost\u002F$1 permanent;\n\nlocation \u002F {\n    try_files $uri.html $uri.xml $uri $uri\u002F =404;\n}\n","nginx",[165,3697,3698,3716,3731,3746,3750,3758,3792],{"__ignoreMap":59},[198,3699,3700,3703,3706,3709,3711,3714],{"class":200,"line":201},[198,3701,3702],{"class":1956},"rewrite",[198,3704,3705],{"class":1387}," ^\u002Fdotclear\u002Findex.php\u002Fpost\u002F\\d+\u002F\\d+\u002F\\d+\u002F\\d+-(.*)$",[198,3707,3708],{"class":1383}," \u002Fpost\u002F$",[198,3710,61],{"class":1387},[198,3712,3713],{"class":1956}," permanent",[198,3715,2008],{"class":1383},[198,3717,3718,3720,3723,3725,3727,3729],{"class":200,"line":207},[198,3719,3702],{"class":1956},[198,3721,3722],{"class":1387}," ^\u002Fpost\u002F\\d+\u002F\\d+\u002F\\d+\u002F\\d+-(.*)$",[198,3724,3708],{"class":1383},[198,3726,61],{"class":1387},[198,3728,3713],{"class":1956},[198,3730,2008],{"class":1383},[198,3732,3733,3735,3738,3740,3742,3744],{"class":200,"line":213},[198,3734,3702],{"class":1956},[198,3736,3737],{"class":1387}," ^\u002Fpost\u002F\\d+\u002F\\d+\u002F\\d+\u002F(.*)$",[198,3739,3708],{"class":1383},[198,3741,61],{"class":1387},[198,3743,3713],{"class":1956},[198,3745,2008],{"class":1383},[198,3747,3748],{"class":200,"line":220},[198,3749,217],{"emptyLinePlaceholder":216},[198,3751,3752,3755],{"class":200,"line":254},[198,3753,3754],{"class":1956},"location",[198,3756,3757],{"class":1383}," \u002F {\n",[198,3759,3760,3763,3766,3769,3772,3774,3777,3779,3782,3784,3787,3790],{"class":200,"line":260},[198,3761,3762],{"class":1956},"    try_files ",[198,3764,3765],{"class":1383},"$",[198,3767,3768],{"class":1387},"uri",[198,3770,3771],{"class":1383},".html $",[198,3773,3768],{"class":1387},[198,3775,3776],{"class":1383},".xml $",[198,3778,3768],{"class":1387},[198,3780,3781],{"class":1383}," $",[198,3783,3768],{"class":1387},[198,3785,3786],{"class":1383},"\u002F ",[198,3788,3789],{"class":1417},"=404",[198,3791,2008],{"class":1383},[198,3793,3794],{"class":200,"line":266},[198,3795,1613],{"class":1383},[11,3797,3798,3799,3802,3803,3806,3807,3809,3810,3812],{},"Les premières lignes permettent de reprendre les anciennes adresses\n",[165,3800,3801],{},"dotclear",", et la commande ",[165,3804,3805],{},"try_files"," permet de reprendre les adresses\nexistantes et de les compléter par ",[165,3808,3508],{}," et par ",[165,3811,3512],{}," selon le besoin.",[1714,3814,3816],{"id":3815},"modification-du-thème","Modification du thème",[11,3818,3819,3820,3823],{},"Enfin j'ai écrit un nouveau thème dans le dossier ",[165,3821,3822],{},"themes\u002Fshadoware",". Ce\nthème est fait pour coller le plus possible à celui que j'avais sur le\nsite dotclear.",[11,3825,3826],{},"Il génère donc la page de la même manière que dotclear le faisait (à\nquelques différences prés) pour éviter de devoir ré-écrire la feuille de\nstyle CSS.",[11,3828,3829,3830,3835,3836,3839,3840,3843,3844,41],{},"L'écriture du thème n'est en soit pas très compliqué, car ",[15,3831,3834],{"href":3832,"rel":3833},"http:\u002F\u002Fjinja.pocoo.org\u002Fdocs\u002F",[24],"jinja2"," est\nassez simple d'utilisation. Je me suis inspiré des thèmes ",[165,3837,3838],{},"simple"," et\n",[165,3841,3842],{},"notmyidea"," pour écrire le thème, basé sur celui que j'avais sous\n",[165,3845,3801],{},[11,3847,3848,3849,41],{},"Vous pouvez trouver le thème au ",[198,3850,3851],{},"lien suivant",[11,3853,3854],{},[3390,3855],{"alt":3856,"src":3857},"Theme","\u002FLogiciels\u002Fmigration\u002Fsite.png",[1714,3859,3861],{"id":3860},"importation-des-commentaires","Importation des commentaires",[11,3863,3864],{},"Les commentaires existants sur mon blog actuel peuvent parfois contenir\ndes informations complémentaires. Les ignorer lors de la migration est\ntout a fait possible, mais j'ai préféré les récupérer.",[11,3866,3867,3868,3871],{},"Pour cela j'ai installé le ",[198,3869,3870],{},"plugin comments",". Ensuite j'ai modifié le\nthème pour ajouter l'affichage des commentaires :",[190,3873,3875],{"className":1374,"code":3874,"language":1376,"meta":59,"style":59},"{% if article.comments %}\n\u003Cdiv id=\"comments\">\n  \u003Ch3>Commentaires\u003C\u002Fh3>\n  \u003Cdl>\n    {% for comment in article.comments %}\n    \u003Cdt>\n      \u003Ca class=\"comment-number\" href=\"#\">{{ loop.index }}.\u003C\u002Fa>\n      Le {{ comment.date }} par {{ comment.author }}\n    \u003C\u002Fdt>\n    \u003Cdd>\n      \u003Cp>{{ comment.content }}\u003C\u002Fp>\n    \u003C\u002Fdd>\n    {% endfor %}\n  \u003C\u002Fdl>\n\u003C\u002Fdiv>\n{% endif %}\n",[165,3876,3877,3882,3896,3909,3918,3923,3932,3960,3965,3973,3982,3995,4003,4008,4016,4024],{"__ignoreMap":59},[198,3878,3879],{"class":200,"line":201},[198,3880,3881],{"class":1383},"{% if article.comments %}\n",[198,3883,3884,3886,3888,3890,3892,3894],{"class":200,"line":207},[198,3885,1384],{"class":1383},[198,3887,1414],{"class":1387},[198,3889,1437],{"class":1417},[198,3891,1421],{"class":1383},[198,3893,1442],{"class":1424},[198,3895,1391],{"class":1383},[198,3897,3898,3900,3902,3905,3907],{"class":200,"line":213},[198,3899,1401],{"class":1383},[198,3901,1714],{"class":1387},[198,3903,3904],{"class":1383},">Commentaires\u003C\u002F",[198,3906,1714],{"class":1387},[198,3908,1391],{"class":1383},[198,3910,3911,3913,3916],{"class":200,"line":220},[198,3912,1401],{"class":1383},[198,3914,3915],{"class":1387},"dl",[198,3917,1391],{"class":1383},[198,3919,3920],{"class":200,"line":254},[198,3921,3922],{"class":1383},"    {% for comment in article.comments %}\n",[198,3924,3925,3927,3930],{"class":200,"line":260},[198,3926,1411],{"class":1383},[198,3928,3929],{"class":1387},"dt",[198,3931,1391],{"class":1383},[198,3933,3934,3936,3938,3940,3942,3945,3948,3950,3953,3956,3958],{"class":200,"line":266},[198,3935,1432],{"class":1383},[198,3937,15],{"class":1387},[198,3939,1418],{"class":1417},[198,3941,1421],{"class":1383},[198,3943,3944],{"class":1424},"\"comment-number\"",[198,3946,3947],{"class":1417}," href",[198,3949,1421],{"class":1383},[198,3951,3952],{"class":1424},"\"#\"",[198,3954,3955],{"class":1383},">{{ loop.index }}.\u003C\u002F",[198,3957,15],{"class":1387},[198,3959,1391],{"class":1383},[198,3961,3962],{"class":200,"line":272},[198,3963,3964],{"class":1383},"      Le {{ comment.date }} par {{ comment.author }}\n",[198,3966,3967,3969,3971],{"class":200,"line":278},[198,3968,1535],{"class":1383},[198,3970,3929],{"class":1387},[198,3972,1391],{"class":1383},[198,3974,3975,3977,3980],{"class":200,"line":283},[198,3976,1411],{"class":1383},[198,3978,3979],{"class":1387},"dd",[198,3981,1391],{"class":1383},[198,3983,3984,3986,3988,3991,3993],{"class":200,"line":288},[198,3985,1432],{"class":1383},[198,3987,11],{"class":1387},[198,3989,3990],{"class":1383},">{{ comment.content }}\u003C\u002F",[198,3992,11],{"class":1387},[198,3994,1391],{"class":1383},[198,3996,3997,3999,4001],{"class":200,"line":450},[198,3998,1535],{"class":1383},[198,4000,3979],{"class":1387},[198,4002,1391],{"class":1383},[198,4004,4005],{"class":200,"line":456},[198,4006,4007],{"class":1383},"    {% endfor %}\n",[198,4009,4010,4012,4014],{"class":200,"line":462},[198,4011,1544],{"class":1383},[198,4013,3915],{"class":1387},[198,4015,1391],{"class":1383},[198,4017,4018,4020,4022],{"class":200,"line":468},[198,4019,1553],{"class":1383},[198,4021,1414],{"class":1387},[198,4023,1391],{"class":1383},[198,4025,4026],{"class":200,"line":473},[198,4027,4028],{"class":1383},"{% endif %}\n",[11,4030,4031],{},"Cela permet d'afficher les commentaires à l'aide du plugin. Par contre le\nproblème est que les commentaires provenant de dotclear ne sont pas\nimportés.",[11,4033,4034],{},"Du coup j'ai modifié le script d'import, pour en faire un qui importe les\ncommentaires. Il doit être lancé séparément du script d'import\ntraditionnel.",[11,4036,4037,4040],{},[198,4038,4039],{},"Voici donc le script"," permettant de récupérer les commentaires.",[1714,4042,4044],{"id":4043},"gestion-du-tag-planet-libre","Gestion du tag planet libre",[11,4046,4047],{},"Afin de pouvoir publier des articles sur le planet libre, je proposais\njusqu'ici des articles sur le planet libre à l'aide d'un tag de type\nplanet.",[11,4049,4050],{},"L'utilisation d'un tag de type planet permet de filtrer les articles\nque je souhaite mettre sur le planet libre. Par contre avec pelican,\nl'utilisation de ce tag fausse le calcul des billets liés.",[11,4052,4053],{},"Du coup j'ai décidé que la génération du flux ATOM donné au planet sera\ngénérée avec les articles qui posséderont un metatag déposé au début de\nchaque billet. Sous la présence du tag avec la valeur true, le billet est\najouté dans le flux ATOM des planets.",[11,4055,4056],{},"Pour ajouter le tag, il faut donc au début de l'article écrire le texte\nsuivant :",[190,4058,4062],{"className":4059,"code":4060,"language":4061,"meta":59,"style":59},"language-markdown shiki shiki-themes one-dark-pro","Title: Passage du site sous Pelican\nTags: dedie\nPlanet: true\n\nBonjour à tous,\n\nCela fait bien longtemps que je n'ai rien écrit sur ce site. Et pour\ncause, je suis bien occupé 😄.\n","markdown",[165,4063,4064,4069,4074,4079,4083,4088,4092,4097],{"__ignoreMap":59},[198,4065,4066],{"class":200,"line":201},[198,4067,4068],{"class":1383},"Title: Passage du site sous Pelican\n",[198,4070,4071],{"class":200,"line":207},[198,4072,4073],{"class":1383},"Tags: dedie\n",[198,4075,4076],{"class":200,"line":213},[198,4077,4078],{"class":1383},"Planet: true\n",[198,4080,4081],{"class":200,"line":220},[198,4082,217],{"emptyLinePlaceholder":216},[198,4084,4085],{"class":200,"line":254},[198,4086,4087],{"class":1383},"Bonjour à tous,\n",[198,4089,4090],{"class":200,"line":260},[198,4091,217],{"emptyLinePlaceholder":216},[198,4093,4094],{"class":200,"line":266},[198,4095,4096],{"class":1383},"Cela fait bien longtemps que je n'ai rien écrit sur ce site. Et pour\n",[198,4098,4099],{"class":200,"line":272},[198,4100,4101],{"class":1383},"cause, je suis bien occupé 😄.\n",[11,4103,4104,4105,4108,4109,41],{},"Pour ce faire j'ai écrit une extension à pelican qui génére un flux nommé\n",[165,4106,4107],{},"{OUTPUT_PATH}\u002F{TAG_FEED_ATOM}"," (avec %s remplacé par planet). Vous pouvez\ntélécharger l'",[198,4110,4111],{},"extension au lien suivant",[1714,4113,4115],{"id":4114},"création-dune-page-404","Création d'une page 404",[11,4117,4118],{},"Afin d'avoir une belle page 404 si la page n'est pas correctement trouvée\n(par exemple si certaines URLs ne correspondent plus à celle de dotclear),\nj'ai défini au niveau de pelican, la création d'une belle page 404 de la\nmanière suivante :",[190,4120,4122],{"className":3518,"code":4121,"language":3520,"meta":59,"style":59},"TEMPLATE_PAGES = {'error404.html': 'error404.html'}\n",[165,4123,4124],{"__ignoreMap":59},[198,4125,4126,4129,4131,4134,4137,4139,4141],{"class":200,"line":201},[198,4127,4128],{"class":1417},"TEMPLATE_PAGES",[198,4130,2221],{"class":2220},[198,4132,4133],{"class":1383}," {",[198,4135,4136],{"class":1424},"'error404.html'",[198,4138,2998],{"class":1383},[198,4140,4136],{"class":1424},[198,4142,1613],{"class":1383},[11,4144,4145,4146,4148,4149,4152],{},"J'ai alors créé dans le dossier ",[165,4147,3416],{}," le fichier ",[165,4150,4151],{},"error404.html"," avec\nle contenu suivant :",[190,4154,4157],{"className":4155,"code":4156,"language":3834,"meta":59,"style":59},"language-jinja2 shiki shiki-themes one-dark-pro","{% extends \"base.html\" %}\n{% block title %}Page non trouvée{% endblock %}\n{% block piwik_title %}404{% endblock %}\n{% block content %}\n\u003Csection id=\"content\">\n    \u003Cdiv id=\"content-info\">\n        \u003Ch2>Document non trouvé\u003C\u002Fh2>\n    \u003C\u002Fdiv>\n    \u003Cdiv class=\"content-inner\">\n        \u003Cp>Le document que vous cherchez n'existe pas.\u003C\u002Fp>\n    \u003C\u002Fdiv>\n\u003C\u002Fsection>\n{% endblock %}\n",[165,4158,4159,4164,4169,4174,4179,4184,4189,4194,4199,4204,4209,4213,4218],{"__ignoreMap":59},[198,4160,4161],{"class":200,"line":201},[198,4162,4163],{},"{% extends \"base.html\" %}\n",[198,4165,4166],{"class":200,"line":207},[198,4167,4168],{},"{% block title %}Page non trouvée{% endblock %}\n",[198,4170,4171],{"class":200,"line":213},[198,4172,4173],{},"{% block piwik_title %}404{% endblock %}\n",[198,4175,4176],{"class":200,"line":220},[198,4177,4178],{},"{% block content %}\n",[198,4180,4181],{"class":200,"line":254},[198,4182,4183],{},"\u003Csection id=\"content\">\n",[198,4185,4186],{"class":200,"line":260},[198,4187,4188],{},"    \u003Cdiv id=\"content-info\">\n",[198,4190,4191],{"class":200,"line":266},[198,4192,4193],{},"        \u003Ch2>Document non trouvé\u003C\u002Fh2>\n",[198,4195,4196],{"class":200,"line":272},[198,4197,4198],{},"    \u003C\u002Fdiv>\n",[198,4200,4201],{"class":200,"line":278},[198,4202,4203],{},"    \u003Cdiv class=\"content-inner\">\n",[198,4205,4206],{"class":200,"line":283},[198,4207,4208],{},"        \u003Cp>Le document que vous cherchez n'existe pas.\u003C\u002Fp>\n",[198,4210,4211],{"class":200,"line":288},[198,4212,4198],{},[198,4214,4215],{"class":200,"line":450},[198,4216,4217],{},"\u003C\u002Fsection>\n",[198,4219,4220],{"class":200,"line":456},[198,4221,4222],{},"{% endblock %}\n",[11,4224,4225],{},"Enfin, comme j'utilise le serveur nginx pour servir mes pages j'ai ajouté\nla règle (toute simple) suivante pour définir ma page 404 :",[190,4227,4229],{"className":3693,"code":4228,"language":3695,"meta":59,"style":59},"error_page 404 \u002Ferror404.html;\n",[165,4230,4231],{"__ignoreMap":59},[198,4232,4233,4236,4239],{"class":200,"line":201},[198,4234,4235],{"class":1956},"error_page ",[198,4237,4238],{"class":1417},"404",[198,4240,4241],{"class":1383}," \u002Ferror404.html;\n",[1660,4243,4244],{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}",{"title":59,"searchDepth":207,"depth":207,"links":4246},[4247,4248,4249],{"id":3296,"depth":207,"text":3297},{"id":3352,"depth":207,"text":3353},{"id":3365,"depth":207,"text":3366,"children":4250},[4251,4252,4253,4254,4255,4256,4257,4258],{"id":3375,"depth":213,"text":3376},{"id":3402,"depth":213,"text":3403},{"id":3420,"depth":213,"text":3421},{"id":3498,"depth":213,"text":3499},{"id":3815,"depth":213,"text":3816},{"id":3860,"depth":213,"text":3861},{"id":4043,"depth":213,"text":4044},{"id":4114,"depth":213,"text":4115},"2013-01-12",{"type":8,"value":4261},[4262,4264,4266,4268],[11,4263,3284],{},[11,4265,3287],{},[11,4267,3290],{},[11,4269,3293],{},{"planet":216},"\u002Fpost\u002Fmigration-to-pelican",{"title":3279,"description":3284},"migration-to-pelican","posts\u002FLogiciels\u002F2013-01-12-migration-to-pelican",[1704],"RjPEE1XKQzoFIQDsH16W_XStvfsUCDU0KyWZDWKPIXs",{"id":4278,"title":4279,"author":6,"body":4280,"category":1672,"categorySlug":1673,"date":4922,"description":4923,"excerpt":4924,"extension":194,"location":1697,"meta":4936,"navigation":216,"path":4937,"published":216,"seo":4938,"slug":4700,"stem":4939,"tags":4940,"timeToRead":220,"__hash__":4942},"posts\u002Fposts\u002FLogiciels\u002F2008-10-22-email2trac.md","Email2Trac",{"type":8,"value":4281,"toc":4915},[4282,4291,4294,4297,4309,4317,4321,4332,4337,4343,4375,4379,4397,4432,4443,4447,4465,4532,4540,4544,4547,4565,4576,4580,4598,4602,4617,4623,4628,4634,4641,4656,4662,4682,4702,4706,4712,4733,4740,4746,4758,4783,4798,4804,4810,4829,4838,4842,4845,4864,4867,4883,4912],[11,4283,4284,4286,4287,4290],{},[1812,4285,4279],{}," est un logiciel permettant de créer un ticket sous ",[1812,4288,4289],{},"Trac","\nen envoyant un mail au système de suivi de ticket.",[11,4292,4293],{},"L'intérêt d'envoyer un mail au système de suivi plutôt que de se\nconnecter sur le site Internet pour faire ses rapports d'anomalie, est\nde faciliter l'accès à de nouvelles personnes.En effet, il est parfois\nplus facile d'envoyer un mail avec son client mail préféré (en\nconsidérant que le logiciel est quasiment toujours ouvert, ce qui doit\nêtre le cas en entreprise) que d'ouvrir le navigateur pour envoyer une\nanomalie de temps en temps (ouvrir le site, se logger, remplir tous les\nchamps, ...).",[11,4295,4296],{},"Ceci peut également être utilisé par un outil de rapport de bug,\nenvoyant un mail automatique (avec confirmation de l'utilisateur) au\ncrash dudit logiciel.",[11,4298,4299,4300,4303,4308],{},"Comme dit précédemment, ",[1812,4301,4302],{},"EMail2Trac",[52,4304,4305],{},[15,4306,61],{"href":56,"ariaDescribedBy":4307,"dataFootnoteRef":59,"id":60},[58]," permet",[83,4310,4311,4314],{},[86,4312,4313],{},"d'ajouter un ticket en envoyant un mail, avec des fichiers attachés",[86,4315,4316],{},"mettre à jour un ticket (en répondant au mail du ticket par exemple)",[1714,4318,4320],{"id":4319},"installation","Installation",[11,4322,4323,4324,4326,4327,4331],{},"Pour installer ",[1812,4325,4279],{},", il faut télécharger le ",[15,4328,4330],{"href":4329},"ftp:\u002F\u002Fftp.sara.nl\u002Fpub\u002Foutgoing\u002Femail2trac.tar.gz","source"," et le\ndécompresser dans un dossier temporaire (ou utilisateur).",[4333,4334,4336],"h4",{"id":4335},"sans-gestionnaire-de-paquet","Sans gestionnaire de paquet",[11,4338,4339,4340],{},"Ensuite la compilation se fait à l'aide des habituelles ",[165,4341,4342],{},"autotools",[190,4344,4346],{"className":3436,"code":4345,"language":3438,"meta":59,"style":59},"configure --prefix=\u002Fusr\u002Flocal --with-mta_user=nobody --with-trac_user=www-data\nmake\nmake install\n",[165,4347,4348,4362,4367],{"__ignoreMap":59},[198,4349,4350,4353,4356,4359],{"class":200,"line":201},[198,4351,4352],{"class":2202},"configure",[198,4354,4355],{"class":1417}," --prefix=\u002Fusr\u002Flocal",[198,4357,4358],{"class":1417}," --with-mta_user=nobody",[198,4360,4361],{"class":1417}," --with-trac_user=www-data\n",[198,4363,4364],{"class":200,"line":207},[198,4365,4366],{"class":2202},"make\n",[198,4368,4369,4372],{"class":200,"line":213},[198,4370,4371],{"class":2202},"make",[198,4373,4374],{"class":1424}," install\n",[4333,4376,4378],{"id":4377},"sous-debian","Sous Debian",[11,4380,4381,4382,2688,4385,4388,4389,4392,4393,4396],{},"Après avoir installé les paquets ",[165,4383,4384],{},"cdbs",[165,4386,4387],{},"autotools-dev",", vous pouvez\nexécuter les commandes suivante en ",[1812,4390,4391],{},"root"," (ou la première à l'aide de\n",[1812,4394,4395],{},"fakeroot",") :",[190,4398,4400],{"className":3436,"code":4399,"language":3438,"meta":59,"style":59},"debian\u002Frules binary\ndpkg -i ..\u002Femail2trac_\u003Cversion>.deb\n",[165,4401,4402,4410],{"__ignoreMap":59},[198,4403,4404,4407],{"class":200,"line":201},[198,4405,4406],{"class":2202},"debian\u002Frules",[198,4408,4409],{"class":1424}," binary\n",[198,4411,4412,4415,4418,4421,4423,4426,4429],{"class":200,"line":207},[198,4413,4414],{"class":2202},"dpkg",[198,4416,4417],{"class":1417}," -i",[198,4419,4420],{"class":1424}," ..\u002Femail2trac_",[198,4422,1384],{"class":1383},[198,4424,4425],{"class":1424},"versio",[198,4427,4428],{"class":1383},"n>",[198,4430,4431],{"class":1424},".deb\n",[11,4433,4434,4435,4438,4439],{},"Pour le gestionnaire de paquets ",[1812,4436,4437],{},"RPM"," vous pouvez visiter la page\n",[15,4440,4441],{"href":4441,"rel":4442},"https:\u002F\u002Fsubtrac.sara.nl\u002Foss\u002Femail2trac\u002Fwiki\u002FEmail2tracInstallation",[24],[1714,4444,4446],{"id":4445},"configuration-de-lapplication","Configuration de l'application",[11,4448,4449,4450,4453,4454,4462,4463,41],{},"La deuxième étape est l'édition du fichier ",[165,4451,4452],{},"\u002Fetc\u002Femail2trac.conf",". Dans\nce fichier les informations à renseigner concerne la gestion du projet\nTrac",[52,4455,4456],{},[15,4457,4461],{"href":4458,"ariaDescribedBy":4459,"dataFootnoteRef":59,"id":4460},"#user-content-fn-2",[58],"user-content-fnref-2","2"," par ",[1812,4464,4279],{},[190,4466,4470],{"className":4467,"code":4468,"language":4469,"meta":59,"style":59},"language-ini shiki shiki-themes one-dark-pro","[DEFAULT]\nproject: \u002Fwww\u002Fsite\u002Ftrac\u002Fprojet1\nspam_level: 5\ndrop_spam: 1\nticket_update: 1\nstrip_signature: 1\n\n[projet2]\nproject: \u002Fwww\u002Fsite\u002Ftrac\u002Fprojet2\nspam_level: 5\ndrop_spam: 1\nticket_update: 1\nstrip_signature: 1\n","ini",[165,4471,4472,4477,4482,4487,4492,4497,4502,4506,4511,4516,4520,4524,4528],{"__ignoreMap":59},[198,4473,4474],{"class":200,"line":201},[198,4475,4476],{"class":2202},"[DEFAULT]\n",[198,4478,4479],{"class":200,"line":207},[198,4480,4481],{"class":1424},"project: \u002Fwww\u002Fsite\u002Ftrac\u002Fprojet1\n",[198,4483,4484],{"class":200,"line":213},[198,4485,4486],{"class":1424},"spam_level: 5\n",[198,4488,4489],{"class":200,"line":220},[198,4490,4491],{"class":1424},"drop_spam: 1\n",[198,4493,4494],{"class":200,"line":254},[198,4495,4496],{"class":1424},"ticket_update: 1\n",[198,4498,4499],{"class":200,"line":260},[198,4500,4501],{"class":1424},"strip_signature: 1\n",[198,4503,4504],{"class":200,"line":266},[198,4505,217],{"emptyLinePlaceholder":216},[198,4507,4508],{"class":200,"line":272},[198,4509,4510],{"class":2202},"[projet2]\n",[198,4512,4513],{"class":200,"line":278},[198,4514,4515],{"class":1424},"project: \u002Fwww\u002Fsite\u002Ftrac\u002Fprojet2\n",[198,4517,4518],{"class":200,"line":283},[198,4519,4486],{"class":1424},[198,4521,4522],{"class":200,"line":288},[198,4523,4491],{"class":1424},[198,4525,4526],{"class":200,"line":450},[198,4527,4496],{"class":1424},[198,4529,4530],{"class":200,"line":456},[198,4531,4501],{"class":1424},[11,4533,4534,4535,41],{},"Les différentes options dépendent de ce que vous souhaitez avoir. Les\ndifférentes possibilités sont à l'adresse ",[15,4536,4539],{"href":4537,"rel":4538},"https:\u002F\u002Fsubtrac.sara.nl\u002Foss\u002Femail2trac\u002Fwiki\u002FEmail2tracConfiguration",[24],"suivante",[4333,4541,4543],{"id":4542},"spam","Spam",[11,4545,4546],{},"La gestion du SPAM se fait à l'aide des 3 lignes :",[190,4548,4550],{"className":4467,"code":4549,"language":4469,"meta":59,"style":59},"spam_level: 5\ndrop_spam: 1\nspam_header: X-Spam-Level\n",[165,4551,4552,4556,4560],{"__ignoreMap":59},[198,4553,4554],{"class":200,"line":201},[198,4555,4486],{"class":1424},[198,4557,4558],{"class":200,"line":207},[198,4559,4491],{"class":1424},[198,4561,4562],{"class":200,"line":213},[198,4563,4564],{"class":1424},"spam_header: X-Spam-Level\n",[11,4566,4567,4568,4571,4572,4575],{},"La ligne ",[165,4569,4570],{},"spam_header"," étant à configurer suivant votre politique de\ngestion des spams (utilisation de ",[1812,4573,4574],{},"SpamAssassin"," ou d'un autre\nutilitaire).",[1714,4577,4579],{"id":4578},"configuration-de-postfix","Configuration de Postfix",[11,4581,4582,4583,4585,4586,4588,4589,4592,4593],{},"Il faut maintenant configurer notre système de messagerie pour intégrer\n",[1812,4584,4279],{},". Nous allons détailler ici la mise en place de ",[1812,4587,4279],{},"\nsous ",[1812,4590,4591],{},"Postfix",". Pour les autres serveurs mails vous pouvez visiter la\npage : ",[15,4594,4597],{"href":4595,"rel":4596},"http:\u002F\u002Fsubtrac.sara.nl\u002Foss\u002Femail2trac\u002Fwiki",[24],"http:\u002F\u002Fsubtrac.sara.nl\u002Foss\u002Femail2trac\u002Fwiki\u002FEmail2tracMta",[4333,4599,4601],{"id":4600},"aliases","Aliases",[11,4603,4604,4605,4608,4609,4612,4613,4616],{},"La première méthode concerne la modification du fichier des ",[1812,4606,4607],{},"alias"," pour\nune configuration standard de ",[1812,4610,4611],{},"postfix",". Nous allons commencer par\nmodifier le fichier ",[165,4614,4615],{},"\u002Fetc\u002Faliases"," en ajoutant la ligne suivante (pour\nle projet 1) :",[190,4618,4621],{"className":4619,"code":4620,"language":1839},[1837],"projet1: |\"\u002Fusr\u002Fbin\u002Frun_email2trac\"\n",[165,4622,4620],{"__ignoreMap":59},[11,4624,4625,4626,4396],{},"Il est également possible de préciser le projet sur lequel il faut\ntravailler (projet définit dans ",[165,4627,4452],{},[190,4629,4632],{"className":4630,"code":4631,"language":1839},[1837],"projet2: |\"\u002Fusr\u002Fbin\u002Frun_email2trac --project=projet2 --ticket_prefix=devel\"\n",[165,4633,4631],{"__ignoreMap":59},[11,4635,4636,4637,4640],{},"Dans le fichier ",[165,4638,4639],{},"\u002Fetc\u002Fpostfix\u002Fmain.cf",", il faut avoir défini\nl'emplacement des alias de la manière suivante :",[190,4642,4644],{"className":4467,"code":4643,"language":4469,"meta":59,"style":59},"alias_maps = hash:\u002Fetc\u002Faliases\n",[165,4645,4646],{"__ignoreMap":59},[198,4647,4648,4651,4653],{"class":200,"line":201},[198,4649,4650],{"class":1956},"alias_maps",[198,4652,2221],{"class":1383},[198,4654,4655],{"class":1424}," hash:\u002Fetc\u002Faliases\n",[11,4657,4658,4659,4661],{},"Les commandes suivantes permettent de mettre à jour le fichier des alias\net demander à ",[1812,4660,4591],{}," de recharger la configuration :",[190,4663,4665],{"className":3436,"code":4664,"language":3438,"meta":59,"style":59},"postaliases \u002Fetc\u002Faliases\npostfix reload\n",[165,4666,4667,4675],{"__ignoreMap":59},[198,4668,4669,4672],{"class":200,"line":201},[198,4670,4671],{"class":2202},"postaliases",[198,4673,4674],{"class":1424}," \u002Fetc\u002Faliases\n",[198,4676,4677,4679],{"class":200,"line":207},[198,4678,4611],{"class":2202},[198,4680,4681],{"class":1424}," reload\n",[11,4683,4684,4685,3839,4691,4697,4698,4701],{},"Une fois ceci terminé, les mails envoyé à ",[1812,4686,4687],{},[15,4688,4690],{"href":4689},"mailto:projet1@domain.org","projet1@domain.org",[1812,4692,4693],{},[15,4694,4696],{"href":4695},"mailto:projet2@domaine.org","projet2@domaine.org"," seront automatiquement redirigés vers ",[1812,4699,4700],{},"email2trac","\nqui s'occupera de créer le ticket dans votre système de suivi.",[4333,4703,4705],{"id":4704},"transport","Transport",[11,4707,4708,4709,4711],{},"Cette configuration concerne les personnes qui ont une configuration\nplus complexe de ",[1812,4710,4611],{}," par exemple en gérant des domaines virtuels.\nIl est alors possible de définir une redirection des tickets pour un\nsous domaine.",[11,4713,4714,4715,4718,4719,4725,4726,4732],{},"Nous avons donc créé le sous-domaine ",[1812,4716,4717],{},"tickets.domaine.org"," et voulons\nque les mails envoyés à ",[1812,4720,4721],{},[15,4722,4724],{"href":4723},"mailto:projet1@tickets.domaine.org","projet1@tickets.domaine.org"," est\n",[1812,4727,4728],{},[15,4729,4731],{"href":4730},"mailto:projet2@tickets.domaine.org","projet2@tickets.domaine.org"," soient redirigés vers email2trac.",[11,4734,4735,4736,4739],{},"Pour cela nous allons créer un fichier ",[165,4737,4738],{},"\u002Fetc\u002Fpostfix\u002Ftransport"," avec les\nlignes ci-dessous :",[190,4741,4744],{"className":4742,"code":4743,"language":1839},[1837],"projet1@tickets.domaine.org  projet1:\nprojet2@tickets.domaine.org  projet2:\n",[165,4745,4743],{"__ignoreMap":59},[11,4747,4748,4749,4751,4752,4754,4755,41],{},"Puis dans le fichier ",[165,4750,4639],{}," nous allons définir que pour\nle sous domaine ",[1812,4753,4717],{},", il faut lire et utiliser le\nfichier des transports. (Attention il ne faut pas ajouter ce\nsous-domaine dans ",[165,4756,4757],{},"mydestination",[190,4759,4761],{"className":4467,"code":4760,"language":4469,"meta":59,"style":59},"relay_domains = tickets.domaine.org\ntransport_maps = hash:\u002Fetc\u002Fpostfix\u002Ftransport\n",[165,4762,4763,4773],{"__ignoreMap":59},[198,4764,4765,4768,4770],{"class":200,"line":201},[198,4766,4767],{"class":1956},"relay_domains",[198,4769,2221],{"class":1383},[198,4771,4772],{"class":1424}," tickets.domaine.org\n",[198,4774,4775,4778,4780],{"class":200,"line":207},[198,4776,4777],{"class":1956},"transport_maps",[198,4779,2221],{"class":1383},[198,4781,4782],{"class":1424}," hash:\u002Fetc\u002Fpostfix\u002Ftransport\n",[11,4784,4785,4786,4789,4790,4793,4794,4797],{},"Ensuite, il nous faut définir dans le fichier ",[165,4787,4788],{},"\u002Fetc\u002Fpostfix\u002Fmaster.cf","\nnotre nouveau mode de transport. Il n'est pas obligé d'utiliser\n",[165,4791,4792],{},"run_email2trac"," qui fait un changement d'utilisateur, car dans le\nfichier ",[165,4795,4796],{},"master.cf"," on peut directement définir l'utilisateur de\ndestination.",[190,4799,4802],{"className":4800,"code":4801,"language":1839},[1837],"projet1      unix  -       n       n       -       -       pipe\n    flags=FR user=www-data argv=\u002Fusr\u002Fbin\u002Femail2trac\n    ${nexthop} ${user}\nprojet2      unix  -       n       n       -       -       pipe\n    flags=FR user=www-data argv=\u002Fusr\u002Fbin\u002Femail2trac\n    ${nexthop} ${user}\\r\n",[165,4803,4801],{"__ignoreMap":59},[11,4805,4806,4807,4809],{},"Enfin il faut redémarrer ",[1812,4808,4611],{}," :",[190,4811,4813],{"className":3436,"code":4812,"language":3438,"meta":59,"style":59},"postmap \u002Fetc\u002Fpostfix\u002Ftransport\npostfix reload\n",[165,4814,4815,4823],{"__ignoreMap":59},[198,4816,4817,4820],{"class":200,"line":201},[198,4818,4819],{"class":2202},"postmap",[198,4821,4822],{"class":1424}," \u002Fetc\u002Fpostfix\u002Ftransport\n",[198,4824,4825,4827],{"class":200,"line":207},[198,4826,4611],{"class":2202},[198,4828,4681],{"class":1424},[11,4830,4831,4832,41],{},"Et voilà vous pouvez envoyer vos mails à\n",[1812,4833,4834],{},[15,4835,4837],{"href":4836},"mailto:projet1@tickets.shadoware.org","projet1@tickets.shadoware.org",[1714,4839,4841],{"id":4840},"tester","Tester",[11,4843,4844],{},"Pour tester il est possible d'envoyer un mail, comme ceci :",[190,4846,4848],{"className":3436,"code":4847,"language":3438,"meta":59,"style":59},"mail projet1@tickets.shadoware.org \u003C ticket.txt\n",[165,4849,4850],{"__ignoreMap":59},[198,4851,4852,4855,4858,4861],{"class":200,"line":201},[198,4853,4854],{"class":2202},"mail",[198,4856,4857],{"class":1424}," projet1@tickets.shadoware.org",[198,4859,4860],{"class":1383}," \u003C ",[198,4862,4863],{"class":1424},"ticket.txt\n",[11,4865,4866],{},"En cas de problème, vous pouvez vérifier que email2trac est bien\nconfiguré avec la commande :",[190,4868,4870],{"className":3436,"code":4869,"language":3438,"meta":59,"style":59},"email2trac --project=projet1 \u003C ticket.txt\n",[165,4871,4872],{"__ignoreMap":59},[198,4873,4874,4876,4879,4881],{"class":200,"line":201},[198,4875,4700],{"class":2202},[198,4877,4878],{"class":1417}," --project=projet1",[198,4880,4860],{"class":1383},[198,4882,4863],{"class":1424},[1636,4884,4886,4889],{"className":4885,"dataFootnotes":59},[1639],[72,4887,1644],{"className":4888,"id":58},[1643],[1646,4890,4891,4900],{},[86,4892,4893,4896,4897],{"id":1650},[15,4894,4597],{"href":4595,"rel":4895},[24]," ",[15,4898,1658],{"href":1654,"ariaLabel":1655,"className":4899,"dataFootnoteBackref":59},[1657],[86,4901,4903,4896,4907],{"id":4902},"user-content-fn-2",[15,4904,4905],{"href":4905,"rel":4906},"http:\u002F\u002Ftrac.edgewall.org\u002F",[24],[15,4908,1658],{"href":4909,"ariaLabel":4910,"className":4911,"dataFootnoteBackref":59},"#user-content-fnref-2","Back to reference 2",[1657],[1660,4913,4914],{},"html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}",{"title":59,"searchDepth":207,"depth":207,"links":4916},[4917,4918,4919,4920,4921],{"id":4319,"depth":213,"text":4320},{"id":4445,"depth":213,"text":4446},{"id":4578,"depth":213,"text":4579},{"id":4840,"depth":213,"text":4841},{"id":58,"depth":207,"text":1644},"2008-10-22","Email2Trac est un logiciel permettant de créer un ticket sous Trac\nen envoyant un mail au système de suivi de ticket.",{"type":8,"value":4925},[4926,4932,4934],[11,4927,4928,4286,4930,4290],{},[1812,4929,4279],{},[1812,4931,4289],{},[11,4933,4293],{},[11,4935,4296],{},{},"\u002Fpost\u002Femail2trac",{"title":4279,"description":4923},"posts\u002FLogiciels\u002F2008-10-22-email2trac",[4941,1704],"debian","llLWYwDr2WQzswEZDA9vDYeLWcGqHIhabMKl6VUmCmo",{"id":4944,"title":4945,"author":6,"body":4946,"category":6178,"categorySlug":6179,"date":6180,"description":3284,"excerpt":6181,"extension":194,"location":1697,"meta":6321,"navigation":216,"path":6322,"published":216,"seo":6323,"slug":6324,"stem":6325,"tags":6326,"timeToRead":266,"__hash__":6328},"posts\u002Fposts\u002FProgrammation\u002F2024-06-14-max-old-space.md","Quelle est la valeur par défaut de max-old-space-size dans NodeJS ?",{"type":8,"value":4947,"toc":6176},[4948,4950,4957,4960,5126,5129,5135,5150,5153,5156,5186,5189,5195,5204,5207,5210,5221,5419,5428,5437,5605,5613,5755,5771,6061,6064,6090,6096,6099,6102,6105,6170,6173],[11,4949,3284],{},[11,4951,4952,4953,4956],{},"Lors de nos développements en NodeJS, il arrive parfois que l'on se retrouve confronté à des erreurs. Certaines de ces\nerreurs ne se reproduisent pas en local, mais uniquement sur un environnement distant. C'est ce qui nous est arrivé\nrécemment lors de l'exécution de la commande ",[165,4954,4955],{},"npm ci"," sur la chaîne de déploiement continue.",[11,4958,4959],{},"L'erreur que nous avons rencontrée est la suivante :",[190,4961,4965],{"className":4962,"code":4963,"language":4964,"meta":59,"style":59},"language-shell shiki shiki-themes one-dark-pro","\u003C--- Last few GCs --->\n\n[14040:0x56930a0]    96150 ms: Mark-Compact 2012.5 (2093.0) -> 2011.8 (2092.0) MB, 902.72 \u002F 17.13 ms  (average mu = 0.416, current mu = 0.217) allocation failure; scavenge might not succeed\n[14040:0x56930a0]    97002 ms: Mark-Compact 2019.6 (2092.0) -> 2019.1 (2112.8) MB, 843.10 \u002F 0.00 ms  (average mu = 0.251, current mu = 0.011) allocation failure; scavenge might not succeed\n\n\u003C--- JS stacktrace --->\n\nFATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory\n","shell",[165,4966,4967,4972,4976,5029,5073,5077,5082,5086],{"__ignoreMap":59},[198,4968,4969],{"class":200,"line":201},[198,4970,4971],{"class":1383},"\u003C--- Last few GCs --->\n",[198,4973,4974],{"class":200,"line":207},[198,4975,217],{"emptyLinePlaceholder":216},[198,4977,4978,4981,4984,4987,4990,4993,4996,4999,5001,5004,5007,5009,5011,5014,5017,5020,5023,5026],{"class":200,"line":213},[198,4979,4980],{"class":1383},"[14040:0x56930a0]    96150 ms: Mark-Compact 2012.5 (",[198,4982,4983],{"class":2202},"2093.0",[198,4985,4986],{"class":1383},") -> 2011.8 (",[198,4988,4989],{"class":2202},"2092.0",[198,4991,4992],{"class":1383},") MB, 902.72 \u002F 17.13 ms  (",[198,4994,4995],{"class":2202},"average",[198,4997,4998],{"class":1424}," mu",[198,5000,2221],{"class":1424},[198,5002,5003],{"class":1424}," 0.416,",[198,5005,5006],{"class":1424}," current",[198,5008,4998],{"class":1424},[198,5010,2221],{"class":1424},[198,5012,5013],{"class":1417}," 0.217",[198,5015,5016],{"class":1383},") allocation failure; ",[198,5018,5019],{"class":2202},"scavenge",[198,5021,5022],{"class":1424}," might",[198,5024,5025],{"class":1424}," not",[198,5027,5028],{"class":1424}," succeed\n",[198,5030,5031,5034,5036,5039,5042,5045,5047,5049,5051,5054,5056,5058,5060,5063,5065,5067,5069,5071],{"class":200,"line":220},[198,5032,5033],{"class":1383},"[14040:0x56930a0]    97002 ms: Mark-Compact 2019.6 (",[198,5035,4989],{"class":2202},[198,5037,5038],{"class":1383},") -> 2019.1 (",[198,5040,5041],{"class":2202},"2112.8",[198,5043,5044],{"class":1383},") MB, 843.10 \u002F 0.00 ms  (",[198,5046,4995],{"class":2202},[198,5048,4998],{"class":1424},[198,5050,2221],{"class":1424},[198,5052,5053],{"class":1424}," 0.251,",[198,5055,5006],{"class":1424},[198,5057,4998],{"class":1424},[198,5059,2221],{"class":1424},[198,5061,5062],{"class":1417}," 0.011",[198,5064,5016],{"class":1383},[198,5066,5019],{"class":2202},[198,5068,5022],{"class":1424},[198,5070,5025],{"class":1424},[198,5072,5028],{"class":1424},[198,5074,5075],{"class":200,"line":254},[198,5076,217],{"emptyLinePlaceholder":216},[198,5078,5079],{"class":200,"line":260},[198,5080,5081],{"class":1383},"\u003C--- JS stacktrace --->\n",[198,5083,5084],{"class":200,"line":266},[198,5085,217],{"emptyLinePlaceholder":216},[198,5087,5088,5091,5094,5097,5100,5103,5106,5109,5112,5115,5117,5120,5123],{"class":200,"line":272},[198,5089,5090],{"class":2202},"FATAL",[198,5092,5093],{"class":1424}," ERROR:",[198,5095,5096],{"class":1424}," Reached",[198,5098,5099],{"class":1424}," heap",[198,5101,5102],{"class":1424}," limit",[198,5104,5105],{"class":1424}," Allocation",[198,5107,5108],{"class":1424}," failed",[198,5110,5111],{"class":1424}," -",[198,5113,5114],{"class":1424}," JavaScript",[198,5116,5099],{"class":1424},[198,5118,5119],{"class":1424}," out",[198,5121,5122],{"class":1424}," of",[198,5124,5125],{"class":1424}," memory\n",[11,5127,5128],{},"Cette erreur se produit lorsque la mémoire allouée pour NodeJS est insuffisante (le garbage collector de NodeJS n'arrive\npas à nettoyer la mémoire). Pour résoudre ce problème, l'une des possibilités est d'augmenter la mémoire allouée à NodeJS.",[11,5130,5131,5132,5134],{},"Une autre possibilité est de comprendre pourquoi le programme a besoin d'autant de mémoire et de le corriger, car\nle problème peut venir d'une fuite de mémoire. Dans notre cas, c'est la commande ",[165,5133,4955],{}," qui est en cause. Et la\nconsommation de mémoire dépend du nombre de paquets que nous avons en dépendance (et qui eux-mêmes en ont).",[11,5136,5137,5138,5141,5142,5145,5146,5149],{},"Pour augmenter la mémoire allouée à NodeJS, il faut ajouter l'option ",[165,5139,5140],{},"--max-old-space-size"," à la commande ",[165,5143,5144],{},"node",".\nOn peut également modifier la variable d'environnement ",[165,5147,5148],{},"NODE_OPTIONS"," pour définir la taille de la mémoire allouée à\nNodeJS.",[11,5151,5152],{},"Lors de la modification de la mémoire allouée à NodeJS, il est important de prendre en compte la mémoire disponible sur\nla machine et la mémoire utilisée par les autres processus.",[11,5154,5155],{},"Voici un exemple pour augmenter la mémoire allouée à NodeJS à 4 Go :",[190,5157,5159],{"className":3436,"code":5158,"language":3438,"meta":59,"style":59},"export NODE_OPTIONS=--max-old-space-size=4096\nnpm ci\n",[165,5160,5161,5178],{"__ignoreMap":59},[198,5162,5163,5166,5169,5171,5173,5175],{"class":200,"line":201},[198,5164,5165],{"class":1956},"export",[198,5167,5168],{"class":1387}," NODE_OPTIONS",[198,5170,1421],{"class":2220},[198,5172,5140],{"class":1387},[198,5174,1421],{"class":2220},[198,5176,5177],{"class":1417},"4096\n",[198,5179,5180,5183],{"class":200,"line":207},[198,5181,5182],{"class":2202},"npm",[198,5184,5185],{"class":1424}," ci\n",[11,5187,5188],{},"Mais avant d'augmenter la mémoire allouée à NodeJS, nous allons nous poser une question :",[5190,5191,5192],"blockquote",{},[11,5193,5194],{},"Pourquoi ai-je le problème sur la chaîne de déploiement et pas sur mon poste en local, malgré le fait que la version\nde NodeJS soit identique ?",[11,5196,5197,5198,5203],{},"Pour répondre à cette question, nous avons commencé par une petite recherche sur le grand réseau. Nous avons trouvé un\narticle très intéressant sur le site ",[15,5199,5202],{"href":5200,"rel":5201},"https:\u002F\u002Fmedium.com\u002Fgeekculture\u002Fnode-js-default-memory-settings-3c0fe8a9ba1",[24],"Medium",".\nDans cet article, une expérimentation a été faite pour déterminer la mémoire allouée par défaut à NodeJS en fonction de\nla version de NodeJS.",[11,5205,5206],{},"Cela montre que dans la version de NodeJS 20 que nous utilisons, la limite devrait être de 4Go par défaut. Mais\npourquoi avons-nous cette erreur, sachant que dans le message d'erreur, la mémoire allouée est de 2Go ?",[11,5208,5209],{},"Pour trouver plus d'informations, nous avons dû nous plonger dans le code source de NodeJS, qui embarque lui-même le code\nsource du moteur V8. Nous allons nous concentrer sur la dernière version de NodeJS.",[11,5211,5212,5213,5216,5217,5220],{},"Pour trouver plus d'informations, nous avons essayé de rechercher dans le code les endroits qui parlent de max_old_space_size. Cette\nrecherche m'a amené à la fonction ",[165,5214,5215],{},"MaxOldGenerationSize"," dans le fichier ",[165,5218,5219],{},"deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap.cc"," :",[190,5222,5226],{"className":5223,"code":5224,"language":5225,"meta":59,"style":59},"language-cpp shiki shiki-themes one-dark-pro","\u002F\u002F deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap.cc\n\n\u002F\u002F line 362\nsize_t Heap::MaxOldGenerationSize(uint64_t physical_memory) {\n  size_t max_size = V8HeapTrait::kMaxSize;\n  \u002F\u002F Increase the heap size from 2GB to 4GB for 64-bit systems with physical\n  \u002F\u002F memory at least 16GB. The theshold is set to 15GB to accomodate for some\n  \u002F\u002F memory being reserved by the hardware.\n  constexpr bool x64_bit = Heap::kHeapLimitMultiplier >= 2;\n  if (v8_flags.huge_max_old_generation_size && x64_bit &&\n      (physical_memory \u002F GB) >= 15) {\n    DCHECK_EQ(max_size \u002F GB, 2u);\n    max_size *= 2;\n  }\n  return std::min(max_size, AllocatorLimitOnMaxOldGenerationSize());\n}\n","cpp",[165,5227,5228,5233,5237,5242,5266,5279,5284,5289,5294,5318,5340,5358,5378,5390,5395,5415],{"__ignoreMap":59},[198,5229,5230],{"class":200,"line":201},[198,5231,5232],{"class":1930},"\u002F\u002F deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap.cc\n",[198,5234,5235],{"class":200,"line":207},[198,5236,217],{"emptyLinePlaceholder":216},[198,5238,5239],{"class":200,"line":213},[198,5240,5241],{"class":1930},"\u002F\u002F line 362\n",[198,5243,5244,5247,5250,5253,5255,5257,5260,5264],{"class":200,"line":220},[198,5245,5246],{"class":1956},"size_t",[198,5248,5249],{"class":1960}," Heap",[198,5251,5252],{"class":1383},"::",[198,5254,5215],{"class":2202},[198,5256,2206],{"class":1383},[198,5258,5259],{"class":1956},"uint64_t",[198,5261,5263],{"class":5262},"s_ZVi"," physical_memory",[198,5265,2212],{"class":1383},[198,5267,5268,5271,5274,5276],{"class":200,"line":254},[198,5269,5270],{"class":1956},"  size_t",[198,5272,5273],{"class":1383}," max_size ",[198,5275,1421],{"class":1956},[198,5277,5278],{"class":1383}," V8HeapTrait::kMaxSize;\n",[198,5280,5281],{"class":200,"line":260},[198,5282,5283],{"class":1930},"  \u002F\u002F Increase the heap size from 2GB to 4GB for 64-bit systems with physical\n",[198,5285,5286],{"class":200,"line":266},[198,5287,5288],{"class":1930},"  \u002F\u002F memory at least 16GB. The theshold is set to 15GB to accomodate for some\n",[198,5290,5291],{"class":200,"line":272},[198,5292,5293],{"class":1930},"  \u002F\u002F memory being reserved by the hardware.\n",[198,5295,5296,5299,5302,5305,5307,5310,5313,5316],{"class":200,"line":278},[198,5297,5298],{"class":1956},"  constexpr",[198,5300,5301],{"class":1956}," bool",[198,5303,5304],{"class":1383}," x64_bit ",[198,5306,1421],{"class":1956},[198,5308,5309],{"class":1383}," Heap::kHeapLimitMultiplier ",[198,5311,5312],{"class":1956},">=",[198,5314,5315],{"class":1417}," 2",[198,5317,2008],{"class":1383},[198,5319,5320,5323,5325,5328,5330,5333,5335,5337],{"class":200,"line":283},[198,5321,5322],{"class":1956},"  if",[198,5324,2288],{"class":1383},[198,5326,5327],{"class":1960},"v8_flags",[198,5329,41],{"class":1383},[198,5331,5332],{"class":1387},"huge_max_old_generation_size",[198,5334,2493],{"class":2220},[198,5336,5304],{"class":1383},[198,5338,5339],{"class":2220},"&&\n",[198,5341,5342,5345,5348,5351,5353,5356],{"class":200,"line":288},[198,5343,5344],{"class":1383},"      (physical_memory ",[198,5346,5347],{"class":1956},"\u002F",[198,5349,5350],{"class":1383}," GB) ",[198,5352,5312],{"class":1956},[198,5354,5355],{"class":1417}," 15",[198,5357,2212],{"class":1383},[198,5359,5360,5363,5366,5368,5371,5373,5376],{"class":200,"line":450},[198,5361,5362],{"class":2202},"    DCHECK_EQ",[198,5364,5365],{"class":1383},"(max_size ",[198,5367,5347],{"class":1956},[198,5369,5370],{"class":1383}," GB, ",[198,5372,4461],{"class":1417},[198,5374,5375],{"class":1387},"u",[198,5377,2280],{"class":1383},[198,5379,5380,5383,5386,5388],{"class":200,"line":456},[198,5381,5382],{"class":1383},"    max_size ",[198,5384,5385],{"class":1956},"*=",[198,5387,5315],{"class":1417},[198,5389,2008],{"class":1383},[198,5391,5392],{"class":200,"line":462},[198,5393,5394],{"class":1383},"  }\n",[198,5396,5397,5400,5403,5406,5409,5412],{"class":200,"line":468},[198,5398,5399],{"class":1956},"  return",[198,5401,5402],{"class":1383}," std::",[198,5404,5405],{"class":2202},"min",[198,5407,5408],{"class":1383},"(max_size, ",[198,5410,5411],{"class":2202},"AllocatorLimitOnMaxOldGenerationSize",[198,5413,5414],{"class":1383},"());\n",[198,5416,5417],{"class":200,"line":473},[198,5418,1613],{"class":1383},[11,5420,5421,5422,2688,5425,41],{},"Pour pouvoir rassembler les morceaux, nous devons donc connaître ",[165,5423,5424],{},"V8HeapTrait::kMaxSize",[165,5426,5427],{},"Heap::kHeapLimitMultiplier",[11,5429,5430,5431,5433,5434,5220],{},"La valeur de ",[165,5432,5424],{}," est définie dans le fichier ",[165,5435,5436],{},"deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap-controller.h",[190,5438,5440],{"className":5223,"code":5439,"language":5225,"meta":59,"style":59},"\u002F\u002F deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap-controller.h\n\n\u002F\u002F line 16\nstruct BaseControllerTrait {\n  static constexpr size_t kMinSize = 128u * Heap::kHeapLimitMultiplier * MB;\n  static constexpr size_t kMaxSize = 1024u * Heap::kHeapLimitMultiplier * MB;\n\n  static constexpr double kMinGrowingFactor = 1.1;\n  static constexpr double kMaxGrowingFactor = 4.0;\n  static constexpr double kConservativeGrowingFactor = 1.3;\n  static constexpr double kTargetMutatorUtilization = 0.97;\n};\n",[165,5441,5442,5447,5451,5456,5466,5498,5524,5528,5547,5565,5583,5601],{"__ignoreMap":59},[198,5443,5444],{"class":200,"line":201},[198,5445,5446],{"class":1930},"\u002F\u002F deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap-controller.h\n",[198,5448,5449],{"class":200,"line":207},[198,5450,217],{"emptyLinePlaceholder":216},[198,5452,5453],{"class":200,"line":213},[198,5454,5455],{"class":1930},"\u002F\u002F line 16\n",[198,5457,5458,5461,5464],{"class":200,"line":220},[198,5459,5460],{"class":1956},"struct",[198,5462,5463],{"class":1960}," BaseControllerTrait",[198,5465,1964],{"class":1383},[198,5467,5468,5471,5474,5477,5480,5482,5485,5487,5490,5492,5495],{"class":200,"line":254},[198,5469,5470],{"class":1956},"  static",[198,5472,5473],{"class":1956}," constexpr",[198,5475,5476],{"class":1956}," size_t",[198,5478,5479],{"class":1383}," kMinSize ",[198,5481,1421],{"class":1956},[198,5483,5484],{"class":1417}," 128",[198,5486,5375],{"class":1387},[198,5488,5489],{"class":1956}," *",[198,5491,5309],{"class":1383},[198,5493,5494],{"class":1956},"*",[198,5496,5497],{"class":1383}," MB;\n",[198,5499,5500,5502,5504,5506,5509,5511,5514,5516,5518,5520,5522],{"class":200,"line":260},[198,5501,5470],{"class":1956},[198,5503,5473],{"class":1956},[198,5505,5476],{"class":1956},[198,5507,5508],{"class":1383}," kMaxSize ",[198,5510,1421],{"class":1956},[198,5512,5513],{"class":1417}," 1024",[198,5515,5375],{"class":1387},[198,5517,5489],{"class":1956},[198,5519,5309],{"class":1383},[198,5521,5494],{"class":1956},[198,5523,5497],{"class":1383},[198,5525,5526],{"class":200,"line":266},[198,5527,217],{"emptyLinePlaceholder":216},[198,5529,5530,5532,5534,5537,5540,5542,5545],{"class":200,"line":272},[198,5531,5470],{"class":1956},[198,5533,5473],{"class":1956},[198,5535,5536],{"class":1956}," double",[198,5538,5539],{"class":1383}," kMinGrowingFactor ",[198,5541,1421],{"class":1956},[198,5543,5544],{"class":1417}," 1.1",[198,5546,2008],{"class":1383},[198,5548,5549,5551,5553,5555,5558,5560,5563],{"class":200,"line":278},[198,5550,5470],{"class":1956},[198,5552,5473],{"class":1956},[198,5554,5536],{"class":1956},[198,5556,5557],{"class":1383}," kMaxGrowingFactor ",[198,5559,1421],{"class":1956},[198,5561,5562],{"class":1417}," 4.0",[198,5564,2008],{"class":1383},[198,5566,5567,5569,5571,5573,5576,5578,5581],{"class":200,"line":283},[198,5568,5470],{"class":1956},[198,5570,5473],{"class":1956},[198,5572,5536],{"class":1956},[198,5574,5575],{"class":1383}," kConservativeGrowingFactor ",[198,5577,1421],{"class":1956},[198,5579,5580],{"class":1417}," 1.3",[198,5582,2008],{"class":1383},[198,5584,5585,5587,5589,5591,5594,5596,5599],{"class":200,"line":288},[198,5586,5470],{"class":1956},[198,5588,5473],{"class":1956},[198,5590,5536],{"class":1956},[198,5592,5593],{"class":1383}," kTargetMutatorUtilization ",[198,5595,1421],{"class":1956},[198,5597,5598],{"class":1417}," 0.97",[198,5600,2008],{"class":1383},[198,5602,5603],{"class":200,"line":450},[198,5604,929],{"class":1383},[11,5606,5607,5608,5433,5610,5220],{},"Enfin, la valeur de ",[165,5609,5427],{},[165,5611,5612],{},"deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap.h",[190,5614,5616],{"className":5223,"code":5615,"language":5225,"meta":59,"style":59},"\u002F\u002F deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap.h\n\n\u002F\u002F line 306\n#if V8_OS_ANDROID\n  \u002F\u002F Don't apply pointer multiplier on Android since it has no swap space and\n  \u002F\u002F should instead adapt it's heap size based on available physical memory.\n  static const int kPointerMultiplier = 1;\n  static const int kHeapLimitMultiplier = 1;\n#else\n  static const int kPointerMultiplier = kTaggedSize \u002F 4;\n  \u002F\u002F The heap limit needs to be computed based on the system pointer size\n  \u002F\u002F because we want a pointer-compressed heap to have larger limit than\n  \u002F\u002F an ordinary 32-bit which that is constrained by 2GB virtual address space.\n  static const int kHeapLimitMultiplier = kSystemPointerSize \u002F 4;\n#endif\n",[165,5617,5618,5623,5627,5632,5640,5645,5650,5670,5687,5692,5714,5719,5724,5729,5750],{"__ignoreMap":59},[198,5619,5620],{"class":200,"line":201},[198,5621,5622],{"class":1930},"\u002F\u002F deps\u002Fv8\u002Fsrc\u002Fheap\u002Fheap.h\n",[198,5624,5625],{"class":200,"line":207},[198,5626,217],{"emptyLinePlaceholder":216},[198,5628,5629],{"class":200,"line":213},[198,5630,5631],{"class":1930},"\u002F\u002F line 306\n",[198,5633,5634,5637],{"class":200,"line":220},[198,5635,5636],{"class":1956},"#if",[198,5638,5639],{"class":2202}," V8_OS_ANDROID\n",[198,5641,5642],{"class":200,"line":254},[198,5643,5644],{"class":1930},"  \u002F\u002F Don't apply pointer multiplier on Android since it has no swap space and\n",[198,5646,5647],{"class":200,"line":260},[198,5648,5649],{"class":1930},"  \u002F\u002F should instead adapt it's heap size based on available physical memory.\n",[198,5651,5652,5654,5657,5660,5663,5665,5668],{"class":200,"line":266},[198,5653,5470],{"class":1956},[198,5655,5656],{"class":1956}," const",[198,5658,5659],{"class":1956}," int",[198,5661,5662],{"class":1383}," kPointerMultiplier ",[198,5664,1421],{"class":1956},[198,5666,5667],{"class":1417}," 1",[198,5669,2008],{"class":1383},[198,5671,5672,5674,5676,5678,5681,5683,5685],{"class":200,"line":272},[198,5673,5470],{"class":1956},[198,5675,5656],{"class":1956},[198,5677,5659],{"class":1956},[198,5679,5680],{"class":1383}," kHeapLimitMultiplier ",[198,5682,1421],{"class":1956},[198,5684,5667],{"class":1417},[198,5686,2008],{"class":1383},[198,5688,5689],{"class":200,"line":278},[198,5690,5691],{"class":1956},"#else\n",[198,5693,5694,5696,5698,5700,5702,5704,5707,5709,5712],{"class":200,"line":283},[198,5695,5470],{"class":1956},[198,5697,5656],{"class":1956},[198,5699,5659],{"class":1956},[198,5701,5662],{"class":1383},[198,5703,1421],{"class":1956},[198,5705,5706],{"class":1383}," kTaggedSize ",[198,5708,5347],{"class":1956},[198,5710,5711],{"class":1417}," 4",[198,5713,2008],{"class":1383},[198,5715,5716],{"class":200,"line":288},[198,5717,5718],{"class":1930},"  \u002F\u002F The heap limit needs to be computed based on the system pointer size\n",[198,5720,5721],{"class":200,"line":450},[198,5722,5723],{"class":1930},"  \u002F\u002F because we want a pointer-compressed heap to have larger limit than\n",[198,5725,5726],{"class":200,"line":456},[198,5727,5728],{"class":1930},"  \u002F\u002F an ordinary 32-bit which that is constrained by 2GB virtual address space.\n",[198,5730,5731,5733,5735,5737,5739,5741,5744,5746,5748],{"class":200,"line":462},[198,5732,5470],{"class":1956},[198,5734,5656],{"class":1956},[198,5736,5659],{"class":1956},[198,5738,5680],{"class":1383},[198,5740,1421],{"class":1956},[198,5742,5743],{"class":1383}," kSystemPointerSize ",[198,5745,5347],{"class":1956},[198,5747,5711],{"class":1417},[198,5749,2008],{"class":1383},[198,5751,5752],{"class":200,"line":468},[198,5753,5754],{"class":1956},"#endif\n",[11,5756,5430,5757,5760,5761,5764,5765,5768,5769,5220],{},[165,5758,5759],{},"kHeapLimitMultiplier"," dépend elle-même de ",[165,5762,5763],{},"kSystemPointerSize",", qui n'est pas définie dans ce fichier. C'est\ndans le fichier ",[165,5766,5767],{},"deps\u002Fv8\u002Fsrc\u002Fbase\u002Fplatform\u002Fplatform.h"," que nous allons trouver la valeur de ",[165,5770,5763],{},[190,5772,5774],{"className":5223,"code":5773,"language":5225,"meta":59,"style":59},"\u002F\u002F deps\u002Fv8\u002Fsrc\u002Fbase\u002Fplatform\u002Fplatform.h\n\n\u002F\u002F line 84\nV8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index) {\n  const intptr_t kTibInlineTlsOffset = 0xE10;\n  const intptr_t kTibExtraTlsOffset = 0xF94;\n  const intptr_t kMaxInlineSlots = 64;\n  const intptr_t kMaxSlots = kMaxInlineSlots + 1024;\n  const intptr_t kSystemPointerSize = sizeof(void*);\n  DCHECK(0 \u003C= index && index \u003C kMaxSlots);\n  USE(kMaxSlots);\n  if (index \u003C kMaxInlineSlots) {\n    return static_cast\u003Cintptr_t>(\n        __readfsdword(kTibInlineTlsOffset + kSystemPointerSize * index));\n  }\n  intptr_t extra = static_cast\u003Cintptr_t>(__readfsdword(kTibExtraTlsOffset));\n  if (!extra) return 0;\n  return *reinterpret_cast\u003Cintptr_t*>(extra + kSystemPointerSize *\n                                                  (index - kMaxInlineSlots));\n}\n",[165,5775,5776,5781,5785,5790,5808,5829,5847,5863,5883,5903,5929,5937,5949,5961,5978,5982,6004,6024,6046,6057],{"__ignoreMap":59},[198,5777,5778],{"class":200,"line":201},[198,5779,5780],{"class":1930},"\u002F\u002F deps\u002Fv8\u002Fsrc\u002Fbase\u002Fplatform\u002Fplatform.h\n",[198,5782,5783],{"class":200,"line":207},[198,5784,217],{"emptyLinePlaceholder":216},[198,5786,5787],{"class":200,"line":213},[198,5788,5789],{"class":1930},"\u002F\u002F line 84\n",[198,5791,5792,5795,5798,5801,5803,5805],{"class":200,"line":220},[198,5793,5794],{"class":1383},"V8_INLINE ",[198,5796,5797],{"class":1956},"intptr_t",[198,5799,5800],{"class":2202}," InternalGetExistingThreadLocal",[198,5802,2206],{"class":1383},[198,5804,5797],{"class":1956},[198,5806,5807],{"class":1383}," index) {\n",[198,5809,5810,5813,5816,5819,5821,5824,5827],{"class":200,"line":254},[198,5811,5812],{"class":1956},"  const",[198,5814,5815],{"class":1956}," intptr_t",[198,5817,5818],{"class":1383}," kTibInlineTlsOffset ",[198,5820,1421],{"class":1956},[198,5822,5823],{"class":1387}," 0x",[198,5825,5826],{"class":1417},"E10",[198,5828,2008],{"class":1383},[198,5830,5831,5833,5835,5838,5840,5842,5845],{"class":200,"line":260},[198,5832,5812],{"class":1956},[198,5834,5815],{"class":1956},[198,5836,5837],{"class":1383}," kTibExtraTlsOffset ",[198,5839,1421],{"class":1956},[198,5841,5823],{"class":1387},[198,5843,5844],{"class":1417},"F94",[198,5846,2008],{"class":1383},[198,5848,5849,5851,5853,5856,5858,5861],{"class":200,"line":266},[198,5850,5812],{"class":1956},[198,5852,5815],{"class":1956},[198,5854,5855],{"class":1383}," kMaxInlineSlots ",[198,5857,1421],{"class":1956},[198,5859,5860],{"class":1417}," 64",[198,5862,2008],{"class":1383},[198,5864,5865,5867,5869,5872,5874,5876,5879,5881],{"class":200,"line":272},[198,5866,5812],{"class":1956},[198,5868,5815],{"class":1956},[198,5870,5871],{"class":1383}," kMaxSlots ",[198,5873,1421],{"class":1956},[198,5875,5855],{"class":1383},[198,5877,5878],{"class":1956},"+",[198,5880,5513],{"class":1417},[198,5882,2008],{"class":1383},[198,5884,5885,5887,5889,5891,5893,5896,5898,5901],{"class":200,"line":278},[198,5886,5812],{"class":1956},[198,5888,5815],{"class":1956},[198,5890,5743],{"class":1383},[198,5892,1421],{"class":1956},[198,5894,5895],{"class":1956}," sizeof",[198,5897,2206],{"class":1383},[198,5899,5900],{"class":1956},"void*",[198,5902,2280],{"class":1383},[198,5904,5905,5908,5910,5913,5916,5919,5922,5924,5926],{"class":200,"line":283},[198,5906,5907],{"class":2202},"  DCHECK",[198,5909,2206],{"class":1383},[198,5911,5912],{"class":1417},"0",[198,5914,5915],{"class":1956}," \u003C=",[198,5917,5918],{"class":1383}," index ",[198,5920,5921],{"class":2220},"&&",[198,5923,5918],{"class":1383},[198,5925,1384],{"class":1956},[198,5927,5928],{"class":1383}," kMaxSlots);\n",[198,5930,5931,5934],{"class":200,"line":288},[198,5932,5933],{"class":2202},"  USE",[198,5935,5936],{"class":1383},"(kMaxSlots);\n",[198,5938,5939,5941,5944,5946],{"class":200,"line":450},[198,5940,5322],{"class":1956},[198,5942,5943],{"class":1383}," (index ",[198,5945,1384],{"class":1956},[198,5947,5948],{"class":1383}," kMaxInlineSlots) {\n",[198,5950,5951,5953,5956,5959],{"class":200,"line":456},[198,5952,2618],{"class":1956},[198,5954,5955],{"class":1383}," static_cast",[198,5957,5958],{"class":1956},"\u003Cintptr_t>",[198,5960,2775],{"class":1383},[198,5962,5963,5966,5969,5971,5973,5975],{"class":200,"line":462},[198,5964,5965],{"class":2202},"        __readfsdword",[198,5967,5968],{"class":1383},"(kTibInlineTlsOffset ",[198,5970,5878],{"class":1956},[198,5972,5743],{"class":1383},[198,5974,5494],{"class":1956},[198,5976,5977],{"class":1383}," index));\n",[198,5979,5980],{"class":200,"line":468},[198,5981,5394],{"class":1383},[198,5983,5984,5987,5990,5992,5994,5996,5998,6001],{"class":200,"line":473},[198,5985,5986],{"class":1956},"  intptr_t",[198,5988,5989],{"class":1383}," extra ",[198,5991,1421],{"class":1956},[198,5993,5955],{"class":1383},[198,5995,5958],{"class":1956},[198,5997,2206],{"class":1383},[198,5999,6000],{"class":2202},"__readfsdword",[198,6002,6003],{"class":1383},"(kTibExtraTlsOffset));\n",[198,6005,6006,6008,6010,6013,6016,6019,6022],{"class":200,"line":478},[198,6007,5322],{"class":1956},[198,6009,2288],{"class":1383},[198,6011,6012],{"class":2220},"!",[198,6014,6015],{"class":1383},"extra) ",[198,6017,6018],{"class":1956},"return",[198,6020,6021],{"class":1417}," 0",[198,6023,2008],{"class":1383},[198,6025,6026,6028,6030,6033,6036,6039,6041,6043],{"class":200,"line":484},[198,6027,5399],{"class":1956},[198,6029,5489],{"class":1956},[198,6031,6032],{"class":1383},"reinterpret_cast",[198,6034,6035],{"class":1956},"\u003Cintptr_t*>",[198,6037,6038],{"class":1383},"(extra ",[198,6040,5878],{"class":1956},[198,6042,5743],{"class":1383},[198,6044,6045],{"class":1956},"*\n",[198,6047,6048,6051,6054],{"class":200,"line":490},[198,6049,6050],{"class":1383},"                                                  (index ",[198,6052,6053],{"class":1956},"-",[198,6055,6056],{"class":1383}," kMaxInlineSlots));\n",[198,6058,6059],{"class":200,"line":1068},[198,6060,1613],{"class":1383},[11,6062,6063],{},"Nous avons ainsi tous les éléments pour reconstituer le puzzle :",[83,6065,6066,6071,6080],{},[86,6067,6068,6070],{},[165,6069,5763],{}," permet de définir la taille d'un pointeur. Sur un système 64 bits, la taille d'un pointeur est\nde 8 octets, alors que sur un système 32 bits, la taille d'un pointeur est de 4 octets.",[86,6072,6073,6075,6076,6079],{},[165,6074,5759],{}," possède la valeur de 1 sur Android, mais pour les autres systèmes, la valeur est de\n",[165,6077,6078],{},"kSystemPointerSize \u002F 4",", soit 2 sur un système 64 bits et 1 sur un système 32 bits.",[86,6081,6082,6085,6086,6089],{},[165,6083,6084],{},"kMaxSize"," vaut ",[165,6087,6088],{},"1024 * kHeapLimitMultiplier * MB",", soit 1024 MB sur un système 32 bits et 2048 MB sur un système 64\nbits.",[11,6091,6092,6093,6095],{},"Enfin, en lisant le code de la fonction ",[165,6094,5215],{},", on comprend que la mémoire allouée à NodeJS est de 2Go\npar défaut.",[11,6097,6098],{},"Mais si le système est un système 64 bits (pointeur de 8 octets) et que la mémoire disponible sur la machine est\nsupérieure à 15Go, alors la mémoire allouée est multipliée par 2, soit 4Go.",[11,6100,6101],{},"Cela explique pourquoi sur nos postes de développement surpuissants, nous n'avons pas l'erreur car la mémoire allouée est de\n4Go par défaut. Mais sur la chaîne de déploiement, la mémoire allouée est de 2Go par défaut, car la machine ne possède\nque 8Go (ce qui est largement suffisant).",[11,6103,6104],{},"Voici un petit tableau récapitulatif:",[6106,6107,6108,6127],"table",{},[6109,6110,6111],"thead",{},[6112,6113,6114,6118,6121,6124],"tr",{},[6115,6116,6117],"th",{},"Système",[6115,6119,6120],{},"Taille du pointeur",[6115,6122,6123],{},"Mémoire disponible",[6115,6125,6126],{},"Mémoire allouée par défaut",[6128,6129,6130,6145,6158],"tbody",{},[6112,6131,6132,6136,6139,6142],{},[6133,6134,6135],"td",{},"32 bits",[6133,6137,6138],{},"4 octets",[6133,6140,6141],{},"OSEF",[6133,6143,6144],{},"2Go",[6112,6146,6147,6150,6153,6156],{},[6133,6148,6149],{},"64 bits",[6133,6151,6152],{},"8 octets",[6133,6154,6155],{},"\u003C 15Go",[6133,6157,6144],{},[6112,6159,6160,6162,6164,6167],{},[6133,6161,6149],{},[6133,6163,6152],{},[6133,6165,6166],{},">= 15Go",[6133,6168,6169],{},"4Go",[11,6171,6172],{},"J'espère que cet article vous a permis de faire un petit voyage dans le code source de NodeJS et de\ncomprendre comment est calculée la valeur par défaut de max-old-space-size.",[1660,6174,6175],{},"html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html pre.shiki code .sU0A5, html code.shiki .sU0A5{--shiki-default:#E5C07B}html pre.shiki code .s_ZVi, html code.shiki .s_ZVi{--shiki-default:#E06C75;--shiki-default-font-style:italic}",{"title":59,"searchDepth":207,"depth":207,"links":6177},[],"Programmation","programmation","2024-06-14",{"type":8,"value":6182},[6183,6185,6189,6191,6319],[11,6184,3284],{},[11,6186,4952,6187,4956],{},[165,6188,4955],{},[11,6190,4959],{},[190,6192,6193],{"className":4962,"code":4963,"language":4964,"meta":59,"style":59},[165,6194,6195,6199,6203,6241,6279,6283,6287,6291],{"__ignoreMap":59},[198,6196,6197],{"class":200,"line":201},[198,6198,4971],{"class":1383},[198,6200,6201],{"class":200,"line":207},[198,6202,217],{"emptyLinePlaceholder":216},[198,6204,6205,6207,6209,6211,6213,6215,6217,6219,6221,6223,6225,6227,6229,6231,6233,6235,6237,6239],{"class":200,"line":213},[198,6206,4980],{"class":1383},[198,6208,4983],{"class":2202},[198,6210,4986],{"class":1383},[198,6212,4989],{"class":2202},[198,6214,4992],{"class":1383},[198,6216,4995],{"class":2202},[198,6218,4998],{"class":1424},[198,6220,2221],{"class":1424},[198,6222,5003],{"class":1424},[198,6224,5006],{"class":1424},[198,6226,4998],{"class":1424},[198,6228,2221],{"class":1424},[198,6230,5013],{"class":1417},[198,6232,5016],{"class":1383},[198,6234,5019],{"class":2202},[198,6236,5022],{"class":1424},[198,6238,5025],{"class":1424},[198,6240,5028],{"class":1424},[198,6242,6243,6245,6247,6249,6251,6253,6255,6257,6259,6261,6263,6265,6267,6269,6271,6273,6275,6277],{"class":200,"line":220},[198,6244,5033],{"class":1383},[198,6246,4989],{"class":2202},[198,6248,5038],{"class":1383},[198,6250,5041],{"class":2202},[198,6252,5044],{"class":1383},[198,6254,4995],{"class":2202},[198,6256,4998],{"class":1424},[198,6258,2221],{"class":1424},[198,6260,5053],{"class":1424},[198,6262,5006],{"class":1424},[198,6264,4998],{"class":1424},[198,6266,2221],{"class":1424},[198,6268,5062],{"class":1417},[198,6270,5016],{"class":1383},[198,6272,5019],{"class":2202},[198,6274,5022],{"class":1424},[198,6276,5025],{"class":1424},[198,6278,5028],{"class":1424},[198,6280,6281],{"class":200,"line":254},[198,6282,217],{"emptyLinePlaceholder":216},[198,6284,6285],{"class":200,"line":260},[198,6286,5081],{"class":1383},[198,6288,6289],{"class":200,"line":266},[198,6290,217],{"emptyLinePlaceholder":216},[198,6292,6293,6295,6297,6299,6301,6303,6305,6307,6309,6311,6313,6315,6317],{"class":200,"line":272},[198,6294,5090],{"class":2202},[198,6296,5093],{"class":1424},[198,6298,5096],{"class":1424},[198,6300,5099],{"class":1424},[198,6302,5102],{"class":1424},[198,6304,5105],{"class":1424},[198,6306,5108],{"class":1424},[198,6308,5111],{"class":1424},[198,6310,5114],{"class":1424},[198,6312,5099],{"class":1424},[198,6314,5119],{"class":1424},[198,6316,5122],{"class":1424},[198,6318,5125],{"class":1424},[1660,6320,6175],{},{"planet":216},"\u002Fpost\u002Fmax-old-space",{"title":4945,"description":3284},"max-old-space","posts\u002FProgrammation\u002F2024-06-14-max-old-space",[1705,6327],"nodejs","rKoBJuRBkLYyVgc8etB7XZPEzRbfpMzHtNOUEWqjpL8",{"id":6330,"title":6331,"author":6,"body":6332,"category":6178,"categorySlug":6179,"date":10499,"description":10500,"excerpt":10501,"extension":194,"location":1697,"meta":10517,"navigation":216,"path":10518,"published":216,"seo":10519,"slug":10520,"stem":10521,"tags":10522,"timeToRead":1092,"__hash__":10526},"posts\u002Fposts\u002FWoodstock\u002F2024-03-14_pr_backuppc_pool.md","Woodstock Backup - Reverse engineering de BackupPC",{"type":8,"value":6333,"toc":10481},[6334,6343,6346,6349,6356,6360,6363,6372,6380,6389,6397,6400,6403,6406,6409,6412,6415,6418,6422,6428,6437,6453,6462,6466,6469,6532,6536,6539,6547,6550,6554,6570,6577,6585,6588,6597,6600,6607,6610,6617,6620,6623,6627,6634,6637,6640,6645,6648,6652,6665,6671,6877,6880,6889,6895,6904,6907,6910,7170,7189,7197,7222,7479,7482,8100,8122,8128,8142,8609,8615,8804,8808,8811,8814,8829,9197,9204,9211,9214,9218,9221,9240,9248,9251,9255,9258,9266,9269,9272,9286,9295,9305,9365,9368,9439,9442,9730,9740,9747,9879,9886,10032,10041,10044,10051,10054,10061,10064,10245,10248,10252,10255,10264,10267,10271,10278,10287,10410,10416,10419,10430,10433,10449,10453,10456,10464,10470,10473,10475,10478],[11,6335,6336,6337,6342],{},"Une partie de cet article a été publiée sur ",[15,6338,6341],{"href":6339,"rel":6340},"https:\u002F\u002Flinuxfr.org\u002Fusers\u002Fsan_guickoo\u002Fjournaux\u002Fpullrequest-d-une-application-en-rust",[24],"LinuxFR",".\nAprès avoir reçu quelques retours, j'ai décidé de publier une version modifiée et améliorée de cet article sur mon blog.",[11,6344,6345],{},"Je remercie donc la communauté de LinuxFR pour ses retours. 😄",[11,6347,6348],{},"Les commentaires sur le code ou sur l'article sont les bienvenus.",[11,6350,6351],{},[3390,6352],{"src":6353,"alt":59,"className":6354},"\u002FWoodstock\u002Fhdd_unsplash.jpg",[6355],"img-center",[72,6357,6359],{"id":6358},"le-commencement","Le commencement",[11,6361,6362],{},"Actuellement, j'utilise BackupPC pour sauvegarder mes données. BackupPC est un logiciel de sauvegarde qui se connecte à\ndifférents ordinateurs via SSH et utilise rsync pour sauvegarder les données. Il fonctionne parfaitement avec des\nordinateurs Linux et un peu moins bien sur des ordinateurs Windows où il faut installer un rsyncd\u002FCygwin (les données ne\nsont pas protégées par SSH dans ce cas).",[11,6364,6365,6366,6371],{},"Par ailleurs, je développe ",[15,6367,6370],{"href":6368,"rel":6369},"https:\u002F\u002Fshadoware.org\u002Fpost\u002Fwoodstock",[24],"mon propre logiciel de sauvegarde",". C'est un défi\npersonnel que je me suis lancé pour répondre à mes propres besoins (et aussi pour le plaisir).",[11,6373,6374,6375,41],{},"Mon premier prototype est écrit en TypeScript et utilise rsync couplé avec Btrfs pour faire des sauvegardes\nincrémentales. Malheureusement, quelques problèmes liés à l'utilisation de Btrfs m'ont fait abandonner ce prototype\n(problème avec la création d'un grand nombre de snapshots et un système de fichier un peu trop plein). J'en parle dans\n",[15,6376,6379],{"href":6377,"rel":6378},"https:\u002F\u002Fshadoware.org\u002Fpost\u002Fwoodstock_brtfs",[24],"un article sur mon blog",[11,6381,6382,6383,6388],{},"Je me suis donc orienté vers l'écriture de mon propre pool de stockage de données. L'écriture dans ce pool de stockage\nm'oblige à écrire mon propre logiciel de synchronisation. BackupPC a fait le choix de rester sur rsync et donc à créer\nun ",[15,6384,6387],{"href":6385,"rel":6386},"https:\u002F\u002Fgithub.com\u002Fbackuppc\u002Frsync-bpc",[24],"fork de rsync"," capable de se connecter en rsync sur les machines à\nsauvegarder, tout en étant capable d'écrire le résultat dans le pool de backuppc, au format de backuppc. Pour ma part,\nj'ai choisi de développer mon protocole basé sur GRPC (et donc HTTP\u002F2).",[11,6390,6391,6392,41],{},"J'ai donc fait un second prototype, toujours en TypeScript, pour tester mon idée. Je suis satisfait du résultat, mais\nles limites du moteur JavaScript font de ce prototype un simple prototype. Là aussi, j'en parle dans\n",[15,6393,6396],{"href":6394,"rel":6395},"https:\u002F\u002Fshadoware.org\u002Fpost\u002Fwoodstock_rust",[24],"un autre article de mon blog",[11,6398,6399],{},"Je vais donc réécrire la partie la plus importante de ce programme en Rust. Pourquoi Rust ? Dans ma jeunesse (enfin,\nj'avais entre 20 et 30 ans), j'adorais programmer en C\u002FC++. Je me souviens d'avoir programmé un petit IDE en C++ avec\nQt. Lors du développement en C++, il m'arrivait parfois de me retrouver avec des fuites de mémoire, des erreurs de\nsegmentation, ainsi que des problèmes de concurrence d'accès aux données.",[11,6401,6402],{},"C++ m'a beaucoup appris sur le fonctionnement d'une machine, la gestion de la mémoire, la gestion du multithreading,\netc. Tout le monde devrait commencer par ce langage 😄.",[11,6404,6405],{},"Rust est un langage qui a été conçu pour éviter ces problèmes. Après avoir lu la documentation, j'ai adoré le concept.\nDu coup, j'ai décidé que ce serait une très bonne idée d'apprendre à l'utiliser. (Surtout qu'on en entend beaucoup\nparler en ce moment).",[11,6407,6408],{},"Vous trouvez que je digresse beaucoup ? C'est possible.",[11,6410,6411],{},"Revenons à notre programme.",[11,6413,6414],{},"Je me suis dit qu'avant d'écrire la gestion de mon pool de stockage en Rust, je voulais faire un script qui me permette\nde migrer le contenu de mon pool de stockage de BackupPC vers mon nouveau pool de stockage. Et de le faire en Rust.",[11,6416,6417],{},"Pour cela, j'ai besoin de comprendre comment fonctionne le pool de stockage de BackupPC. Le faire avec le code source\nde BackupPC sera amusant et pas trop compliqué.",[72,6419,6421],{"id":6420},"description-du-pool-de-stockage-de-backuppc","Description du pool de stockage de BackupPC",[11,6423,6424],{},[3390,6425],{"src":6426,"alt":6427},"https:\u002F\u002Fbackuppc.github.io\u002Fbackuppc\u002Fimages\u002Flogos\u002Flogo.svg","BackupPC Logo",[11,6429,6430,6431,6436],{},"La ",[15,6432,6435],{"href":6433,"rel":6434},"https:\u002F\u002Fbackuppc.github.io\u002Fbackuppc\u002FBackupPC.html",[24],"documentation de BackupPC"," décrit déjà pas mal de choses :",[83,6438,6439,6446],{},[86,6440,6441],{},[15,6442,6445],{"href":6443,"rel":6444},"https:\u002F\u002Fbackuppc.github.io\u002Fbackuppc\u002FBackupPC.html#Storage-layout",[24],"Comment sont stockés les fichiers dans le pool de stockage ?",[86,6447,6448],{},[15,6449,6452],{"href":6450,"rel":6451},"https:\u002F\u002Fbackuppc.github.io\u002Fbackuppc\u002FBackupPC.html#Compressed-file-format",[24],"Une description succincte du format des fichiers compressés",[11,6454,6455,6456,6461],{},"Ensuite, pour obtenir les détails, il faut aller lire le ",[15,6457,6460],{"href":6458,"rel":6459},"https:\u002F\u002Fgithub.com\u002Fbackuppc\u002Fbackuppc-xs",[24],"code source en C"," qui\nsert de liaison avec le code en Perl. BackupPC est originellement écrit en Perl (entièrement, si je ne me trompe pas,\npour la version 3). La version 4 a été partiellement réécrite en C pour la partie qui gère le pool de stockage. Cette\npartie est utilisée par le rsync modifié et par la partie Perl à travers la bibliothèque de bindings.",[1714,6463,6465],{"id":6464},"la-constitution-du-pool","La constitution du pool",[11,6467,6468],{},"Le pool de stockage de BackupPC est principalement constitué de plusieurs dossiers :",[83,6470,6471,6517,6523],{},[86,6472,6473,6476,6477],{},[165,6474,6475],{},"pc"," : Ce dossier répertorie les sauvegardes des différentes machines, organisées par machine puis par sauvegarde.\n",[83,6478,6479,6484],{},[86,6480,6481],{},[165,6482,6483],{},"host1",[86,6485,6486,6489,6490,6492,6493],{},[165,6487,6488],{},"host2"," : Le dossier de la machine ",[165,6491,6488],{},".\n",[83,6494,6495,6501,6506,6510,6515],{},[86,6496,6497,6500],{},[165,6498,6499],{},"backups"," : Un fichier au format TSV (Tab Separated Values) qui liste les sauvegardes de la machine avec leurs\ninformations.",[86,6502,6503,6505],{},[165,6504,61],{}," : La sauvegarde où les dossiers sont représentés à l'aide du système de fichiers, et les fichiers sont listés\ndans des fichiers d'attributs. Le hash du fichier d'attribut dans le pool est contenu dans le nom du fichier\n(exemple : attrib_33fe8f9ae2f5cedbea63b9d3ea767ac0).",[86,6507,6508],{},[165,6509,4461],{},[86,6511,6512],{},[165,6513,6514],{},"3",[86,6516,1282],{},[86,6518,6519,6522],{},[165,6520,6521],{},"pool"," : Dans ce dossier, les fichiers sont stockés en utilisant leur hash MD5. Les fichiers sont répartis sur deux\nniveaux dans 128 dossiers dont le nom est constitué des 7 premiers bits des deux premiers octets. Si deux fichiers ont\nle même MD5, un nombre est accolé au hash pour les différencier.",[86,6524,6525,6528,6529,6531],{},[165,6526,6527],{},"cpool"," : La structure de ce dossier est la même que celle du dossier ",[165,6530,6521],{},". Il s'agit d'un pool de stockage\ncompressé.",[1714,6533,6535],{"id":6534},"le-format-des-fichiers-compressés","Le format des fichiers compressés",[11,6537,6538],{},"Voici la description du fichier compressé selon la documentation (traduction libre) :",[5190,6540,6541,6544],{},[11,6542,6543],{},"Le format de fichier compressé est généré par Compress::Zlib::deflate avec une modification mineure, mais\nimportante. Comme Compress::Zlib::inflate gonfle entièrement son argument en mémoire, il pourrait consommer de\ngrandes quantités de mémoire s'il décompressait un fichier très compressé. Par exemple, un fichier de 200 Mo de 0x0\nbytes se compresse à environ 200 Ko. Si Compress::Zlib::inflate était appelé avec ce seul tampon de 200 Ko, il\naurait besoin d'allouer 200 Mo de mémoire pour retourner le résultat.",[11,6545,6546],{},"BackupPC surveille l'efficacité de la compression d'un fichier. Si un gros fichier a un taux de compression très élevé\n(ce qui signifie qu'il utilisera beaucoup de mémoire lorsqu'il sera décompressé), BackupPC appelle la méthode flush(), qui\ntermine proprement la compression en cours. BackupPC commence alors une nouvelle section et ajoute simplement le\nfichier de sortie. Ainsi, le format de fichier compressé de BackupPC est une ou plusieurs sections\u002Fflushes\nconcaténées. Les ratios spécifiques que BackupPC utilise sont que si un morceau de 6 Mo se compresse à moins de 64\nKo, alors un flush sera effectué.",[11,6548,6549],{},"Donc, dans notre cas, nous devons être capables de lire un fichier compressé comme une suite de fichiers compressés\nconcaténés les uns après les autres.",[1714,6551,6553],{"id":6552},"le-format-des-fichiers-dattributs","Le format des fichiers d'attributs",[11,6555,6556,6561,6562,6565,6566,6569],{},[15,6557,6560],{"href":6558,"rel":6559},"https:\u002F\u002Fbackuppc.github.io\u002Fbackuppc\u002FBackupPC.html#Attribute-file-format",[24],"Dans la documentation",", il est expliqué que\ndans la version 4, on retrouve un fichier ",[165,6563,6564],{},"attrib_33fe8f9ae2f5cedbea63b9d3ea767ac0"," dans les différents dossiers de la\nmachine (",[165,6567,6568],{},"__TOPDIR__\u002Fpc\u002Fhost1",").\nLe nom du fichier contient le hash du fichier d'attributs que l'on peut retrouver dans le pool de stockage.",[11,6571,6572,6573,6576],{},"Pour accéder à un fichier du pool de stockage, il faut aller dans le dossier ",[165,6574,6575],{},"__TOPDIR__\u002Fpc"," et lire le nom du fichier\nd'attribut pour retrouver le hash du fichier compressé correspondant au nom du dossier que l'on veut lire. Enfin, il\nfaut lire le fichier compressé pour obtenir les données.",[11,6578,6579,6580,41],{},"Le contenu du fichier d'attribut n'est pas décrit. Cependant, on peut le retrouver dans le fichier\n",[15,6581,6584],{"href":6582,"rel":6583},"https:\u002F\u002Fgithub.com\u002Fbackuppc\u002Fbackuppc-xs\u002Fblob\u002Fmaster\u002Fbpc_attrib.c#L626",[24],"bpc_attribs.c",[11,6586,6587],{},"Le fichier d'attribut est encodé en binaire. Il s'agit d'une suite de varint (entier encodé sur un nombre variable\nd'octets).",[11,6589,6590,6591,6596],{},"Un ",[15,6592,6595],{"href":6593,"rel":6594},"https:\u002F\u002Fen.wikipedia.org\u002Fwiki\u002FVariable-length_quantity",[24],"Varint"," est un entier qui est encodé sur un nombre variable\nd'octets. Le premier bit de chaque octet indique si l'entier est terminé ou s'il faut lire un autre octet. Le reste des\nbits de l'octet représente l'entier.",[11,6598,6599],{},"Voici une représentation d'un Varint depuis Wikipedia :",[11,6601,6602],{},[3390,6603],{"src":6604,"alt":6605,"className":6606},"https:\u002F\u002Fupload.wikimedia.org\u002Fwikipedia\u002Fcommons\u002Fthumb\u002Fc\u002Fc6\u002FUintvar_coding.svg\u002F1920px-Uintvar_coding.svg.png","Image représentant un Varint (Source : Wikipedia)",[6355],[11,6608,6609],{},"D'après le code source de BackupPC, le fichier d'attribut est encodé de la manière suivante :",[11,6611,6612,6613,6616],{},"Le fichier commence par un numéro magique ",[165,6614,6615],{},"0x17565353",". Ensuite, pour chaque fichier, on retrouve les attributs du\nfichier. Pour chaque attribut, on retrouve les xattrs.",[3390,6618],{"src":6619},"https:\u002F\u002Fwww.plantuml.com\u002Fplantuml\u002Fpng\u002FXL8nJWCn4Epl5TC11H8eEf2kIa530HqIhHDlxbRosSUkVKgUb7VaOyW7KKWuGsLxPpIptjcbHYDnPtfNTMGiIOExxVrZ_L0lwaLbOXHUfQXD1TnYDC8-Dd31jucIm2RuqETZm-kEIIe0q2ZissOEEYhuqA-4OA_8HpdiIM49SJSGjjdpZ3kLBStgM1EfvD47ItXxVNul4HBR4jIMeMZOkQ8f--nw0g4cZTGQiOVz-GHu99FolzQX7uHKEVZ_naLmJ5unT3lbZqGAJG8tFvkVANL6kqlnLTfiSjuN6AvVdcgao8xriCSGlXo4eeGqai0QhxaoXE1k9gKfisQw_hac17SC_9jywg98-Ar6S0QZSST7KNEEioHlyxf_0W00",[11,6621,6622],{},"Il ne me reste donc plus qu'à reproduire tout cela en Rust.",[72,6624,6626],{"id":6625},"le-développement-en-rust","Le développement en Rust",[11,6628,6629],{},[3390,6630],{"src":6631,"alt":6632,"className":6633},"\u002FWoodstock\u002Frust_unsplash.jpg","Rust",[6355],[11,6635,6636],{},"Pour le développement de ce programme, j'ai établi certaines limites. Je me suis concentré uniquement sur la lecture des\nfichiers du pool qui sont en version 4. Ma version de BackupPC est la version 4, et j'ai migré l'intégralité du pool de\nstockage depuis la version 3.",[11,6638,6639],{},"Je n'ai donc pas de données en version 3 pour tester mon programme.",[11,6641,6642],{},[1892,6643,6644],{},"Si vous souhaitez tester mon programme ou l'utiliser, sachez qu'il n'est pas compatible avec la version 3 de BackupPC,\nni avec la version 4 si votre pool est un mélange de versions V3 et V4.",[11,6646,6647],{},"Si le besoin se fait sentir plus tard, il sera toujours possible d'améliorer tout cela.",[1714,6649,6651],{"id":6650},"les-fichiers-compressés","Les fichiers compressés",[11,6653,6654,6655,6658,6659,6662,6663,41],{},"J'ai donc commencé par développer un programme qui, à partir d'un hash, est capable de décompresser un fichier de ce\npool. Pour décompresser un fichier BackupPC compressé avec ",[165,6656,6657],{},"zlib",", j'ai choisi d'utiliser la bibliothèque ",[165,6660,6661],{},"flate2",", qui\nest une alternative Rust à la bibliothèque standard ",[165,6664,6657],{},[11,6666,6667,6668,6670],{},"La bibliothèque ",[165,6669,6661],{}," permet de décompresser un fichier en utilisant la notion de BufReader en Rust. La version\nsimplifiée pour décompresser un fichier du pool est donc la suivante :",[190,6672,6676],{"className":6673,"code":6674,"language":6675,"meta":59,"style":59},"language-rust shiki shiki-themes one-dark-pro","use flate2::bufread::ZlibDecoder;\nuse std::fs::File;\n\nfn main() {\n    let f = File::open(\"33fe8f9ae2f5cedbea63b9d3ea767ac0\").unwrap();\n    let b = BufReader::new(f);\n    let mut z = ZlibEncoder::new(b);\n    let mut buffer = Vec::new();\n    z.read_to_end(&mut buffer).unwrap();\n    println!(\"{:?}\", buffer);\n}\n","rust",[165,6677,6678,6698,6717,6721,6732,6762,6786,6812,6832,6856,6873],{"__ignoreMap":59},[198,6679,6680,6683,6686,6688,6691,6693,6696],{"class":200,"line":201},[198,6681,6682],{"class":1956},"use",[198,6684,6685],{"class":1960}," flate2",[198,6687,5252],{"class":1383},[198,6689,6690],{"class":1960},"bufread",[198,6692,5252],{"class":1383},[198,6694,6695],{"class":1960},"ZlibDecoder",[198,6697,2008],{"class":1383},[198,6699,6700,6702,6705,6707,6710,6712,6715],{"class":200,"line":207},[198,6701,6682],{"class":1956},[198,6703,6704],{"class":1960}," std",[198,6706,5252],{"class":1383},[198,6708,6709],{"class":1960},"fs",[198,6711,5252],{"class":1383},[198,6713,6714],{"class":1960},"File",[198,6716,2008],{"class":1383},[198,6718,6719],{"class":200,"line":213},[198,6720,217],{"emptyLinePlaceholder":216},[198,6722,6723,6726,6729],{"class":200,"line":220},[198,6724,6725],{"class":1956},"fn",[198,6727,6728],{"class":2202}," main",[198,6730,6731],{"class":1383},"() {\n",[198,6733,6734,6737,6740,6742,6745,6747,6750,6752,6755,6757,6760],{"class":200,"line":254},[198,6735,6736],{"class":1956},"    let",[198,6738,6739],{"class":1387}," f",[198,6741,2221],{"class":2220},[198,6743,6744],{"class":1960}," File",[198,6746,5252],{"class":1383},[198,6748,6749],{"class":2202},"open",[198,6751,2206],{"class":1383},[198,6753,6754],{"class":1424},"\"33fe8f9ae2f5cedbea63b9d3ea767ac0\"",[198,6756,958],{"class":1383},[198,6758,6759],{"class":2202},"unwrap",[198,6761,2244],{"class":1383},[198,6763,6764,6766,6769,6771,6774,6776,6779,6781,6784],{"class":200,"line":260},[198,6765,6736],{"class":1956},[198,6767,6768],{"class":1387}," b",[198,6770,2221],{"class":2220},[198,6772,6773],{"class":1960}," BufReader",[198,6775,5252],{"class":1383},[198,6777,6778],{"class":2202},"new",[198,6780,2206],{"class":1383},[198,6782,6783],{"class":1387},"f",[198,6785,2280],{"class":1383},[198,6787,6788,6790,6793,6796,6798,6801,6803,6805,6807,6810],{"class":200,"line":266},[198,6789,6736],{"class":1956},[198,6791,6792],{"class":1956}," mut",[198,6794,6795],{"class":1387}," z",[198,6797,2221],{"class":2220},[198,6799,6800],{"class":1960}," ZlibEncoder",[198,6802,5252],{"class":1383},[198,6804,6778],{"class":2202},[198,6806,2206],{"class":1383},[198,6808,6809],{"class":1387},"b",[198,6811,2280],{"class":1383},[198,6813,6814,6816,6818,6821,6823,6826,6828,6830],{"class":200,"line":272},[198,6815,6736],{"class":1956},[198,6817,6792],{"class":1956},[198,6819,6820],{"class":1387}," buffer",[198,6822,2221],{"class":2220},[198,6824,6825],{"class":1960}," Vec",[198,6827,5252],{"class":1383},[198,6829,6778],{"class":2202},[198,6831,2244],{"class":1383},[198,6833,6834,6837,6839,6842,6845,6848,6850,6852,6854],{"class":200,"line":278},[198,6835,6836],{"class":1387},"    z",[198,6838,41],{"class":1383},[198,6840,6841],{"class":2202},"read_to_end",[198,6843,6844],{"class":1383},"(&",[198,6846,6847],{"class":1956},"mut",[198,6849,6820],{"class":1387},[198,6851,958],{"class":1383},[198,6853,6759],{"class":2202},[198,6855,2244],{"class":1383},[198,6857,6858,6861,6863,6866,6868,6871],{"class":200,"line":283},[198,6859,6860],{"class":2202},"    println!",[198,6862,2206],{"class":1383},[198,6864,6865],{"class":1424},"\"{:?}\"",[198,6867,2764],{"class":1383},[198,6869,6870],{"class":1387},"buffer",[198,6872,2280],{"class":1383},[198,6874,6875],{"class":200,"line":288},[198,6876,1613],{"class":1383},[11,6878,6879],{},"Malheureusement, ce code ne fonctionne pas à tous les coups. Pour les plus petits fichiers de mon pool, cela fonctionne\ntrès bien, mais quand on se retrouve avec les fichiers volumineux que BackupPC a décidé de découper, cela ne fonctionne\nplus.",[11,6881,6882,6883,6888],{},"De plus, dans certains cas, BackupPC ",[15,6884,6887],{"href":6885,"rel":6886},"https:\u002F\u002Fgithub.com\u002Fbackuppc\u002Fbackuppc-xs\u002Fblob\u002Fmaster\u002Fbpc_fileZIO.c#L214",[24],"remplace certains octets","\npour indiquer que l'on est au début d'un nouveau bloc de données zlib, ou pour indiquer que l'on a ajouté à la fin une\nchecksum md4.",[11,6890,6891,6892,6894],{},"Comme certains fichiers peuvent être volumineux, je ne peux pas faire un ",[165,6893,6841],{}," pour lire le fichier en\nmémoire et le modifier.",[11,6896,6897,6898,6903],{},"Le fichier ",[15,6899,6902],{"href":6900,"rel":6901},"https:\u002F\u002Fgithub.com\u002Fbackuppc\u002Fbackuppc-xs\u002Fblob\u002Fmaster\u002Fbpc_fileZIO.c",[24],"bpc_fileZIO.c"," permet de comprendre\ncomment sont encodés les fichiers compressés.",[11,6905,6906],{},"Lors de la lecture d'un fichier compressé, si la lecture de la compression s'arrête et qu'il reste encore des octets\nà lire, alors il faut recommencer une nouvelle décompression.",[11,6908,6909],{},"On peut aussi voir le bout de code suivant :",[190,6911,6915],{"className":6912,"code":6913,"language":6914,"meta":59,"style":59},"language-c shiki shiki-themes one-dark-pro","\u002F\u002F https:\u002F\u002Fgithub.com\u002Fbackuppc\u002Fbackuppc-xs\u002Fblob\u002Fmaster\u002Fbpc_fileZIO.c#L219C15-L237C18\nif ( fd->strm.next_in[0] == 0xd6 || fd->strm.next_in[0] == 0xd7 ) {\n    \u002F*\n     * Flag 0xd6 or 0xd7 means this is a compressed file with\n     * appended md4 block checksums for rsync.  Change\n     * the first byte back to 0x78 and proceed.\n     *\u002F\n    fd->strm.next_in[0] = 0x78;\n} else if ( fd->strm.next_in[0] == 0xb3 ) {\n    \u002F*\n     * Flag 0xb3 means this is the start of the rsync\n     * block checksums, so consider this as EOF for\n     * the compressed file.  Also seek the file so\n     * it is positioned at the 0xb3.\n     *\u002F\n    fd->eof = 1;\n    \u002F* TODO: check return status *\u002F\n    lseek(fd->fd, -fd->strm.avail_in, SEEK_CUR);\n    fd->strm.avail_in = 0;\n}\n","c",[165,6916,6917,6922,6981,6986,6991,6996,7001,7006,7035,7068,7072,7077,7082,7087,7092,7096,7111,7116,7148,7166],{"__ignoreMap":59},[198,6918,6919],{"class":200,"line":201},[198,6920,6921],{"class":1930},"\u002F\u002F https:\u002F\u002Fgithub.com\u002Fbackuppc\u002Fbackuppc-xs\u002Fblob\u002Fmaster\u002Fbpc_fileZIO.c#L219C15-L237C18\n",[198,6923,6924,6927,6930,6932,6935,6938,6941,6943,6946,6948,6950,6953,6956,6959,6961,6963,6965,6967,6969,6971,6973,6975,6978],{"class":200,"line":207},[198,6925,6926],{"class":1956},"if",[198,6928,6929],{"class":1383}," ( fd",[198,6931,2227],{"class":1956},[198,6933,6934],{"class":1383},"strm.",[198,6936,6937],{"class":1387},"next_in",[198,6939,6940],{"class":1383},"[",[198,6942,5912],{"class":1417},[198,6944,6945],{"class":1383},"] ",[198,6947,2487],{"class":1956},[198,6949,5823],{"class":1387},[198,6951,6952],{"class":1417},"d6",[198,6954,6955],{"class":2220}," ||",[198,6957,6958],{"class":1383}," fd",[198,6960,2227],{"class":1956},[198,6962,6934],{"class":1383},[198,6964,6937],{"class":1387},[198,6966,6940],{"class":1383},[198,6968,5912],{"class":1417},[198,6970,6945],{"class":1383},[198,6972,2487],{"class":1956},[198,6974,5823],{"class":1387},[198,6976,6977],{"class":1417},"d7",[198,6979,6980],{"class":1383}," ) {\n",[198,6982,6983],{"class":200,"line":213},[198,6984,6985],{"class":1930},"    \u002F*\n",[198,6987,6988],{"class":200,"line":220},[198,6989,6990],{"class":1930},"     * Flag 0xd6 or 0xd7 means this is a compressed file with\n",[198,6992,6993],{"class":200,"line":254},[198,6994,6995],{"class":1930},"     * appended md4 block checksums for rsync.  Change\n",[198,6997,6998],{"class":200,"line":260},[198,6999,7000],{"class":1930},"     * the first byte back to 0x78 and proceed.\n",[198,7002,7003],{"class":200,"line":266},[198,7004,7005],{"class":1930},"     *\u002F\n",[198,7007,7008,7011,7013,7016,7018,7020,7022,7024,7026,7028,7030,7033],{"class":200,"line":272},[198,7009,7010],{"class":1960},"    fd",[198,7012,2227],{"class":1383},[198,7014,7015],{"class":1960},"strm",[198,7017,41],{"class":1383},[198,7019,6937],{"class":1387},[198,7021,6940],{"class":1383},[198,7023,5912],{"class":1417},[198,7025,6945],{"class":1383},[198,7027,1421],{"class":1956},[198,7029,5823],{"class":1387},[198,7031,7032],{"class":1417},"78",[198,7034,2008],{"class":1383},[198,7036,7037,7040,7042,7045,7047,7049,7051,7053,7055,7057,7059,7061,7063,7066],{"class":200,"line":278},[198,7038,7039],{"class":1383},"} ",[198,7041,2416],{"class":1956},[198,7043,7044],{"class":1956}," if",[198,7046,6929],{"class":1383},[198,7048,2227],{"class":1956},[198,7050,6934],{"class":1383},[198,7052,6937],{"class":1387},[198,7054,6940],{"class":1383},[198,7056,5912],{"class":1417},[198,7058,6945],{"class":1383},[198,7060,2487],{"class":1956},[198,7062,5823],{"class":1387},[198,7064,7065],{"class":1417},"b3",[198,7067,6980],{"class":1383},[198,7069,7070],{"class":200,"line":283},[198,7071,6985],{"class":1930},[198,7073,7074],{"class":200,"line":288},[198,7075,7076],{"class":1930},"     * Flag 0xb3 means this is the start of the rsync\n",[198,7078,7079],{"class":200,"line":450},[198,7080,7081],{"class":1930},"     * block checksums, so consider this as EOF for\n",[198,7083,7084],{"class":200,"line":456},[198,7085,7086],{"class":1930},"     * the compressed file.  Also seek the file so\n",[198,7088,7089],{"class":200,"line":462},[198,7090,7091],{"class":1930},"     * it is positioned at the 0xb3.\n",[198,7093,7094],{"class":200,"line":468},[198,7095,7005],{"class":1930},[198,7097,7098,7100,7102,7105,7107,7109],{"class":200,"line":473},[198,7099,7010],{"class":1960},[198,7101,2227],{"class":1383},[198,7103,7104],{"class":1387},"eof",[198,7106,2221],{"class":1956},[198,7108,5667],{"class":1417},[198,7110,2008],{"class":1383},[198,7112,7113],{"class":200,"line":478},[198,7114,7115],{"class":1930},"    \u002F* TODO: check return status *\u002F\n",[198,7117,7118,7121,7123,7126,7128,7130,7132,7134,7136,7138,7140,7142,7145],{"class":200,"line":484},[198,7119,7120],{"class":2202},"    lseek",[198,7122,2206],{"class":1383},[198,7124,7125],{"class":1960},"fd",[198,7127,2227],{"class":1383},[198,7129,7125],{"class":1387},[198,7131,2764],{"class":1383},[198,7133,6053],{"class":1956},[198,7135,7125],{"class":1960},[198,7137,2227],{"class":1383},[198,7139,7015],{"class":1960},[198,7141,41],{"class":1383},[198,7143,7144],{"class":1387},"avail_in",[198,7146,7147],{"class":1383},", SEEK_CUR);\n",[198,7149,7150,7152,7154,7156,7158,7160,7162,7164],{"class":200,"line":490},[198,7151,7010],{"class":1960},[198,7153,2227],{"class":1383},[198,7155,7015],{"class":1960},[198,7157,41],{"class":1383},[198,7159,7144],{"class":1387},[198,7161,2221],{"class":1956},[198,7163,6021],{"class":1417},[198,7165,2008],{"class":1383},[198,7167,7168],{"class":200,"line":1068},[198,7169,1613],{"class":1383},[11,7171,7172,7173,7176,7177,7180,7181,7184,7185,7188],{},"Si, en début de flux, on trouve ",[165,7174,7175],{},"0xd6"," ou ",[165,7178,7179],{},"0xd7",", il faut changer le premier octet en ",[165,7182,7183],{},"0x78"," et continuer la lecture. En\nfin de flux, si on trouve ",[165,7186,7187],{},"0xb3",", on considère que c'est la fin du fichier compressé. (De notre côté, nous ne nous\nintéresserons pas à la partie checksum md4).",[11,7190,6667,7191,7193,7194,7196],{},[165,7192,6661],{}," ne permet pas de faire cela simplement. J'ai donc dû lire le code de ",[165,7195,6661],{}," pour comprendre\ncomment je pouvais agir pour lire un fichier compressé de BackupPC.",[11,7198,7199,7206,7207,7209,7210,7213,7214,7217,7218,7221],{},[15,7200,7203,7204],{"href":7201,"rel":7202},"https:\u002F\u002Fgithub.com\u002Frust-lang\u002Fflate2-rs\u002Fblob\u002Fmain\u002Fsrc\u002Fbufreader.rs#L73",[24],"Le code suivant de la bibliothèque ",[165,7205,6661],{},"\npermet de voir que ",[165,7208,6661],{}," a besoin, dans son constructeur, d'un ",[165,7211,7212],{},"BufRead"," pour lire un fichier compressé. Il utilise\nla méthode ",[165,7215,7216],{},"fill_buf"," pour remplir un tampon et la méthode ",[165,7219,7220],{},"consume"," pour consommer le tampon.",[190,7223,7225],{"className":6673,"code":7224,"language":6675,"meta":59,"style":59},"\u002F\u002F https:\u002F\u002Fgithub.com\u002Frust-lang\u002Fflate2-rs\u002Fblob\u002Fmain\u002Fsrc\u002Fbufreader.rs#L73\nimpl\u003CR: Read> Read for BufReader\u003CR> {\n    fn read(&mut self, buf: &mut [u8]) -> io::Result\u003Cusize> {\n        \u002F\u002F If we don't have any buffered data and we're doing a massive read\n        \u002F\u002F (larger than our internal buffer), bypass our internal buffer\n        \u002F\u002F entirely.\n        if self.pos == self.cap && buf.len() >= self.buf.len() {\n            return self.inner.read(buf);\n        }\n        let nread = {\n            let mut rem = self.fill_buf()?;\n            rem.read(buf)?\n        };\n        self.consume(nread);\n        Ok(nread)\n    }\n}\n",[165,7226,7227,7232,7264,7313,7318,7323,7328,7367,7386,7390,7402,7423,7439,7444,7460,7471,7475],{"__ignoreMap":59},[198,7228,7229],{"class":200,"line":201},[198,7230,7231],{"class":1930},"\u002F\u002F https:\u002F\u002Fgithub.com\u002Frust-lang\u002Fflate2-rs\u002Fblob\u002Fmain\u002Fsrc\u002Fbufreader.rs#L73\n",[198,7233,7234,7237,7239,7242,7244,7247,7250,7252,7255,7257,7259,7261],{"class":200,"line":207},[198,7235,7236],{"class":1956},"impl",[198,7238,1384],{"class":1383},[198,7240,7241],{"class":1960},"R",[198,7243,2998],{"class":1383},[198,7245,7246],{"class":1960},"Read",[198,7248,7249],{"class":1383},"> ",[198,7251,7246],{"class":1960},[198,7253,7254],{"class":1956}," for",[198,7256,6773],{"class":1960},[198,7258,1384],{"class":1383},[198,7260,7241],{"class":1960},[198,7262,7263],{"class":1383},"> {\n",[198,7265,7266,7269,7272,7274,7276,7279,7281,7284,7287,7289,7292,7295,7298,7301,7303,7306,7308,7311],{"class":200,"line":213},[198,7267,7268],{"class":1956},"    fn",[198,7270,7271],{"class":2202}," read",[198,7273,6844],{"class":1383},[198,7275,6847],{"class":1956},[198,7277,7278],{"class":1960}," self",[198,7280,2764],{"class":1383},[198,7282,7283],{"class":1387},"buf",[198,7285,7286],{"class":1383},": &",[198,7288,6847],{"class":1956},[198,7290,7291],{"class":1383}," [",[198,7293,7294],{"class":1960},"u8",[198,7296,7297],{"class":1383},"]) -> ",[198,7299,7300],{"class":1960},"io",[198,7302,5252],{"class":1383},[198,7304,7305],{"class":1960},"Result",[198,7307,1384],{"class":1383},[198,7309,7310],{"class":1960},"usize",[198,7312,7263],{"class":1383},[198,7314,7315],{"class":200,"line":220},[198,7316,7317],{"class":1930},"        \u002F\u002F If we don't have any buffered data and we're doing a massive read\n",[198,7319,7320],{"class":200,"line":254},[198,7321,7322],{"class":1930},"        \u002F\u002F (larger than our internal buffer), bypass our internal buffer\n",[198,7324,7325],{"class":200,"line":260},[198,7326,7327],{"class":1930},"        \u002F\u002F entirely.\n",[198,7329,7330,7332,7334,7337,7339,7341,7344,7346,7349,7351,7354,7356,7358,7360,7363,7365],{"class":200,"line":266},[198,7331,2304],{"class":1956},[198,7333,7278],{"class":1960},[198,7335,7336],{"class":1383},".pos ",[198,7338,2487],{"class":2220},[198,7340,7278],{"class":1960},[198,7342,7343],{"class":1383},".cap ",[198,7345,5921],{"class":2220},[198,7347,7348],{"class":1387}," buf",[198,7350,41],{"class":1383},[198,7352,7353],{"class":2202},"len",[198,7355,2484],{"class":1383},[198,7357,5312],{"class":2220},[198,7359,7278],{"class":1960},[198,7361,7362],{"class":1383},".buf.",[198,7364,7353],{"class":2202},[198,7366,6731],{"class":1383},[198,7368,7369,7372,7374,7377,7380,7382,7384],{"class":200,"line":272},[198,7370,7371],{"class":1956},"            return",[198,7373,7278],{"class":1960},[198,7375,7376],{"class":1383},".inner.",[198,7378,7379],{"class":2202},"read",[198,7381,2206],{"class":1383},[198,7383,7283],{"class":1387},[198,7385,2280],{"class":1383},[198,7387,7388],{"class":200,"line":278},[198,7389,2442],{"class":1383},[198,7391,7392,7395,7398,7400],{"class":200,"line":283},[198,7393,7394],{"class":1956},"        let",[198,7396,7397],{"class":1387}," nread",[198,7399,2221],{"class":2220},[198,7401,1964],{"class":1383},[198,7403,7404,7407,7409,7412,7414,7416,7418,7420],{"class":200,"line":288},[198,7405,7406],{"class":1956},"            let",[198,7408,6792],{"class":1956},[198,7410,7411],{"class":1387}," rem",[198,7413,2221],{"class":2220},[198,7415,7278],{"class":1960},[198,7417,41],{"class":1383},[198,7419,7216],{"class":2202},[198,7421,7422],{"class":1383},"()?;\n",[198,7424,7425,7428,7430,7432,7434,7436],{"class":200,"line":450},[198,7426,7427],{"class":1387},"            rem",[198,7429,41],{"class":1383},[198,7431,7379],{"class":2202},[198,7433,2206],{"class":1383},[198,7435,7283],{"class":1387},[198,7437,7438],{"class":1383},")?\n",[198,7440,7441],{"class":200,"line":456},[198,7442,7443],{"class":1383},"        };\n",[198,7445,7446,7449,7451,7453,7455,7458],{"class":200,"line":462},[198,7447,7448],{"class":1960},"        self",[198,7450,41],{"class":1383},[198,7452,7220],{"class":2202},[198,7454,2206],{"class":1383},[198,7456,7457],{"class":1387},"nread",[198,7459,2280],{"class":1383},[198,7461,7462,7465,7467,7469],{"class":200,"line":468},[198,7463,7464],{"class":1960},"        Ok",[198,7466,2206],{"class":1383},[198,7468,7457],{"class":1387},[198,7470,2845],{"class":1383},[198,7472,7473],{"class":200,"line":473},[198,7474,2447],{"class":1383},[198,7476,7477],{"class":200,"line":478},[198,7478,1613],{"class":1383},[11,7480,7481],{},"J'ai donc commencé par développer un adaptateur qui s'intercale entre le fichier et le décompresseur. Cet adaptateur\na pour objectif de reproduire le comportement de BackupPC et de remplacer les octets en début de fichier.",[190,7483,7485],{"className":6673,"code":7484,"language":6675,"meta":59,"style":59},"struct InterpretAdapter\u003CR: BufRead> {\n    inner: R,\n    first: bool,\n    temp: Option\u003CVec\u003Cu8>>,\n}\n\nimpl\u003CR: BufRead> InterpretAdapter\u003CR> {\n    fn new(inner: R) -> Self {\n        Self {\n            inner,\n            first: true,\n            temp: None,\n        }\n    }\n\n    fn reset(&mut self) {\n        self.first = true;\n        self.temp = None;\n    }\n}\n...\nimpl\u003CR: BufRead> BufRead for InterpretAdapter\u003CR> {\n    fn fill_buf(&mut self) -> io::Result\u003C&[u8]> {\n        if self.temp.is_none() {\n            let buf = self.inner.fill_buf()?;\n            let mut buf = buf.to_vec();\n\n            if self.first && !buf.is_empty() {\n                self.first = false;\n\n                if buf[0] == 0xd6 || buf[0] == 0xd7 {\n                    buf[0] = 0x78;\n                } else if buf[0] == 0xb3 {\n                    \u002F\u002F EOF\n                    buf = Vec::new();\n                }\n            }\n\n            self.temp = Some(buf);\n        }\n\n        Ok(self.temp.as_ref().unwrap())\n    }\n\n    fn consume(&mut self, amt: usize) {\n        if amt > 0 {\n            self.temp = None;\n            self.inner.consume(amt);\n        }\n    }\n}\n",[165,7486,7487,7504,7515,7527,7549,7553,7557,7580,7603,7610,7617,7629,7641,7645,7649,7653,7668,7682,7696,7700,7704,7709,7735,7764,7778,7794,7813,7817,7840,7854,7858,7893,7911,7935,7940,7954,7959,7964,7968,7986,7990,7994,8016,8020,8024,8048,8062,8074,8088,8092,8096],{"__ignoreMap":59},[198,7488,7489,7491,7494,7496,7498,7500,7502],{"class":200,"line":201},[198,7490,5460],{"class":1956},[198,7492,7493],{"class":1960}," InterpretAdapter",[198,7495,1384],{"class":1383},[198,7497,7241],{"class":1960},[198,7499,2998],{"class":1383},[198,7501,7212],{"class":1960},[198,7503,7263],{"class":1383},[198,7505,7506,7509,7511,7513],{"class":200,"line":207},[198,7507,7508],{"class":1387},"    inner",[198,7510,2998],{"class":1383},[198,7512,7241],{"class":1960},[198,7514,1757],{"class":1383},[198,7516,7517,7520,7522,7525],{"class":200,"line":213},[198,7518,7519],{"class":1387},"    first",[198,7521,2998],{"class":1383},[198,7523,7524],{"class":1960},"bool",[198,7526,1757],{"class":1383},[198,7528,7529,7532,7534,7537,7539,7542,7544,7546],{"class":200,"line":220},[198,7530,7531],{"class":1387},"    temp",[198,7533,2998],{"class":1383},[198,7535,7536],{"class":1960},"Option",[198,7538,1384],{"class":1383},[198,7540,7541],{"class":1960},"Vec",[198,7543,1384],{"class":1383},[198,7545,7294],{"class":1960},[198,7547,7548],{"class":1383},">>,\n",[198,7550,7551],{"class":200,"line":254},[198,7552,1613],{"class":1383},[198,7554,7555],{"class":200,"line":260},[198,7556,217],{"emptyLinePlaceholder":216},[198,7558,7559,7561,7563,7565,7567,7569,7571,7574,7576,7578],{"class":200,"line":266},[198,7560,7236],{"class":1956},[198,7562,1384],{"class":1383},[198,7564,7241],{"class":1960},[198,7566,2998],{"class":1383},[198,7568,7212],{"class":1960},[198,7570,7249],{"class":1383},[198,7572,7573],{"class":1960},"InterpretAdapter",[198,7575,1384],{"class":1383},[198,7577,7241],{"class":1960},[198,7579,7263],{"class":1383},[198,7581,7582,7584,7586,7588,7591,7593,7595,7598,7601],{"class":200,"line":272},[198,7583,7268],{"class":1956},[198,7585,2341],{"class":2202},[198,7587,2206],{"class":1383},[198,7589,7590],{"class":1387},"inner",[198,7592,2998],{"class":1383},[198,7594,7241],{"class":1960},[198,7596,7597],{"class":1383},") -> ",[198,7599,7600],{"class":1960},"Self",[198,7602,1964],{"class":1383},[198,7604,7605,7608],{"class":200,"line":278},[198,7606,7607],{"class":1960},"        Self",[198,7609,1964],{"class":1383},[198,7611,7612,7615],{"class":200,"line":283},[198,7613,7614],{"class":1387},"            inner",[198,7616,1757],{"class":1383},[198,7618,7619,7622,7624,7627],{"class":200,"line":288},[198,7620,7621],{"class":1387},"            first",[198,7623,2998],{"class":1383},[198,7625,7626],{"class":1417},"true",[198,7628,1757],{"class":1383},[198,7630,7631,7634,7636,7639],{"class":200,"line":450},[198,7632,7633],{"class":1387},"            temp",[198,7635,2998],{"class":1383},[198,7637,7638],{"class":1960},"None",[198,7640,1757],{"class":1383},[198,7642,7643],{"class":200,"line":456},[198,7644,2442],{"class":1383},[198,7646,7647],{"class":200,"line":462},[198,7648,2447],{"class":1383},[198,7650,7651],{"class":200,"line":468},[198,7652,217],{"emptyLinePlaceholder":216},[198,7654,7655,7657,7660,7662,7664,7666],{"class":200,"line":473},[198,7656,7268],{"class":1956},[198,7658,7659],{"class":2202}," reset",[198,7661,6844],{"class":1383},[198,7663,6847],{"class":1956},[198,7665,7278],{"class":1960},[198,7667,2212],{"class":1383},[198,7669,7670,7672,7675,7677,7680],{"class":200,"line":478},[198,7671,7448],{"class":1960},[198,7673,7674],{"class":1383},".first ",[198,7676,1421],{"class":2220},[198,7678,7679],{"class":1417}," true",[198,7681,2008],{"class":1383},[198,7683,7684,7686,7689,7691,7694],{"class":200,"line":484},[198,7685,7448],{"class":1960},[198,7687,7688],{"class":1383},".temp ",[198,7690,1421],{"class":2220},[198,7692,7693],{"class":1960}," None",[198,7695,2008],{"class":1383},[198,7697,7698],{"class":200,"line":490},[198,7699,2447],{"class":1383},[198,7701,7702],{"class":200,"line":1068},[198,7703,1613],{"class":1383},[198,7705,7706],{"class":200,"line":1074},[198,7707,7708],{"class":1383},"...\n",[198,7710,7711,7713,7715,7717,7719,7721,7723,7725,7727,7729,7731,7733],{"class":200,"line":1080},[198,7712,7236],{"class":1956},[198,7714,1384],{"class":1383},[198,7716,7241],{"class":1960},[198,7718,2998],{"class":1383},[198,7720,7212],{"class":1960},[198,7722,7249],{"class":1383},[198,7724,7212],{"class":1960},[198,7726,7254],{"class":1956},[198,7728,7493],{"class":1960},[198,7730,1384],{"class":1383},[198,7732,7241],{"class":1960},[198,7734,7263],{"class":1383},[198,7736,7737,7739,7742,7744,7746,7748,7750,7752,7754,7756,7759,7761],{"class":200,"line":1086},[198,7738,7268],{"class":1956},[198,7740,7741],{"class":2202}," fill_buf",[198,7743,6844],{"class":1383},[198,7745,6847],{"class":1956},[198,7747,7278],{"class":1960},[198,7749,7597],{"class":1383},[198,7751,7300],{"class":1960},[198,7753,5252],{"class":1383},[198,7755,7305],{"class":1960},[198,7757,7758],{"class":1383},"\u003C&[",[198,7760,7294],{"class":1960},[198,7762,7763],{"class":1383},"]> {\n",[198,7765,7766,7768,7770,7773,7776],{"class":200,"line":1092},[198,7767,2304],{"class":1956},[198,7769,7278],{"class":1960},[198,7771,7772],{"class":1383},".temp.",[198,7774,7775],{"class":2202},"is_none",[198,7777,6731],{"class":1383},[198,7779,7780,7782,7784,7786,7788,7790,7792],{"class":200,"line":1098},[198,7781,7406],{"class":1956},[198,7783,7348],{"class":1387},[198,7785,2221],{"class":2220},[198,7787,7278],{"class":1960},[198,7789,7376],{"class":1383},[198,7791,7216],{"class":2202},[198,7793,7422],{"class":1383},[198,7795,7796,7798,7800,7802,7804,7806,7808,7811],{"class":200,"line":1104},[198,7797,7406],{"class":1956},[198,7799,6792],{"class":1956},[198,7801,7348],{"class":1387},[198,7803,2221],{"class":2220},[198,7805,7348],{"class":1387},[198,7807,41],{"class":1383},[198,7809,7810],{"class":2202},"to_vec",[198,7812,2244],{"class":1383},[198,7814,7815],{"class":200,"line":1110},[198,7816,217],{"emptyLinePlaceholder":216},[198,7818,7819,7822,7824,7826,7828,7831,7833,7835,7838],{"class":200,"line":1116},[198,7820,7821],{"class":1956},"            if",[198,7823,7278],{"class":1960},[198,7825,7674],{"class":1383},[198,7827,5921],{"class":2220},[198,7829,7830],{"class":2220}," !",[198,7832,7283],{"class":1387},[198,7834,41],{"class":1383},[198,7836,7837],{"class":2202},"is_empty",[198,7839,6731],{"class":1383},[198,7841,7842,7845,7847,7849,7852],{"class":200,"line":1122},[198,7843,7844],{"class":1960},"                self",[198,7846,7674],{"class":1383},[198,7848,1421],{"class":2220},[198,7850,7851],{"class":1417}," false",[198,7853,2008],{"class":1383},[198,7855,7856],{"class":200,"line":1128},[198,7857,217],{"emptyLinePlaceholder":216},[198,7859,7860,7863,7865,7867,7869,7871,7873,7876,7878,7880,7882,7884,7886,7888,7891],{"class":200,"line":1134},[198,7861,7862],{"class":1956},"                if",[198,7864,7348],{"class":1387},[198,7866,6940],{"class":1383},[198,7868,5912],{"class":1417},[198,7870,6945],{"class":1383},[198,7872,2487],{"class":2220},[198,7874,7875],{"class":1417}," 0xd6",[198,7877,6955],{"class":2220},[198,7879,7348],{"class":1387},[198,7881,6940],{"class":1383},[198,7883,5912],{"class":1417},[198,7885,6945],{"class":1383},[198,7887,2487],{"class":2220},[198,7889,7890],{"class":1417}," 0xd7",[198,7892,1964],{"class":1383},[198,7894,7895,7898,7900,7902,7904,7906,7909],{"class":200,"line":1140},[198,7896,7897],{"class":1387},"                    buf",[198,7899,6940],{"class":1383},[198,7901,5912],{"class":1417},[198,7903,6945],{"class":1383},[198,7905,1421],{"class":2220},[198,7907,7908],{"class":1417}," 0x78",[198,7910,2008],{"class":1383},[198,7912,7913,7916,7918,7920,7922,7924,7926,7928,7930,7933],{"class":200,"line":1146},[198,7914,7915],{"class":1383},"                } ",[198,7917,2416],{"class":1956},[198,7919,7044],{"class":1956},[198,7921,7348],{"class":1387},[198,7923,6940],{"class":1383},[198,7925,5912],{"class":1417},[198,7927,6945],{"class":1383},[198,7929,2487],{"class":2220},[198,7931,7932],{"class":1417}," 0xb3",[198,7934,1964],{"class":1383},[198,7936,7937],{"class":200,"line":1151},[198,7938,7939],{"class":1930},"                    \u002F\u002F EOF\n",[198,7941,7942,7944,7946,7948,7950,7952],{"class":200,"line":1157},[198,7943,7897],{"class":1387},[198,7945,2221],{"class":2220},[198,7947,6825],{"class":1960},[198,7949,5252],{"class":1383},[198,7951,6778],{"class":2202},[198,7953,2244],{"class":1383},[198,7955,7956],{"class":200,"line":1163},[198,7957,7958],{"class":1383},"                }\n",[198,7960,7961],{"class":200,"line":1169},[198,7962,7963],{"class":1383},"            }\n",[198,7965,7966],{"class":200,"line":1175},[198,7967,217],{"emptyLinePlaceholder":216},[198,7969,7970,7973,7975,7977,7980,7982,7984],{"class":200,"line":1181},[198,7971,7972],{"class":1960},"            self",[198,7974,7688],{"class":1383},[198,7976,1421],{"class":2220},[198,7978,7979],{"class":1960}," Some",[198,7981,2206],{"class":1383},[198,7983,7283],{"class":1387},[198,7985,2280],{"class":1383},[198,7987,7988],{"class":200,"line":1187},[198,7989,2442],{"class":1383},[198,7991,7992],{"class":200,"line":1193},[198,7993,217],{"emptyLinePlaceholder":216},[198,7995,7996,7998,8000,8003,8005,8008,8011,8013],{"class":200,"line":1199},[198,7997,7464],{"class":1960},[198,7999,2206],{"class":1383},[198,8001,8002],{"class":1960},"self",[198,8004,7772],{"class":1383},[198,8006,8007],{"class":2202},"as_ref",[198,8009,8010],{"class":1383},"().",[198,8012,6759],{"class":2202},[198,8014,8015],{"class":1383},"())\n",[198,8017,8018],{"class":200,"line":1205},[198,8019,2447],{"class":1383},[198,8021,8022],{"class":200,"line":1211},[198,8023,217],{"emptyLinePlaceholder":216},[198,8025,8026,8028,8031,8033,8035,8037,8039,8042,8044,8046],{"class":200,"line":1217},[198,8027,7268],{"class":1956},[198,8029,8030],{"class":2202}," consume",[198,8032,6844],{"class":1383},[198,8034,6847],{"class":1956},[198,8036,7278],{"class":1960},[198,8038,2764],{"class":1383},[198,8040,8041],{"class":1387},"amt",[198,8043,2998],{"class":1383},[198,8045,7310],{"class":1960},[198,8047,2212],{"class":1383},[198,8049,8050,8052,8055,8058,8060],{"class":200,"line":1223},[198,8051,2304],{"class":1956},[198,8053,8054],{"class":1387}," amt",[198,8056,8057],{"class":2220}," >",[198,8059,6021],{"class":1417},[198,8061,1964],{"class":1383},[198,8063,8064,8066,8068,8070,8072],{"class":200,"line":1228},[198,8065,7972],{"class":1960},[198,8067,7688],{"class":1383},[198,8069,1421],{"class":2220},[198,8071,7693],{"class":1960},[198,8073,2008],{"class":1383},[198,8075,8076,8078,8080,8082,8084,8086],{"class":200,"line":1233},[198,8077,7972],{"class":1960},[198,8079,7376],{"class":1383},[198,8081,7220],{"class":2202},[198,8083,2206],{"class":1383},[198,8085,8041],{"class":1387},[198,8087,2280],{"class":1383},[198,8089,8090],{"class":200,"line":1238},[198,8091,2442],{"class":1383},[198,8093,8094],{"class":200,"line":1244},[198,8095,2447],{"class":1383},[198,8097,8098],{"class":200,"line":1250},[198,8099,1613],{"class":1383},[11,8101,8102,8103,8106,8107,8110,8111,8113,8114,8116,8117,2688,8119,8121],{},"Cet adaptateur s'intercale entre le ",[165,8104,8105],{},"BufReader"," et le ",[165,8108,8109],{},"ZLibDecoder",". Du point de vue du ",[165,8112,8109],{},", il doit\nse comporter comme un ",[165,8115,8105],{}," et donc implémenter les méthodes ",[165,8118,7216],{},[165,8120,7220],{},". Dans ces méthodes, je dois\nretourner un tampon.",[11,8123,8124,8125,8127],{},"Je ne peux pas modifier directement le tampon du ",[165,8126,8105],{}," car ce dernier est une référence en lecture seule. Je\ncopie donc le contenu (je n'ai pas trouvé de meilleure manière de faire cela).",[11,8129,8130,8131,8134,8135,8138,8139,8141],{},"Enfin, on peut développer le ",[165,8132,8133],{},"Reader"," qui sera capable de lire les fichiers compressés. Pour cela, j'ai d'abord\nimplémenté une méthode ",[165,8136,8137],{},"read_some_bytes"," qui permet de lire un certain nombre d'octets. Si jamais on arrive à la fin\nd'une section, alors la méthode peut retourner moins que la taille du tampon. Généralement, cela arrive en fin de\nfichier. Quand j'ai utilisé directement cette méthode en tant que méthode ",[165,8140,7379],{},", je me suis retrouvé avec des\ncorruptions.",[190,8143,8145],{"className":6673,"code":8144,"language":6675,"meta":59,"style":59},"pub struct BackupPCReader\u003CR: Read> {\n    decoder: Option\u003CZlibDecoder\u003CInterpretAdapter\u003CBufReader\u003CR>>>>,\n}\n...\nfn read_some_bytes(&mut self, buf: &mut [u8]) -> io::Result\u003Cusize> {\n    loop {\n        let decoder = self.decoder.as_mut();\n        if decoder.is_none() {\n            return Ok(0);\n        }\n\n        let decoder_read_result = decoder.unwrap().read(buf);\n\n        let count = match decoder_read_result {\n            Ok(count) => {\n                count\n            }\n            Err(e) => {\n                return Err(e);\n            }\n        };\n\n        if count != 0 {\n            return Ok(count);\n        }\n\n        if count == 0 {\n            let decoder = self.decoder.take();\n            if let Some(decoder) = decoder {\n                let mut reader = decoder.into_inner();\n                \u002F\u002F S'il reste encore des octets à lire dans reader alors on continue, sinon on s'arrête\n                if reader.fill_buf()?.is_empty() {\n                    return Ok(0);\n                }\n                reader.reset();\n\n                self.decoder = Some(ZlibDecoder::new(reader));\n            }\n        }\n    }\n}\n",[165,8146,8147,8168,8196,8200,8204,8243,8250,8269,8281,8294,8298,8302,8327,8331,8347,8360,8365,8369,8381,8395,8399,8403,8407,8419,8431,8435,8439,8451,8468,8491,8512,8517,8534,8547,8551,8563,8567,8593,8597,8601,8605],{"__ignoreMap":59},[198,8148,8149,8152,8155,8158,8160,8162,8164,8166],{"class":200,"line":201},[198,8150,8151],{"class":1956},"pub",[198,8153,8154],{"class":1956}," struct",[198,8156,8157],{"class":1960}," BackupPCReader",[198,8159,1384],{"class":1383},[198,8161,7241],{"class":1960},[198,8163,2998],{"class":1383},[198,8165,7246],{"class":1960},[198,8167,7263],{"class":1383},[198,8169,8170,8173,8175,8177,8179,8181,8183,8185,8187,8189,8191,8193],{"class":200,"line":207},[198,8171,8172],{"class":1387},"    decoder",[198,8174,2998],{"class":1383},[198,8176,7536],{"class":1960},[198,8178,1384],{"class":1383},[198,8180,6695],{"class":1960},[198,8182,1384],{"class":1383},[198,8184,7573],{"class":1960},[198,8186,1384],{"class":1383},[198,8188,8105],{"class":1960},[198,8190,1384],{"class":1383},[198,8192,7241],{"class":1960},[198,8194,8195],{"class":1383},">>>>,\n",[198,8197,8198],{"class":200,"line":213},[198,8199,1613],{"class":1383},[198,8201,8202],{"class":200,"line":220},[198,8203,7708],{"class":1383},[198,8205,8206,8208,8211,8213,8215,8217,8219,8221,8223,8225,8227,8229,8231,8233,8235,8237,8239,8241],{"class":200,"line":254},[198,8207,6725],{"class":1956},[198,8209,8210],{"class":2202}," read_some_bytes",[198,8212,6844],{"class":1383},[198,8214,6847],{"class":1956},[198,8216,7278],{"class":1960},[198,8218,2764],{"class":1383},[198,8220,7283],{"class":1387},[198,8222,7286],{"class":1383},[198,8224,6847],{"class":1956},[198,8226,7291],{"class":1383},[198,8228,7294],{"class":1960},[198,8230,7297],{"class":1383},[198,8232,7300],{"class":1960},[198,8234,5252],{"class":1383},[198,8236,7305],{"class":1960},[198,8238,1384],{"class":1383},[198,8240,7310],{"class":1960},[198,8242,7263],{"class":1383},[198,8244,8245,8248],{"class":200,"line":260},[198,8246,8247],{"class":1956},"    loop",[198,8249,1964],{"class":1383},[198,8251,8252,8254,8257,8259,8261,8264,8267],{"class":200,"line":266},[198,8253,7394],{"class":1956},[198,8255,8256],{"class":1387}," decoder",[198,8258,2221],{"class":2220},[198,8260,7278],{"class":1960},[198,8262,8263],{"class":1383},".decoder.",[198,8265,8266],{"class":2202},"as_mut",[198,8268,2244],{"class":1383},[198,8270,8271,8273,8275,8277,8279],{"class":200,"line":272},[198,8272,2304],{"class":1956},[198,8274,8256],{"class":1387},[198,8276,41],{"class":1383},[198,8278,7775],{"class":2202},[198,8280,6731],{"class":1383},[198,8282,8283,8285,8288,8290,8292],{"class":200,"line":278},[198,8284,7371],{"class":1956},[198,8286,8287],{"class":1960}," Ok",[198,8289,2206],{"class":1383},[198,8291,5912],{"class":1417},[198,8293,2280],{"class":1383},[198,8295,8296],{"class":200,"line":283},[198,8297,2442],{"class":1383},[198,8299,8300],{"class":200,"line":288},[198,8301,217],{"emptyLinePlaceholder":216},[198,8303,8304,8306,8309,8311,8313,8315,8317,8319,8321,8323,8325],{"class":200,"line":450},[198,8305,7394],{"class":1956},[198,8307,8308],{"class":1387}," decoder_read_result",[198,8310,2221],{"class":2220},[198,8312,8256],{"class":1387},[198,8314,41],{"class":1383},[198,8316,6759],{"class":2202},[198,8318,8010],{"class":1383},[198,8320,7379],{"class":2202},[198,8322,2206],{"class":1383},[198,8324,7283],{"class":1387},[198,8326,2280],{"class":1383},[198,8328,8329],{"class":200,"line":456},[198,8330,217],{"emptyLinePlaceholder":216},[198,8332,8333,8335,8338,8340,8343,8345],{"class":200,"line":462},[198,8334,7394],{"class":1956},[198,8336,8337],{"class":1387}," count",[198,8339,2221],{"class":2220},[198,8341,8342],{"class":1956}," match",[198,8344,8308],{"class":1387},[198,8346,1964],{"class":1383},[198,8348,8349,8352,8354,8357],{"class":200,"line":468},[198,8350,8351],{"class":1960},"            Ok",[198,8353,2206],{"class":1383},[198,8355,8356],{"class":1387},"count",[198,8358,8359],{"class":1383},") => {\n",[198,8361,8362],{"class":200,"line":473},[198,8363,8364],{"class":1387},"                count\n",[198,8366,8367],{"class":200,"line":478},[198,8368,7963],{"class":1383},[198,8370,8371,8374,8376,8379],{"class":200,"line":484},[198,8372,8373],{"class":1960},"            Err",[198,8375,2206],{"class":1383},[198,8377,8378],{"class":1387},"e",[198,8380,8359],{"class":1383},[198,8382,8383,8386,8389,8391,8393],{"class":200,"line":490},[198,8384,8385],{"class":1956},"                return",[198,8387,8388],{"class":1960}," Err",[198,8390,2206],{"class":1383},[198,8392,8378],{"class":1387},[198,8394,2280],{"class":1383},[198,8396,8397],{"class":200,"line":1068},[198,8398,7963],{"class":1383},[198,8400,8401],{"class":200,"line":1074},[198,8402,7443],{"class":1383},[198,8404,8405],{"class":200,"line":1080},[198,8406,217],{"emptyLinePlaceholder":216},[198,8408,8409,8411,8413,8415,8417],{"class":200,"line":1086},[198,8410,2304],{"class":1956},[198,8412,8337],{"class":1387},[198,8414,2499],{"class":2220},[198,8416,6021],{"class":1417},[198,8418,1964],{"class":1383},[198,8420,8421,8423,8425,8427,8429],{"class":200,"line":1092},[198,8422,7371],{"class":1956},[198,8424,8287],{"class":1960},[198,8426,2206],{"class":1383},[198,8428,8356],{"class":1387},[198,8430,2280],{"class":1383},[198,8432,8433],{"class":200,"line":1098},[198,8434,2442],{"class":1383},[198,8436,8437],{"class":200,"line":1104},[198,8438,217],{"emptyLinePlaceholder":216},[198,8440,8441,8443,8445,8447,8449],{"class":200,"line":1110},[198,8442,2304],{"class":1956},[198,8444,8337],{"class":1387},[198,8446,2294],{"class":2220},[198,8448,6021],{"class":1417},[198,8450,1964],{"class":1383},[198,8452,8453,8455,8457,8459,8461,8463,8466],{"class":200,"line":1116},[198,8454,7406],{"class":1956},[198,8456,8256],{"class":1387},[198,8458,2221],{"class":2220},[198,8460,7278],{"class":1960},[198,8462,8263],{"class":1383},[198,8464,8465],{"class":2202},"take",[198,8467,2244],{"class":1383},[198,8469,8470,8472,8475,8477,8479,8482,8485,8487,8489],{"class":200,"line":1122},[198,8471,7821],{"class":1956},[198,8473,8474],{"class":1956}," let",[198,8476,7979],{"class":1960},[198,8478,2206],{"class":1383},[198,8480,8481],{"class":1387},"decoder",[198,8483,8484],{"class":1383},") ",[198,8486,1421],{"class":2220},[198,8488,8256],{"class":1387},[198,8490,1964],{"class":1383},[198,8492,8493,8496,8498,8501,8503,8505,8507,8510],{"class":200,"line":1128},[198,8494,8495],{"class":1956},"                let",[198,8497,6792],{"class":1956},[198,8499,8500],{"class":1387}," reader",[198,8502,2221],{"class":2220},[198,8504,8256],{"class":1387},[198,8506,41],{"class":1383},[198,8508,8509],{"class":2202},"into_inner",[198,8511,2244],{"class":1383},[198,8513,8514],{"class":200,"line":1134},[198,8515,8516],{"class":1930},"                \u002F\u002F S'il reste encore des octets à lire dans reader alors on continue, sinon on s'arrête\n",[198,8518,8519,8521,8523,8525,8527,8530,8532],{"class":200,"line":1140},[198,8520,7862],{"class":1956},[198,8522,8500],{"class":1387},[198,8524,41],{"class":1383},[198,8526,7216],{"class":2202},[198,8528,8529],{"class":1383},"()?.",[198,8531,7837],{"class":2202},[198,8533,6731],{"class":1383},[198,8535,8536,8539,8541,8543,8545],{"class":200,"line":1146},[198,8537,8538],{"class":1956},"                    return",[198,8540,8287],{"class":1960},[198,8542,2206],{"class":1383},[198,8544,5912],{"class":1417},[198,8546,2280],{"class":1383},[198,8548,8549],{"class":200,"line":1151},[198,8550,7958],{"class":1383},[198,8552,8553,8556,8558,8561],{"class":200,"line":1157},[198,8554,8555],{"class":1387},"                reader",[198,8557,41],{"class":1383},[198,8559,8560],{"class":2202},"reset",[198,8562,2244],{"class":1383},[198,8564,8565],{"class":200,"line":1163},[198,8566,217],{"emptyLinePlaceholder":216},[198,8568,8569,8571,8574,8576,8578,8580,8582,8584,8586,8588,8591],{"class":200,"line":1169},[198,8570,7844],{"class":1960},[198,8572,8573],{"class":1383},".decoder ",[198,8575,1421],{"class":2220},[198,8577,7979],{"class":1960},[198,8579,2206],{"class":1383},[198,8581,6695],{"class":1960},[198,8583,5252],{"class":1383},[198,8585,6778],{"class":2202},[198,8587,2206],{"class":1383},[198,8589,8590],{"class":1387},"reader",[198,8592,2528],{"class":1383},[198,8594,8595],{"class":200,"line":1175},[198,8596,7963],{"class":1383},[198,8598,8599],{"class":200,"line":1181},[198,8600,2442],{"class":1383},[198,8602,8603],{"class":200,"line":1187},[198,8604,2447],{"class":1383},[198,8606,8607],{"class":200,"line":1193},[198,8608,1613],{"class":1383},[11,8610,8611,8612,8614],{},"J'ai donc rédigé une méthode ",[165,8613,7379],{}," qui remplit le tampon tant que le nombre d'octets lus est inférieur à la taille du\ntampon. On ne retourne 0 que dans le cas où la lecture du fichier est terminée.",[190,8616,8618],{"className":6673,"code":8617,"language":6675,"meta":59,"style":59},"fn read(&mut self, buf: &mut [u8]) -> io::Result\u003Cusize> {\n    let mut total_bytes_read = 0;\n\n    while total_bytes_read \u003C buf.len() {\n        let bytes_to_read = &mut buf[total_bytes_read..];\n        let bytes_read = self.read_some_bytes(bytes_to_read)?;\n        total_bytes_read += bytes_read;\n\n        if bytes_read == 0 {\n            break;\n        }\n    }\n\n    Ok(total_bytes_read)\n}\n",[165,8619,8620,8658,8673,8677,8695,8719,8742,8754,8758,8770,8777,8781,8785,8789,8800],{"__ignoreMap":59},[198,8621,8622,8624,8626,8628,8630,8632,8634,8636,8638,8640,8642,8644,8646,8648,8650,8652,8654,8656],{"class":200,"line":201},[198,8623,6725],{"class":1956},[198,8625,7271],{"class":2202},[198,8627,6844],{"class":1383},[198,8629,6847],{"class":1956},[198,8631,7278],{"class":1960},[198,8633,2764],{"class":1383},[198,8635,7283],{"class":1387},[198,8637,7286],{"class":1383},[198,8639,6847],{"class":1956},[198,8641,7291],{"class":1383},[198,8643,7294],{"class":1960},[198,8645,7297],{"class":1383},[198,8647,7300],{"class":1960},[198,8649,5252],{"class":1383},[198,8651,7305],{"class":1960},[198,8653,1384],{"class":1383},[198,8655,7310],{"class":1960},[198,8657,7263],{"class":1383},[198,8659,8660,8662,8664,8667,8669,8671],{"class":200,"line":207},[198,8661,6736],{"class":1956},[198,8663,6792],{"class":1956},[198,8665,8666],{"class":1387}," total_bytes_read",[198,8668,2221],{"class":2220},[198,8670,6021],{"class":1417},[198,8672,2008],{"class":1383},[198,8674,8675],{"class":200,"line":213},[198,8676,217],{"emptyLinePlaceholder":216},[198,8678,8679,8682,8684,8687,8689,8691,8693],{"class":200,"line":220},[198,8680,8681],{"class":1956},"    while",[198,8683,8666],{"class":1387},[198,8685,8686],{"class":2220}," \u003C",[198,8688,7348],{"class":1387},[198,8690,41],{"class":1383},[198,8692,7353],{"class":2202},[198,8694,6731],{"class":1383},[198,8696,8697,8699,8702,8704,8707,8709,8711,8713,8716],{"class":200,"line":254},[198,8698,7394],{"class":1956},[198,8700,8701],{"class":1387}," bytes_to_read",[198,8703,2221],{"class":2220},[198,8705,8706],{"class":1383}," &",[198,8708,6847],{"class":1956},[198,8710,7348],{"class":1387},[198,8712,6940],{"class":1383},[198,8714,8715],{"class":1387},"total_bytes_read",[198,8717,8718],{"class":1383},"..];\n",[198,8720,8721,8723,8726,8728,8730,8732,8734,8736,8739],{"class":200,"line":260},[198,8722,7394],{"class":1956},[198,8724,8725],{"class":1387}," bytes_read",[198,8727,2221],{"class":2220},[198,8729,7278],{"class":1960},[198,8731,41],{"class":1383},[198,8733,8137],{"class":2202},[198,8735,2206],{"class":1383},[198,8737,8738],{"class":1387},"bytes_to_read",[198,8740,8741],{"class":1383},")?;\n",[198,8743,8744,8747,8750,8752],{"class":200,"line":266},[198,8745,8746],{"class":1387},"        total_bytes_read",[198,8748,8749],{"class":2220}," +=",[198,8751,8725],{"class":1387},[198,8753,2008],{"class":1383},[198,8755,8756],{"class":200,"line":272},[198,8757,217],{"emptyLinePlaceholder":216},[198,8759,8760,8762,8764,8766,8768],{"class":200,"line":278},[198,8761,2304],{"class":1956},[198,8763,8725],{"class":1387},[198,8765,2294],{"class":2220},[198,8767,6021],{"class":1417},[198,8769,1964],{"class":1383},[198,8771,8772,8775],{"class":200,"line":283},[198,8773,8774],{"class":1956},"            break",[198,8776,2008],{"class":1383},[198,8778,8779],{"class":200,"line":288},[198,8780,2442],{"class":1383},[198,8782,8783],{"class":200,"line":450},[198,8784,2447],{"class":1383},[198,8786,8787],{"class":200,"line":456},[198,8788,217],{"emptyLinePlaceholder":216},[198,8790,8791,8794,8796,8798],{"class":200,"line":462},[198,8792,8793],{"class":1960},"    Ok",[198,8795,2206],{"class":1383},[198,8797,8715],{"class":1387},[198,8799,2845],{"class":1383},[198,8801,8802],{"class":200,"line":468},[198,8803,1613],{"class":1383},[1714,8805,8807],{"id":8806},"les-fichiers-dattributs","Les fichiers d'attributs",[11,8809,8810],{},"Les fichiers d'attributs sont d'abord des fichiers compressés en utilisant la méthode décrite précédemment. J'ai donc\nutilisé le Reader que j'ai écrit précédemment pour décompresser les fichiers au fur et à mesure de leur lecture.",[11,8812,8813],{},"Je me suis ensuite attaqué au décodage des fichiers d'attributs. En réécrivant le code, j'ai découvert que certains\nnombres étaient mal encodés, ce qui provoquait des erreurs de décodage que j'ai dû gérer avec plus de flexibilité.",[11,8815,8816,8817,8819,8820,8822,8823,8828],{},"Pour lire un ",[165,8818,6595],{},", j'ai ajouté un trait au trait ",[165,8821,7246],{},". Je me suis basé sur le ",[15,8824,8827],{"href":8825,"rel":8826},"https:\u002F\u002Fgithub.com\u002Fbackuppc\u002Fbackuppc-xs\u002Fblob\u002Fmaster\u002Fbpc_attrib.c#L548",[24],"code C de BackupPC",",\ntout en modifiant la philosophie pour répondre au fonctionnement d'un Reader Rust.",[190,8830,8832],{"className":6673,"code":8831,"language":6675,"meta":59,"style":59},"pub trait VarintRead: Read {\n    fn read_varint(&mut self) -> io::Result\u003Cu64> {\n        let mut result = 0;\n        let mut shift = 0;\n\n        loop {\n            let mut buf: [u8; 1] = [0u8; 1];\n            self.read_exact(&mut buf)?;\n\n            let byte = buf[0];\n            let val = (byte & 0x7F) as u64;\n            if shift >= 64 || val \u003C\u003C shift >> shift != val {\n                eprintln!(\"Varint too large: probably corrupted data\");\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    \"Varint too large: probably corrupted data\",\n                ));\n            }\n\n            result |= val \u003C\u003C shift;\n            if byte & 0x80 == 0 {\n                return Ok(result);\n            }\n            shift += 7;\n        }\n    }\n}\n",[165,8833,8834,8850,8878,8893,8908,8912,8919,8954,8971,8975,8992,9022,9053,9065,9086,9103,9110,9115,9119,9123,9139,9156,9169,9173,9185,9189,9193],{"__ignoreMap":59},[198,8835,8836,8838,8841,8844,8846,8848],{"class":200,"line":201},[198,8837,8151],{"class":1956},[198,8839,8840],{"class":1956}," trait",[198,8842,8843],{"class":1960}," VarintRead",[198,8845,2998],{"class":1383},[198,8847,7246],{"class":1960},[198,8849,1964],{"class":1383},[198,8851,8852,8854,8857,8859,8861,8863,8865,8867,8869,8871,8873,8876],{"class":200,"line":207},[198,8853,7268],{"class":1956},[198,8855,8856],{"class":2202}," read_varint",[198,8858,6844],{"class":1383},[198,8860,6847],{"class":1956},[198,8862,7278],{"class":1960},[198,8864,7597],{"class":1383},[198,8866,7300],{"class":1960},[198,8868,5252],{"class":1383},[198,8870,7305],{"class":1960},[198,8872,1384],{"class":1383},[198,8874,8875],{"class":1960},"u64",[198,8877,7263],{"class":1383},[198,8879,8880,8882,8884,8887,8889,8891],{"class":200,"line":213},[198,8881,7394],{"class":1956},[198,8883,6792],{"class":1956},[198,8885,8886],{"class":1387}," result",[198,8888,2221],{"class":2220},[198,8890,6021],{"class":1417},[198,8892,2008],{"class":1383},[198,8894,8895,8897,8899,8902,8904,8906],{"class":200,"line":220},[198,8896,7394],{"class":1956},[198,8898,6792],{"class":1956},[198,8900,8901],{"class":1387}," shift",[198,8903,2221],{"class":2220},[198,8905,6021],{"class":1417},[198,8907,2008],{"class":1383},[198,8909,8910],{"class":200,"line":254},[198,8911,217],{"emptyLinePlaceholder":216},[198,8913,8914,8917],{"class":200,"line":260},[198,8915,8916],{"class":1956},"        loop",[198,8918,1964],{"class":1383},[198,8920,8921,8923,8925,8927,8930,8932,8935,8937,8939,8941,8943,8945,8947,8949,8951],{"class":200,"line":266},[198,8922,7406],{"class":1956},[198,8924,6792],{"class":1956},[198,8926,7348],{"class":1387},[198,8928,8929],{"class":1383},": [",[198,8931,7294],{"class":1960},[198,8933,8934],{"class":1383},"; ",[198,8936,61],{"class":1417},[198,8938,6945],{"class":1383},[198,8940,1421],{"class":2220},[198,8942,7291],{"class":1383},[198,8944,5912],{"class":1417},[198,8946,7294],{"class":1960},[198,8948,8934],{"class":1383},[198,8950,61],{"class":1417},[198,8952,8953],{"class":1383},"];\n",[198,8955,8956,8958,8960,8963,8965,8967,8969],{"class":200,"line":272},[198,8957,7972],{"class":1960},[198,8959,41],{"class":1383},[198,8961,8962],{"class":2202},"read_exact",[198,8964,6844],{"class":1383},[198,8966,6847],{"class":1956},[198,8968,7348],{"class":1387},[198,8970,8741],{"class":1383},[198,8972,8973],{"class":200,"line":278},[198,8974,217],{"emptyLinePlaceholder":216},[198,8976,8977,8979,8982,8984,8986,8988,8990],{"class":200,"line":283},[198,8978,7406],{"class":1956},[198,8980,8981],{"class":1387}," byte",[198,8983,2221],{"class":2220},[198,8985,7348],{"class":1387},[198,8987,6940],{"class":1383},[198,8989,5912],{"class":1417},[198,8991,8953],{"class":1383},[198,8993,8994,8996,8999,9001,9003,9006,9009,9012,9014,9017,9020],{"class":200,"line":288},[198,8995,7406],{"class":1956},[198,8997,8998],{"class":1387}," val",[198,9000,2221],{"class":2220},[198,9002,2288],{"class":1383},[198,9004,9005],{"class":1387},"byte",[198,9007,9008],{"class":1383}," & ",[198,9010,9011],{"class":1417},"0x7F",[198,9013,8484],{"class":1383},[198,9015,9016],{"class":1956},"as",[198,9018,9019],{"class":1960}," u64",[198,9021,2008],{"class":1383},[198,9023,9024,9026,9028,9031,9033,9035,9037,9040,9042,9045,9047,9049,9051],{"class":200,"line":450},[198,9025,7821],{"class":1956},[198,9027,8901],{"class":1387},[198,9029,9030],{"class":2220}," >=",[198,9032,5860],{"class":1417},[198,9034,6955],{"class":2220},[198,9036,8998],{"class":1387},[198,9038,9039],{"class":2220}," \u003C\u003C",[198,9041,8901],{"class":1387},[198,9043,9044],{"class":2220}," >>",[198,9046,8901],{"class":1387},[198,9048,2499],{"class":2220},[198,9050,8998],{"class":1387},[198,9052,1964],{"class":1383},[198,9054,9055,9058,9060,9063],{"class":200,"line":456},[198,9056,9057],{"class":2202},"                eprintln!",[198,9059,2206],{"class":1383},[198,9061,9062],{"class":1424},"\"Varint too large: probably corrupted data\"",[198,9064,2280],{"class":1383},[198,9066,9067,9069,9071,9073,9075,9077,9080,9082,9084],{"class":200,"line":462},[198,9068,8385],{"class":1956},[198,9070,8388],{"class":1960},[198,9072,2206],{"class":1383},[198,9074,7300],{"class":1960},[198,9076,5252],{"class":1383},[198,9078,9079],{"class":1960},"Error",[198,9081,5252],{"class":1383},[198,9083,6778],{"class":2202},[198,9085,2775],{"class":1383},[198,9087,9088,9091,9093,9096,9098,9101],{"class":200,"line":468},[198,9089,9090],{"class":1960},"                    io",[198,9092,5252],{"class":1383},[198,9094,9095],{"class":1960},"ErrorKind",[198,9097,5252],{"class":1383},[198,9099,9100],{"class":1960},"InvalidData",[198,9102,1757],{"class":1383},[198,9104,9105,9108],{"class":200,"line":473},[198,9106,9107],{"class":1424},"                    \"Varint too large: probably corrupted data\"",[198,9109,1757],{"class":1383},[198,9111,9112],{"class":200,"line":478},[198,9113,9114],{"class":1383},"                ));\n",[198,9116,9117],{"class":200,"line":484},[198,9118,7963],{"class":1383},[198,9120,9121],{"class":200,"line":490},[198,9122,217],{"emptyLinePlaceholder":216},[198,9124,9125,9128,9131,9133,9135,9137],{"class":200,"line":1068},[198,9126,9127],{"class":1387},"            result",[198,9129,9130],{"class":2220}," |=",[198,9132,8998],{"class":1387},[198,9134,9039],{"class":2220},[198,9136,8901],{"class":1387},[198,9138,2008],{"class":1383},[198,9140,9141,9143,9145,9147,9150,9152,9154],{"class":200,"line":1074},[198,9142,7821],{"class":1956},[198,9144,8981],{"class":1387},[198,9146,9008],{"class":1383},[198,9148,9149],{"class":1417},"0x80",[198,9151,2294],{"class":2220},[198,9153,6021],{"class":1417},[198,9155,1964],{"class":1383},[198,9157,9158,9160,9162,9164,9167],{"class":200,"line":1080},[198,9159,8385],{"class":1956},[198,9161,8287],{"class":1960},[198,9163,2206],{"class":1383},[198,9165,9166],{"class":1387},"result",[198,9168,2280],{"class":1383},[198,9170,9171],{"class":200,"line":1086},[198,9172,7963],{"class":1383},[198,9174,9175,9178,9180,9183],{"class":200,"line":1092},[198,9176,9177],{"class":1387},"            shift",[198,9179,8749],{"class":2220},[198,9181,9182],{"class":1417}," 7",[198,9184,2008],{"class":1383},[198,9186,9187],{"class":200,"line":1098},[198,9188,2442],{"class":1383},[198,9190,9191],{"class":200,"line":1104},[198,9192,2447],{"class":1383},[198,9194,9195],{"class":200,"line":1110},[198,9196,1613],{"class":1383},[11,9198,9199,9200,9203],{},"Au cours de mes tests pour lire les fichiers d'attributs du pool, j'ai rencontré de nombreuses erreurs de décodage (avec\nle message ci-dessus : ",[1812,9201,9202],{},"Varint too large: probably corrupted data","). Ce qui est rassurant, c'est que cela n'est pas lié\nà mon algorithme. BackupPC rencontre le même problème lors du décodage de ses propres fichiers (ce qui se traduit dans\nson cas par une date en janvier 1970) :",[11,9205,9206],{},[3390,9207],{"src":9208,"alt":9209,"className":9210},"\u002FWoodstock\u002F2024-03-14_pr_backuppc_pool_1.png","Fichier corrompu",[6355],[11,9212,9213],{},"La question est donc : mes données sont-elles corrompues ou s'agit-il d'un bug de BackupPC ? Je ne vais pas obtenir de\nréponse à cette question.",[1714,9215,9217],{"id":9216},"la-lecture-des-machines-et-des-sauvegardes","La lecture des machines et des sauvegardes",[11,9219,9220],{},"La partie la plus ardue est terminée.",[83,9222,9223,9228,9234],{},[86,9224,9225,9226,41],{},"Pour lister les machines, il suffit de lister les dossiers du répertoire ",[165,9227,6575],{},[86,9229,9230,9231,41],{},"Pour lister les sauvegardes, il faut lire le fichier texte (tsv) ",[165,9232,9233],{},"__TOPDIR__\u002Fpc\u002F\u003Cmachine>\u002Fbackups",[86,9235,9236,9237,41],{},"Pour lister les dossiers partagés, il faut lister les dossiers du répertoire ",[165,9238,9239],{},"__TOPDIR__\u002Fpc\u002F\u003Cmachine>\u002F\u003Cbackup>",[11,9241,9242,9243,41],{},"J'ai écrit ces trois méthodes dans ce fichier, que je vous invite à consulter. Il n'est pas très complexe : ",[15,9244,9247],{"href":9245,"rel":9246},"https:\u002F\u002Fgogs.shadoware.org\u002Fphoenix\u002Fbackuppc_pool\u002Fsrc\u002Fbranch\u002Fmaster\u002Fsrc\u002Fhosts.rs",[24],"hosts.rs",[11,9249,9250],{},"Je peux donc affirmer que j'ai réussi à lire les fichiers du pool de BackupPC. Pour mieux visualiser le résultat, j'ai\ndécidé de me lancer un défi supplémentaire : écrire un pilote FUSE pour visualiser le pool de stockage.",[1714,9252,9254],{"id":9253},"le-driver-fuse","Le driver FUSE",[11,9256,9257],{},"L'étape suivante consiste donc à développer un pilote FUSE qui intègre tout cela. Il s'agit de lire les fichiers\nd'attributs pour reconstituer la structure du système de fichiers (qui sont dans le pool et compressés), et de lire les\nfichiers compressés pour les données.",[11,9259,9260,9261,41],{},"Pour gérer la partie du système de fichiers, j'ai utilisé la bibliothèque ",[15,9262,9265],{"href":9263,"rel":9264},"https:\u002F\u002Fdocs.rs\u002Ffuser\u002Flatest\u002Ffuser\u002Findex.html",[24],"fuser",[11,9267,9268],{},"Le cœur du système ayant été développé, la partie système de fichiers consiste principalement à décoder le chemin fourni\npar FUSE, à décompressé et lire le fichier d'attributs. Dans le cas où l'utilisateur souhaite lire le contenu d'un\nfichier, il faut décompresser le fichier compressé.",[11,9270,9271],{},"J'ai donc la partie système de fichiers qui gère les requêtes FUSE et les transmet à la partie vue (avec un système de\ncache), et la partie vue qui prend un chemin et le transforme dans le format suivant en appelant les différentes\nméthodes précédentes :",[83,9273,9274,9277,9280,9283],{},[86,9275,9276],{},"nom de l'hôte",[86,9278,9279],{},"numéro de sauvegarde",[86,9281,9282],{},"chemin du partage",[86,9284,9285],{},"chemin",[11,9287,9288,9289,9294],{},"Le décodage est réalisé dans le fichier ",[15,9290,9293],{"href":9291,"rel":9292},"https:\u002F\u002Fgogs.shadoware.org\u002Fphoenix\u002Fbackuppc_pool\u002Fsrc\u002Fbranch\u002Fmaster\u002Fsrc\u002Fview.rs",[24],"view.rs",".\nPour cette partie, j'ai ajouté des tests unitaires. Ces tests unitaires m'ont permis d'itérer plus rapidement pour\nconstruire le système de fichiers (sans avoir à monter ce dernier à chaque fois).",[11,9296,9297,9298,9300,9301,9304],{},"On appelle la méthode avec le chemin découpé à chaque ",[165,9299,5347],{}," pour obtenir les différents éléments du chemin (sous forme de\n",[165,9302,9303],{},"&[&str]",").:",[190,9306,9308],{"className":6673,"code":9307,"language":6675,"meta":59,"style":59},"pub fn list(&self, path: &[&str]) -> Result\u003CVec\u003CFileAttributes>> {\n    match path.len() {\n",[165,9309,9310,9351],{"__ignoreMap":59},[198,9311,9312,9314,9317,9320,9322,9324,9326,9329,9332,9335,9337,9339,9341,9343,9345,9348],{"class":200,"line":201},[198,9313,8151],{"class":1956},[198,9315,9316],{"class":1956}," fn",[198,9318,9319],{"class":2202}," list",[198,9321,6844],{"class":1383},[198,9323,8002],{"class":1960},[198,9325,2764],{"class":1383},[198,9327,9328],{"class":1387},"path",[198,9330,9331],{"class":1383},": &[&",[198,9333,9334],{"class":1960},"str",[198,9336,7297],{"class":1383},[198,9338,7305],{"class":1960},[198,9340,1384],{"class":1383},[198,9342,7541],{"class":1960},[198,9344,1384],{"class":1383},[198,9346,9347],{"class":1960},"FileAttributes",[198,9349,9350],{"class":1383},">> {\n",[198,9352,9353,9356,9359,9361,9363],{"class":200,"line":207},[198,9354,9355],{"class":1956},"    match",[198,9357,9358],{"class":1387}," path",[198,9360,41],{"class":1383},[198,9362,7353],{"class":2202},[198,9364,6731],{"class":1383},[11,9366,9367],{},"On commence d'abord par examiner le nombre d'éléments dans le chemin. Si nous n'avons aucun élément, cela signifie que\nnous sommes à la racine et que nous souhaitons obtenir la liste des machines.",[190,9369,9371],{"className":6673,"code":9370,"language":6675,"meta":59,"style":59},"        0 => {\n            let hosts = self.hosts.list_hosts()?;\n            Ok(hosts.into_iter().map(FileAttributes::from_host).collect())\n        }\n",[165,9372,9373,9381,9400,9435],{"__ignoreMap":59},[198,9374,9375,9378],{"class":200,"line":201},[198,9376,9377],{"class":1417},"        0",[198,9379,9380],{"class":1383}," => {\n",[198,9382,9383,9385,9388,9390,9392,9395,9398],{"class":200,"line":207},[198,9384,7406],{"class":1956},[198,9386,9387],{"class":1387}," hosts",[198,9389,2221],{"class":2220},[198,9391,7278],{"class":1960},[198,9393,9394],{"class":1383},".hosts.",[198,9396,9397],{"class":2202},"list_hosts",[198,9399,7422],{"class":1383},[198,9401,9402,9404,9406,9409,9411,9414,9416,9419,9421,9423,9425,9428,9430,9433],{"class":200,"line":213},[198,9403,8351],{"class":1960},[198,9405,2206],{"class":1383},[198,9407,9408],{"class":1387},"hosts",[198,9410,41],{"class":1383},[198,9412,9413],{"class":2202},"into_iter",[198,9415,8010],{"class":1383},[198,9417,9418],{"class":2202},"map",[198,9420,2206],{"class":1383},[198,9422,9347],{"class":1960},[198,9424,5252],{"class":1383},[198,9426,9427],{"class":1387},"from_host",[198,9429,958],{"class":1383},[198,9431,9432],{"class":2202},"collect",[198,9434,8015],{"class":1383},[198,9436,9437],{"class":200,"line":220},[198,9438,2442],{"class":1383},[11,9440,9441],{},"Si nous avons un seul élément, alors c'est le nom de la machine. Nous souhaitons donc récupérer la liste des sauvegardes\nassociées à cette machine.",[190,9443,9445],{"className":6673,"code":9444,"language":6675,"meta":59,"style":59},"        1 => {\n            let backups = self.hosts.list_backups(path[0]);\n            match backups {\n                Ok(backups) => Ok(backups\n                    .into_iter()\n                    .map(|a| FileAttributes::from_backup(&a))\n                    .collect()),\n                Err(err) => {\n                    \u002F\u002F If the file isn't found, it's because we should return empty vec\n                    if let Some(io_err) = err.downcast_ref::\u003Cstd::io::Error>() {\n                        if io_err.kind() == std::io::ErrorKind::NotFound {\n                            Ok(Vec::new())\n                        } else {\n                            Err(err)\n                        }\n                    } else {\n                        Err(err)\n                    }\n                }\n            }\n        }\n",[165,9446,9447,9454,9481,9490,9510,9520,9550,9559,9571,9576,9619,9653,9668,9677,9688,9693,9702,9713,9718,9722,9726],{"__ignoreMap":59},[198,9448,9449,9452],{"class":200,"line":201},[198,9450,9451],{"class":1417},"        1",[198,9453,9380],{"class":1383},[198,9455,9456,9458,9461,9463,9465,9467,9470,9472,9474,9476,9478],{"class":200,"line":207},[198,9457,7406],{"class":1956},[198,9459,9460],{"class":1387}," backups",[198,9462,2221],{"class":2220},[198,9464,7278],{"class":1960},[198,9466,9394],{"class":1383},[198,9468,9469],{"class":2202},"list_backups",[198,9471,2206],{"class":1383},[198,9473,9328],{"class":1387},[198,9475,6940],{"class":1383},[198,9477,5912],{"class":1417},[198,9479,9480],{"class":1383},"]);\n",[198,9482,9483,9486,9488],{"class":200,"line":213},[198,9484,9485],{"class":1956},"            match",[198,9487,9460],{"class":1387},[198,9489,1964],{"class":1383},[198,9491,9492,9495,9497,9499,9502,9505,9507],{"class":200,"line":220},[198,9493,9494],{"class":1960},"                Ok",[198,9496,2206],{"class":1383},[198,9498,6499],{"class":1387},[198,9500,9501],{"class":1383},") => ",[198,9503,9504],{"class":1960},"Ok",[198,9506,2206],{"class":1383},[198,9508,9509],{"class":1387},"backups\n",[198,9511,9512,9515,9517],{"class":200,"line":254},[198,9513,9514],{"class":1383},"                    .",[198,9516,9413],{"class":2202},[198,9518,9519],{"class":1383},"()\n",[198,9521,9522,9524,9526,9528,9531,9533,9535,9538,9540,9543,9545,9547],{"class":200,"line":260},[198,9523,9514],{"class":1383},[198,9525,9418],{"class":2202},[198,9527,2206],{"class":1383},[198,9529,9530],{"class":2220},"|",[198,9532,15],{"class":1387},[198,9534,9530],{"class":2220},[198,9536,9537],{"class":1960}," FileAttributes",[198,9539,5252],{"class":1383},[198,9541,9542],{"class":2202},"from_backup",[198,9544,6844],{"class":1383},[198,9546,15],{"class":1387},[198,9548,9549],{"class":1383},"))\n",[198,9551,9552,9554,9556],{"class":200,"line":266},[198,9553,9514],{"class":1383},[198,9555,9432],{"class":2202},[198,9557,9558],{"class":1383},"()),\n",[198,9560,9561,9564,9566,9569],{"class":200,"line":272},[198,9562,9563],{"class":1960},"                Err",[198,9565,2206],{"class":1383},[198,9567,9568],{"class":1387},"err",[198,9570,8359],{"class":1383},[198,9572,9573],{"class":200,"line":278},[198,9574,9575],{"class":1930},"                    \u002F\u002F If the file isn't found, it's because we should return empty vec\n",[198,9577,9578,9581,9583,9585,9587,9590,9592,9594,9597,9599,9602,9605,9608,9610,9612,9614,9616],{"class":200,"line":283},[198,9579,9580],{"class":1956},"                    if",[198,9582,8474],{"class":1956},[198,9584,7979],{"class":1960},[198,9586,2206],{"class":1383},[198,9588,9589],{"class":1387},"io_err",[198,9591,8484],{"class":1383},[198,9593,1421],{"class":2220},[198,9595,9596],{"class":1387}," err",[198,9598,41],{"class":1383},[198,9600,9601],{"class":2202},"downcast_ref",[198,9603,9604],{"class":1383},"::\u003C",[198,9606,9607],{"class":1960},"std",[198,9609,5252],{"class":1383},[198,9611,7300],{"class":1960},[198,9613,5252],{"class":1383},[198,9615,9079],{"class":1960},[198,9617,9618],{"class":1383},">() {\n",[198,9620,9621,9624,9627,9629,9632,9634,9636,9638,9640,9642,9644,9646,9648,9651],{"class":200,"line":288},[198,9622,9623],{"class":1956},"                        if",[198,9625,9626],{"class":1387}," io_err",[198,9628,41],{"class":1383},[198,9630,9631],{"class":2202},"kind",[198,9633,2484],{"class":1383},[198,9635,2487],{"class":2220},[198,9637,6704],{"class":1960},[198,9639,5252],{"class":1383},[198,9641,7300],{"class":1960},[198,9643,5252],{"class":1383},[198,9645,9095],{"class":1960},[198,9647,5252],{"class":1383},[198,9649,9650],{"class":1960},"NotFound",[198,9652,1964],{"class":1383},[198,9654,9655,9658,9660,9662,9664,9666],{"class":200,"line":450},[198,9656,9657],{"class":1960},"                            Ok",[198,9659,2206],{"class":1383},[198,9661,7541],{"class":1960},[198,9663,5252],{"class":1383},[198,9665,6778],{"class":2202},[198,9667,8015],{"class":1383},[198,9669,9670,9673,9675],{"class":200,"line":456},[198,9671,9672],{"class":1383},"                        } ",[198,9674,2416],{"class":1956},[198,9676,1964],{"class":1383},[198,9678,9679,9682,9684,9686],{"class":200,"line":462},[198,9680,9681],{"class":1960},"                            Err",[198,9683,2206],{"class":1383},[198,9685,9568],{"class":1387},[198,9687,2845],{"class":1383},[198,9689,9690],{"class":200,"line":468},[198,9691,9692],{"class":1383},"                        }\n",[198,9694,9695,9698,9700],{"class":200,"line":473},[198,9696,9697],{"class":1383},"                    } ",[198,9699,2416],{"class":1956},[198,9701,1964],{"class":1383},[198,9703,9704,9707,9709,9711],{"class":200,"line":478},[198,9705,9706],{"class":1960},"                        Err",[198,9708,2206],{"class":1383},[198,9710,9568],{"class":1387},[198,9712,2845],{"class":1383},[198,9714,9715],{"class":200,"line":484},[198,9716,9717],{"class":1383},"                    }\n",[198,9719,9720],{"class":200,"line":490},[198,9721,7958],{"class":1383},[198,9723,9724],{"class":200,"line":1068},[198,9725,7963],{"class":1383},[198,9727,9728],{"class":200,"line":1074},[198,9729,2442],{"class":1383},[11,9731,9732,9733,9736,9737,9739],{},"Si nous avons plus de deux éléments, alors nous souhaitons retourner au moins le partage, voire les fichiers à\nsauvegarder. Le problème est que le nom du partage ",[165,9734,9735],{},"share"," peut lui-même contenir des ",[165,9738,5347],{},". Il peut donc être composé de\nplusieurs éléments.",[11,9741,9742,9743,9746],{},"Le but de la méthode ",[165,9744,9745],{},"list_shares_of"," est de retourner le partage si ce dernier est un partage valide, ainsi que la\npartie du chemin qui suit le partage.",[190,9748,9750],{"className":6673,"code":9749,"language":6675,"meta":59,"style":59},"        _ => {\n            let (shares, selected_share, share_size) =\n                self.list_shares_of(path[0], path[1].parse::\u003Cu32>().unwrap_or(0), &path[2..])?;\n\n            let shares = shares.into_iter().map(FileAttributes::from_share).collect();\n",[165,9751,9752,9759,9783,9841,9845],{"__ignoreMap":59},[198,9753,9754,9757],{"class":200,"line":201},[198,9755,9756],{"class":1387},"        _",[198,9758,9380],{"class":1383},[198,9760,9761,9763,9765,9768,9770,9773,9775,9778,9780],{"class":200,"line":207},[198,9762,7406],{"class":1956},[198,9764,2288],{"class":1383},[198,9766,9767],{"class":1387},"shares",[198,9769,2764],{"class":1383},[198,9771,9772],{"class":1387},"selected_share",[198,9774,2764],{"class":1383},[198,9776,9777],{"class":1387},"share_size",[198,9779,8484],{"class":1383},[198,9781,9782],{"class":2220},"=\n",[198,9784,9785,9787,9789,9791,9793,9795,9797,9799,9802,9804,9806,9808,9811,9814,9816,9819,9822,9825,9827,9829,9832,9834,9836,9838],{"class":200,"line":213},[198,9786,7844],{"class":1960},[198,9788,41],{"class":1383},[198,9790,9745],{"class":2202},[198,9792,2206],{"class":1383},[198,9794,9328],{"class":1387},[198,9796,6940],{"class":1383},[198,9798,5912],{"class":1417},[198,9800,9801],{"class":1383},"], ",[198,9803,9328],{"class":1387},[198,9805,6940],{"class":1383},[198,9807,61],{"class":1417},[198,9809,9810],{"class":1383},"].",[198,9812,9813],{"class":2202},"parse",[198,9815,9604],{"class":1383},[198,9817,9818],{"class":1960},"u32",[198,9820,9821],{"class":1383},">().",[198,9823,9824],{"class":2202},"unwrap_or",[198,9826,2206],{"class":1383},[198,9828,5912],{"class":1417},[198,9830,9831],{"class":1383},"), &",[198,9833,9328],{"class":1387},[198,9835,6940],{"class":1383},[198,9837,4461],{"class":1417},[198,9839,9840],{"class":1383},"..])?;\n",[198,9842,9843],{"class":200,"line":220},[198,9844,217],{"emptyLinePlaceholder":216},[198,9846,9847,9849,9852,9854,9856,9858,9860,9862,9864,9866,9868,9870,9873,9875,9877],{"class":200,"line":254},[198,9848,7406],{"class":1956},[198,9850,9851],{"class":1387}," shares",[198,9853,2221],{"class":2220},[198,9855,9851],{"class":1387},[198,9857,41],{"class":1383},[198,9859,9413],{"class":2202},[198,9861,8010],{"class":1383},[198,9863,9418],{"class":2202},[198,9865,2206],{"class":1383},[198,9867,9347],{"class":1960},[198,9869,5252],{"class":1383},[198,9871,9872],{"class":1387},"from_share",[198,9874,958],{"class":1383},[198,9876,9432],{"class":2202},[198,9878,2244],{"class":1383},[11,9880,9881,9882,9885],{},"Une fois que nous avons le nom de la machine, le numéro de la sauvegarde et le partage, nous pouvons appeler la méthode\n",[165,9883,9884],{},"list_file_from_dir"," pour récupérer les fichiers du sous-dossier du partage.",[190,9887,9889],{"className":6673,"code":9888,"language":6675,"meta":59,"style":59},"            match selected_share {\n                None => Ok(shares),\n                Some(selected_share) => self.list_file_from_dir(\n                    path[0],\n                    path[1].parse::\u003Cu32>().unwrap_or(0),\n                    &selected_share,\n                    &path[(2 + share_size)..].join(\"\u002F\"),\n                ),\n            }\n        }\n    }\n}\n",[165,9890,9891,9900,9916,9935,9947,9973,9982,10011,10016,10020,10024,10028],{"__ignoreMap":59},[198,9892,9893,9895,9898],{"class":200,"line":201},[198,9894,9485],{"class":1956},[198,9896,9897],{"class":1387}," selected_share",[198,9899,1964],{"class":1383},[198,9901,9902,9905,9907,9909,9911,9913],{"class":200,"line":207},[198,9903,9904],{"class":1960},"                None",[198,9906,2629],{"class":1383},[198,9908,9504],{"class":1960},[198,9910,2206],{"class":1383},[198,9912,9767],{"class":1387},[198,9914,9915],{"class":1383},"),\n",[198,9917,9918,9921,9923,9925,9927,9929,9931,9933],{"class":200,"line":213},[198,9919,9920],{"class":1960},"                Some",[198,9922,2206],{"class":1383},[198,9924,9772],{"class":1387},[198,9926,9501],{"class":1383},[198,9928,8002],{"class":1960},[198,9930,41],{"class":1383},[198,9932,9884],{"class":2202},[198,9934,2775],{"class":1383},[198,9936,9937,9940,9942,9944],{"class":200,"line":220},[198,9938,9939],{"class":1387},"                    path",[198,9941,6940],{"class":1383},[198,9943,5912],{"class":1417},[198,9945,9946],{"class":1383},"],\n",[198,9948,9949,9951,9953,9955,9957,9959,9961,9963,9965,9967,9969,9971],{"class":200,"line":254},[198,9950,9939],{"class":1387},[198,9952,6940],{"class":1383},[198,9954,61],{"class":1417},[198,9956,9810],{"class":1383},[198,9958,9813],{"class":2202},[198,9960,9604],{"class":1383},[198,9962,9818],{"class":1960},[198,9964,9821],{"class":1383},[198,9966,9824],{"class":2202},[198,9968,2206],{"class":1383},[198,9970,5912],{"class":1417},[198,9972,9915],{"class":1383},[198,9974,9975,9978,9980],{"class":200,"line":260},[198,9976,9977],{"class":1383},"                    &",[198,9979,9772],{"class":1387},[198,9981,1757],{"class":1383},[198,9983,9984,9986,9988,9991,9993,9996,9998,10001,10004,10006,10009],{"class":200,"line":266},[198,9985,9977],{"class":1383},[198,9987,9328],{"class":1387},[198,9989,9990],{"class":1383},"[(",[198,9992,4461],{"class":1417},[198,9994,9995],{"class":1383}," + ",[198,9997,9777],{"class":1387},[198,9999,10000],{"class":1383},")..].",[198,10002,10003],{"class":2202},"join",[198,10005,2206],{"class":1383},[198,10007,10008],{"class":1424},"\"\u002F\"",[198,10010,9915],{"class":1383},[198,10012,10013],{"class":200,"line":272},[198,10014,10015],{"class":1383},"                ),\n",[198,10017,10018],{"class":200,"line":278},[198,10019,7963],{"class":1383},[198,10021,10022],{"class":200,"line":283},[198,10023,2442],{"class":1383},[198,10025,10026],{"class":200,"line":288},[198,10027,2447],{"class":1383},[198,10029,10030],{"class":200,"line":450},[198,10031,1613],{"class":1383},[11,10033,10034,10035,10040],{},"Enfin, pour la partie FUSE, je vous invite à consulter le fichier ",[15,10036,10039],{"href":10037,"rel":10038},"https:\u002F\u002Fgogs.shadoware.org\u002Fphoenix\u002Fbackuppc_pool\u002Fsrc\u002Fbranch\u002Fmaster\u002Fsrc\u002Ffilesystem.rs",[24],"filesystem.rs",".\nCe fichier fait simplement le lien entre la partie FUSE et la partie vue.",[11,10042,10043],{},"Sur la partie FUSE, j'ai ajouté un cache pour éviter de lire plusieurs fois le même fichier (d'attributs) dans le pool.",[11,10045,10046,10047,10050],{},"Une fois le système de fichiers construit, il était nécessaire de le tester avec des tests réels. Le premier test a\nconsisté à parcourir l'ensemble du système de fichiers pour vérifier si la partie attribut fonctionnait correctement.\nPour cela, j'ai utilisé le programme ",[165,10048,10049],{},"filelight",". Ce programme permet de parcourir le système de fichiers et de\nvisualiser la taille des fichiers.",[11,10052,10053],{},"Voici un exemple sur une partie de la sauvegarde :",[11,10055,10056],{},[3390,10057],{"src":10058,"alt":10059,"className":10060},"\u002FWoodstock\u002Ffilelight_localhost.png","Filelight",[6355],[11,10062,10063],{},"Enfin, pour tester la capacité du programme à lire tous les fichiers du système de fichiers, j'ai écrit un petit script\nshell.",[190,10065,10067],{"className":3436,"code":10066,"language":3438,"meta":59,"style":59},"#!\u002Fbin\u002Fbash\n\n# Fichiers de sortie\noutput_file=\"md5sums.txt\"\nerror_file=\"errors.txt\"\n\n# Parcourir tous les fichiers du système de fichiers\nfind \u002Fhome\u002Fphoenix\u002Ftmp\u002Ftest -type f -print0 | while IFS= read -r -d '' file; do\n    # Essayer de calculer le hash MD5 du fichier\n    if md5sum \"$file\" >> \"$output_file\"; then\n        echo \"Processed $file\"\n    else\n        # Si le fichier ne peut pas être lu, écrire le nom du fichier dans le fichier d'erreur\n        echo \"Failed to process $file\" >> \"$error_file\"\n    fi\ndone\n",[165,10068,10069,10074,10078,10083,10093,10103,10107,10112,10156,10161,10192,10205,10210,10215,10235,10240],{"__ignoreMap":59},[198,10070,10071],{"class":200,"line":201},[198,10072,10073],{"class":1930},"#!\u002Fbin\u002Fbash\n",[198,10075,10076],{"class":200,"line":207},[198,10077,217],{"emptyLinePlaceholder":216},[198,10079,10080],{"class":200,"line":213},[198,10081,10082],{"class":1930},"# Fichiers de sortie\n",[198,10084,10085,10088,10090],{"class":200,"line":220},[198,10086,10087],{"class":1387},"output_file",[198,10089,1421],{"class":2220},[198,10091,10092],{"class":1424},"\"md5sums.txt\"\n",[198,10094,10095,10098,10100],{"class":200,"line":254},[198,10096,10097],{"class":1387},"error_file",[198,10099,1421],{"class":2220},[198,10101,10102],{"class":1424},"\"errors.txt\"\n",[198,10104,10105],{"class":200,"line":260},[198,10106,217],{"emptyLinePlaceholder":216},[198,10108,10109],{"class":200,"line":266},[198,10110,10111],{"class":1930},"# Parcourir tous les fichiers du système de fichiers\n",[198,10113,10114,10116,10119,10122,10124,10127,10129,10132,10135,10137,10139,10142,10145,10148,10151,10153],{"class":200,"line":272},[198,10115,2273],{"class":2202},[198,10117,10118],{"class":1424}," \u002Fhome\u002Fphoenix\u002Ftmp\u002Ftest",[198,10120,10121],{"class":1417}," -type",[198,10123,6739],{"class":1424},[198,10125,10126],{"class":1417}," -print0",[198,10128,3166],{"class":1383},[198,10130,10131],{"class":1956},"while",[198,10133,10134],{"class":1387}," IFS",[198,10136,1421],{"class":2220},[198,10138,7271],{"class":2220},[198,10140,10141],{"class":1417}," -r",[198,10143,10144],{"class":1417}," -d",[198,10146,10147],{"class":1424}," ''",[198,10149,10150],{"class":1424}," file",[198,10152,8934],{"class":1383},[198,10154,10155],{"class":1956},"do\n",[198,10157,10158],{"class":200,"line":278},[198,10159,10160],{"class":1930},"    # Essayer de calculer le hash MD5 du fichier\n",[198,10162,10163,10165,10168,10171,10174,10177,10180,10182,10185,10187,10189],{"class":200,"line":283},[198,10164,2285],{"class":1956},[198,10166,10167],{"class":2202}," md5sum",[198,10169,10170],{"class":1424}," \"",[198,10172,10173],{"class":1387},"$file",[198,10175,10176],{"class":1424},"\"",[198,10178,10179],{"class":1383}," >> ",[198,10181,10176],{"class":1424},[198,10183,10184],{"class":1387},"$output_file",[198,10186,10176],{"class":1424},[198,10188,8934],{"class":1383},[198,10190,10191],{"class":1956},"then\n",[198,10193,10194,10197,10200,10202],{"class":200,"line":288},[198,10195,10196],{"class":2220},"        echo",[198,10198,10199],{"class":1424}," \"Processed ",[198,10201,10173],{"class":1387},[198,10203,10204],{"class":1424},"\"\n",[198,10206,10207],{"class":200,"line":450},[198,10208,10209],{"class":1956},"    else\n",[198,10211,10212],{"class":200,"line":456},[198,10213,10214],{"class":1930},"        # Si le fichier ne peut pas être lu, écrire le nom du fichier dans le fichier d'erreur\n",[198,10216,10217,10219,10222,10224,10226,10228,10230,10233],{"class":200,"line":462},[198,10218,10196],{"class":2220},[198,10220,10221],{"class":1424}," \"Failed to process ",[198,10223,10173],{"class":1387},[198,10225,10176],{"class":1424},[198,10227,10179],{"class":1383},[198,10229,10176],{"class":1424},[198,10231,10232],{"class":1387},"$error_file",[198,10234,10204],{"class":1424},[198,10236,10237],{"class":200,"line":468},[198,10238,10239],{"class":1956},"    fi\n",[198,10241,10242],{"class":200,"line":473},[198,10243,10244],{"class":1956},"done\n",[11,10246,10247],{},"J'ai récemment commencé à développer un autre programme en Rust qui utilise la notion de multithreading.",[1714,10249,10251],{"id":10250},"les-avantages-de-rust","Les avantages de Rust",[11,10253,10254],{},"En travaillant sur ce petit programme Rust, j'ai apprécié plusieurs aspects du langage. Rust offre la possibilité\nd'écrire du code de bas niveau sans avoir à gérer la mémoire comme en C, ce qui m'a procuré un sentiment de sécurité. De\nplus, la documentation de Rust est bien conçue et m'a permis de progresser rapidement.",[11,10256,10257,10258,10263],{},"J'ai également trouvé la syntaxe de Rust très lisible, à condition de ne pas utiliser les durées de vie. La présence de\nnombreux packages (crates) sur ",[15,10259,10262],{"href":10260,"rel":10261},"https:\u002F\u002Fcrates.io\u002F",[24],"crates.io"," facilite le développement rapide de fonctionnalités.",[11,10265,10266],{},"Clippy, un outil de vérification du code Rust, m'a été très utile. Il donne des conseils pour améliorer le code, ce qui\nm'a aidé à progresser, même s'il me reste encore du chemin à parcourir.",[1714,10268,10270],{"id":10269},"les-défis-rencontrés-avec-rust","Les défis rencontrés avec Rust",[11,10272,10273,10274,10277],{},"Malgré ces avantages, j'ai rencontré quelques difficultés, probablement dues à ma méconnaissance du langage Rust. Par\nexemple, pour certaines parties du code, je me suis retrouvé avec du code contenant le mot ",[1812,10275,10276],{},"unsafe",". J'ai refusé de\nl'utiliser, ce qui a rendu mon code plus complexe.",[11,10279,10280,10281,10284,10285,5220],{},"J'ai un cas particulier pour lequel je n'ai pas trouvé de solution. Dans mon logiciel de sauvegarde, je lis des noms de\nfichier que je stocke en tant que ",[165,10282,10283],{},"[u8]"," en Protobuf dans un fichier. Si je traite ces noms de fichier en tant que\nchaîne de caractères, je me retrouve avec des erreurs potentielles de conversion si le nom de fichier n'est pas en UTF-8\nsous Linux et en UTF-16 sous Windows. Pour stocker donc sous forme d'octet, j'utilise ces méthodes qui m'obligent à\nutiliser ",[165,10286,10276],{},[190,10288,10290],{"className":6673,"code":10289,"language":6675,"meta":59,"style":59},"#[must_use]\npub fn osstr_to_vec(path: &OsStr) -> Vec\u003Cu8> {\n    path.as_encoded_bytes().to_vec()\n}\n\n#[must_use]\npub fn vec_to_osstr(vec: &[u8]) -> OsString {\n    unsafe { OsString::from_encoded_bytes_unchecked(vec.to_owned()) }\n}\n",[165,10291,10292,10297,10325,10341,10345,10349,10353,10379,10406],{"__ignoreMap":59},[198,10293,10294],{"class":200,"line":201},[198,10295,10296],{"class":1383},"#[must_use]\n",[198,10298,10299,10301,10303,10306,10308,10310,10312,10315,10317,10319,10321,10323],{"class":200,"line":207},[198,10300,8151],{"class":1956},[198,10302,9316],{"class":1956},[198,10304,10305],{"class":2202}," osstr_to_vec",[198,10307,2206],{"class":1383},[198,10309,9328],{"class":1387},[198,10311,7286],{"class":1383},[198,10313,10314],{"class":1960},"OsStr",[198,10316,7597],{"class":1383},[198,10318,7541],{"class":1960},[198,10320,1384],{"class":1383},[198,10322,7294],{"class":1960},[198,10324,7263],{"class":1383},[198,10326,10327,10330,10332,10335,10337,10339],{"class":200,"line":213},[198,10328,10329],{"class":1387},"    path",[198,10331,41],{"class":1383},[198,10333,10334],{"class":2202},"as_encoded_bytes",[198,10336,8010],{"class":1383},[198,10338,7810],{"class":2202},[198,10340,9519],{"class":1383},[198,10342,10343],{"class":200,"line":220},[198,10344,1613],{"class":1383},[198,10346,10347],{"class":200,"line":254},[198,10348,217],{"emptyLinePlaceholder":216},[198,10350,10351],{"class":200,"line":260},[198,10352,10296],{"class":1383},[198,10354,10355,10357,10359,10362,10364,10367,10370,10372,10374,10377],{"class":200,"line":266},[198,10356,8151],{"class":1956},[198,10358,9316],{"class":1956},[198,10360,10361],{"class":2202}," vec_to_osstr",[198,10363,2206],{"class":1383},[198,10365,10366],{"class":1387},"vec",[198,10368,10369],{"class":1383},": &[",[198,10371,7294],{"class":1960},[198,10373,7297],{"class":1383},[198,10375,10376],{"class":1960},"OsString",[198,10378,1964],{"class":1383},[198,10380,10381,10384,10387,10389,10391,10394,10396,10398,10400,10403],{"class":200,"line":272},[198,10382,10383],{"class":1956},"    unsafe",[198,10385,10386],{"class":1383}," { ",[198,10388,10376],{"class":1960},[198,10390,5252],{"class":1383},[198,10392,10393],{"class":2202},"from_encoded_bytes_unchecked",[198,10395,2206],{"class":1383},[198,10397,10366],{"class":1387},[198,10399,41],{"class":1383},[198,10401,10402],{"class":2202},"to_owned",[198,10404,10405],{"class":1383},"()) }\n",[198,10407,10408],{"class":200,"line":278},[198,10409,1613],{"class":1383},[11,10411,10412,10413,10415],{},"Le problème est que dans l'interface, des noms Windows ou Linux peuvent être affichés. Je ne souhaite pas que le\nprogramme plante, mais qu'au pire des cas, il affiche un nom de fichier incorrect. Je ne suis pas sûr que le code écrit\nsoit la meilleure solution. (D'après mes tests, il fonctionne). Une meilleure solution pour convertir un ",[165,10414,10314],{}," en\nString en fonction de l'encodage actuel (la variable d'environnement LANG sous Linux) aurait été pratique.",[11,10417,10418],{},"La gestion de la mémoire, bien que semblant simple au premier abord, devient rapidement complexe lorsqu'on veut faire du\nmultithreading. On se retrouve à mettre des structures dans des Box, des Mutex et des Arc, ce qui complique la syntaxe.",[11,10420,10421,10422,10425,10426,10429],{},"L'introduction de dynamisme, notamment pour la gestion des erreurs, nécessite l'utilisation du mot-clé ",[165,10423,10424],{},"dyn",", ce qui\npeut également devenir complexe. Je me retrouve avec presque toutes mes méthodes qui retournent un\n",[165,10427,10428],{},"Result\u003C???, Box\u003Cdyn Error>>",". Là aussi, je me demande si c'est une bonne pratique.",[11,10431,10432],{},"De plus, Rust semble souvent nous obliger à cloner des objets, alors que j'aurais parfois préféré utiliser simplement la\nréférence de l'objet. Mais comme potentiellement Rust n'arrive pas à déterminer si dans un cas de multithreading la\nvariable sera toujours valide, on doit la cloner. Parfois dans ces cas, je me dis qu'en C, je sais quand j'alloue, quand\nje désalloue, qui a le droit de lire et d'écrire. De mes souvenirs du C et du C++, j'avais plus de contrôle, le code me\nparaissait plus facile à écrire. Maintenant, le moindre oubli, petite erreur, peut être fatal, et Rust nous protège de\ncela. Bref, je pense simplement que je dois encore prendre le temps de me familiariser avec la philosophie de Rust.",[11,10434,10435,10436,2764,10439,2764,10442,7176,10445,10448],{},"Enfin, les erreurs de compilation ont été un gros défi. J'ai passé des heures à essayer de comprendre certaines erreurs,\nà ajuster les durées de vie ou à ajouter ",[165,10437,10438],{},"static",[165,10440,10441],{},"Send",[165,10443,10444],{},"Sync",[165,10446,10447],{},"Clone"," sans savoir quelle était la bonne façon de\nfaire.",[1714,10450,10452],{"id":10451},"les-tests-unitaires","Les tests unitaires",[11,10454,10455],{},"J'ai réalisé des tests unitaires pour une partie du développement. Cependant, l'écriture de ces tests a été difficile,\nsurtout en comparaison avec des bibliothèques comme Jest en JavaScript.",[11,10457,10458,10459,41],{},"La création de mocks pour les interfaces et les autres fichiers n'est pas native à Rust et n'est pas une tâche simple.\nJ'ai dû utiliser une bibliothèque dédiée, ",[15,10460,10463],{"href":10461,"rel":10462},"https:\u002F\u002Fdocs.rs\u002Fmockall\u002Flatest\u002Fmockall\u002F",[24],"mockall",[11,10465,10466,10467,41],{},"L'utilisation de mocks m'a contraint à créer des structures, alors qu'initialement j'avais des méthodes. J'ai commencé\navec des méthodes statiques, mais leur gestion avec les mocks ne permet pas de réaliser des tests unitaires en\nparallèle. Pour exécuter les tests unitaires, j'ai dû lancer un test à la fois avec la commande\n",[165,10468,10469],{},"RUST_TEST_THREADS=1 cargo test",[11,10471,10472],{},"Cependant, j'ai réussi à modifier les tests unitaires pour qu'ils puissent s'exécuter en parallèle sans supprimer les\nméthodes statiques.",[72,10474,1620],{"id":1619},[11,10476,10477],{},"Maintenant que j'ai écrit ce petit programme, je vais pouvoir créer mon propre pool de stockage. De votre côté,\nn'hésitez pas à me faire des retours sur le programme. Je suis ouvert à toutes les critiques. De plus, si vous utilisez\nBackupPC (en version 4 uniquement et avec un pool de stockage en version 4), vous pouvez tester mon programme et\nl'utiliser.",[1660,10479,10480],{},"html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sU0A5, html code.shiki .sU0A5{--shiki-default:#E5C07B}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}",{"title":59,"searchDepth":207,"depth":207,"links":10482},[10483,10484,10489,10498],{"id":6358,"depth":207,"text":6359},{"id":6420,"depth":207,"text":6421,"children":10485},[10486,10487,10488],{"id":6464,"depth":213,"text":6465},{"id":6534,"depth":213,"text":6535},{"id":6552,"depth":213,"text":6553},{"id":6625,"depth":207,"text":6626,"children":10490},[10491,10492,10493,10494,10495,10496,10497],{"id":6650,"depth":213,"text":6651},{"id":8806,"depth":213,"text":8807},{"id":9216,"depth":213,"text":9217},{"id":9253,"depth":213,"text":9254},{"id":10250,"depth":213,"text":10251},{"id":10269,"depth":213,"text":10270},{"id":10451,"depth":213,"text":10452},{"id":1619,"depth":207,"text":1620},"2024-05-07","Une partie de cet article a été publiée sur LinuxFR.\nAprès avoir reçu quelques retours, j'ai décidé de publier une version modifiée et améliorée de cet article sur mon blog.",{"type":8,"value":10502},[10503,10508,10510,10512],[11,10504,6336,10505,6342],{},[15,10506,6341],{"href":6339,"rel":10507},[24],[11,10509,6345],{},[11,10511,6348],{},[11,10513,10514],{},[3390,10515],{"src":6353,"alt":59,"className":10516},[6355],{"planet":216},"\u002Fpost\u002Fpr_backuppc_pool",{"title":6331,"description":10500},"pr_backuppc_pool","posts\u002FWoodstock\u002F2024-03-14_pr_backuppc_pool",[10523,10524,10525,1705,6327],"woodstock","backup","sauvegarde","JVBo68qbMHY70AJ8I83XDPaOAeqZhhqQNzs8jDhZhvY",{"id":10528,"title":10529,"author":6,"body":10530,"category":6178,"categorySlug":6179,"date":18006,"description":59,"excerpt":18007,"extension":194,"location":1697,"meta":18015,"navigation":216,"path":18016,"published":216,"seo":18017,"slug":18018,"stem":18019,"tags":18020,"timeToRead":478,"__hash__":18021},"posts\u002Fposts\u002FWoodstock\u002F2023-05-10_woodstock_rust.md","Woodstock Backup - Optimiser la consommation mémoire de Node.js avec Rust",{"type":8,"value":10531,"toc":17996},[10532,10536,10539,10542,10546,10549,12025,12028,12031,12099,12102,12105,12109,12116,12119,12122,12125,12223,12226,12286,12292,12296,12299,12309,14220,14223,14283,14286,14289,14292,14296,14299,14302,14305,14308,14315,14318,14321,14324,15891,15894,16239,16242,16280,16283,16290,16293,16301,16304,16312,17546,17552,17923,17926,17929,17968,17971,17974,17977,17980,17982,17985,17993],[72,10533,10535],{"id":10534},"introduction","Introduction",[11,10537,10538],{},"Node.js est un environnement d'exécution JavaScript côté serveur qui repose sur le moteur JavaScript V8 de Google. Il\nest utilisé pour développer des applications serveur en back-end d'une application web, des outils en ligne de commande\net des applications desktop. Cependant, la consommation de mémoire peut être un problème pour certaines applications\nNode.js, en particulier celles qui manipulent de grandes quantités de données ou des données volumineuses.",[11,10540,10541],{},"Dans cet article, nous allons voir comment optimiser la consommation de mémoire d'une application Node.js en le couplant\navec Rust. Rust est un langage de programmation système qui offre des performances similaires à celles du C++, tout en\noffrant une sécurité de mémoire à la compilation. Rust peut être utilisé pour écrire des bibliothèques C\u002FC++ natives\npour Node.js.",[72,10543,10545],{"id":10544},"problématique","Problématique",[11,10547,10548],{},"J'ai développé un logiciel de sauvegarde appelé Woodstock Backup, écrit en TypeScript. Lors du lancement des\nsauvegardes, il crée une représentation du système de fichier en mémoire et nécessite une grande quantité de mémoire.\nPour illustrer cela, nous avons reproduit notre cas avec le code suivant :",[190,10550,10552],{"className":388,"code":10551,"language":390,"meta":59,"style":59},"const filesize = require(\"filesize.js\");\nconst fs = require(\"fs\");\n\u002F\u002F Utilisation des méthodes de sérialisation et de désérialisation du moteur V8\nconst { serialize, deserialize } = require(\"v8\");\n\n\u002F\u002F Méthode pour générer une chaîne de caractère contenant des caractères aléatoires\nfunction randomString(size) {\n  const buffer = Buffer.alloc(size);\n  for (let i = 0; i \u003C size; i++) {\n    buffer[i] = Math.floor(Math.random() * 256);\n  }\n  return buffer;\n}\n\n\u002F\u002F Méthode pour générer un nombre aléatoire de la taille d'un nombre de 53 bits\nfunction randomNumber() {\n  return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);\n}\n\n\u002F\u002F Création d'un objet de test en javascript contenant que des données aléatoires\nconst testObject = () => ({\n  path: randomString(100),\n  stats: {\n    ownerId: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    groupId: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    size: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    compressedSize: {\n      low: randomNumber(),\n      high: randomNumber(),\n      unsigned: true,\n    },\n    lastRead: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    lastModified: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    created: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    mode: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    dev: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    rdev: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    ino: { low: randomNumber(), high: randomNumber(), unsigned: true },\n    nlink: { low: randomNumber(), high: randomNumber(), unsigned: true },\n  },\n  chunks: [randomString(32), randomString(32), randomString(32)],\n  sha256: randomString(32),\n});\n\n\u002F\u002F Lancement du GC pour s'assurer que la mémoire utilisé ne contient que les objets de test\nglobal.gc();\n\u002F\u002F On recupère la mémoire utilisé avant le test\nconst memoryBefore = process.memoryUsage().heapUsed;\n\u002F\u002F On recupère le temps avant le test (pour mesurer le temps de traitement)\nconst time = Date.now();\n\n\u002F\u002F Création des objets. J'ai du lancer plusieurs fois le script pour trouver une valeur qui ne causé pas de crash de \n\u002F\u002F Node.JS pour cause de manque de mémoire\nconst nbObjects = 1_300_000;\nconst testArray = new Array(nbObjects);\nfor (let i = 0; i \u003C nbObjects; i++) {\n  testArray[i] = testObject();\n}\n\n\u002F\u002F Combien de temps à pris la création des objets\nconsole.log(\"Creation time: \", Date.now() - time);\n\u002F\u002F Lancement du GC pour s'assurer que nous n'avons pas d'autres reliquats\nglobal.gc();\n\u002F\u002F Récupération de la mémoire après le test\nconst memoryAfter = process.memoryUsage().heapUsed;\n\nconsole.log(\"Memory consumption: \", filesize.default(memoryAfter - memoryBefore));\nconsole.log(\"Memory consumption by objects: \", filesize.default((memoryAfter - memoryBefore) \u002F nbObjects));\n\n\u002F\u002F Dans la suite on va écrire un fichier contenant le contenu de la mémoire. Cela a été fait initiallement pour \n\u002F\u002F s'assurer que le GC ne supprime pas mes objets car non utilisés.\nconst time2 = Date.now();\n\n\u002F\u002F Remove test file if exist\ntry {\n  fs.unlinkSync(\"test\");\n} catch (e) {}\n\nconst stream = fs.createWriteStream(\"test\");\n\n\u002F\u002F C'est moche, mais c'est pour tester\nstream.on(\"close\", () => {\n  console.log(\"Write to file time: \", Date.now() - time2);\n  \u002F\u002F Size of file test on disk\n  const stats = fs.statSync(\"test\");\n  console.log(\"Size of file on disk: \", filesize.default(stats.size));\n  console.log(\n    \"Size of object in the file\",\n    filesize.default(stats.size \u002F nbObjects)\n  );\n});\n\nfor (const obj of testArray) {\n  stream.write(serialize(obj));\n}\nstream.end();\n",[165,10553,10554,10574,10592,10597,10625,10629,10634,10649,10671,10707,10747,10751,10759,10763,10767,10772,10781,10809,10813,10817,10822,10840,10857,10865,10903,10934,10965,10972,10984,10995,11006,11010,11041,11072,11103,11134,11165,11196,11227,11258,11262,11296,11311,11316,11320,11325,11337,11342,11366,11371,11390,11394,11400,11406,11421,11443,11475,11493,11498,11503,11509,11542,11548,11559,11565,11587,11592,11627,11666,11671,11677,11683,11701,11706,11712,11720,11738,11753,11758,11781,11786,11792,11815,11846,11852,11875,11908,11919,11927,11952,11958,11963,11968,11986,12008,12013],{"__ignoreMap":59},[198,10555,10556,10559,10562,10564,10567,10569,10572],{"class":200,"line":201},[198,10557,10558],{"class":1956},"const",[198,10560,10561],{"class":1960}," filesize",[198,10563,2221],{"class":2220},[198,10565,10566],{"class":2202}," require",[198,10568,2206],{"class":1383},[198,10570,10571],{"class":1424},"\"filesize.js\"",[198,10573,2280],{"class":1383},[198,10575,10576,10578,10581,10583,10585,10587,10590],{"class":200,"line":207},[198,10577,10558],{"class":1956},[198,10579,10580],{"class":1960}," fs",[198,10582,2221],{"class":2220},[198,10584,10566],{"class":2202},[198,10586,2206],{"class":1383},[198,10588,10589],{"class":1424},"\"fs\"",[198,10591,2280],{"class":1383},[198,10593,10594],{"class":200,"line":213},[198,10595,10596],{"class":1930},"\u002F\u002F Utilisation des méthodes de sérialisation et de désérialisation du moteur V8\n",[198,10598,10599,10601,10603,10606,10608,10611,10614,10616,10618,10620,10623],{"class":200,"line":220},[198,10600,10558],{"class":1956},[198,10602,10386],{"class":1383},[198,10604,10605],{"class":1960},"serialize",[198,10607,2764],{"class":1383},[198,10609,10610],{"class":1960},"deserialize",[198,10612,10613],{"class":1383}," } ",[198,10615,1421],{"class":2220},[198,10617,10566],{"class":2202},[198,10619,2206],{"class":1383},[198,10621,10622],{"class":1424},"\"v8\"",[198,10624,2280],{"class":1383},[198,10626,10627],{"class":200,"line":254},[198,10628,217],{"emptyLinePlaceholder":216},[198,10630,10631],{"class":200,"line":260},[198,10632,10633],{"class":1930},"\u002F\u002F Méthode pour générer une chaîne de caractère contenant des caractères aléatoires\n",[198,10635,10636,10639,10642,10644,10647],{"class":200,"line":266},[198,10637,10638],{"class":1956},"function",[198,10640,10641],{"class":2202}," randomString",[198,10643,2206],{"class":1383},[198,10645,10646],{"class":5262},"size",[198,10648,2212],{"class":1383},[198,10650,10651,10653,10655,10657,10660,10662,10665,10667,10669],{"class":200,"line":272},[198,10652,5812],{"class":1956},[198,10654,6820],{"class":1960},[198,10656,2221],{"class":2220},[198,10658,10659],{"class":1960}," Buffer",[198,10661,41],{"class":1383},[198,10663,10664],{"class":2202},"alloc",[198,10666,2206],{"class":1383},[198,10668,10646],{"class":1387},[198,10670,2280],{"class":1383},[198,10672,10673,10676,10678,10681,10684,10686,10688,10690,10693,10695,10698,10700,10702,10705],{"class":200,"line":278},[198,10674,10675],{"class":1956},"  for",[198,10677,2288],{"class":1383},[198,10679,10680],{"class":1956},"let",[198,10682,10683],{"class":1387}," i",[198,10685,2221],{"class":2220},[198,10687,6021],{"class":1417},[198,10689,8934],{"class":1383},[198,10691,10692],{"class":1387},"i",[198,10694,8686],{"class":2220},[198,10696,10697],{"class":1387}," size",[198,10699,8934],{"class":1383},[198,10701,10692],{"class":1387},[198,10703,10704],{"class":2220},"++",[198,10706,2212],{"class":1383},[198,10708,10709,10712,10714,10716,10718,10720,10723,10725,10728,10730,10733,10735,10738,10740,10742,10745],{"class":200,"line":283},[198,10710,10711],{"class":1387},"    buffer",[198,10713,6940],{"class":1383},[198,10715,10692],{"class":1387},[198,10717,6945],{"class":1383},[198,10719,1421],{"class":2220},[198,10721,10722],{"class":1960}," Math",[198,10724,41],{"class":1383},[198,10726,10727],{"class":2202},"floor",[198,10729,2206],{"class":1383},[198,10731,10732],{"class":1960},"Math",[198,10734,41],{"class":1383},[198,10736,10737],{"class":2202},"random",[198,10739,2484],{"class":1383},[198,10741,5494],{"class":2220},[198,10743,10744],{"class":1417}," 256",[198,10746,2280],{"class":1383},[198,10748,10749],{"class":200,"line":288},[198,10750,5394],{"class":1383},[198,10752,10753,10755,10757],{"class":200,"line":450},[198,10754,5399],{"class":1956},[198,10756,6820],{"class":1387},[198,10758,2008],{"class":1383},[198,10760,10761],{"class":200,"line":456},[198,10762,1613],{"class":1383},[198,10764,10765],{"class":200,"line":462},[198,10766,217],{"emptyLinePlaceholder":216},[198,10768,10769],{"class":200,"line":468},[198,10770,10771],{"class":1930},"\u002F\u002F Méthode pour générer un nombre aléatoire de la taille d'un nombre de 53 bits\n",[198,10773,10774,10776,10779],{"class":200,"line":473},[198,10775,10638],{"class":1956},[198,10777,10778],{"class":2202}," randomNumber",[198,10780,6731],{"class":1383},[198,10782,10783,10785,10787,10789,10791,10793,10795,10797,10799,10801,10803,10806],{"class":200,"line":478},[198,10784,5399],{"class":1956},[198,10786,10722],{"class":1960},[198,10788,41],{"class":1383},[198,10790,10727],{"class":2202},[198,10792,2206],{"class":1383},[198,10794,10732],{"class":1960},[198,10796,41],{"class":1383},[198,10798,10737],{"class":2202},[198,10800,2484],{"class":1383},[198,10802,5494],{"class":2220},[198,10804,10805],{"class":1960}," Number",[198,10807,10808],{"class":1383},".MAX_SAFE_INTEGER);\n",[198,10810,10811],{"class":200,"line":484},[198,10812,1613],{"class":1383},[198,10814,10815],{"class":200,"line":490},[198,10816,217],{"emptyLinePlaceholder":216},[198,10818,10819],{"class":200,"line":1068},[198,10820,10821],{"class":1930},"\u002F\u002F Création d'un objet de test en javascript contenant que des données aléatoires\n",[198,10823,10824,10826,10829,10831,10834,10837],{"class":200,"line":1074},[198,10825,10558],{"class":1956},[198,10827,10828],{"class":2202}," testObject",[198,10830,2221],{"class":2220},[198,10832,10833],{"class":1383}," () ",[198,10835,10836],{"class":1956},"=>",[198,10838,10839],{"class":1383}," ({\n",[198,10841,10842,10845,10847,10850,10852,10855],{"class":200,"line":1080},[198,10843,10844],{"class":1387},"  path",[198,10846,2998],{"class":1383},[198,10848,10849],{"class":2202},"randomString",[198,10851,2206],{"class":1383},[198,10853,10854],{"class":1417},"100",[198,10856,9915],{"class":1383},[198,10858,10859,10862],{"class":200,"line":1086},[198,10860,10861],{"class":1387},"  stats",[198,10863,10864],{"class":1383},": {\n",[198,10866,10867,10870,10873,10876,10878,10881,10884,10887,10889,10891,10893,10896,10898,10900],{"class":200,"line":1092},[198,10868,10869],{"class":1387},"    ownerId",[198,10871,10872],{"class":1383},": { ",[198,10874,10875],{"class":1387},"low",[198,10877,2998],{"class":1383},[198,10879,10880],{"class":2202},"randomNumber",[198,10882,10883],{"class":1383},"(), ",[198,10885,10886],{"class":1387},"high",[198,10888,2998],{"class":1383},[198,10890,10880],{"class":2202},[198,10892,10883],{"class":1383},[198,10894,10895],{"class":1387},"unsigned",[198,10897,2998],{"class":1383},[198,10899,7626],{"class":1417},[198,10901,10902],{"class":1383}," },\n",[198,10904,10905,10908,10910,10912,10914,10916,10918,10920,10922,10924,10926,10928,10930,10932],{"class":200,"line":1098},[198,10906,10907],{"class":1387},"    groupId",[198,10909,10872],{"class":1383},[198,10911,10875],{"class":1387},[198,10913,2998],{"class":1383},[198,10915,10880],{"class":2202},[198,10917,10883],{"class":1383},[198,10919,10886],{"class":1387},[198,10921,2998],{"class":1383},[198,10923,10880],{"class":2202},[198,10925,10883],{"class":1383},[198,10927,10895],{"class":1387},[198,10929,2998],{"class":1383},[198,10931,7626],{"class":1417},[198,10933,10902],{"class":1383},[198,10935,10936,10939,10941,10943,10945,10947,10949,10951,10953,10955,10957,10959,10961,10963],{"class":200,"line":1104},[198,10937,10938],{"class":1387},"    size",[198,10940,10872],{"class":1383},[198,10942,10875],{"class":1387},[198,10944,2998],{"class":1383},[198,10946,10880],{"class":2202},[198,10948,10883],{"class":1383},[198,10950,10886],{"class":1387},[198,10952,2998],{"class":1383},[198,10954,10880],{"class":2202},[198,10956,10883],{"class":1383},[198,10958,10895],{"class":1387},[198,10960,2998],{"class":1383},[198,10962,7626],{"class":1417},[198,10964,10902],{"class":1383},[198,10966,10967,10970],{"class":200,"line":1110},[198,10968,10969],{"class":1387},"    compressedSize",[198,10971,10864],{"class":1383},[198,10973,10974,10977,10979,10981],{"class":200,"line":1116},[198,10975,10976],{"class":1387},"      low",[198,10978,2998],{"class":1383},[198,10980,10880],{"class":2202},[198,10982,10983],{"class":1383},"(),\n",[198,10985,10986,10989,10991,10993],{"class":200,"line":1122},[198,10987,10988],{"class":1387},"      high",[198,10990,2998],{"class":1383},[198,10992,10880],{"class":2202},[198,10994,10983],{"class":1383},[198,10996,10997,11000,11002,11004],{"class":200,"line":1128},[198,10998,10999],{"class":1387},"      unsigned",[198,11001,2998],{"class":1383},[198,11003,7626],{"class":1417},[198,11005,1757],{"class":1383},[198,11007,11008],{"class":200,"line":1134},[198,11009,493],{"class":1383},[198,11011,11012,11015,11017,11019,11021,11023,11025,11027,11029,11031,11033,11035,11037,11039],{"class":200,"line":1140},[198,11013,11014],{"class":1387},"    lastRead",[198,11016,10872],{"class":1383},[198,11018,10875],{"class":1387},[198,11020,2998],{"class":1383},[198,11022,10880],{"class":2202},[198,11024,10883],{"class":1383},[198,11026,10886],{"class":1387},[198,11028,2998],{"class":1383},[198,11030,10880],{"class":2202},[198,11032,10883],{"class":1383},[198,11034,10895],{"class":1387},[198,11036,2998],{"class":1383},[198,11038,7626],{"class":1417},[198,11040,10902],{"class":1383},[198,11042,11043,11046,11048,11050,11052,11054,11056,11058,11060,11062,11064,11066,11068,11070],{"class":200,"line":1146},[198,11044,11045],{"class":1387},"    lastModified",[198,11047,10872],{"class":1383},[198,11049,10875],{"class":1387},[198,11051,2998],{"class":1383},[198,11053,10880],{"class":2202},[198,11055,10883],{"class":1383},[198,11057,10886],{"class":1387},[198,11059,2998],{"class":1383},[198,11061,10880],{"class":2202},[198,11063,10883],{"class":1383},[198,11065,10895],{"class":1387},[198,11067,2998],{"class":1383},[198,11069,7626],{"class":1417},[198,11071,10902],{"class":1383},[198,11073,11074,11077,11079,11081,11083,11085,11087,11089,11091,11093,11095,11097,11099,11101],{"class":200,"line":1151},[198,11075,11076],{"class":1387},"    created",[198,11078,10872],{"class":1383},[198,11080,10875],{"class":1387},[198,11082,2998],{"class":1383},[198,11084,10880],{"class":2202},[198,11086,10883],{"class":1383},[198,11088,10886],{"class":1387},[198,11090,2998],{"class":1383},[198,11092,10880],{"class":2202},[198,11094,10883],{"class":1383},[198,11096,10895],{"class":1387},[198,11098,2998],{"class":1383},[198,11100,7626],{"class":1417},[198,11102,10902],{"class":1383},[198,11104,11105,11108,11110,11112,11114,11116,11118,11120,11122,11124,11126,11128,11130,11132],{"class":200,"line":1157},[198,11106,11107],{"class":1387},"    mode",[198,11109,10872],{"class":1383},[198,11111,10875],{"class":1387},[198,11113,2998],{"class":1383},[198,11115,10880],{"class":2202},[198,11117,10883],{"class":1383},[198,11119,10886],{"class":1387},[198,11121,2998],{"class":1383},[198,11123,10880],{"class":2202},[198,11125,10883],{"class":1383},[198,11127,10895],{"class":1387},[198,11129,2998],{"class":1383},[198,11131,7626],{"class":1417},[198,11133,10902],{"class":1383},[198,11135,11136,11139,11141,11143,11145,11147,11149,11151,11153,11155,11157,11159,11161,11163],{"class":200,"line":1163},[198,11137,11138],{"class":1387},"    dev",[198,11140,10872],{"class":1383},[198,11142,10875],{"class":1387},[198,11144,2998],{"class":1383},[198,11146,10880],{"class":2202},[198,11148,10883],{"class":1383},[198,11150,10886],{"class":1387},[198,11152,2998],{"class":1383},[198,11154,10880],{"class":2202},[198,11156,10883],{"class":1383},[198,11158,10895],{"class":1387},[198,11160,2998],{"class":1383},[198,11162,7626],{"class":1417},[198,11164,10902],{"class":1383},[198,11166,11167,11170,11172,11174,11176,11178,11180,11182,11184,11186,11188,11190,11192,11194],{"class":200,"line":1169},[198,11168,11169],{"class":1387},"    rdev",[198,11171,10872],{"class":1383},[198,11173,10875],{"class":1387},[198,11175,2998],{"class":1383},[198,11177,10880],{"class":2202},[198,11179,10883],{"class":1383},[198,11181,10886],{"class":1387},[198,11183,2998],{"class":1383},[198,11185,10880],{"class":2202},[198,11187,10883],{"class":1383},[198,11189,10895],{"class":1387},[198,11191,2998],{"class":1383},[198,11193,7626],{"class":1417},[198,11195,10902],{"class":1383},[198,11197,11198,11201,11203,11205,11207,11209,11211,11213,11215,11217,11219,11221,11223,11225],{"class":200,"line":1175},[198,11199,11200],{"class":1387},"    ino",[198,11202,10872],{"class":1383},[198,11204,10875],{"class":1387},[198,11206,2998],{"class":1383},[198,11208,10880],{"class":2202},[198,11210,10883],{"class":1383},[198,11212,10886],{"class":1387},[198,11214,2998],{"class":1383},[198,11216,10880],{"class":2202},[198,11218,10883],{"class":1383},[198,11220,10895],{"class":1387},[198,11222,2998],{"class":1383},[198,11224,7626],{"class":1417},[198,11226,10902],{"class":1383},[198,11228,11229,11232,11234,11236,11238,11240,11242,11244,11246,11248,11250,11252,11254,11256],{"class":200,"line":1181},[198,11230,11231],{"class":1387},"    nlink",[198,11233,10872],{"class":1383},[198,11235,10875],{"class":1387},[198,11237,2998],{"class":1383},[198,11239,10880],{"class":2202},[198,11241,10883],{"class":1383},[198,11243,10886],{"class":1387},[198,11245,2998],{"class":1383},[198,11247,10880],{"class":2202},[198,11249,10883],{"class":1383},[198,11251,10895],{"class":1387},[198,11253,2998],{"class":1383},[198,11255,7626],{"class":1417},[198,11257,10902],{"class":1383},[198,11259,11260],{"class":200,"line":1187},[198,11261,764],{"class":1383},[198,11263,11264,11267,11269,11271,11273,11276,11279,11281,11283,11285,11287,11289,11291,11293],{"class":200,"line":1193},[198,11265,11266],{"class":1387},"  chunks",[198,11268,8929],{"class":1383},[198,11270,10849],{"class":2202},[198,11272,2206],{"class":1383},[198,11274,11275],{"class":1417},"32",[198,11277,11278],{"class":1383},"), ",[198,11280,10849],{"class":2202},[198,11282,2206],{"class":1383},[198,11284,11275],{"class":1417},[198,11286,11278],{"class":1383},[198,11288,10849],{"class":2202},[198,11290,2206],{"class":1383},[198,11292,11275],{"class":1417},[198,11294,11295],{"class":1383},")],\n",[198,11297,11298,11301,11303,11305,11307,11309],{"class":200,"line":1199},[198,11299,11300],{"class":1387},"  sha256",[198,11302,2998],{"class":1383},[198,11304,10849],{"class":2202},[198,11306,2206],{"class":1383},[198,11308,11275],{"class":1417},[198,11310,9915],{"class":1383},[198,11312,11313],{"class":200,"line":1205},[198,11314,11315],{"class":1383},"});\n",[198,11317,11318],{"class":200,"line":1211},[198,11319,217],{"emptyLinePlaceholder":216},[198,11321,11322],{"class":200,"line":1217},[198,11323,11324],{"class":1930},"\u002F\u002F Lancement du GC pour s'assurer que la mémoire utilisé ne contient que les objets de test\n",[198,11326,11327,11330,11332,11335],{"class":200,"line":1223},[198,11328,11329],{"class":1960},"global",[198,11331,41],{"class":1383},[198,11333,11334],{"class":2202},"gc",[198,11336,2244],{"class":1383},[198,11338,11339],{"class":200,"line":1228},[198,11340,11341],{"class":1930},"\u002F\u002F On recupère la mémoire utilisé avant le test\n",[198,11343,11344,11346,11349,11351,11354,11356,11359,11361,11364],{"class":200,"line":1233},[198,11345,10558],{"class":1956},[198,11347,11348],{"class":1960}," memoryBefore",[198,11350,2221],{"class":2220},[198,11352,11353],{"class":1960}," process",[198,11355,41],{"class":1383},[198,11357,11358],{"class":2202},"memoryUsage",[198,11360,8010],{"class":1383},[198,11362,11363],{"class":1387},"heapUsed",[198,11365,2008],{"class":1383},[198,11367,11368],{"class":200,"line":1238},[198,11369,11370],{"class":1930},"\u002F\u002F On recupère le temps avant le test (pour mesurer le temps de traitement)\n",[198,11372,11373,11375,11378,11380,11383,11385,11388],{"class":200,"line":1244},[198,11374,10558],{"class":1956},[198,11376,11377],{"class":1960}," time",[198,11379,2221],{"class":2220},[198,11381,11382],{"class":1960}," Date",[198,11384,41],{"class":1383},[198,11386,11387],{"class":2202},"now",[198,11389,2244],{"class":1383},[198,11391,11392],{"class":200,"line":1250},[198,11393,217],{"emptyLinePlaceholder":216},[198,11395,11397],{"class":200,"line":11396},52,[198,11398,11399],{"class":1930},"\u002F\u002F Création des objets. J'ai du lancer plusieurs fois le script pour trouver une valeur qui ne causé pas de crash de \n",[198,11401,11403],{"class":200,"line":11402},53,[198,11404,11405],{"class":1930},"\u002F\u002F Node.JS pour cause de manque de mémoire\n",[198,11407,11409,11411,11414,11416,11419],{"class":200,"line":11408},54,[198,11410,10558],{"class":1956},[198,11412,11413],{"class":1960}," nbObjects",[198,11415,2221],{"class":2220},[198,11417,11418],{"class":1417}," 1_300_000",[198,11420,2008],{"class":1383},[198,11422,11424,11426,11429,11431,11433,11436,11438,11441],{"class":200,"line":11423},55,[198,11425,10558],{"class":1956},[198,11427,11428],{"class":1960}," testArray",[198,11430,2221],{"class":2220},[198,11432,2341],{"class":1956},[198,11434,11435],{"class":2202}," Array",[198,11437,2206],{"class":1383},[198,11439,11440],{"class":1387},"nbObjects",[198,11442,2280],{"class":1383},[198,11444,11446,11449,11451,11453,11455,11457,11459,11461,11463,11465,11467,11469,11471,11473],{"class":200,"line":11445},56,[198,11447,11448],{"class":1956},"for",[198,11450,2288],{"class":1383},[198,11452,10680],{"class":1956},[198,11454,10683],{"class":1387},[198,11456,2221],{"class":2220},[198,11458,6021],{"class":1417},[198,11460,8934],{"class":1383},[198,11462,10692],{"class":1387},[198,11464,8686],{"class":2220},[198,11466,11413],{"class":1387},[198,11468,8934],{"class":1383},[198,11470,10692],{"class":1387},[198,11472,10704],{"class":2220},[198,11474,2212],{"class":1383},[198,11476,11478,11481,11483,11485,11487,11489,11491],{"class":200,"line":11477},57,[198,11479,11480],{"class":1387},"  testArray",[198,11482,6940],{"class":1383},[198,11484,10692],{"class":1387},[198,11486,6945],{"class":1383},[198,11488,1421],{"class":2220},[198,11490,10828],{"class":2202},[198,11492,2244],{"class":1383},[198,11494,11496],{"class":200,"line":11495},58,[198,11497,1613],{"class":1383},[198,11499,11501],{"class":200,"line":11500},59,[198,11502,217],{"emptyLinePlaceholder":216},[198,11504,11506],{"class":200,"line":11505},60,[198,11507,11508],{"class":1930},"\u002F\u002F Combien de temps à pris la création des objets\n",[198,11510,11512,11515,11517,11520,11522,11525,11527,11530,11532,11534,11536,11538,11540],{"class":200,"line":11511},61,[198,11513,11514],{"class":1960},"console",[198,11516,41],{"class":1383},[198,11518,11519],{"class":2202},"log",[198,11521,2206],{"class":1383},[198,11523,11524],{"class":1424},"\"Creation time: \"",[198,11526,2764],{"class":1383},[198,11528,11529],{"class":1960},"Date",[198,11531,41],{"class":1383},[198,11533,11387],{"class":2202},[198,11535,2484],{"class":1383},[198,11537,6053],{"class":2220},[198,11539,11377],{"class":1387},[198,11541,2280],{"class":1383},[198,11543,11545],{"class":200,"line":11544},62,[198,11546,11547],{"class":1930},"\u002F\u002F Lancement du GC pour s'assurer que nous n'avons pas d'autres reliquats\n",[198,11549,11551,11553,11555,11557],{"class":200,"line":11550},63,[198,11552,11329],{"class":1960},[198,11554,41],{"class":1383},[198,11556,11334],{"class":2202},[198,11558,2244],{"class":1383},[198,11560,11562],{"class":200,"line":11561},64,[198,11563,11564],{"class":1930},"\u002F\u002F Récupération de la mémoire après le test\n",[198,11566,11568,11570,11573,11575,11577,11579,11581,11583,11585],{"class":200,"line":11567},65,[198,11569,10558],{"class":1956},[198,11571,11572],{"class":1960}," memoryAfter",[198,11574,2221],{"class":2220},[198,11576,11353],{"class":1960},[198,11578,41],{"class":1383},[198,11580,11358],{"class":2202},[198,11582,8010],{"class":1383},[198,11584,11363],{"class":1387},[198,11586,2008],{"class":1383},[198,11588,11590],{"class":200,"line":11589},66,[198,11591,217],{"emptyLinePlaceholder":216},[198,11593,11595,11597,11599,11601,11603,11606,11608,11611,11613,11616,11618,11621,11623,11625],{"class":200,"line":11594},67,[198,11596,11514],{"class":1960},[198,11598,41],{"class":1383},[198,11600,11519],{"class":2202},[198,11602,2206],{"class":1383},[198,11604,11605],{"class":1424},"\"Memory consumption: \"",[198,11607,2764],{"class":1383},[198,11609,11610],{"class":1960},"filesize",[198,11612,41],{"class":1383},[198,11614,11615],{"class":2202},"default",[198,11617,2206],{"class":1383},[198,11619,11620],{"class":1387},"memoryAfter",[198,11622,5111],{"class":2220},[198,11624,11348],{"class":1387},[198,11626,2528],{"class":1383},[198,11628,11630,11632,11634,11636,11638,11641,11643,11645,11647,11649,11652,11654,11656,11658,11660,11662,11664],{"class":200,"line":11629},68,[198,11631,11514],{"class":1960},[198,11633,41],{"class":1383},[198,11635,11519],{"class":2202},[198,11637,2206],{"class":1383},[198,11639,11640],{"class":1424},"\"Memory consumption by objects: \"",[198,11642,2764],{"class":1383},[198,11644,11610],{"class":1960},[198,11646,41],{"class":1383},[198,11648,11615],{"class":2202},[198,11650,11651],{"class":1383},"((",[198,11653,11620],{"class":1387},[198,11655,5111],{"class":2220},[198,11657,11348],{"class":1387},[198,11659,8484],{"class":1383},[198,11661,5347],{"class":2220},[198,11663,11413],{"class":1387},[198,11665,2528],{"class":1383},[198,11667,11669],{"class":200,"line":11668},69,[198,11670,217],{"emptyLinePlaceholder":216},[198,11672,11674],{"class":200,"line":11673},70,[198,11675,11676],{"class":1930},"\u002F\u002F Dans la suite on va écrire un fichier contenant le contenu de la mémoire. Cela a été fait initiallement pour \n",[198,11678,11680],{"class":200,"line":11679},71,[198,11681,11682],{"class":1930},"\u002F\u002F s'assurer que le GC ne supprime pas mes objets car non utilisés.\n",[198,11684,11686,11688,11691,11693,11695,11697,11699],{"class":200,"line":11685},72,[198,11687,10558],{"class":1956},[198,11689,11690],{"class":1960}," time2",[198,11692,2221],{"class":2220},[198,11694,11382],{"class":1960},[198,11696,41],{"class":1383},[198,11698,11387],{"class":2202},[198,11700,2244],{"class":1383},[198,11702,11704],{"class":200,"line":11703},73,[198,11705,217],{"emptyLinePlaceholder":216},[198,11707,11709],{"class":200,"line":11708},74,[198,11710,11711],{"class":1930},"\u002F\u002F Remove test file if exist\n",[198,11713,11715,11718],{"class":200,"line":11714},75,[198,11716,11717],{"class":1956},"try",[198,11719,1964],{"class":1383},[198,11721,11723,11726,11728,11731,11733,11736],{"class":200,"line":11722},76,[198,11724,11725],{"class":1960},"  fs",[198,11727,41],{"class":1383},[198,11729,11730],{"class":2202},"unlinkSync",[198,11732,2206],{"class":1383},[198,11734,11735],{"class":1424},"\"test\"",[198,11737,2280],{"class":1383},[198,11739,11741,11743,11746,11748,11750],{"class":200,"line":11740},77,[198,11742,7039],{"class":1383},[198,11744,11745],{"class":1956},"catch",[198,11747,2288],{"class":1383},[198,11749,8378],{"class":1387},[198,11751,11752],{"class":1383},") {}\n",[198,11754,11756],{"class":200,"line":11755},78,[198,11757,217],{"emptyLinePlaceholder":216},[198,11759,11761,11763,11766,11768,11770,11772,11775,11777,11779],{"class":200,"line":11760},79,[198,11762,10558],{"class":1956},[198,11764,11765],{"class":1960}," stream",[198,11767,2221],{"class":2220},[198,11769,10580],{"class":1960},[198,11771,41],{"class":1383},[198,11773,11774],{"class":2202},"createWriteStream",[198,11776,2206],{"class":1383},[198,11778,11735],{"class":1424},[198,11780,2280],{"class":1383},[198,11782,11784],{"class":200,"line":11783},80,[198,11785,217],{"emptyLinePlaceholder":216},[198,11787,11789],{"class":200,"line":11788},81,[198,11790,11791],{"class":1930},"\u002F\u002F C'est moche, mais c'est pour tester\n",[198,11793,11795,11798,11800,11803,11805,11808,11811,11813],{"class":200,"line":11794},82,[198,11796,11797],{"class":1960},"stream",[198,11799,41],{"class":1383},[198,11801,11802],{"class":2202},"on",[198,11804,2206],{"class":1383},[198,11806,11807],{"class":1424},"\"close\"",[198,11809,11810],{"class":1383},", () ",[198,11812,10836],{"class":1956},[198,11814,1964],{"class":1383},[198,11816,11818,11821,11823,11825,11827,11830,11832,11834,11836,11838,11840,11842,11844],{"class":200,"line":11817},83,[198,11819,11820],{"class":1960},"  console",[198,11822,41],{"class":1383},[198,11824,11519],{"class":2202},[198,11826,2206],{"class":1383},[198,11828,11829],{"class":1424},"\"Write to file time: \"",[198,11831,2764],{"class":1383},[198,11833,11529],{"class":1960},[198,11835,41],{"class":1383},[198,11837,11387],{"class":2202},[198,11839,2484],{"class":1383},[198,11841,6053],{"class":2220},[198,11843,11690],{"class":1387},[198,11845,2280],{"class":1383},[198,11847,11849],{"class":200,"line":11848},84,[198,11850,11851],{"class":1930},"  \u002F\u002F Size of file test on disk\n",[198,11853,11855,11857,11860,11862,11864,11866,11869,11871,11873],{"class":200,"line":11854},85,[198,11856,5812],{"class":1956},[198,11858,11859],{"class":1960}," stats",[198,11861,2221],{"class":2220},[198,11863,10580],{"class":1960},[198,11865,41],{"class":1383},[198,11867,11868],{"class":2202},"statSync",[198,11870,2206],{"class":1383},[198,11872,11735],{"class":1424},[198,11874,2280],{"class":1383},[198,11876,11878,11880,11882,11884,11886,11889,11891,11893,11895,11897,11899,11902,11904,11906],{"class":200,"line":11877},86,[198,11879,11820],{"class":1960},[198,11881,41],{"class":1383},[198,11883,11519],{"class":2202},[198,11885,2206],{"class":1383},[198,11887,11888],{"class":1424},"\"Size of file on disk: \"",[198,11890,2764],{"class":1383},[198,11892,11610],{"class":1960},[198,11894,41],{"class":1383},[198,11896,11615],{"class":2202},[198,11898,2206],{"class":1383},[198,11900,11901],{"class":1960},"stats",[198,11903,41],{"class":1383},[198,11905,10646],{"class":1387},[198,11907,2528],{"class":1383},[198,11909,11911,11913,11915,11917],{"class":200,"line":11910},87,[198,11912,11820],{"class":1960},[198,11914,41],{"class":1383},[198,11916,11519],{"class":2202},[198,11918,2775],{"class":1383},[198,11920,11922,11925],{"class":200,"line":11921},88,[198,11923,11924],{"class":1424},"    \"Size of object in the file\"",[198,11926,1757],{"class":1383},[198,11928,11930,11933,11935,11937,11939,11941,11943,11945,11948,11950],{"class":200,"line":11929},89,[198,11931,11932],{"class":1960},"    filesize",[198,11934,41],{"class":1383},[198,11936,11615],{"class":2202},[198,11938,2206],{"class":1383},[198,11940,11901],{"class":1960},[198,11942,41],{"class":1383},[198,11944,10646],{"class":1387},[198,11946,11947],{"class":2220}," \u002F",[198,11949,11413],{"class":1387},[198,11951,2845],{"class":1383},[198,11953,11955],{"class":200,"line":11954},90,[198,11956,11957],{"class":1383},"  );\n",[198,11959,11961],{"class":200,"line":11960},91,[198,11962,11315],{"class":1383},[198,11964,11966],{"class":200,"line":11965},92,[198,11967,217],{"emptyLinePlaceholder":216},[198,11969,11971,11973,11975,11977,11980,11982,11984],{"class":200,"line":11970},93,[198,11972,11448],{"class":1956},[198,11974,2288],{"class":1383},[198,11976,10558],{"class":1956},[198,11978,11979],{"class":1960}," obj",[198,11981,5122],{"class":1956},[198,11983,11428],{"class":1387},[198,11985,2212],{"class":1383},[198,11987,11989,11992,11994,11997,11999,12001,12003,12006],{"class":200,"line":11988},94,[198,11990,11991],{"class":1960},"  stream",[198,11993,41],{"class":1383},[198,11995,11996],{"class":2202},"write",[198,11998,2206],{"class":1383},[198,12000,10605],{"class":2202},[198,12002,2206],{"class":1383},[198,12004,12005],{"class":1387},"obj",[198,12007,2528],{"class":1383},[198,12009,12011],{"class":200,"line":12010},95,[198,12012,1613],{"class":1383},[198,12014,12016,12018,12020,12023],{"class":200,"line":12015},96,[198,12017,11797],{"class":1960},[198,12019,41],{"class":1383},[198,12021,12022],{"class":2202},"end",[198,12024,2244],{"class":1383},[11,12026,12027],{},"En estimant rapidement la mémoire que la taille de l'objet aurait dû prendre, je l'estime à environ 432 octets (12\nnombres de 2*64 bits + 1 octet de boolean + 128 caractères pour les chunks et 100 caractères pour le nom).",[11,12029,12030],{},"Le code n'est pas le plus propre, mais le but est ici d'illustrer rapidement la problématique. Voici le résultat de ce\ntest :",[6106,12032,12033,12041],{},[6109,12034,12035],{},[6112,12036,12037,12039],{},[6115,12038],{},[6115,12040],{},[6128,12042,12043,12051,12059,12067,12075,12083,12091],{},[6112,12044,12045,12048],{},[6133,12046,12047],{},"Nombre d'objets créés",[6133,12049,12050],{},"1 300 000",[6112,12052,12053,12056],{},[6133,12054,12055],{},"Temps de création",[6133,12057,12058],{},"15 secondes",[6112,12060,12061,12064],{},[6133,12062,12063],{},"Consommation mémoire",[6133,12065,12066],{},"2,8 Go",[6112,12068,12069,12072],{},[6133,12070,12071],{},"Consommation moyenne par objet",[6133,12073,12074],{},"2,2 Ko",[6112,12076,12077,12080],{},[6133,12078,12079],{},"Temps d'écriture dans le fichier",[6133,12081,12082],{},"91 secondes",[6112,12084,12085,12088],{},[6133,12086,12087],{},"Taille du fichier sur le disque",[6133,12089,12090],{},"1,1 Go",[6112,12092,12093,12096],{},[6133,12094,12095],{},"Taille moyenne d'un objet dans le fichier",[6133,12097,12098],{},"903 octets",[11,12100,12101],{},"Avec ce premier exemple, on peut déjà constater que la consommation mémoire est très importante. En effet, on est à\n2,2Ko par objet au lieu des 432 estimés (soit 5 fois plus). La taille des objets dans le fichier est déjà un peu plus\nraisonnable.",[11,12103,12104],{},"La seule explication au fait que la consommation mémoire soit aussi importante est, je pense, liée au fait que dans V8,\nles structures sont toutes des objets avec des méthodes par défaut et une structure minimaliste (les Buffers également).",[72,12106,12108],{"id":12107},"test-avec-un-bigint","Test avec un BigInt",[11,12110,12111,12112,12115],{},"La question que l'on peut se poser est : pourquoi utiliser la structure ",[165,12113,12114],{},"{ low: Number, high: Number, unsigned: Bool }"," ?",[11,12117,12118],{},"J'utilise cette structure car pour la persistance, j'utilise la librairie protobuf.js qui ne supporte pas les BigInt,\nmais qui utilise à la place la librairie long.js qui utilise cette structure.",[11,12120,12121],{},"J'ai donc effectué un test en remplaçant chaque objet complexe par le nouveau type BigInt de Node.js. Voici le code :",[11,12123,12124],{},"Pour générer le nombre aléatoire, je me base sur un entier de 2*53 bits.",[190,12126,12128],{"className":388,"code":12127,"language":390,"meta":59,"style":59},"function randomNumber() {\n  return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);\n}\n\nfunction randomBigInt() {\n  return (BigInt(randomNumber()) \u003C\u003C 53n) + BigInt(randomNumber());\n}\n",[165,12129,12130,12138,12164,12168,12172,12181,12219],{"__ignoreMap":59},[198,12131,12132,12134,12136],{"class":200,"line":201},[198,12133,10638],{"class":1956},[198,12135,10778],{"class":2202},[198,12137,6731],{"class":1383},[198,12139,12140,12142,12144,12146,12148,12150,12152,12154,12156,12158,12160,12162],{"class":200,"line":207},[198,12141,5399],{"class":1956},[198,12143,10722],{"class":1960},[198,12145,41],{"class":1383},[198,12147,10727],{"class":2202},[198,12149,2206],{"class":1383},[198,12151,10732],{"class":1960},[198,12153,41],{"class":1383},[198,12155,10737],{"class":2202},[198,12157,2484],{"class":1383},[198,12159,5494],{"class":2220},[198,12161,10805],{"class":1960},[198,12163,10808],{"class":1383},[198,12165,12166],{"class":200,"line":213},[198,12167,1613],{"class":1383},[198,12169,12170],{"class":200,"line":220},[198,12171,217],{"emptyLinePlaceholder":216},[198,12173,12174,12176,12179],{"class":200,"line":254},[198,12175,10638],{"class":1956},[198,12177,12178],{"class":2202}," randomBigInt",[198,12180,6731],{"class":1383},[198,12182,12183,12185,12187,12190,12192,12194,12197,12200,12203,12206,12208,12210,12213,12215,12217],{"class":200,"line":260},[198,12184,5399],{"class":1956},[198,12186,2288],{"class":1383},[198,12188,12189],{"class":2202},"BigInt",[198,12191,2206],{"class":1383},[198,12193,10880],{"class":2202},[198,12195,12196],{"class":1383},"()) ",[198,12198,12199],{"class":2220},"\u003C\u003C",[198,12201,12202],{"class":1417}," 53",[198,12204,12205],{"class":1956},"n",[198,12207,8484],{"class":1383},[198,12209,5878],{"class":2220},[198,12211,12212],{"class":2202}," BigInt",[198,12214,2206],{"class":1383},[198,12216,10880],{"class":2202},[198,12218,5414],{"class":1383},[198,12220,12221],{"class":200,"line":266},[198,12222,1613],{"class":1383},[11,12224,12225],{},"Le résultat est le suivant:",[6106,12227,12228,12236],{},[6109,12229,12230],{},[6112,12231,12232,12234],{},[6115,12233],{},[6115,12235],{},[6128,12237,12238,12244,12251,12258,12265,12272,12279],{},[6112,12239,12240,12242],{},[6133,12241,12047],{},[6133,12243,12050],{},[6112,12245,12246,12248],{},[6133,12247,12055],{},[6133,12249,12250],{},"14 secondes",[6112,12252,12253,12255],{},[6133,12254,12063],{},[6133,12256,12257],{},"2,1 Go",[6112,12259,12260,12262],{},[6133,12261,12071],{},[6133,12263,12264],{},"1,7 Ko",[6112,12266,12267,12269],{},[6133,12268,12079],{},[6133,12270,12271],{},"40 secondes",[6112,12273,12274,12276],{},[6133,12275,12087],{},[6133,12277,12278],{},"747,8 Mo",[6112,12280,12281,12283],{},[6133,12282,12095],{},[6133,12284,12285],{},"603 octets",[11,12287,12288,12289,12291],{},"L'utilisation de ",[165,12290,12189],{}," permet de réduire la consommation mémoire de 25% et la taille des objets dans le fichier de\n33%. La taille des objets sur le disque est acceptable. En revanche, la consommation mémoire de Node.js reste trop\nimportante.",[72,12293,12295],{"id":12294},"ecriture-du-même-code-en-rust","Ecriture du même code en Rust",[11,12297,12298],{},"Il est possible d'optimiser certaines parties de l'application grâce à la notion de node_modules natifs. Habituellement,\nces modules sont écrits en C++ en utilisant N-API. Il existe des bindings pour Rust, ce qui permet d'écrire une partie\nde l'application en Rust et de l'utiliser dans Node.JS.",[11,12300,12301,12302,12305,12306,41],{},"Pour comparer les performances de Rust et de Node.js, j'ai écrit le même code en Rust. Pour les nombres, je me suis basé\nsur des entiers de 64 bits et pour le nom de fichier, sur un ",[165,12303,12304],{},"Vec\u003Cu8>",". Je me suis basé sur une table de 32 caractères\npour le ",[165,12307,12308],{},"Sha256",[190,12310,12312],{"className":6673,"code":12311,"language":6675,"meta":59,"style":59},"use humansize::{format_size, make_format, DECIMAL};\nuse procinfo::pid;\nuse rand::{rngs::ThreadRng, Rng};\nuse serde::{Deserialize, Serialize};\nuse std::io::BufWriter;\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct Stats {\n    owner_id: u64,\n    group_id: u64,\n    size: u64,\n    compressed_size: u64,\n    last_read: u64,\n    last_modified: u64,\n    created: u64,\n    mode: u64,\n    dev: u64,\n    rdev: u64,\n    ino: u64,\n    nlink: u64,\n}\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct Sha256 {\n    data: [u8; 32],\n}\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct TestObject {\n    #[serde(with = \"serde_bytes\")]\n    path: Vec\u003Cu8>,\n    stats: Stats,\n\n    chunks: Vec\u003CSha256>,\n    sha256: Sha256,\n}\n\nfn generate_random_number(rng: &mut ThreadRng) -> u64 {\n    rng.gen()\n}\n\nfn generate_random_vect(rng: &mut ThreadRng, size: usize) -> Vec\u003Cu8> {\n    let mut vect: Vec\u003Cu8> = Vec::with_capacity(size);\n    for _ in 0..size {\n        vect.push(rng.gen());\n    }\n    vect\n}\n\nfn generate_random_sha256(rng: &mut ThreadRng) -> Sha256 {\n    let mut sha256 = Sha256 { data: [0; 32] };\n    for i in 0..32 {\n        sha256.data[i] = rng.gen();\n    }\n    sha256\n}\n\nfn main() {\n    let formatter = make_format(DECIMAL);\n    let mut rng = rand::thread_rng();\n    \u002F\u002F Get the memory consumption of the current process\n    let memory = pid::statm_self().unwrap();\n    \u002F\u002F Get the current time in ms\n    let now = std::time::SystemTime::now()\n        .duration_since(std::time::UNIX_EPOCH)\n        .unwrap()\n        .as_millis();\n\n    \u002F\u002F Create a vector with 1_300_000 elements of type TestObject\n    let nb_object = 1_300_000;\n    let mut test_objects: Vec\u003CTestObject> = Vec::with_capacity(nb_object);\n    for _ in 0..nb_object {\n        test_objects.push(TestObject {\n            path: generate_random_vect(&mut rng, 100),\n            stats: Stats {\n                owner_id: generate_random_number(&mut rng),\n                group_id: generate_random_number(&mut rng),\n                size: generate_random_number(&mut rng),\n                compressed_size: generate_random_number(&mut rng),\n                last_read: generate_random_number(&mut rng),\n                last_modified: generate_random_number(&mut rng),\n                created: generate_random_number(&mut rng),\n                mode: generate_random_number(&mut rng),\n                dev: generate_random_number(&mut rng),\n                rdev: generate_random_number(&mut rng),\n                ino: generate_random_number(&mut rng),\n                nlink: generate_random_number(&mut rng),\n            },\n            chunks: vec![\n                generate_random_sha256(&mut rng),\n                generate_random_sha256(&mut rng),\n                generate_random_sha256(&mut rng),\n            ],\n            sha256: generate_random_sha256(&mut rng),\n        });\n    }\n\n    let now_after_creation = std::time::SystemTime::now()\n        .duration_since(std::time::UNIX_EPOCH)\n        .unwrap()\n        .as_millis();\n    \u002F\u002F Calculate the creation time\n    println!(\"Creation time: {} ms\", now_after_creation - now);\n\n    \u002F\u002F Get the memory consumption of the current process\n    let memory_after_creation = pid::statm_self().unwrap();\n    \u002F\u002F Show memory consumption\n    println!(\n        \"Memory consumption after creation: {}\",\n        formatter((memory_after_creation.size - memory.size) * 4096)\n    );\n    \u002F\u002F Show average memory consumption per object\n    println!(\n        \"Average memory consumption per object: {}\",\n        formatter(((memory_after_creation.size - memory.size) * 4096) \u002F nb_object)\n    );\n\n    \u002F\u002F Remove the file test.bin if it exists\n    match std::fs::remove_file(\"test.bin\") {\n        Ok(_) => {}\n        Err(_) => {}\n    }\n\n    \u002F\u002F Serialize all the objects in a file\n    let file = std::fs::File::create(\"test.bin\").unwrap();\n    let mut buffile = BufWriter::new(file);\n    for test_object in test_objects.iter() {\n        bincode::serialize_into(&mut buffile, test_object).unwrap();\n    }\n\n    \u002F\u002F Show time to write\n    let now_after_serialization = std::time::SystemTime::now()\n        .duration_since(std::time::UNIX_EPOCH)\n        .unwrap()\n        .as_millis();\n\n    println!(\n        \"Write to file time: {} ms\",\n        now_after_serialization - now_after_creation\n    );\n\n    \u002F\u002F Get the file size and the average object size in file\n    let metadata = std::fs::metadata(\"test.bin\").unwrap();\n    println!(\n        \"Size of file on disk: {}\",\n        format_size(metadata.len(), DECIMAL)\n    );\n    println!(\n        \"Size of object in the file: {}\",\n        format_size(metadata.len() \u002F nb_object as u64, DECIMAL)\n    );\n}\n",[165,12313,12314,12329,12339,12364,12383,12400,12404,12423,12432,12443,12454,12464,12475,12486,12497,12507,12517,12527,12537,12547,12557,12561,12565,12581,12590,12605,12609,12613,12629,12638,12650,12665,12677,12681,12696,12707,12711,12715,12740,12752,12756,12760,12795,12829,12849,12869,12873,12878,12882,12886,12909,12938,12954,12977,12981,12986,12990,12994,13002,13020,13039,13044,13067,13072,13099,13122,13130,13139,13143,13148,13161,13196,13212,13227,13249,13260,13278,13295,13312,13329,13346,13363,13380,13397,13414,13431,13448,13465,13470,13483,13496,13508,13520,13525,13543,13548,13552,13557,13583,13604,13613,13622,13628,13650,13655,13660,13682,13688,13695,13703,13728,13734,13740,13747,13755,13780,13785,13790,13796,13819,13832,13844,13849,13854,13860,13894,13920,13939,13967,13972,13977,13983,14009,14030,14039,14048,14053,14060,14068,14079,14084,14089,14095,14126,14133,14141,14161,14166,14173,14181,14210,14215],{"__ignoreMap":59},[198,12315,12316,12318,12321,12324,12327],{"class":200,"line":201},[198,12317,6682],{"class":1956},[198,12319,12320],{"class":1960}," humansize",[198,12322,12323],{"class":1383},"::{format_size, make_format, ",[198,12325,12326],{"class":1960},"DECIMAL",[198,12328,929],{"class":1383},[198,12330,12331,12333,12336],{"class":200,"line":207},[198,12332,6682],{"class":1956},[198,12334,12335],{"class":1960}," procinfo",[198,12337,12338],{"class":1383},"::pid;\n",[198,12340,12341,12343,12346,12349,12352,12354,12357,12359,12362],{"class":200,"line":213},[198,12342,6682],{"class":1956},[198,12344,12345],{"class":1960}," rand",[198,12347,12348],{"class":1383},"::{",[198,12350,12351],{"class":1960},"rngs",[198,12353,5252],{"class":1383},[198,12355,12356],{"class":1960},"ThreadRng",[198,12358,2764],{"class":1383},[198,12360,12361],{"class":1960},"Rng",[198,12363,929],{"class":1383},[198,12365,12366,12368,12371,12373,12376,12378,12381],{"class":200,"line":220},[198,12367,6682],{"class":1956},[198,12369,12370],{"class":1960}," serde",[198,12372,12348],{"class":1383},[198,12374,12375],{"class":1960},"Deserialize",[198,12377,2764],{"class":1383},[198,12379,12380],{"class":1960},"Serialize",[198,12382,929],{"class":1383},[198,12384,12385,12387,12389,12391,12393,12395,12398],{"class":200,"line":254},[198,12386,6682],{"class":1956},[198,12388,6704],{"class":1960},[198,12390,5252],{"class":1383},[198,12392,7300],{"class":1960},[198,12394,5252],{"class":1383},[198,12396,12397],{"class":1960},"BufWriter",[198,12399,2008],{"class":1383},[198,12401,12402],{"class":200,"line":260},[198,12403,217],{"emptyLinePlaceholder":216},[198,12405,12406,12409,12411,12413,12415,12417,12420],{"class":200,"line":266},[198,12407,12408],{"class":1383},"#[derive(",[198,12410,12380],{"class":1960},[198,12412,2764],{"class":1383},[198,12414,12375],{"class":1960},[198,12416,2764],{"class":1383},[198,12418,12419],{"class":1960},"Debug",[198,12421,12422],{"class":1383},")]\n",[198,12424,12425,12427,12430],{"class":200,"line":272},[198,12426,5460],{"class":1956},[198,12428,12429],{"class":1960}," Stats",[198,12431,1964],{"class":1383},[198,12433,12434,12437,12439,12441],{"class":200,"line":278},[198,12435,12436],{"class":1387},"    owner_id",[198,12438,2998],{"class":1383},[198,12440,8875],{"class":1960},[198,12442,1757],{"class":1383},[198,12444,12445,12448,12450,12452],{"class":200,"line":283},[198,12446,12447],{"class":1387},"    group_id",[198,12449,2998],{"class":1383},[198,12451,8875],{"class":1960},[198,12453,1757],{"class":1383},[198,12455,12456,12458,12460,12462],{"class":200,"line":288},[198,12457,10938],{"class":1387},[198,12459,2998],{"class":1383},[198,12461,8875],{"class":1960},[198,12463,1757],{"class":1383},[198,12465,12466,12469,12471,12473],{"class":200,"line":450},[198,12467,12468],{"class":1387},"    compressed_size",[198,12470,2998],{"class":1383},[198,12472,8875],{"class":1960},[198,12474,1757],{"class":1383},[198,12476,12477,12480,12482,12484],{"class":200,"line":456},[198,12478,12479],{"class":1387},"    last_read",[198,12481,2998],{"class":1383},[198,12483,8875],{"class":1960},[198,12485,1757],{"class":1383},[198,12487,12488,12491,12493,12495],{"class":200,"line":462},[198,12489,12490],{"class":1387},"    last_modified",[198,12492,2998],{"class":1383},[198,12494,8875],{"class":1960},[198,12496,1757],{"class":1383},[198,12498,12499,12501,12503,12505],{"class":200,"line":468},[198,12500,11076],{"class":1387},[198,12502,2998],{"class":1383},[198,12504,8875],{"class":1960},[198,12506,1757],{"class":1383},[198,12508,12509,12511,12513,12515],{"class":200,"line":473},[198,12510,11107],{"class":1387},[198,12512,2998],{"class":1383},[198,12514,8875],{"class":1960},[198,12516,1757],{"class":1383},[198,12518,12519,12521,12523,12525],{"class":200,"line":478},[198,12520,11138],{"class":1387},[198,12522,2998],{"class":1383},[198,12524,8875],{"class":1960},[198,12526,1757],{"class":1383},[198,12528,12529,12531,12533,12535],{"class":200,"line":484},[198,12530,11169],{"class":1387},[198,12532,2998],{"class":1383},[198,12534,8875],{"class":1960},[198,12536,1757],{"class":1383},[198,12538,12539,12541,12543,12545],{"class":200,"line":490},[198,12540,11200],{"class":1387},[198,12542,2998],{"class":1383},[198,12544,8875],{"class":1960},[198,12546,1757],{"class":1383},[198,12548,12549,12551,12553,12555],{"class":200,"line":1068},[198,12550,11231],{"class":1387},[198,12552,2998],{"class":1383},[198,12554,8875],{"class":1960},[198,12556,1757],{"class":1383},[198,12558,12559],{"class":200,"line":1074},[198,12560,1613],{"class":1383},[198,12562,12563],{"class":200,"line":1080},[198,12564,217],{"emptyLinePlaceholder":216},[198,12566,12567,12569,12571,12573,12575,12577,12579],{"class":200,"line":1086},[198,12568,12408],{"class":1383},[198,12570,12380],{"class":1960},[198,12572,2764],{"class":1383},[198,12574,12375],{"class":1960},[198,12576,2764],{"class":1383},[198,12578,12419],{"class":1960},[198,12580,12422],{"class":1383},[198,12582,12583,12585,12588],{"class":200,"line":1092},[198,12584,5460],{"class":1956},[198,12586,12587],{"class":1960}," Sha256",[198,12589,1964],{"class":1383},[198,12591,12592,12595,12597,12599,12601,12603],{"class":200,"line":1098},[198,12593,12594],{"class":1387},"    data",[198,12596,8929],{"class":1383},[198,12598,7294],{"class":1960},[198,12600,8934],{"class":1383},[198,12602,11275],{"class":1417},[198,12604,9946],{"class":1383},[198,12606,12607],{"class":200,"line":1104},[198,12608,1613],{"class":1383},[198,12610,12611],{"class":200,"line":1110},[198,12612,217],{"emptyLinePlaceholder":216},[198,12614,12615,12617,12619,12621,12623,12625,12627],{"class":200,"line":1116},[198,12616,12408],{"class":1383},[198,12618,12380],{"class":1960},[198,12620,2764],{"class":1383},[198,12622,12375],{"class":1960},[198,12624,2764],{"class":1383},[198,12626,12419],{"class":1960},[198,12628,12422],{"class":1383},[198,12630,12631,12633,12636],{"class":200,"line":1122},[198,12632,5460],{"class":1956},[198,12634,12635],{"class":1960}," TestObject",[198,12637,1964],{"class":1383},[198,12639,12640,12643,12645,12648],{"class":200,"line":1128},[198,12641,12642],{"class":1383},"    #[serde(with ",[198,12644,1421],{"class":2220},[198,12646,12647],{"class":1424}," \"serde_bytes\"",[198,12649,12422],{"class":1383},[198,12651,12652,12654,12656,12658,12660,12662],{"class":200,"line":1134},[198,12653,10329],{"class":1387},[198,12655,2998],{"class":1383},[198,12657,7541],{"class":1960},[198,12659,1384],{"class":1383},[198,12661,7294],{"class":1960},[198,12663,12664],{"class":1383},">,\n",[198,12666,12667,12670,12672,12675],{"class":200,"line":1140},[198,12668,12669],{"class":1387},"    stats",[198,12671,2998],{"class":1383},[198,12673,12674],{"class":1960},"Stats",[198,12676,1757],{"class":1383},[198,12678,12679],{"class":200,"line":1146},[198,12680,217],{"emptyLinePlaceholder":216},[198,12682,12683,12686,12688,12690,12692,12694],{"class":200,"line":1151},[198,12684,12685],{"class":1387},"    chunks",[198,12687,2998],{"class":1383},[198,12689,7541],{"class":1960},[198,12691,1384],{"class":1383},[198,12693,12308],{"class":1960},[198,12695,12664],{"class":1383},[198,12697,12698,12701,12703,12705],{"class":200,"line":1157},[198,12699,12700],{"class":1387},"    sha256",[198,12702,2998],{"class":1383},[198,12704,12308],{"class":1960},[198,12706,1757],{"class":1383},[198,12708,12709],{"class":200,"line":1163},[198,12710,1613],{"class":1383},[198,12712,12713],{"class":200,"line":1169},[198,12714,217],{"emptyLinePlaceholder":216},[198,12716,12717,12719,12722,12724,12727,12729,12731,12734,12736,12738],{"class":200,"line":1175},[198,12718,6725],{"class":1956},[198,12720,12721],{"class":2202}," generate_random_number",[198,12723,2206],{"class":1383},[198,12725,12726],{"class":1387},"rng",[198,12728,7286],{"class":1383},[198,12730,6847],{"class":1956},[198,12732,12733],{"class":1960}," ThreadRng",[198,12735,7597],{"class":1383},[198,12737,8875],{"class":1960},[198,12739,1964],{"class":1383},[198,12741,12742,12745,12747,12750],{"class":200,"line":1181},[198,12743,12744],{"class":1387},"    rng",[198,12746,41],{"class":1383},[198,12748,12749],{"class":2202},"gen",[198,12751,9519],{"class":1383},[198,12753,12754],{"class":200,"line":1187},[198,12755,1613],{"class":1383},[198,12757,12758],{"class":200,"line":1193},[198,12759,217],{"emptyLinePlaceholder":216},[198,12761,12762,12764,12767,12769,12771,12773,12775,12777,12779,12781,12783,12785,12787,12789,12791,12793],{"class":200,"line":1199},[198,12763,6725],{"class":1956},[198,12765,12766],{"class":2202}," generate_random_vect",[198,12768,2206],{"class":1383},[198,12770,12726],{"class":1387},[198,12772,7286],{"class":1383},[198,12774,6847],{"class":1956},[198,12776,12733],{"class":1960},[198,12778,2764],{"class":1383},[198,12780,10646],{"class":1387},[198,12782,2998],{"class":1383},[198,12784,7310],{"class":1960},[198,12786,7597],{"class":1383},[198,12788,7541],{"class":1960},[198,12790,1384],{"class":1383},[198,12792,7294],{"class":1960},[198,12794,7263],{"class":1383},[198,12796,12797,12799,12801,12804,12806,12808,12810,12812,12814,12816,12818,12820,12823,12825,12827],{"class":200,"line":1205},[198,12798,6736],{"class":1956},[198,12800,6792],{"class":1956},[198,12802,12803],{"class":1387}," vect",[198,12805,2998],{"class":1383},[198,12807,7541],{"class":1960},[198,12809,1384],{"class":1383},[198,12811,7294],{"class":1960},[198,12813,7249],{"class":1383},[198,12815,1421],{"class":2220},[198,12817,6825],{"class":1960},[198,12819,5252],{"class":1383},[198,12821,12822],{"class":2202},"with_capacity",[198,12824,2206],{"class":1383},[198,12826,10646],{"class":1387},[198,12828,2280],{"class":1383},[198,12830,12831,12834,12837,12840,12842,12845,12847],{"class":200,"line":1211},[198,12832,12833],{"class":1956},"    for",[198,12835,12836],{"class":1387}," _",[198,12838,12839],{"class":1956}," in",[198,12841,6021],{"class":1417},[198,12843,12844],{"class":1383},"..",[198,12846,10646],{"class":1387},[198,12848,1964],{"class":1383},[198,12850,12851,12854,12856,12859,12861,12863,12865,12867],{"class":200,"line":1217},[198,12852,12853],{"class":1387},"        vect",[198,12855,41],{"class":1383},[198,12857,12858],{"class":2202},"push",[198,12860,2206],{"class":1383},[198,12862,12726],{"class":1387},[198,12864,41],{"class":1383},[198,12866,12749],{"class":1956},[198,12868,5414],{"class":1383},[198,12870,12871],{"class":200,"line":1223},[198,12872,2447],{"class":1383},[198,12874,12875],{"class":200,"line":1228},[198,12876,12877],{"class":1387},"    vect\n",[198,12879,12880],{"class":200,"line":1233},[198,12881,1613],{"class":1383},[198,12883,12884],{"class":200,"line":1238},[198,12885,217],{"emptyLinePlaceholder":216},[198,12887,12888,12890,12893,12895,12897,12899,12901,12903,12905,12907],{"class":200,"line":1244},[198,12889,6725],{"class":1956},[198,12891,12892],{"class":2202}," generate_random_sha256",[198,12894,2206],{"class":1383},[198,12896,12726],{"class":1387},[198,12898,7286],{"class":1383},[198,12900,6847],{"class":1956},[198,12902,12733],{"class":1960},[198,12904,7597],{"class":1383},[198,12906,12308],{"class":1960},[198,12908,1964],{"class":1383},[198,12910,12911,12913,12915,12918,12920,12922,12924,12927,12929,12931,12933,12935],{"class":200,"line":1250},[198,12912,6736],{"class":1956},[198,12914,6792],{"class":1956},[198,12916,12917],{"class":1387}," sha256",[198,12919,2221],{"class":2220},[198,12921,12587],{"class":1960},[198,12923,10386],{"class":1383},[198,12925,12926],{"class":1387},"data",[198,12928,8929],{"class":1383},[198,12930,5912],{"class":1417},[198,12932,8934],{"class":1383},[198,12934,11275],{"class":1417},[198,12936,12937],{"class":1383},"] };\n",[198,12939,12940,12942,12944,12946,12948,12950,12952],{"class":200,"line":11396},[198,12941,12833],{"class":1956},[198,12943,10683],{"class":1387},[198,12945,12839],{"class":1956},[198,12947,6021],{"class":1417},[198,12949,12844],{"class":1383},[198,12951,11275],{"class":1417},[198,12953,1964],{"class":1383},[198,12955,12956,12959,12962,12964,12966,12968,12971,12973,12975],{"class":200,"line":11402},[198,12957,12958],{"class":1387},"        sha256",[198,12960,12961],{"class":1383},".data[",[198,12963,10692],{"class":1387},[198,12965,6945],{"class":1383},[198,12967,1421],{"class":2220},[198,12969,12970],{"class":1387}," rng",[198,12972,41],{"class":1383},[198,12974,12749],{"class":2202},[198,12976,2244],{"class":1383},[198,12978,12979],{"class":200,"line":11408},[198,12980,2447],{"class":1383},[198,12982,12983],{"class":200,"line":11423},[198,12984,12985],{"class":1387},"    sha256\n",[198,12987,12988],{"class":200,"line":11445},[198,12989,1613],{"class":1383},[198,12991,12992],{"class":200,"line":11477},[198,12993,217],{"emptyLinePlaceholder":216},[198,12995,12996,12998,13000],{"class":200,"line":11495},[198,12997,6725],{"class":1956},[198,12999,6728],{"class":2202},[198,13001,6731],{"class":1383},[198,13003,13004,13006,13009,13011,13014,13016,13018],{"class":200,"line":11500},[198,13005,6736],{"class":1956},[198,13007,13008],{"class":1387}," formatter",[198,13010,2221],{"class":2220},[198,13012,13013],{"class":2202}," make_format",[198,13015,2206],{"class":1383},[198,13017,12326],{"class":1417},[198,13019,2280],{"class":1383},[198,13021,13022,13024,13026,13028,13030,13032,13034,13037],{"class":200,"line":11505},[198,13023,6736],{"class":1956},[198,13025,6792],{"class":1956},[198,13027,12970],{"class":1387},[198,13029,2221],{"class":2220},[198,13031,12345],{"class":1960},[198,13033,5252],{"class":1383},[198,13035,13036],{"class":2202},"thread_rng",[198,13038,2244],{"class":1383},[198,13040,13041],{"class":200,"line":11511},[198,13042,13043],{"class":1930},"    \u002F\u002F Get the memory consumption of the current process\n",[198,13045,13046,13048,13051,13053,13056,13058,13061,13063,13065],{"class":200,"line":11544},[198,13047,6736],{"class":1956},[198,13049,13050],{"class":1387}," memory",[198,13052,2221],{"class":2220},[198,13054,13055],{"class":1960}," pid",[198,13057,5252],{"class":1383},[198,13059,13060],{"class":2202},"statm_self",[198,13062,8010],{"class":1383},[198,13064,6759],{"class":2202},[198,13066,2244],{"class":1383},[198,13068,13069],{"class":200,"line":11550},[198,13070,13071],{"class":1930},"    \u002F\u002F Get the current time in ms\n",[198,13073,13074,13076,13079,13081,13083,13085,13088,13090,13093,13095,13097],{"class":200,"line":11561},[198,13075,6736],{"class":1956},[198,13077,13078],{"class":1387}," now",[198,13080,2221],{"class":2220},[198,13082,6704],{"class":1960},[198,13084,5252],{"class":1383},[198,13086,13087],{"class":1960},"time",[198,13089,5252],{"class":1383},[198,13091,13092],{"class":1960},"SystemTime",[198,13094,5252],{"class":1383},[198,13096,11387],{"class":2202},[198,13098,9519],{"class":1383},[198,13100,13101,13104,13107,13109,13111,13113,13115,13117,13120],{"class":200,"line":11567},[198,13102,13103],{"class":1383},"        .",[198,13105,13106],{"class":2202},"duration_since",[198,13108,2206],{"class":1383},[198,13110,9607],{"class":1960},[198,13112,5252],{"class":1383},[198,13114,13087],{"class":1960},[198,13116,5252],{"class":1383},[198,13118,13119],{"class":1417},"UNIX_EPOCH",[198,13121,2845],{"class":1383},[198,13123,13124,13126,13128],{"class":200,"line":11589},[198,13125,13103],{"class":1383},[198,13127,6759],{"class":2202},[198,13129,9519],{"class":1383},[198,13131,13132,13134,13137],{"class":200,"line":11594},[198,13133,13103],{"class":1383},[198,13135,13136],{"class":2202},"as_millis",[198,13138,2244],{"class":1383},[198,13140,13141],{"class":200,"line":11629},[198,13142,217],{"emptyLinePlaceholder":216},[198,13144,13145],{"class":200,"line":11668},[198,13146,13147],{"class":1930},"    \u002F\u002F Create a vector with 1_300_000 elements of type TestObject\n",[198,13149,13150,13152,13155,13157,13159],{"class":200,"line":11673},[198,13151,6736],{"class":1956},[198,13153,13154],{"class":1387}," nb_object",[198,13156,2221],{"class":2220},[198,13158,11418],{"class":1417},[198,13160,2008],{"class":1383},[198,13162,13163,13165,13167,13170,13172,13174,13176,13179,13181,13183,13185,13187,13189,13191,13194],{"class":200,"line":11679},[198,13164,6736],{"class":1956},[198,13166,6792],{"class":1956},[198,13168,13169],{"class":1387}," test_objects",[198,13171,2998],{"class":1383},[198,13173,7541],{"class":1960},[198,13175,1384],{"class":1383},[198,13177,13178],{"class":1960},"TestObject",[198,13180,7249],{"class":1383},[198,13182,1421],{"class":2220},[198,13184,6825],{"class":1960},[198,13186,5252],{"class":1383},[198,13188,12822],{"class":2202},[198,13190,2206],{"class":1383},[198,13192,13193],{"class":1387},"nb_object",[198,13195,2280],{"class":1383},[198,13197,13198,13200,13202,13204,13206,13208,13210],{"class":200,"line":11685},[198,13199,12833],{"class":1956},[198,13201,12836],{"class":1387},[198,13203,12839],{"class":1956},[198,13205,6021],{"class":1417},[198,13207,12844],{"class":1383},[198,13209,13193],{"class":1387},[198,13211,1964],{"class":1383},[198,13213,13214,13217,13219,13221,13223,13225],{"class":200,"line":11703},[198,13215,13216],{"class":1387},"        test_objects",[198,13218,41],{"class":1383},[198,13220,12858],{"class":2202},[198,13222,2206],{"class":1383},[198,13224,13178],{"class":1960},[198,13226,1964],{"class":1383},[198,13228,13229,13232,13234,13237,13239,13241,13243,13245,13247],{"class":200,"line":11708},[198,13230,13231],{"class":1387},"            path",[198,13233,2998],{"class":1383},[198,13235,13236],{"class":2202},"generate_random_vect",[198,13238,6844],{"class":1383},[198,13240,6847],{"class":1956},[198,13242,12970],{"class":1387},[198,13244,2764],{"class":1383},[198,13246,10854],{"class":1417},[198,13248,9915],{"class":1383},[198,13250,13251,13254,13256,13258],{"class":200,"line":11714},[198,13252,13253],{"class":1387},"            stats",[198,13255,2998],{"class":1383},[198,13257,12674],{"class":1960},[198,13259,1964],{"class":1383},[198,13261,13262,13265,13267,13270,13272,13274,13276],{"class":200,"line":11722},[198,13263,13264],{"class":1387},"                owner_id",[198,13266,2998],{"class":1383},[198,13268,13269],{"class":2202},"generate_random_number",[198,13271,6844],{"class":1383},[198,13273,6847],{"class":1956},[198,13275,12970],{"class":1387},[198,13277,9915],{"class":1383},[198,13279,13280,13283,13285,13287,13289,13291,13293],{"class":200,"line":11740},[198,13281,13282],{"class":1387},"                group_id",[198,13284,2998],{"class":1383},[198,13286,13269],{"class":2202},[198,13288,6844],{"class":1383},[198,13290,6847],{"class":1956},[198,13292,12970],{"class":1387},[198,13294,9915],{"class":1383},[198,13296,13297,13300,13302,13304,13306,13308,13310],{"class":200,"line":11755},[198,13298,13299],{"class":1387},"                size",[198,13301,2998],{"class":1383},[198,13303,13269],{"class":2202},[198,13305,6844],{"class":1383},[198,13307,6847],{"class":1956},[198,13309,12970],{"class":1387},[198,13311,9915],{"class":1383},[198,13313,13314,13317,13319,13321,13323,13325,13327],{"class":200,"line":11760},[198,13315,13316],{"class":1387},"                compressed_size",[198,13318,2998],{"class":1383},[198,13320,13269],{"class":2202},[198,13322,6844],{"class":1383},[198,13324,6847],{"class":1956},[198,13326,12970],{"class":1387},[198,13328,9915],{"class":1383},[198,13330,13331,13334,13336,13338,13340,13342,13344],{"class":200,"line":11783},[198,13332,13333],{"class":1387},"                last_read",[198,13335,2998],{"class":1383},[198,13337,13269],{"class":2202},[198,13339,6844],{"class":1383},[198,13341,6847],{"class":1956},[198,13343,12970],{"class":1387},[198,13345,9915],{"class":1383},[198,13347,13348,13351,13353,13355,13357,13359,13361],{"class":200,"line":11788},[198,13349,13350],{"class":1387},"                last_modified",[198,13352,2998],{"class":1383},[198,13354,13269],{"class":2202},[198,13356,6844],{"class":1383},[198,13358,6847],{"class":1956},[198,13360,12970],{"class":1387},[198,13362,9915],{"class":1383},[198,13364,13365,13368,13370,13372,13374,13376,13378],{"class":200,"line":11794},[198,13366,13367],{"class":1387},"                created",[198,13369,2998],{"class":1383},[198,13371,13269],{"class":2202},[198,13373,6844],{"class":1383},[198,13375,6847],{"class":1956},[198,13377,12970],{"class":1387},[198,13379,9915],{"class":1383},[198,13381,13382,13385,13387,13389,13391,13393,13395],{"class":200,"line":11817},[198,13383,13384],{"class":1387},"                mode",[198,13386,2998],{"class":1383},[198,13388,13269],{"class":2202},[198,13390,6844],{"class":1383},[198,13392,6847],{"class":1956},[198,13394,12970],{"class":1387},[198,13396,9915],{"class":1383},[198,13398,13399,13402,13404,13406,13408,13410,13412],{"class":200,"line":11848},[198,13400,13401],{"class":1387},"                dev",[198,13403,2998],{"class":1383},[198,13405,13269],{"class":2202},[198,13407,6844],{"class":1383},[198,13409,6847],{"class":1956},[198,13411,12970],{"class":1387},[198,13413,9915],{"class":1383},[198,13415,13416,13419,13421,13423,13425,13427,13429],{"class":200,"line":11854},[198,13417,13418],{"class":1387},"                rdev",[198,13420,2998],{"class":1383},[198,13422,13269],{"class":2202},[198,13424,6844],{"class":1383},[198,13426,6847],{"class":1956},[198,13428,12970],{"class":1387},[198,13430,9915],{"class":1383},[198,13432,13433,13436,13438,13440,13442,13444,13446],{"class":200,"line":11877},[198,13434,13435],{"class":1387},"                ino",[198,13437,2998],{"class":1383},[198,13439,13269],{"class":2202},[198,13441,6844],{"class":1383},[198,13443,6847],{"class":1956},[198,13445,12970],{"class":1387},[198,13447,9915],{"class":1383},[198,13449,13450,13453,13455,13457,13459,13461,13463],{"class":200,"line":11910},[198,13451,13452],{"class":1387},"                nlink",[198,13454,2998],{"class":1383},[198,13456,13269],{"class":2202},[198,13458,6844],{"class":1383},[198,13460,6847],{"class":1956},[198,13462,12970],{"class":1387},[198,13464,9915],{"class":1383},[198,13466,13467],{"class":200,"line":11921},[198,13468,13469],{"class":1383},"            },\n",[198,13471,13472,13475,13477,13480],{"class":200,"line":11929},[198,13473,13474],{"class":1387},"            chunks",[198,13476,2998],{"class":1383},[198,13478,13479],{"class":2202},"vec!",[198,13481,13482],{"class":1383},"[\n",[198,13484,13485,13488,13490,13492,13494],{"class":200,"line":11954},[198,13486,13487],{"class":2202},"                generate_random_sha256",[198,13489,6844],{"class":1383},[198,13491,6847],{"class":1956},[198,13493,12970],{"class":1387},[198,13495,9915],{"class":1383},[198,13497,13498,13500,13502,13504,13506],{"class":200,"line":11960},[198,13499,13487],{"class":2202},[198,13501,6844],{"class":1383},[198,13503,6847],{"class":1956},[198,13505,12970],{"class":1387},[198,13507,9915],{"class":1383},[198,13509,13510,13512,13514,13516,13518],{"class":200,"line":11965},[198,13511,13487],{"class":2202},[198,13513,6844],{"class":1383},[198,13515,6847],{"class":1956},[198,13517,12970],{"class":1387},[198,13519,9915],{"class":1383},[198,13521,13522],{"class":200,"line":11970},[198,13523,13524],{"class":1383},"            ],\n",[198,13526,13527,13530,13532,13535,13537,13539,13541],{"class":200,"line":11988},[198,13528,13529],{"class":1387},"            sha256",[198,13531,2998],{"class":1383},[198,13533,13534],{"class":2202},"generate_random_sha256",[198,13536,6844],{"class":1383},[198,13538,6847],{"class":1956},[198,13540,12970],{"class":1387},[198,13542,9915],{"class":1383},[198,13544,13545],{"class":200,"line":12010},[198,13546,13547],{"class":1383},"        });\n",[198,13549,13550],{"class":200,"line":12015},[198,13551,2447],{"class":1383},[198,13553,13555],{"class":200,"line":13554},97,[198,13556,217],{"emptyLinePlaceholder":216},[198,13558,13560,13562,13565,13567,13569,13571,13573,13575,13577,13579,13581],{"class":200,"line":13559},98,[198,13561,6736],{"class":1956},[198,13563,13564],{"class":1387}," now_after_creation",[198,13566,2221],{"class":2220},[198,13568,6704],{"class":1960},[198,13570,5252],{"class":1383},[198,13572,13087],{"class":1960},[198,13574,5252],{"class":1383},[198,13576,13092],{"class":1960},[198,13578,5252],{"class":1383},[198,13580,11387],{"class":2202},[198,13582,9519],{"class":1383},[198,13584,13586,13588,13590,13592,13594,13596,13598,13600,13602],{"class":200,"line":13585},99,[198,13587,13103],{"class":1383},[198,13589,13106],{"class":2202},[198,13591,2206],{"class":1383},[198,13593,9607],{"class":1960},[198,13595,5252],{"class":1383},[198,13597,13087],{"class":1960},[198,13599,5252],{"class":1383},[198,13601,13119],{"class":1417},[198,13603,2845],{"class":1383},[198,13605,13607,13609,13611],{"class":200,"line":13606},100,[198,13608,13103],{"class":1383},[198,13610,6759],{"class":2202},[198,13612,9519],{"class":1383},[198,13614,13616,13618,13620],{"class":200,"line":13615},101,[198,13617,13103],{"class":1383},[198,13619,13136],{"class":2202},[198,13621,2244],{"class":1383},[198,13623,13625],{"class":200,"line":13624},102,[198,13626,13627],{"class":1930},"    \u002F\u002F Calculate the creation time\n",[198,13629,13631,13633,13635,13638,13640,13643,13646,13648],{"class":200,"line":13630},103,[198,13632,6860],{"class":2202},[198,13634,2206],{"class":1383},[198,13636,13637],{"class":1424},"\"Creation time: {} ms\"",[198,13639,2764],{"class":1383},[198,13641,13642],{"class":1387},"now_after_creation",[198,13644,13645],{"class":1383}," - ",[198,13647,11387],{"class":1387},[198,13649,2280],{"class":1383},[198,13651,13653],{"class":200,"line":13652},104,[198,13654,217],{"emptyLinePlaceholder":216},[198,13656,13658],{"class":200,"line":13657},105,[198,13659,13043],{"class":1930},[198,13661,13663,13665,13668,13670,13672,13674,13676,13678,13680],{"class":200,"line":13662},106,[198,13664,6736],{"class":1956},[198,13666,13667],{"class":1387}," memory_after_creation",[198,13669,2221],{"class":2220},[198,13671,13055],{"class":1960},[198,13673,5252],{"class":1383},[198,13675,13060],{"class":2202},[198,13677,8010],{"class":1383},[198,13679,6759],{"class":2202},[198,13681,2244],{"class":1383},[198,13683,13685],{"class":200,"line":13684},107,[198,13686,13687],{"class":1930},"    \u002F\u002F Show memory consumption\n",[198,13689,13691,13693],{"class":200,"line":13690},108,[198,13692,6860],{"class":2202},[198,13694,2775],{"class":1383},[198,13696,13698,13701],{"class":200,"line":13697},109,[198,13699,13700],{"class":1424},"        \"Memory consumption after creation: {}\"",[198,13702,1757],{"class":1383},[198,13704,13706,13709,13711,13714,13717,13720,13723,13726],{"class":200,"line":13705},110,[198,13707,13708],{"class":2202},"        formatter",[198,13710,11651],{"class":1383},[198,13712,13713],{"class":1387},"memory_after_creation",[198,13715,13716],{"class":1383},".size - ",[198,13718,13719],{"class":1387},"memory",[198,13721,13722],{"class":1383},".size) * ",[198,13724,13725],{"class":1417},"4096",[198,13727,2845],{"class":1383},[198,13729,13731],{"class":200,"line":13730},111,[198,13732,13733],{"class":1383},"    );\n",[198,13735,13737],{"class":200,"line":13736},112,[198,13738,13739],{"class":1930},"    \u002F\u002F Show average memory consumption per object\n",[198,13741,13743,13745],{"class":200,"line":13742},113,[198,13744,6860],{"class":2202},[198,13746,2775],{"class":1383},[198,13748,13750,13753],{"class":200,"line":13749},114,[198,13751,13752],{"class":1424},"        \"Average memory consumption per object: {}\"",[198,13754,1757],{"class":1383},[198,13756,13758,13760,13763,13765,13767,13769,13771,13773,13776,13778],{"class":200,"line":13757},115,[198,13759,13708],{"class":2202},[198,13761,13762],{"class":1383},"(((",[198,13764,13713],{"class":1387},[198,13766,13716],{"class":1383},[198,13768,13719],{"class":1387},[198,13770,13722],{"class":1383},[198,13772,13725],{"class":1417},[198,13774,13775],{"class":1383},") \u002F ",[198,13777,13193],{"class":1387},[198,13779,2845],{"class":1383},[198,13781,13783],{"class":200,"line":13782},116,[198,13784,13733],{"class":1383},[198,13786,13788],{"class":200,"line":13787},117,[198,13789,217],{"emptyLinePlaceholder":216},[198,13791,13793],{"class":200,"line":13792},118,[198,13794,13795],{"class":1930},"    \u002F\u002F Remove the file test.bin if it exists\n",[198,13797,13799,13801,13803,13805,13807,13809,13812,13814,13817],{"class":200,"line":13798},119,[198,13800,9355],{"class":1956},[198,13802,6704],{"class":1960},[198,13804,5252],{"class":1383},[198,13806,6709],{"class":1960},[198,13808,5252],{"class":1383},[198,13810,13811],{"class":2202},"remove_file",[198,13813,2206],{"class":1383},[198,13815,13816],{"class":1424},"\"test.bin\"",[198,13818,2212],{"class":1383},[198,13820,13822,13824,13826,13829],{"class":200,"line":13821},120,[198,13823,7464],{"class":1960},[198,13825,2206],{"class":1383},[198,13827,13828],{"class":1387},"_",[198,13830,13831],{"class":1383},") => {}\n",[198,13833,13835,13838,13840,13842],{"class":200,"line":13834},121,[198,13836,13837],{"class":1960},"        Err",[198,13839,2206],{"class":1383},[198,13841,13828],{"class":1387},[198,13843,13831],{"class":1383},[198,13845,13847],{"class":200,"line":13846},122,[198,13848,2447],{"class":1383},[198,13850,13852],{"class":200,"line":13851},123,[198,13853,217],{"emptyLinePlaceholder":216},[198,13855,13857],{"class":200,"line":13856},124,[198,13858,13859],{"class":1930},"    \u002F\u002F Serialize all the objects in a file\n",[198,13861,13863,13865,13867,13869,13871,13873,13875,13877,13879,13881,13884,13886,13888,13890,13892],{"class":200,"line":13862},125,[198,13864,6736],{"class":1956},[198,13866,10150],{"class":1387},[198,13868,2221],{"class":2220},[198,13870,6704],{"class":1960},[198,13872,5252],{"class":1383},[198,13874,6709],{"class":1960},[198,13876,5252],{"class":1383},[198,13878,6714],{"class":1960},[198,13880,5252],{"class":1383},[198,13882,13883],{"class":2202},"create",[198,13885,2206],{"class":1383},[198,13887,13816],{"class":1424},[198,13889,958],{"class":1383},[198,13891,6759],{"class":2202},[198,13893,2244],{"class":1383},[198,13895,13897,13899,13901,13904,13906,13909,13911,13913,13915,13918],{"class":200,"line":13896},126,[198,13898,6736],{"class":1956},[198,13900,6792],{"class":1956},[198,13902,13903],{"class":1387}," buffile",[198,13905,2221],{"class":2220},[198,13907,13908],{"class":1960}," BufWriter",[198,13910,5252],{"class":1383},[198,13912,6778],{"class":2202},[198,13914,2206],{"class":1383},[198,13916,13917],{"class":1387},"file",[198,13919,2280],{"class":1383},[198,13921,13923,13925,13928,13930,13932,13934,13937],{"class":200,"line":13922},127,[198,13924,12833],{"class":1956},[198,13926,13927],{"class":1387}," test_object",[198,13929,12839],{"class":1956},[198,13931,13169],{"class":1387},[198,13933,41],{"class":1383},[198,13935,13936],{"class":2202},"iter",[198,13938,6731],{"class":1383},[198,13940,13942,13945,13947,13950,13952,13954,13956,13958,13961,13963,13965],{"class":200,"line":13941},128,[198,13943,13944],{"class":1960},"        bincode",[198,13946,5252],{"class":1383},[198,13948,13949],{"class":2202},"serialize_into",[198,13951,6844],{"class":1383},[198,13953,6847],{"class":1956},[198,13955,13903],{"class":1387},[198,13957,2764],{"class":1383},[198,13959,13960],{"class":1387},"test_object",[198,13962,958],{"class":1383},[198,13964,6759],{"class":2202},[198,13966,2244],{"class":1383},[198,13968,13970],{"class":200,"line":13969},129,[198,13971,2447],{"class":1383},[198,13973,13975],{"class":200,"line":13974},130,[198,13976,217],{"emptyLinePlaceholder":216},[198,13978,13980],{"class":200,"line":13979},131,[198,13981,13982],{"class":1930},"    \u002F\u002F Show time to write\n",[198,13984,13986,13988,13991,13993,13995,13997,13999,14001,14003,14005,14007],{"class":200,"line":13985},132,[198,13987,6736],{"class":1956},[198,13989,13990],{"class":1387}," now_after_serialization",[198,13992,2221],{"class":2220},[198,13994,6704],{"class":1960},[198,13996,5252],{"class":1383},[198,13998,13087],{"class":1960},[198,14000,5252],{"class":1383},[198,14002,13092],{"class":1960},[198,14004,5252],{"class":1383},[198,14006,11387],{"class":2202},[198,14008,9519],{"class":1383},[198,14010,14012,14014,14016,14018,14020,14022,14024,14026,14028],{"class":200,"line":14011},133,[198,14013,13103],{"class":1383},[198,14015,13106],{"class":2202},[198,14017,2206],{"class":1383},[198,14019,9607],{"class":1960},[198,14021,5252],{"class":1383},[198,14023,13087],{"class":1960},[198,14025,5252],{"class":1383},[198,14027,13119],{"class":1417},[198,14029,2845],{"class":1383},[198,14031,14033,14035,14037],{"class":200,"line":14032},134,[198,14034,13103],{"class":1383},[198,14036,6759],{"class":2202},[198,14038,9519],{"class":1383},[198,14040,14042,14044,14046],{"class":200,"line":14041},135,[198,14043,13103],{"class":1383},[198,14045,13136],{"class":2202},[198,14047,2244],{"class":1383},[198,14049,14051],{"class":200,"line":14050},136,[198,14052,217],{"emptyLinePlaceholder":216},[198,14054,14056,14058],{"class":200,"line":14055},137,[198,14057,6860],{"class":2202},[198,14059,2775],{"class":1383},[198,14061,14063,14066],{"class":200,"line":14062},138,[198,14064,14065],{"class":1424},"        \"Write to file time: {} ms\"",[198,14067,1757],{"class":1383},[198,14069,14071,14074,14076],{"class":200,"line":14070},139,[198,14072,14073],{"class":1387},"        now_after_serialization",[198,14075,13645],{"class":1383},[198,14077,14078],{"class":1387},"now_after_creation\n",[198,14080,14082],{"class":200,"line":14081},140,[198,14083,13733],{"class":1383},[198,14085,14087],{"class":200,"line":14086},141,[198,14088,217],{"emptyLinePlaceholder":216},[198,14090,14092],{"class":200,"line":14091},142,[198,14093,14094],{"class":1930},"    \u002F\u002F Get the file size and the average object size in file\n",[198,14096,14098,14100,14103,14105,14107,14109,14111,14113,14116,14118,14120,14122,14124],{"class":200,"line":14097},143,[198,14099,6736],{"class":1956},[198,14101,14102],{"class":1387}," metadata",[198,14104,2221],{"class":2220},[198,14106,6704],{"class":1960},[198,14108,5252],{"class":1383},[198,14110,6709],{"class":1960},[198,14112,5252],{"class":1383},[198,14114,14115],{"class":2202},"metadata",[198,14117,2206],{"class":1383},[198,14119,13816],{"class":1424},[198,14121,958],{"class":1383},[198,14123,6759],{"class":2202},[198,14125,2244],{"class":1383},[198,14127,14129,14131],{"class":200,"line":14128},144,[198,14130,6860],{"class":2202},[198,14132,2775],{"class":1383},[198,14134,14136,14139],{"class":200,"line":14135},145,[198,14137,14138],{"class":1424},"        \"Size of file on disk: {}\"",[198,14140,1757],{"class":1383},[198,14142,14144,14147,14149,14151,14153,14155,14157,14159],{"class":200,"line":14143},146,[198,14145,14146],{"class":2202},"        format_size",[198,14148,2206],{"class":1383},[198,14150,14115],{"class":1387},[198,14152,41],{"class":1383},[198,14154,7353],{"class":2202},[198,14156,10883],{"class":1383},[198,14158,12326],{"class":1417},[198,14160,2845],{"class":1383},[198,14162,14164],{"class":200,"line":14163},147,[198,14165,13733],{"class":1383},[198,14167,14169,14171],{"class":200,"line":14168},148,[198,14170,6860],{"class":2202},[198,14172,2775],{"class":1383},[198,14174,14176,14179],{"class":200,"line":14175},149,[198,14177,14178],{"class":1424},"        \"Size of object in the file: {}\"",[198,14180,1757],{"class":1383},[198,14182,14184,14186,14188,14190,14192,14194,14197,14199,14202,14204,14206,14208],{"class":200,"line":14183},150,[198,14185,14146],{"class":2202},[198,14187,2206],{"class":1383},[198,14189,14115],{"class":1387},[198,14191,41],{"class":1383},[198,14193,7353],{"class":2202},[198,14195,14196],{"class":1383},"() \u002F ",[198,14198,13193],{"class":1387},[198,14200,14201],{"class":1956}," as",[198,14203,9019],{"class":1960},[198,14205,2764],{"class":1383},[198,14207,12326],{"class":1417},[198,14209,2845],{"class":1383},[198,14211,14213],{"class":200,"line":14212},151,[198,14214,13733],{"class":1383},[198,14216,14218],{"class":200,"line":14217},152,[198,14219,1613],{"class":1383},[11,14221,14222],{},"Ce qui donne le résultat suivant :",[6106,14224,14225,14233],{},[6109,14226,14227],{},[6112,14228,14229,14231],{},[6115,14230],{},[6115,14232],{},[6128,14234,14235,14241,14248,14255,14262,14269,14276],{},[6112,14236,14237,14239],{},[6133,14238,12047],{},[6133,14240,12050],{},[6112,14242,14243,14245],{},[6133,14244,12055],{},[6133,14246,14247],{},"2 secondes",[6112,14249,14250,14252],{},[6133,14251,12063],{},[6133,14253,14254],{},"519,92 Mo",[6112,14256,14257,14259],{},[6133,14258,12071],{},[6133,14260,14261],{},"399 octets",[6112,14263,14264,14266],{},[6133,14265,12079],{},[6133,14267,14268],{},"1 seconde",[6112,14270,14271,14273],{},[6133,14272,12087],{},[6133,14274,14275],{},"441,99 Mb",[6112,14277,14278,14280],{},[6133,14279,12095],{},[6133,14281,14282],{},"339 octets",[11,14284,14285],{},"En comparant les résultats obtenus avec Node.js et Rust, on peut conclure que Rust est, sans contestation possible,\nbeaucoup plus performant que Node.js en termes de temps d'exécution et de consommation de mémoire pour la création de\n1,3 million d'objets. En effet, Rust a créé tous les objets en seulement 2 secondes et consommé 519,92 Mo de mémoire,\ntandis que Node.js a pris 15 secondes et consommé 2,8 Go de mémoire.",[11,14287,14288],{},"La consommation moyenne de mémoire par objet est du coup nettement plus faible avec Rust (399 octets) qu'avec\nNode.js (2,2 Ko).",[11,14290,14291],{},"En somme, cette première partie montre clairement que Rust est une alternative intéressante pour les applications\nnécessitant une manipulation intensive de données, en particulier lorsque la performance et la consommation de mémoire\nsont des critères importants.",[72,14293,14295],{"id":14294},"optimisation-de-notre-application","Optimisation de notre application",[11,14297,14298],{},"Pour optimiser notre application en TypeScript, nous allons développer un module natif en Node.js avec Rust. Pour cela,\nnous allons utiliser NAPI.RS.",[11,14300,14301],{},"N-API est une interface de programmation d'applications (API) qui permet aux modules natifs d'être facilement utilisés\ndans Node.js. Cela permet aux développeurs de créer des modules en C++ et de les utiliser dans des projets Node.js\nsans avoir à se soucier de la compatibilité entre les versions de Node.js.",[11,14303,14304],{},"N-API est une API stable et évolutive qui est maintenue par l'équipe Node.js. N-API fournit une interface de\nprogrammation d'applications indépendante du moteur JavaScript utilisé par Node.js. Cela signifie que les modules\ncompilés avec N-API fonctionnent de manière cohérente, quel que soit le moteur JavaScript utilisé par Node.js.",[11,14306,14307],{},"napi.rs est une bibliothèque Rust qui fournit une API pour écrire des modules Node.js en Rust. Elle simplifie la création\nde modules Node.js en fournissant des abstractions de niveau supérieur pour les fonctionnalités N-API. Avec napi.rs, les\ndéveloppeurs Rust peuvent facilement écrire des modules Node.js sans avoir à se soucier des détails techniques de N-API.",[11,14309,14310,14311,41],{},"Nous allons débuter le développement de la partie Rust de notre application. Je ne vais pas détailler la création d'un\nmodule Rust avec NAPI.RS. La documentation est assez bien faite pour cette partie : ",[15,14312,14313],{"href":14313,"rel":14314},"https:\u002F\u002Fnapi.rs\u002Fdocs\u002Fintroduction\u002Fsimple-package",[24],[11,14316,14317],{},"Le module que nous allons écrire doit conserver les objets qu'il crée en mémoire. En effet, si les objets créés côté Rust\nétaient ensuite transférés dans la partie Node.js, la consommation de mémoire serait la même que si nous avions créé\nles objets directement en Node.js.",[11,14319,14320],{},"L'exemple ci-dessous ne fait pas grand-chose, mais c'est un point à prendre en considération lorsque je vais développer\nle module pour mon application. Les objets transférés à la partie JavaScript ne doivent que transiter.",[11,14322,14323],{},"Voici la partie Rust :",[190,14325,14327],{"className":6673,"code":14326,"language":6675,"meta":59,"style":59},"#![deny(clippy::all)]\nuse humansize::{format_size, DECIMAL};\nuse procinfo::pid;\nuse rand::{rngs::ThreadRng, Rng};\n\n#[macro_use]\nextern crate napi_derive;\n\nstruct Stats {\n  owner_id: u64,\n  group_id: u64,\n  size: u64,\n  compressed_size: u64,\n  last_read: u64,\n  last_modified: u64,\n  created: u64,\n  mode: u64,\n  dev: u64,\n  rdev: u64,\n  ino: u64,\n  nlink: u64,\n}\n\nstruct Sha256 {\n  data: [u8; 32],\n}\n\nstruct TestObject {\n  path: Vec\u003Cu8>,\n  stats: Stats,\n\n  chunks: Vec\u003CSha256>,\n  sha256: Sha256,\n}\n\nfn generate_random_number(rng: &mut ThreadRng) -> u64 {\n  rng.gen()\n}\n\nfn generate_random_vect(rng: &mut ThreadRng, size: usize) -> Vec\u003Cu8> {\n  let mut vect: Vec\u003Cu8> = Vec::with_capacity(size);\n  for _ in 0..size {\n    vect.push(rng.gen());\n  }\n  vect\n}\n\nfn generate_random_sha256(rng: &mut ThreadRng) -> Sha256 {\n  let mut sha256 = Sha256 { data: [0; 32] };\n  for i in 0..32 {\n    sha256.data[i] = rng.gen();\n  }\n  sha256\n}\n\npub struct TestObjectWrapper {\n  test_objects: Vec\u003CTestObject>,\n}\n\n#[napi(js_name = \"TestObjectWrapper\")]\npub struct JsTestObjectWrapper {\n  test_object_wrapper: TestObjectWrapper,\n}\n\n#[napi]\nimpl JsTestObjectWrapper {\n  #[napi(constructor)]\n  pub fn new() -> Self {\n    Self {\n      test_object_wrapper: TestObjectWrapper {\n        test_objects: Vec::new(),\n      },\n    }\n  }\n\n  #[napi]\n  pub fn fill(&mut self, nb_object: i32) {\n    let mut rng = rand::thread_rng();\n    \u002F\u002F Get the memory consumption of the current process\n    let memory = pid::statm_self().unwrap();\n    \u002F\u002F Get the current time in ms\n    let now = std::time::SystemTime::now()\n      .duration_since(std::time::UNIX_EPOCH)\n      .unwrap()\n      .as_millis();\n\n    self.test_object_wrapper.test_objects = Vec::with_capacity(nb_object.try_into().unwrap());\n\n    for _ in 0..nb_object {\n      self.test_object_wrapper.test_objects.push(TestObject {\n        path: generate_random_vect(&mut rng, 100),\n        stats: Stats {\n          owner_id: generate_random_number(&mut rng),\n          group_id: generate_random_number(&mut rng),\n          size: generate_random_number(&mut rng),\n          compressed_size: generate_random_number(&mut rng),\n          last_read: generate_random_number(&mut rng),\n          last_modified: generate_random_number(&mut rng),\n          created: generate_random_number(&mut rng),\n          mode: generate_random_number(&mut rng),\n          dev: generate_random_number(&mut rng),\n          rdev: generate_random_number(&mut rng),\n          ino: generate_random_number(&mut rng),\n          nlink: generate_random_number(&mut rng),\n        },\n        chunks: vec![\n          generate_random_sha256(&mut rng),\n          generate_random_sha256(&mut rng),\n          generate_random_sha256(&mut rng),\n        ],\n        sha256: generate_random_sha256(&mut rng),\n      });\n    }\n\n    let now_after_creation = std::time::SystemTime::now()\n      .duration_since(std::time::UNIX_EPOCH)\n      .unwrap()\n      .as_millis();\n    \u002F\u002F Calculate the creation time\n    println!(\"Creation time: {} ms\", now_after_creation - now);\n\n    \u002F\u002F Get the memory consumption of the current process\n    let memory_after_creation = pid::statm_self().unwrap();\n    \u002F\u002F Show memory consumption\n    println!(\n      \"Memory consumption after creation: {}\",\n      format_size((memory_after_creation.size - memory.size) * 4096, DECIMAL)\n    );\n    \u002F\u002F Show average memory consumption per object\n    println!(\n      \"Average memory consumption per object: {}\",\n      format_size(\n        ((memory_after_creation.size - memory.size) * 4096) \u002F nb_object as usize,\n        DECIMAL\n      )\n    );\n  }\n\n  #[napi(js_name = \"toString\")]\n  pub fn to_string(&self) -> String {\n    format!(\n      \"TestObjectWrapper {{ test_objects: {} }}\",\n      self.test_object_wrapper.test_objects.len()\n    )\n  }\n}\n",[165,14328,14329,14334,14347,14355,14375,14379,14384,14395,14399,14407,14418,14429,14440,14451,14462,14473,14484,14495,14506,14517,14528,14539,14543,14547,14555,14570,14574,14578,14586,14600,14610,14614,14628,14638,14642,14646,14668,14679,14683,14687,14721,14754,14770,14789,14793,14798,14802,14806,14828,14854,14870,14890,14894,14899,14903,14907,14918,14933,14937,14941,14953,14964,14976,14980,14984,14989,14997,15002,15018,15025,15036,15050,15054,15058,15062,15066,15071,15097,15115,15119,15139,15143,15167,15188,15196,15204,15208,15239,15243,15259,15275,15296,15307,15324,15341,15358,15375,15392,15409,15426,15443,15460,15477,15494,15511,15515,15526,15539,15551,15563,15568,15584,15589,15593,15597,15621,15641,15649,15657,15661,15679,15683,15687,15707,15711,15717,15724,15747,15751,15755,15761,15768,15774,15800,15805,15810,15814,15818,15822,15834,15854,15861,15868,15878,15883,15887],{"__ignoreMap":59},[198,14330,14331],{"class":200,"line":201},[198,14332,14333],{"class":1383},"#![deny(clippy::all)]\n",[198,14335,14336,14338,14340,14343,14345],{"class":200,"line":207},[198,14337,6682],{"class":1956},[198,14339,12320],{"class":1960},[198,14341,14342],{"class":1383},"::{format_size, ",[198,14344,12326],{"class":1960},[198,14346,929],{"class":1383},[198,14348,14349,14351,14353],{"class":200,"line":213},[198,14350,6682],{"class":1956},[198,14352,12335],{"class":1960},[198,14354,12338],{"class":1383},[198,14356,14357,14359,14361,14363,14365,14367,14369,14371,14373],{"class":200,"line":220},[198,14358,6682],{"class":1956},[198,14360,12345],{"class":1960},[198,14362,12348],{"class":1383},[198,14364,12351],{"class":1960},[198,14366,5252],{"class":1383},[198,14368,12356],{"class":1960},[198,14370,2764],{"class":1383},[198,14372,12361],{"class":1960},[198,14374,929],{"class":1383},[198,14376,14377],{"class":200,"line":254},[198,14378,217],{"emptyLinePlaceholder":216},[198,14380,14381],{"class":200,"line":260},[198,14382,14383],{"class":1383},"#[macro_use]\n",[198,14385,14386,14389,14392],{"class":200,"line":266},[198,14387,14388],{"class":1956},"extern",[198,14390,14391],{"class":1956}," crate",[198,14393,14394],{"class":1383}," napi_derive;\n",[198,14396,14397],{"class":200,"line":272},[198,14398,217],{"emptyLinePlaceholder":216},[198,14400,14401,14403,14405],{"class":200,"line":278},[198,14402,5460],{"class":1956},[198,14404,12429],{"class":1960},[198,14406,1964],{"class":1383},[198,14408,14409,14412,14414,14416],{"class":200,"line":283},[198,14410,14411],{"class":1387},"  owner_id",[198,14413,2998],{"class":1383},[198,14415,8875],{"class":1960},[198,14417,1757],{"class":1383},[198,14419,14420,14423,14425,14427],{"class":200,"line":288},[198,14421,14422],{"class":1387},"  group_id",[198,14424,2998],{"class":1383},[198,14426,8875],{"class":1960},[198,14428,1757],{"class":1383},[198,14430,14431,14434,14436,14438],{"class":200,"line":450},[198,14432,14433],{"class":1387},"  size",[198,14435,2998],{"class":1383},[198,14437,8875],{"class":1960},[198,14439,1757],{"class":1383},[198,14441,14442,14445,14447,14449],{"class":200,"line":456},[198,14443,14444],{"class":1387},"  compressed_size",[198,14446,2998],{"class":1383},[198,14448,8875],{"class":1960},[198,14450,1757],{"class":1383},[198,14452,14453,14456,14458,14460],{"class":200,"line":462},[198,14454,14455],{"class":1387},"  last_read",[198,14457,2998],{"class":1383},[198,14459,8875],{"class":1960},[198,14461,1757],{"class":1383},[198,14463,14464,14467,14469,14471],{"class":200,"line":468},[198,14465,14466],{"class":1387},"  last_modified",[198,14468,2998],{"class":1383},[198,14470,8875],{"class":1960},[198,14472,1757],{"class":1383},[198,14474,14475,14478,14480,14482],{"class":200,"line":473},[198,14476,14477],{"class":1387},"  created",[198,14479,2998],{"class":1383},[198,14481,8875],{"class":1960},[198,14483,1757],{"class":1383},[198,14485,14486,14489,14491,14493],{"class":200,"line":478},[198,14487,14488],{"class":1387},"  mode",[198,14490,2998],{"class":1383},[198,14492,8875],{"class":1960},[198,14494,1757],{"class":1383},[198,14496,14497,14500,14502,14504],{"class":200,"line":484},[198,14498,14499],{"class":1387},"  dev",[198,14501,2998],{"class":1383},[198,14503,8875],{"class":1960},[198,14505,1757],{"class":1383},[198,14507,14508,14511,14513,14515],{"class":200,"line":490},[198,14509,14510],{"class":1387},"  rdev",[198,14512,2998],{"class":1383},[198,14514,8875],{"class":1960},[198,14516,1757],{"class":1383},[198,14518,14519,14522,14524,14526],{"class":200,"line":1068},[198,14520,14521],{"class":1387},"  ino",[198,14523,2998],{"class":1383},[198,14525,8875],{"class":1960},[198,14527,1757],{"class":1383},[198,14529,14530,14533,14535,14537],{"class":200,"line":1074},[198,14531,14532],{"class":1387},"  nlink",[198,14534,2998],{"class":1383},[198,14536,8875],{"class":1960},[198,14538,1757],{"class":1383},[198,14540,14541],{"class":200,"line":1080},[198,14542,1613],{"class":1383},[198,14544,14545],{"class":200,"line":1086},[198,14546,217],{"emptyLinePlaceholder":216},[198,14548,14549,14551,14553],{"class":200,"line":1092},[198,14550,5460],{"class":1956},[198,14552,12587],{"class":1960},[198,14554,1964],{"class":1383},[198,14556,14557,14560,14562,14564,14566,14568],{"class":200,"line":1098},[198,14558,14559],{"class":1387},"  data",[198,14561,8929],{"class":1383},[198,14563,7294],{"class":1960},[198,14565,8934],{"class":1383},[198,14567,11275],{"class":1417},[198,14569,9946],{"class":1383},[198,14571,14572],{"class":200,"line":1104},[198,14573,1613],{"class":1383},[198,14575,14576],{"class":200,"line":1110},[198,14577,217],{"emptyLinePlaceholder":216},[198,14579,14580,14582,14584],{"class":200,"line":1116},[198,14581,5460],{"class":1956},[198,14583,12635],{"class":1960},[198,14585,1964],{"class":1383},[198,14587,14588,14590,14592,14594,14596,14598],{"class":200,"line":1122},[198,14589,10844],{"class":1387},[198,14591,2998],{"class":1383},[198,14593,7541],{"class":1960},[198,14595,1384],{"class":1383},[198,14597,7294],{"class":1960},[198,14599,12664],{"class":1383},[198,14601,14602,14604,14606,14608],{"class":200,"line":1128},[198,14603,10861],{"class":1387},[198,14605,2998],{"class":1383},[198,14607,12674],{"class":1960},[198,14609,1757],{"class":1383},[198,14611,14612],{"class":200,"line":1134},[198,14613,217],{"emptyLinePlaceholder":216},[198,14615,14616,14618,14620,14622,14624,14626],{"class":200,"line":1140},[198,14617,11266],{"class":1387},[198,14619,2998],{"class":1383},[198,14621,7541],{"class":1960},[198,14623,1384],{"class":1383},[198,14625,12308],{"class":1960},[198,14627,12664],{"class":1383},[198,14629,14630,14632,14634,14636],{"class":200,"line":1146},[198,14631,11300],{"class":1387},[198,14633,2998],{"class":1383},[198,14635,12308],{"class":1960},[198,14637,1757],{"class":1383},[198,14639,14640],{"class":200,"line":1151},[198,14641,1613],{"class":1383},[198,14643,14644],{"class":200,"line":1157},[198,14645,217],{"emptyLinePlaceholder":216},[198,14647,14648,14650,14652,14654,14656,14658,14660,14662,14664,14666],{"class":200,"line":1163},[198,14649,6725],{"class":1956},[198,14651,12721],{"class":2202},[198,14653,2206],{"class":1383},[198,14655,12726],{"class":1387},[198,14657,7286],{"class":1383},[198,14659,6847],{"class":1956},[198,14661,12733],{"class":1960},[198,14663,7597],{"class":1383},[198,14665,8875],{"class":1960},[198,14667,1964],{"class":1383},[198,14669,14670,14673,14675,14677],{"class":200,"line":1169},[198,14671,14672],{"class":1387},"  rng",[198,14674,41],{"class":1383},[198,14676,12749],{"class":2202},[198,14678,9519],{"class":1383},[198,14680,14681],{"class":200,"line":1175},[198,14682,1613],{"class":1383},[198,14684,14685],{"class":200,"line":1181},[198,14686,217],{"emptyLinePlaceholder":216},[198,14688,14689,14691,14693,14695,14697,14699,14701,14703,14705,14707,14709,14711,14713,14715,14717,14719],{"class":200,"line":1187},[198,14690,6725],{"class":1956},[198,14692,12766],{"class":2202},[198,14694,2206],{"class":1383},[198,14696,12726],{"class":1387},[198,14698,7286],{"class":1383},[198,14700,6847],{"class":1956},[198,14702,12733],{"class":1960},[198,14704,2764],{"class":1383},[198,14706,10646],{"class":1387},[198,14708,2998],{"class":1383},[198,14710,7310],{"class":1960},[198,14712,7597],{"class":1383},[198,14714,7541],{"class":1960},[198,14716,1384],{"class":1383},[198,14718,7294],{"class":1960},[198,14720,7263],{"class":1383},[198,14722,14723,14726,14728,14730,14732,14734,14736,14738,14740,14742,14744,14746,14748,14750,14752],{"class":200,"line":1193},[198,14724,14725],{"class":1956},"  let",[198,14727,6792],{"class":1956},[198,14729,12803],{"class":1387},[198,14731,2998],{"class":1383},[198,14733,7541],{"class":1960},[198,14735,1384],{"class":1383},[198,14737,7294],{"class":1960},[198,14739,7249],{"class":1383},[198,14741,1421],{"class":2220},[198,14743,6825],{"class":1960},[198,14745,5252],{"class":1383},[198,14747,12822],{"class":2202},[198,14749,2206],{"class":1383},[198,14751,10646],{"class":1387},[198,14753,2280],{"class":1383},[198,14755,14756,14758,14760,14762,14764,14766,14768],{"class":200,"line":1199},[198,14757,10675],{"class":1956},[198,14759,12836],{"class":1387},[198,14761,12839],{"class":1956},[198,14763,6021],{"class":1417},[198,14765,12844],{"class":1383},[198,14767,10646],{"class":1387},[198,14769,1964],{"class":1383},[198,14771,14772,14775,14777,14779,14781,14783,14785,14787],{"class":200,"line":1205},[198,14773,14774],{"class":1387},"    vect",[198,14776,41],{"class":1383},[198,14778,12858],{"class":2202},[198,14780,2206],{"class":1383},[198,14782,12726],{"class":1387},[198,14784,41],{"class":1383},[198,14786,12749],{"class":1956},[198,14788,5414],{"class":1383},[198,14790,14791],{"class":200,"line":1211},[198,14792,5394],{"class":1383},[198,14794,14795],{"class":200,"line":1217},[198,14796,14797],{"class":1387},"  vect\n",[198,14799,14800],{"class":200,"line":1223},[198,14801,1613],{"class":1383},[198,14803,14804],{"class":200,"line":1228},[198,14805,217],{"emptyLinePlaceholder":216},[198,14807,14808,14810,14812,14814,14816,14818,14820,14822,14824,14826],{"class":200,"line":1233},[198,14809,6725],{"class":1956},[198,14811,12892],{"class":2202},[198,14813,2206],{"class":1383},[198,14815,12726],{"class":1387},[198,14817,7286],{"class":1383},[198,14819,6847],{"class":1956},[198,14821,12733],{"class":1960},[198,14823,7597],{"class":1383},[198,14825,12308],{"class":1960},[198,14827,1964],{"class":1383},[198,14829,14830,14832,14834,14836,14838,14840,14842,14844,14846,14848,14850,14852],{"class":200,"line":1238},[198,14831,14725],{"class":1956},[198,14833,6792],{"class":1956},[198,14835,12917],{"class":1387},[198,14837,2221],{"class":2220},[198,14839,12587],{"class":1960},[198,14841,10386],{"class":1383},[198,14843,12926],{"class":1387},[198,14845,8929],{"class":1383},[198,14847,5912],{"class":1417},[198,14849,8934],{"class":1383},[198,14851,11275],{"class":1417},[198,14853,12937],{"class":1383},[198,14855,14856,14858,14860,14862,14864,14866,14868],{"class":200,"line":1244},[198,14857,10675],{"class":1956},[198,14859,10683],{"class":1387},[198,14861,12839],{"class":1956},[198,14863,6021],{"class":1417},[198,14865,12844],{"class":1383},[198,14867,11275],{"class":1417},[198,14869,1964],{"class":1383},[198,14871,14872,14874,14876,14878,14880,14882,14884,14886,14888],{"class":200,"line":1250},[198,14873,12700],{"class":1387},[198,14875,12961],{"class":1383},[198,14877,10692],{"class":1387},[198,14879,6945],{"class":1383},[198,14881,1421],{"class":2220},[198,14883,12970],{"class":1387},[198,14885,41],{"class":1383},[198,14887,12749],{"class":2202},[198,14889,2244],{"class":1383},[198,14891,14892],{"class":200,"line":11396},[198,14893,5394],{"class":1383},[198,14895,14896],{"class":200,"line":11402},[198,14897,14898],{"class":1387},"  sha256\n",[198,14900,14901],{"class":200,"line":11408},[198,14902,1613],{"class":1383},[198,14904,14905],{"class":200,"line":11423},[198,14906,217],{"emptyLinePlaceholder":216},[198,14908,14909,14911,14913,14916],{"class":200,"line":11445},[198,14910,8151],{"class":1956},[198,14912,8154],{"class":1956},[198,14914,14915],{"class":1960}," TestObjectWrapper",[198,14917,1964],{"class":1383},[198,14919,14920,14923,14925,14927,14929,14931],{"class":200,"line":11477},[198,14921,14922],{"class":1387},"  test_objects",[198,14924,2998],{"class":1383},[198,14926,7541],{"class":1960},[198,14928,1384],{"class":1383},[198,14930,13178],{"class":1960},[198,14932,12664],{"class":1383},[198,14934,14935],{"class":200,"line":11495},[198,14936,1613],{"class":1383},[198,14938,14939],{"class":200,"line":11500},[198,14940,217],{"emptyLinePlaceholder":216},[198,14942,14943,14946,14948,14951],{"class":200,"line":11505},[198,14944,14945],{"class":1383},"#[napi(js_name ",[198,14947,1421],{"class":2220},[198,14949,14950],{"class":1424}," \"TestObjectWrapper\"",[198,14952,12422],{"class":1383},[198,14954,14955,14957,14959,14962],{"class":200,"line":11511},[198,14956,8151],{"class":1956},[198,14958,8154],{"class":1956},[198,14960,14961],{"class":1960}," JsTestObjectWrapper",[198,14963,1964],{"class":1383},[198,14965,14966,14969,14971,14974],{"class":200,"line":11544},[198,14967,14968],{"class":1387},"  test_object_wrapper",[198,14970,2998],{"class":1383},[198,14972,14973],{"class":1960},"TestObjectWrapper",[198,14975,1757],{"class":1383},[198,14977,14978],{"class":200,"line":11550},[198,14979,1613],{"class":1383},[198,14981,14982],{"class":200,"line":11561},[198,14983,217],{"emptyLinePlaceholder":216},[198,14985,14986],{"class":200,"line":11567},[198,14987,14988],{"class":1383},"#[napi]\n",[198,14990,14991,14993,14995],{"class":200,"line":11589},[198,14992,7236],{"class":1956},[198,14994,14961],{"class":1960},[198,14996,1964],{"class":1383},[198,14998,14999],{"class":200,"line":11594},[198,15000,15001],{"class":1383},"  #[napi(constructor)]\n",[198,15003,15004,15007,15009,15011,15014,15016],{"class":200,"line":11629},[198,15005,15006],{"class":1956},"  pub",[198,15008,9316],{"class":1956},[198,15010,2341],{"class":2202},[198,15012,15013],{"class":1383},"() -> ",[198,15015,7600],{"class":1960},[198,15017,1964],{"class":1383},[198,15019,15020,15023],{"class":200,"line":11668},[198,15021,15022],{"class":1960},"    Self",[198,15024,1964],{"class":1383},[198,15026,15027,15030,15032,15034],{"class":200,"line":11673},[198,15028,15029],{"class":1387},"      test_object_wrapper",[198,15031,2998],{"class":1383},[198,15033,14973],{"class":1960},[198,15035,1964],{"class":1383},[198,15037,15038,15040,15042,15044,15046,15048],{"class":200,"line":11679},[198,15039,13216],{"class":1387},[198,15041,2998],{"class":1383},[198,15043,7541],{"class":1960},[198,15045,5252],{"class":1383},[198,15047,6778],{"class":2202},[198,15049,10983],{"class":1383},[198,15051,15052],{"class":200,"line":11685},[198,15053,487],{"class":1383},[198,15055,15056],{"class":200,"line":11703},[198,15057,2447],{"class":1383},[198,15059,15060],{"class":200,"line":11708},[198,15061,5394],{"class":1383},[198,15063,15064],{"class":200,"line":11714},[198,15065,217],{"emptyLinePlaceholder":216},[198,15067,15068],{"class":200,"line":11722},[198,15069,15070],{"class":1383},"  #[napi]\n",[198,15072,15073,15075,15077,15080,15082,15084,15086,15088,15090,15092,15095],{"class":200,"line":11740},[198,15074,15006],{"class":1956},[198,15076,9316],{"class":1956},[198,15078,15079],{"class":2202}," fill",[198,15081,6844],{"class":1383},[198,15083,6847],{"class":1956},[198,15085,7278],{"class":1960},[198,15087,2764],{"class":1383},[198,15089,13193],{"class":1387},[198,15091,2998],{"class":1383},[198,15093,15094],{"class":1960},"i32",[198,15096,2212],{"class":1383},[198,15098,15099,15101,15103,15105,15107,15109,15111,15113],{"class":200,"line":11755},[198,15100,6736],{"class":1956},[198,15102,6792],{"class":1956},[198,15104,12970],{"class":1387},[198,15106,2221],{"class":2220},[198,15108,12345],{"class":1960},[198,15110,5252],{"class":1383},[198,15112,13036],{"class":2202},[198,15114,2244],{"class":1383},[198,15116,15117],{"class":200,"line":11760},[198,15118,13043],{"class":1930},[198,15120,15121,15123,15125,15127,15129,15131,15133,15135,15137],{"class":200,"line":11783},[198,15122,6736],{"class":1956},[198,15124,13050],{"class":1387},[198,15126,2221],{"class":2220},[198,15128,13055],{"class":1960},[198,15130,5252],{"class":1383},[198,15132,13060],{"class":2202},[198,15134,8010],{"class":1383},[198,15136,6759],{"class":2202},[198,15138,2244],{"class":1383},[198,15140,15141],{"class":200,"line":11788},[198,15142,13071],{"class":1930},[198,15144,15145,15147,15149,15151,15153,15155,15157,15159,15161,15163,15165],{"class":200,"line":11794},[198,15146,6736],{"class":1956},[198,15148,13078],{"class":1387},[198,15150,2221],{"class":2220},[198,15152,6704],{"class":1960},[198,15154,5252],{"class":1383},[198,15156,13087],{"class":1960},[198,15158,5252],{"class":1383},[198,15160,13092],{"class":1960},[198,15162,5252],{"class":1383},[198,15164,11387],{"class":2202},[198,15166,9519],{"class":1383},[198,15168,15169,15172,15174,15176,15178,15180,15182,15184,15186],{"class":200,"line":11817},[198,15170,15171],{"class":1383},"      .",[198,15173,13106],{"class":2202},[198,15175,2206],{"class":1383},[198,15177,9607],{"class":1960},[198,15179,5252],{"class":1383},[198,15181,13087],{"class":1960},[198,15183,5252],{"class":1383},[198,15185,13119],{"class":1417},[198,15187,2845],{"class":1383},[198,15189,15190,15192,15194],{"class":200,"line":11848},[198,15191,15171],{"class":1383},[198,15193,6759],{"class":2202},[198,15195,9519],{"class":1383},[198,15197,15198,15200,15202],{"class":200,"line":11854},[198,15199,15171],{"class":1383},[198,15201,13136],{"class":2202},[198,15203,2244],{"class":1383},[198,15205,15206],{"class":200,"line":11877},[198,15207,217],{"emptyLinePlaceholder":216},[198,15209,15210,15213,15216,15218,15220,15222,15224,15226,15228,15230,15233,15235,15237],{"class":200,"line":11910},[198,15211,15212],{"class":1960},"    self",[198,15214,15215],{"class":1383},".test_object_wrapper.test_objects ",[198,15217,1421],{"class":2220},[198,15219,6825],{"class":1960},[198,15221,5252],{"class":1383},[198,15223,12822],{"class":2202},[198,15225,2206],{"class":1383},[198,15227,13193],{"class":1387},[198,15229,41],{"class":1383},[198,15231,15232],{"class":2202},"try_into",[198,15234,8010],{"class":1383},[198,15236,6759],{"class":2202},[198,15238,5414],{"class":1383},[198,15240,15241],{"class":200,"line":11921},[198,15242,217],{"emptyLinePlaceholder":216},[198,15244,15245,15247,15249,15251,15253,15255,15257],{"class":200,"line":11929},[198,15246,12833],{"class":1956},[198,15248,12836],{"class":1387},[198,15250,12839],{"class":1956},[198,15252,6021],{"class":1417},[198,15254,12844],{"class":1383},[198,15256,13193],{"class":1387},[198,15258,1964],{"class":1383},[198,15260,15261,15264,15267,15269,15271,15273],{"class":200,"line":11954},[198,15262,15263],{"class":1960},"      self",[198,15265,15266],{"class":1383},".test_object_wrapper.test_objects.",[198,15268,12858],{"class":2202},[198,15270,2206],{"class":1383},[198,15272,13178],{"class":1960},[198,15274,1964],{"class":1383},[198,15276,15277,15280,15282,15284,15286,15288,15290,15292,15294],{"class":200,"line":11960},[198,15278,15279],{"class":1387},"        path",[198,15281,2998],{"class":1383},[198,15283,13236],{"class":2202},[198,15285,6844],{"class":1383},[198,15287,6847],{"class":1956},[198,15289,12970],{"class":1387},[198,15291,2764],{"class":1383},[198,15293,10854],{"class":1417},[198,15295,9915],{"class":1383},[198,15297,15298,15301,15303,15305],{"class":200,"line":11965},[198,15299,15300],{"class":1387},"        stats",[198,15302,2998],{"class":1383},[198,15304,12674],{"class":1960},[198,15306,1964],{"class":1383},[198,15308,15309,15312,15314,15316,15318,15320,15322],{"class":200,"line":11970},[198,15310,15311],{"class":1387},"          owner_id",[198,15313,2998],{"class":1383},[198,15315,13269],{"class":2202},[198,15317,6844],{"class":1383},[198,15319,6847],{"class":1956},[198,15321,12970],{"class":1387},[198,15323,9915],{"class":1383},[198,15325,15326,15329,15331,15333,15335,15337,15339],{"class":200,"line":11988},[198,15327,15328],{"class":1387},"          group_id",[198,15330,2998],{"class":1383},[198,15332,13269],{"class":2202},[198,15334,6844],{"class":1383},[198,15336,6847],{"class":1956},[198,15338,12970],{"class":1387},[198,15340,9915],{"class":1383},[198,15342,15343,15346,15348,15350,15352,15354,15356],{"class":200,"line":12010},[198,15344,15345],{"class":1387},"          size",[198,15347,2998],{"class":1383},[198,15349,13269],{"class":2202},[198,15351,6844],{"class":1383},[198,15353,6847],{"class":1956},[198,15355,12970],{"class":1387},[198,15357,9915],{"class":1383},[198,15359,15360,15363,15365,15367,15369,15371,15373],{"class":200,"line":12015},[198,15361,15362],{"class":1387},"          compressed_size",[198,15364,2998],{"class":1383},[198,15366,13269],{"class":2202},[198,15368,6844],{"class":1383},[198,15370,6847],{"class":1956},[198,15372,12970],{"class":1387},[198,15374,9915],{"class":1383},[198,15376,15377,15380,15382,15384,15386,15388,15390],{"class":200,"line":13554},[198,15378,15379],{"class":1387},"          last_read",[198,15381,2998],{"class":1383},[198,15383,13269],{"class":2202},[198,15385,6844],{"class":1383},[198,15387,6847],{"class":1956},[198,15389,12970],{"class":1387},[198,15391,9915],{"class":1383},[198,15393,15394,15397,15399,15401,15403,15405,15407],{"class":200,"line":13559},[198,15395,15396],{"class":1387},"          last_modified",[198,15398,2998],{"class":1383},[198,15400,13269],{"class":2202},[198,15402,6844],{"class":1383},[198,15404,6847],{"class":1956},[198,15406,12970],{"class":1387},[198,15408,9915],{"class":1383},[198,15410,15411,15414,15416,15418,15420,15422,15424],{"class":200,"line":13585},[198,15412,15413],{"class":1387},"          created",[198,15415,2998],{"class":1383},[198,15417,13269],{"class":2202},[198,15419,6844],{"class":1383},[198,15421,6847],{"class":1956},[198,15423,12970],{"class":1387},[198,15425,9915],{"class":1383},[198,15427,15428,15431,15433,15435,15437,15439,15441],{"class":200,"line":13606},[198,15429,15430],{"class":1387},"          mode",[198,15432,2998],{"class":1383},[198,15434,13269],{"class":2202},[198,15436,6844],{"class":1383},[198,15438,6847],{"class":1956},[198,15440,12970],{"class":1387},[198,15442,9915],{"class":1383},[198,15444,15445,15448,15450,15452,15454,15456,15458],{"class":200,"line":13615},[198,15446,15447],{"class":1387},"          dev",[198,15449,2998],{"class":1383},[198,15451,13269],{"class":2202},[198,15453,6844],{"class":1383},[198,15455,6847],{"class":1956},[198,15457,12970],{"class":1387},[198,15459,9915],{"class":1383},[198,15461,15462,15465,15467,15469,15471,15473,15475],{"class":200,"line":13624},[198,15463,15464],{"class":1387},"          rdev",[198,15466,2998],{"class":1383},[198,15468,13269],{"class":2202},[198,15470,6844],{"class":1383},[198,15472,6847],{"class":1956},[198,15474,12970],{"class":1387},[198,15476,9915],{"class":1383},[198,15478,15479,15482,15484,15486,15488,15490,15492],{"class":200,"line":13630},[198,15480,15481],{"class":1387},"          ino",[198,15483,2998],{"class":1383},[198,15485,13269],{"class":2202},[198,15487,6844],{"class":1383},[198,15489,6847],{"class":1956},[198,15491,12970],{"class":1387},[198,15493,9915],{"class":1383},[198,15495,15496,15499,15501,15503,15505,15507,15509],{"class":200,"line":13652},[198,15497,15498],{"class":1387},"          nlink",[198,15500,2998],{"class":1383},[198,15502,13269],{"class":2202},[198,15504,6844],{"class":1383},[198,15506,6847],{"class":1956},[198,15508,12970],{"class":1387},[198,15510,9915],{"class":1383},[198,15512,15513],{"class":200,"line":13657},[198,15514,481],{"class":1383},[198,15516,15517,15520,15522,15524],{"class":200,"line":13662},[198,15518,15519],{"class":1387},"        chunks",[198,15521,2998],{"class":1383},[198,15523,13479],{"class":2202},[198,15525,13482],{"class":1383},[198,15527,15528,15531,15533,15535,15537],{"class":200,"line":13684},[198,15529,15530],{"class":2202},"          generate_random_sha256",[198,15532,6844],{"class":1383},[198,15534,6847],{"class":1956},[198,15536,12970],{"class":1387},[198,15538,9915],{"class":1383},[198,15540,15541,15543,15545,15547,15549],{"class":200,"line":13690},[198,15542,15530],{"class":2202},[198,15544,6844],{"class":1383},[198,15546,6847],{"class":1956},[198,15548,12970],{"class":1387},[198,15550,9915],{"class":1383},[198,15552,15553,15555,15557,15559,15561],{"class":200,"line":13697},[198,15554,15530],{"class":2202},[198,15556,6844],{"class":1383},[198,15558,6847],{"class":1956},[198,15560,12970],{"class":1387},[198,15562,9915],{"class":1383},[198,15564,15565],{"class":200,"line":13705},[198,15566,15567],{"class":1383},"        ],\n",[198,15569,15570,15572,15574,15576,15578,15580,15582],{"class":200,"line":13730},[198,15571,12958],{"class":1387},[198,15573,2998],{"class":1383},[198,15575,13534],{"class":2202},[198,15577,6844],{"class":1383},[198,15579,6847],{"class":1956},[198,15581,12970],{"class":1387},[198,15583,9915],{"class":1383},[198,15585,15586],{"class":200,"line":13736},[198,15587,15588],{"class":1383},"      });\n",[198,15590,15591],{"class":200,"line":13742},[198,15592,2447],{"class":1383},[198,15594,15595],{"class":200,"line":13749},[198,15596,217],{"emptyLinePlaceholder":216},[198,15598,15599,15601,15603,15605,15607,15609,15611,15613,15615,15617,15619],{"class":200,"line":13757},[198,15600,6736],{"class":1956},[198,15602,13564],{"class":1387},[198,15604,2221],{"class":2220},[198,15606,6704],{"class":1960},[198,15608,5252],{"class":1383},[198,15610,13087],{"class":1960},[198,15612,5252],{"class":1383},[198,15614,13092],{"class":1960},[198,15616,5252],{"class":1383},[198,15618,11387],{"class":2202},[198,15620,9519],{"class":1383},[198,15622,15623,15625,15627,15629,15631,15633,15635,15637,15639],{"class":200,"line":13782},[198,15624,15171],{"class":1383},[198,15626,13106],{"class":2202},[198,15628,2206],{"class":1383},[198,15630,9607],{"class":1960},[198,15632,5252],{"class":1383},[198,15634,13087],{"class":1960},[198,15636,5252],{"class":1383},[198,15638,13119],{"class":1417},[198,15640,2845],{"class":1383},[198,15642,15643,15645,15647],{"class":200,"line":13787},[198,15644,15171],{"class":1383},[198,15646,6759],{"class":2202},[198,15648,9519],{"class":1383},[198,15650,15651,15653,15655],{"class":200,"line":13792},[198,15652,15171],{"class":1383},[198,15654,13136],{"class":2202},[198,15656,2244],{"class":1383},[198,15658,15659],{"class":200,"line":13798},[198,15660,13627],{"class":1930},[198,15662,15663,15665,15667,15669,15671,15673,15675,15677],{"class":200,"line":13821},[198,15664,6860],{"class":2202},[198,15666,2206],{"class":1383},[198,15668,13637],{"class":1424},[198,15670,2764],{"class":1383},[198,15672,13642],{"class":1387},[198,15674,13645],{"class":1383},[198,15676,11387],{"class":1387},[198,15678,2280],{"class":1383},[198,15680,15681],{"class":200,"line":13834},[198,15682,217],{"emptyLinePlaceholder":216},[198,15684,15685],{"class":200,"line":13846},[198,15686,13043],{"class":1930},[198,15688,15689,15691,15693,15695,15697,15699,15701,15703,15705],{"class":200,"line":13851},[198,15690,6736],{"class":1956},[198,15692,13667],{"class":1387},[198,15694,2221],{"class":2220},[198,15696,13055],{"class":1960},[198,15698,5252],{"class":1383},[198,15700,13060],{"class":2202},[198,15702,8010],{"class":1383},[198,15704,6759],{"class":2202},[198,15706,2244],{"class":1383},[198,15708,15709],{"class":200,"line":13856},[198,15710,13687],{"class":1930},[198,15712,15713,15715],{"class":200,"line":13862},[198,15714,6860],{"class":2202},[198,15716,2775],{"class":1383},[198,15718,15719,15722],{"class":200,"line":13896},[198,15720,15721],{"class":1424},"      \"Memory consumption after creation: {}\"",[198,15723,1757],{"class":1383},[198,15725,15726,15729,15731,15733,15735,15737,15739,15741,15743,15745],{"class":200,"line":13922},[198,15727,15728],{"class":2202},"      format_size",[198,15730,11651],{"class":1383},[198,15732,13713],{"class":1387},[198,15734,13716],{"class":1383},[198,15736,13719],{"class":1387},[198,15738,13722],{"class":1383},[198,15740,13725],{"class":1417},[198,15742,2764],{"class":1383},[198,15744,12326],{"class":1417},[198,15746,2845],{"class":1383},[198,15748,15749],{"class":200,"line":13941},[198,15750,13733],{"class":1383},[198,15752,15753],{"class":200,"line":13969},[198,15754,13739],{"class":1930},[198,15756,15757,15759],{"class":200,"line":13974},[198,15758,6860],{"class":2202},[198,15760,2775],{"class":1383},[198,15762,15763,15766],{"class":200,"line":13979},[198,15764,15765],{"class":1424},"      \"Average memory consumption per object: {}\"",[198,15767,1757],{"class":1383},[198,15769,15770,15772],{"class":200,"line":13985},[198,15771,15728],{"class":2202},[198,15773,2775],{"class":1383},[198,15775,15776,15779,15781,15783,15785,15787,15789,15791,15793,15795,15798],{"class":200,"line":14011},[198,15777,15778],{"class":1383},"        ((",[198,15780,13713],{"class":1387},[198,15782,13716],{"class":1383},[198,15784,13719],{"class":1387},[198,15786,13722],{"class":1383},[198,15788,13725],{"class":1417},[198,15790,13775],{"class":1383},[198,15792,13193],{"class":1387},[198,15794,14201],{"class":1956},[198,15796,15797],{"class":1960}," usize",[198,15799,1757],{"class":1383},[198,15801,15802],{"class":200,"line":14032},[198,15803,15804],{"class":1417},"        DECIMAL\n",[198,15806,15807],{"class":200,"line":14041},[198,15808,15809],{"class":1383},"      )\n",[198,15811,15812],{"class":200,"line":14050},[198,15813,13733],{"class":1383},[198,15815,15816],{"class":200,"line":14055},[198,15817,5394],{"class":1383},[198,15819,15820],{"class":200,"line":14062},[198,15821,217],{"emptyLinePlaceholder":216},[198,15823,15824,15827,15829,15832],{"class":200,"line":14070},[198,15825,15826],{"class":1383},"  #[napi(js_name ",[198,15828,1421],{"class":2220},[198,15830,15831],{"class":1424}," \"toString\"",[198,15833,12422],{"class":1383},[198,15835,15836,15838,15840,15843,15845,15847,15849,15852],{"class":200,"line":14081},[198,15837,15006],{"class":1956},[198,15839,9316],{"class":1956},[198,15841,15842],{"class":2202}," to_string",[198,15844,6844],{"class":1383},[198,15846,8002],{"class":1960},[198,15848,7597],{"class":1383},[198,15850,15851],{"class":1960},"String",[198,15853,1964],{"class":1383},[198,15855,15856,15859],{"class":200,"line":14086},[198,15857,15858],{"class":2202},"    format!",[198,15860,2775],{"class":1383},[198,15862,15863,15866],{"class":200,"line":14091},[198,15864,15865],{"class":1424},"      \"TestObjectWrapper {{ test_objects: {} }}\"",[198,15867,1757],{"class":1383},[198,15869,15870,15872,15874,15876],{"class":200,"line":14097},[198,15871,15263],{"class":1960},[198,15873,15266],{"class":1383},[198,15875,7353],{"class":2202},[198,15877,9519],{"class":1383},[198,15879,15880],{"class":200,"line":14128},[198,15881,15882],{"class":1383},"    )\n",[198,15884,15885],{"class":200,"line":14135},[198,15886,5394],{"class":1383},[198,15888,15889],{"class":200,"line":14143},[198,15890,1613],{"class":1383},[11,15892,15893],{},"Pour la parte Node.JS :",[190,15895,15897],{"className":388,"code":15896,"language":390,"meta":59,"style":59},"const test = require(\".\u002Findex.js\");\nconst filesize = require(\"filesize.js\");\nconst fs = require(\"fs\");\nconst { serialize, deserialize } = require(\"v8\");\n\u002F\u002F Start by consuming memory with big object\n\n\u002F\u002F Run GC\nglobal.gc();\n\u002F\u002F Get memory consumption before\nconst memoryBefore = process.memoryUsage().heapUsed;\n\nconst time = Date.now();\n\n\u002F\u002F Create objects\nconst nbObjects = 1_300_000;\nconst testArray = new test.TestObjectWrapper();\ntestArray.fill(nbObjects);\n\n\u002F\u002F Bench creation\nconsole.log(\"Creation time: \", Date.now() - time);\n\n\u002F\u002F Run GC\n\u002F\u002F Get memory consumption after\nconst memoryAfter = process.memoryUsage().heapUsed;\n\n\u002F\u002F Print memory consumption\nconsole.log(\n  \"Memory consumption in JS: \",\n  filesize.default(memoryAfter - memoryBefore)\n);\n\nconsole.log(testArray.toString());\n",[165,15898,15899,15917,15933,15949,15973,15978,15982,15987,15997,16002,16022,16026,16042,16046,16051,16063,16081,16097,16101,16106,16134,16138,16142,16147,16167,16171,16176,16186,16193,16212,16216,16220],{"__ignoreMap":59},[198,15900,15901,15903,15906,15908,15910,15912,15915],{"class":200,"line":201},[198,15902,10558],{"class":1956},[198,15904,15905],{"class":1960}," test",[198,15907,2221],{"class":2220},[198,15909,10566],{"class":2202},[198,15911,2206],{"class":1383},[198,15913,15914],{"class":1424},"\".\u002Findex.js\"",[198,15916,2280],{"class":1383},[198,15918,15919,15921,15923,15925,15927,15929,15931],{"class":200,"line":207},[198,15920,10558],{"class":1956},[198,15922,10561],{"class":1960},[198,15924,2221],{"class":2220},[198,15926,10566],{"class":2202},[198,15928,2206],{"class":1383},[198,15930,10571],{"class":1424},[198,15932,2280],{"class":1383},[198,15934,15935,15937,15939,15941,15943,15945,15947],{"class":200,"line":213},[198,15936,10558],{"class":1956},[198,15938,10580],{"class":1960},[198,15940,2221],{"class":2220},[198,15942,10566],{"class":2202},[198,15944,2206],{"class":1383},[198,15946,10589],{"class":1424},[198,15948,2280],{"class":1383},[198,15950,15951,15953,15955,15957,15959,15961,15963,15965,15967,15969,15971],{"class":200,"line":220},[198,15952,10558],{"class":1956},[198,15954,10386],{"class":1383},[198,15956,10605],{"class":1960},[198,15958,2764],{"class":1383},[198,15960,10610],{"class":1960},[198,15962,10613],{"class":1383},[198,15964,1421],{"class":2220},[198,15966,10566],{"class":2202},[198,15968,2206],{"class":1383},[198,15970,10622],{"class":1424},[198,15972,2280],{"class":1383},[198,15974,15975],{"class":200,"line":254},[198,15976,15977],{"class":1930},"\u002F\u002F Start by consuming memory with big object\n",[198,15979,15980],{"class":200,"line":260},[198,15981,217],{"emptyLinePlaceholder":216},[198,15983,15984],{"class":200,"line":266},[198,15985,15986],{"class":1930},"\u002F\u002F Run GC\n",[198,15988,15989,15991,15993,15995],{"class":200,"line":272},[198,15990,11329],{"class":1960},[198,15992,41],{"class":1383},[198,15994,11334],{"class":2202},[198,15996,2244],{"class":1383},[198,15998,15999],{"class":200,"line":278},[198,16000,16001],{"class":1930},"\u002F\u002F Get memory consumption before\n",[198,16003,16004,16006,16008,16010,16012,16014,16016,16018,16020],{"class":200,"line":283},[198,16005,10558],{"class":1956},[198,16007,11348],{"class":1960},[198,16009,2221],{"class":2220},[198,16011,11353],{"class":1960},[198,16013,41],{"class":1383},[198,16015,11358],{"class":2202},[198,16017,8010],{"class":1383},[198,16019,11363],{"class":1387},[198,16021,2008],{"class":1383},[198,16023,16024],{"class":200,"line":288},[198,16025,217],{"emptyLinePlaceholder":216},[198,16027,16028,16030,16032,16034,16036,16038,16040],{"class":200,"line":450},[198,16029,10558],{"class":1956},[198,16031,11377],{"class":1960},[198,16033,2221],{"class":2220},[198,16035,11382],{"class":1960},[198,16037,41],{"class":1383},[198,16039,11387],{"class":2202},[198,16041,2244],{"class":1383},[198,16043,16044],{"class":200,"line":456},[198,16045,217],{"emptyLinePlaceholder":216},[198,16047,16048],{"class":200,"line":462},[198,16049,16050],{"class":1930},"\u002F\u002F Create objects\n",[198,16052,16053,16055,16057,16059,16061],{"class":200,"line":468},[198,16054,10558],{"class":1956},[198,16056,11413],{"class":1960},[198,16058,2221],{"class":2220},[198,16060,11418],{"class":1417},[198,16062,2008],{"class":1383},[198,16064,16065,16067,16069,16071,16073,16075,16077,16079],{"class":200,"line":473},[198,16066,10558],{"class":1956},[198,16068,11428],{"class":1960},[198,16070,2221],{"class":2220},[198,16072,2341],{"class":1956},[198,16074,15905],{"class":1960},[198,16076,41],{"class":1383},[198,16078,14973],{"class":2202},[198,16080,2244],{"class":1383},[198,16082,16083,16086,16088,16091,16093,16095],{"class":200,"line":478},[198,16084,16085],{"class":1960},"testArray",[198,16087,41],{"class":1383},[198,16089,16090],{"class":2202},"fill",[198,16092,2206],{"class":1383},[198,16094,11440],{"class":1387},[198,16096,2280],{"class":1383},[198,16098,16099],{"class":200,"line":484},[198,16100,217],{"emptyLinePlaceholder":216},[198,16102,16103],{"class":200,"line":490},[198,16104,16105],{"class":1930},"\u002F\u002F Bench creation\n",[198,16107,16108,16110,16112,16114,16116,16118,16120,16122,16124,16126,16128,16130,16132],{"class":200,"line":1068},[198,16109,11514],{"class":1960},[198,16111,41],{"class":1383},[198,16113,11519],{"class":2202},[198,16115,2206],{"class":1383},[198,16117,11524],{"class":1424},[198,16119,2764],{"class":1383},[198,16121,11529],{"class":1960},[198,16123,41],{"class":1383},[198,16125,11387],{"class":2202},[198,16127,2484],{"class":1383},[198,16129,6053],{"class":2220},[198,16131,11377],{"class":1387},[198,16133,2280],{"class":1383},[198,16135,16136],{"class":200,"line":1074},[198,16137,217],{"emptyLinePlaceholder":216},[198,16139,16140],{"class":200,"line":1080},[198,16141,15986],{"class":1930},[198,16143,16144],{"class":200,"line":1086},[198,16145,16146],{"class":1930},"\u002F\u002F Get memory consumption after\n",[198,16148,16149,16151,16153,16155,16157,16159,16161,16163,16165],{"class":200,"line":1092},[198,16150,10558],{"class":1956},[198,16152,11572],{"class":1960},[198,16154,2221],{"class":2220},[198,16156,11353],{"class":1960},[198,16158,41],{"class":1383},[198,16160,11358],{"class":2202},[198,16162,8010],{"class":1383},[198,16164,11363],{"class":1387},[198,16166,2008],{"class":1383},[198,16168,16169],{"class":200,"line":1098},[198,16170,217],{"emptyLinePlaceholder":216},[198,16172,16173],{"class":200,"line":1104},[198,16174,16175],{"class":1930},"\u002F\u002F Print memory consumption\n",[198,16177,16178,16180,16182,16184],{"class":200,"line":1110},[198,16179,11514],{"class":1960},[198,16181,41],{"class":1383},[198,16183,11519],{"class":2202},[198,16185,2775],{"class":1383},[198,16187,16188,16191],{"class":200,"line":1116},[198,16189,16190],{"class":1424},"  \"Memory consumption in JS: \"",[198,16192,1757],{"class":1383},[198,16194,16195,16198,16200,16202,16204,16206,16208,16210],{"class":200,"line":1122},[198,16196,16197],{"class":1960},"  filesize",[198,16199,41],{"class":1383},[198,16201,11615],{"class":2202},[198,16203,2206],{"class":1383},[198,16205,11620],{"class":1387},[198,16207,5111],{"class":2220},[198,16209,11348],{"class":1387},[198,16211,2845],{"class":1383},[198,16213,16214],{"class":200,"line":1128},[198,16215,2280],{"class":1383},[198,16217,16218],{"class":200,"line":1134},[198,16219,217],{"emptyLinePlaceholder":216},[198,16221,16222,16224,16226,16228,16230,16232,16234,16237],{"class":200,"line":1140},[198,16223,11514],{"class":1960},[198,16225,41],{"class":1383},[198,16227,11519],{"class":2202},[198,16229,2206],{"class":1383},[198,16231,16085],{"class":1960},[198,16233,41],{"class":1383},[198,16235,16236],{"class":2202},"toString",[198,16238,5414],{"class":1383},[11,16240,16241],{},"Voici le résultat:",[6106,16243,16244,16252],{},[6109,16245,16246],{},[6112,16247,16248,16250],{},[6115,16249],{},[6115,16251],{},[6128,16253,16254,16260,16266,16273],{},[6112,16255,16256,16258],{},[6133,16257,12047],{},[6133,16259,12050],{},[6112,16261,16262,16264],{},[6133,16263,12055],{},[6133,16265,14268],{},[6112,16267,16268,16270],{},[6133,16269,12063],{},[6133,16271,16272],{},"520,31 Mo",[6112,16274,16275,16277],{},[6133,16276,12071],{},[6133,16278,16279],{},"400 octets",[11,16281,16282],{},"Parfait, le module écrit en Rust va nous permettre de réduire la consommation mémoire de notre application et améliorer\nses performances.",[72,16284,16286,16289],{"id":16285},"conclusion-wasm",[16287,16288,1620],"del",{}," - Wasm",[11,16291,16292],{},"Une alternative possible à l'écriture d'un module natif en Rust est l'utilisation de WebAssembly. WebAssembly est un\nlangage de bas niveau qui permet d'écrire des modules qui seront exécutés dans un environnement sécurisé. Il est\npossible d'écrire des modules en Rust qui seront compilés en WebAssembly.",[11,16294,16295,16296,41],{},"Pour compiler notre module en WebAssembly, nous allons utiliser le compilateur ",[15,16297,16300],{"href":16298,"rel":16299},"https:\u002F\u002Frustwasm.github.io\u002Fwasm-pack\u002F",[24],"wasm-pack",[11,16302,16303],{},"La partie Rust du module n'est pas très différente de la version native. La seule différence est que nous devons\nutiliser le crate wasm-bindgen pour pouvoir utiliser notre module dans Node.JS.",[11,16305,16306,16307,16311],{},"Là encore, la documentation est très bien faite (",[15,16308,16309],{"href":16309,"rel":16310},"https:\u002F\u002Frustwasm.github.io\u002Fdocs\u002Fbook\u002F",[24],"). Je ne vais pas détailler ici\nla création de ce module.",[190,16313,16315],{"className":6673,"code":16314,"language":6675,"meta":59,"style":59},"mod utils;\n\nuse rand::{rngs::ThreadRng, Rng};\n\nuse wasm_bindgen::prelude::*;\n\n\u002F\u002F When the `wee_alloc` feature is enabled, use `wee_alloc` as the global\n\u002F\u002F allocator.\n#[cfg(feature = \"wee_alloc\")]\n#[global_allocator]\nstatic ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;\n\n#[wasm_bindgen]\nstruct Stats {\n    owner_id: u64,\n    group_id: u64,\n    size: u64,\n    compressed_size: u64,\n    last_read: u64,\n    last_modified: u64,\n    created: u64,\n    mode: u64,\n    dev: u64,\n    rdev: u64,\n    ino: u64,\n    nlink: u64,\n}\n\n#[wasm_bindgen]\nstruct Sha256 {\n    data: [u8; 32],\n}\n\n#[wasm_bindgen]\nstruct TestObject {\n    path: Vec\u003Cu8>,\n    stats: Stats,\n\n    chunks: Vec\u003CSha256>,\n    sha256: Sha256,\n}\n\nfn generate_random_number(rng: &mut ThreadRng) -> u64 {\n    rng.gen()\n}\n\nfn generate_random_vect(rng: &mut ThreadRng, size: usize) -> Vec\u003Cu8> {\n    let mut vect: Vec\u003Cu8> = Vec::with_capacity(size);\n    for _ in 0..size {\n        vect.push(rng.gen());\n    }\n    vect\n}\n\nfn generate_random_sha256(rng: &mut ThreadRng) -> Sha256 {\n    let mut sha256 = Sha256 { data: [0; 32] };\n    for i in 0..32 {\n        sha256.data[i] = rng.gen();\n    }\n    sha256\n}\n\n#[wasm_bindgen]\npub struct TestObjectWrapper {\n    test_objects: Vec\u003CTestObject>,\n}\n\n#[wasm_bindgen]\nimpl TestObjectWrapper {\n    #[wasm_bindgen(constructor)]\n    pub fn new() -> Self {\n        Self {\n            test_objects: Vec::new(),\n        }\n    }\n\n    #[wasm_bindgen]\n    pub fn fill(&mut self, nb_object: i32) {\n        let mut rng = rand::thread_rng();\n        \u002F\u002F Get the current time in ms\n        self.test_objects = Vec::with_capacity(nb_object as usize);\n\n        for _ in 0..nb_object {\n            self.test_objects.push(TestObject {\n                path: generate_random_vect(&mut rng, 100),\n                stats: Stats {\n                    owner_id: generate_random_number(&mut rng),\n                    group_id: generate_random_number(&mut rng),\n                    size: generate_random_number(&mut rng),\n                    compressed_size: generate_random_number(&mut rng),\n                    last_read: generate_random_number(&mut rng),\n                    last_modified: generate_random_number(&mut rng),\n                    created: generate_random_number(&mut rng),\n                    mode: generate_random_number(&mut rng),\n                    dev: generate_random_number(&mut rng),\n                    rdev: generate_random_number(&mut rng),\n                    ino: generate_random_number(&mut rng),\n                    nlink: generate_random_number(&mut rng),\n                },\n                chunks: vec![\n                    generate_random_sha256(&mut rng),\n                    generate_random_sha256(&mut rng),\n                    generate_random_sha256(&mut rng),\n                ],\n                sha256: generate_random_sha256(&mut rng),\n            });\n        }\n    }\n\n    #[wasm_bindgen(js_name = toString)]\n    pub fn to_string(&self) -> String {\n        format!(\n            \"TestObjectWrapper {{ test_objects: {} }}\",\n            self.test_objects.len()\n        )\n    }\n}\n",[165,16316,16317,16325,16329,16349,16353,16368,16372,16377,16382,16394,16399,16432,16436,16441,16449,16459,16469,16479,16489,16499,16509,16519,16529,16539,16549,16559,16569,16573,16577,16581,16589,16603,16607,16611,16615,16623,16637,16647,16651,16665,16675,16679,16683,16705,16715,16719,16723,16757,16789,16805,16823,16827,16831,16835,16839,16861,16887,16903,16923,16927,16931,16935,16939,16943,16953,16968,16972,16976,16980,16988,16993,17008,17014,17029,17033,17037,17041,17046,17070,17088,17093,17118,17122,17139,17154,17175,17186,17203,17220,17237,17254,17271,17288,17305,17322,17339,17356,17373,17390,17395,17406,17419,17431,17443,17448,17465,17469,17473,17477,17481,17491,17509,17516,17523,17533,17538,17542],{"__ignoreMap":59},[198,16318,16319,16322],{"class":200,"line":201},[198,16320,16321],{"class":1956},"mod",[198,16323,16324],{"class":1383}," utils;\n",[198,16326,16327],{"class":200,"line":207},[198,16328,217],{"emptyLinePlaceholder":216},[198,16330,16331,16333,16335,16337,16339,16341,16343,16345,16347],{"class":200,"line":213},[198,16332,6682],{"class":1956},[198,16334,12345],{"class":1960},[198,16336,12348],{"class":1383},[198,16338,12351],{"class":1960},[198,16340,5252],{"class":1383},[198,16342,12356],{"class":1960},[198,16344,2764],{"class":1383},[198,16346,12361],{"class":1960},[198,16348,929],{"class":1383},[198,16350,16351],{"class":200,"line":220},[198,16352,217],{"emptyLinePlaceholder":216},[198,16354,16355,16357,16360,16362,16365],{"class":200,"line":254},[198,16356,6682],{"class":1956},[198,16358,16359],{"class":1960}," wasm_bindgen",[198,16361,5252],{"class":1383},[198,16363,16364],{"class":1960},"prelude",[198,16366,16367],{"class":1383},"::*;\n",[198,16369,16370],{"class":200,"line":260},[198,16371,217],{"emptyLinePlaceholder":216},[198,16373,16374],{"class":200,"line":266},[198,16375,16376],{"class":1930},"\u002F\u002F When the `wee_alloc` feature is enabled, use `wee_alloc` as the global\n",[198,16378,16379],{"class":200,"line":272},[198,16380,16381],{"class":1930},"\u002F\u002F allocator.\n",[198,16383,16384,16387,16389,16392],{"class":200,"line":278},[198,16385,16386],{"class":1383},"#[cfg(feature ",[198,16388,1421],{"class":2220},[198,16390,16391],{"class":1424}," \"wee_alloc\"",[198,16393,12422],{"class":1383},[198,16395,16396],{"class":200,"line":283},[198,16397,16398],{"class":1383},"#[global_allocator]\n",[198,16400,16401,16403,16406,16408,16411,16413,16416,16418,16421,16423,16425,16427,16430],{"class":200,"line":288},[198,16402,10438],{"class":1956},[198,16404,16405],{"class":1417}," ALLOC",[198,16407,2998],{"class":1383},[198,16409,16410],{"class":1960},"wee_alloc",[198,16412,5252],{"class":1383},[198,16414,16415],{"class":1960},"WeeAlloc",[198,16417,2221],{"class":2220},[198,16419,16420],{"class":1960}," wee_alloc",[198,16422,5252],{"class":1383},[198,16424,16415],{"class":1960},[198,16426,5252],{"class":1383},[198,16428,16429],{"class":1417},"INIT",[198,16431,2008],{"class":1383},[198,16433,16434],{"class":200,"line":450},[198,16435,217],{"emptyLinePlaceholder":216},[198,16437,16438],{"class":200,"line":456},[198,16439,16440],{"class":1383},"#[wasm_bindgen]\n",[198,16442,16443,16445,16447],{"class":200,"line":462},[198,16444,5460],{"class":1956},[198,16446,12429],{"class":1960},[198,16448,1964],{"class":1383},[198,16450,16451,16453,16455,16457],{"class":200,"line":468},[198,16452,12436],{"class":1387},[198,16454,2998],{"class":1383},[198,16456,8875],{"class":1960},[198,16458,1757],{"class":1383},[198,16460,16461,16463,16465,16467],{"class":200,"line":473},[198,16462,12447],{"class":1387},[198,16464,2998],{"class":1383},[198,16466,8875],{"class":1960},[198,16468,1757],{"class":1383},[198,16470,16471,16473,16475,16477],{"class":200,"line":478},[198,16472,10938],{"class":1387},[198,16474,2998],{"class":1383},[198,16476,8875],{"class":1960},[198,16478,1757],{"class":1383},[198,16480,16481,16483,16485,16487],{"class":200,"line":484},[198,16482,12468],{"class":1387},[198,16484,2998],{"class":1383},[198,16486,8875],{"class":1960},[198,16488,1757],{"class":1383},[198,16490,16491,16493,16495,16497],{"class":200,"line":490},[198,16492,12479],{"class":1387},[198,16494,2998],{"class":1383},[198,16496,8875],{"class":1960},[198,16498,1757],{"class":1383},[198,16500,16501,16503,16505,16507],{"class":200,"line":1068},[198,16502,12490],{"class":1387},[198,16504,2998],{"class":1383},[198,16506,8875],{"class":1960},[198,16508,1757],{"class":1383},[198,16510,16511,16513,16515,16517],{"class":200,"line":1074},[198,16512,11076],{"class":1387},[198,16514,2998],{"class":1383},[198,16516,8875],{"class":1960},[198,16518,1757],{"class":1383},[198,16520,16521,16523,16525,16527],{"class":200,"line":1080},[198,16522,11107],{"class":1387},[198,16524,2998],{"class":1383},[198,16526,8875],{"class":1960},[198,16528,1757],{"class":1383},[198,16530,16531,16533,16535,16537],{"class":200,"line":1086},[198,16532,11138],{"class":1387},[198,16534,2998],{"class":1383},[198,16536,8875],{"class":1960},[198,16538,1757],{"class":1383},[198,16540,16541,16543,16545,16547],{"class":200,"line":1092},[198,16542,11169],{"class":1387},[198,16544,2998],{"class":1383},[198,16546,8875],{"class":1960},[198,16548,1757],{"class":1383},[198,16550,16551,16553,16555,16557],{"class":200,"line":1098},[198,16552,11200],{"class":1387},[198,16554,2998],{"class":1383},[198,16556,8875],{"class":1960},[198,16558,1757],{"class":1383},[198,16560,16561,16563,16565,16567],{"class":200,"line":1104},[198,16562,11231],{"class":1387},[198,16564,2998],{"class":1383},[198,16566,8875],{"class":1960},[198,16568,1757],{"class":1383},[198,16570,16571],{"class":200,"line":1110},[198,16572,1613],{"class":1383},[198,16574,16575],{"class":200,"line":1116},[198,16576,217],{"emptyLinePlaceholder":216},[198,16578,16579],{"class":200,"line":1122},[198,16580,16440],{"class":1383},[198,16582,16583,16585,16587],{"class":200,"line":1128},[198,16584,5460],{"class":1956},[198,16586,12587],{"class":1960},[198,16588,1964],{"class":1383},[198,16590,16591,16593,16595,16597,16599,16601],{"class":200,"line":1134},[198,16592,12594],{"class":1387},[198,16594,8929],{"class":1383},[198,16596,7294],{"class":1960},[198,16598,8934],{"class":1383},[198,16600,11275],{"class":1417},[198,16602,9946],{"class":1383},[198,16604,16605],{"class":200,"line":1140},[198,16606,1613],{"class":1383},[198,16608,16609],{"class":200,"line":1146},[198,16610,217],{"emptyLinePlaceholder":216},[198,16612,16613],{"class":200,"line":1151},[198,16614,16440],{"class":1383},[198,16616,16617,16619,16621],{"class":200,"line":1157},[198,16618,5460],{"class":1956},[198,16620,12635],{"class":1960},[198,16622,1964],{"class":1383},[198,16624,16625,16627,16629,16631,16633,16635],{"class":200,"line":1163},[198,16626,10329],{"class":1387},[198,16628,2998],{"class":1383},[198,16630,7541],{"class":1960},[198,16632,1384],{"class":1383},[198,16634,7294],{"class":1960},[198,16636,12664],{"class":1383},[198,16638,16639,16641,16643,16645],{"class":200,"line":1169},[198,16640,12669],{"class":1387},[198,16642,2998],{"class":1383},[198,16644,12674],{"class":1960},[198,16646,1757],{"class":1383},[198,16648,16649],{"class":200,"line":1175},[198,16650,217],{"emptyLinePlaceholder":216},[198,16652,16653,16655,16657,16659,16661,16663],{"class":200,"line":1181},[198,16654,12685],{"class":1387},[198,16656,2998],{"class":1383},[198,16658,7541],{"class":1960},[198,16660,1384],{"class":1383},[198,16662,12308],{"class":1960},[198,16664,12664],{"class":1383},[198,16666,16667,16669,16671,16673],{"class":200,"line":1187},[198,16668,12700],{"class":1387},[198,16670,2998],{"class":1383},[198,16672,12308],{"class":1960},[198,16674,1757],{"class":1383},[198,16676,16677],{"class":200,"line":1193},[198,16678,1613],{"class":1383},[198,16680,16681],{"class":200,"line":1199},[198,16682,217],{"emptyLinePlaceholder":216},[198,16684,16685,16687,16689,16691,16693,16695,16697,16699,16701,16703],{"class":200,"line":1205},[198,16686,6725],{"class":1956},[198,16688,12721],{"class":2202},[198,16690,2206],{"class":1383},[198,16692,12726],{"class":1387},[198,16694,7286],{"class":1383},[198,16696,6847],{"class":1956},[198,16698,12733],{"class":1960},[198,16700,7597],{"class":1383},[198,16702,8875],{"class":1960},[198,16704,1964],{"class":1383},[198,16706,16707,16709,16711,16713],{"class":200,"line":1211},[198,16708,12744],{"class":1387},[198,16710,41],{"class":1383},[198,16712,12749],{"class":2202},[198,16714,9519],{"class":1383},[198,16716,16717],{"class":200,"line":1217},[198,16718,1613],{"class":1383},[198,16720,16721],{"class":200,"line":1223},[198,16722,217],{"emptyLinePlaceholder":216},[198,16724,16725,16727,16729,16731,16733,16735,16737,16739,16741,16743,16745,16747,16749,16751,16753,16755],{"class":200,"line":1228},[198,16726,6725],{"class":1956},[198,16728,12766],{"class":2202},[198,16730,2206],{"class":1383},[198,16732,12726],{"class":1387},[198,16734,7286],{"class":1383},[198,16736,6847],{"class":1956},[198,16738,12733],{"class":1960},[198,16740,2764],{"class":1383},[198,16742,10646],{"class":1387},[198,16744,2998],{"class":1383},[198,16746,7310],{"class":1960},[198,16748,7597],{"class":1383},[198,16750,7541],{"class":1960},[198,16752,1384],{"class":1383},[198,16754,7294],{"class":1960},[198,16756,7263],{"class":1383},[198,16758,16759,16761,16763,16765,16767,16769,16771,16773,16775,16777,16779,16781,16783,16785,16787],{"class":200,"line":1233},[198,16760,6736],{"class":1956},[198,16762,6792],{"class":1956},[198,16764,12803],{"class":1387},[198,16766,2998],{"class":1383},[198,16768,7541],{"class":1960},[198,16770,1384],{"class":1383},[198,16772,7294],{"class":1960},[198,16774,7249],{"class":1383},[198,16776,1421],{"class":2220},[198,16778,6825],{"class":1960},[198,16780,5252],{"class":1383},[198,16782,12822],{"class":2202},[198,16784,2206],{"class":1383},[198,16786,10646],{"class":1387},[198,16788,2280],{"class":1383},[198,16790,16791,16793,16795,16797,16799,16801,16803],{"class":200,"line":1238},[198,16792,12833],{"class":1956},[198,16794,12836],{"class":1387},[198,16796,12839],{"class":1956},[198,16798,6021],{"class":1417},[198,16800,12844],{"class":1383},[198,16802,10646],{"class":1387},[198,16804,1964],{"class":1383},[198,16806,16807,16809,16811,16813,16815,16817,16819,16821],{"class":200,"line":1244},[198,16808,12853],{"class":1387},[198,16810,41],{"class":1383},[198,16812,12858],{"class":2202},[198,16814,2206],{"class":1383},[198,16816,12726],{"class":1387},[198,16818,41],{"class":1383},[198,16820,12749],{"class":1956},[198,16822,5414],{"class":1383},[198,16824,16825],{"class":200,"line":1250},[198,16826,2447],{"class":1383},[198,16828,16829],{"class":200,"line":11396},[198,16830,12877],{"class":1387},[198,16832,16833],{"class":200,"line":11402},[198,16834,1613],{"class":1383},[198,16836,16837],{"class":200,"line":11408},[198,16838,217],{"emptyLinePlaceholder":216},[198,16840,16841,16843,16845,16847,16849,16851,16853,16855,16857,16859],{"class":200,"line":11423},[198,16842,6725],{"class":1956},[198,16844,12892],{"class":2202},[198,16846,2206],{"class":1383},[198,16848,12726],{"class":1387},[198,16850,7286],{"class":1383},[198,16852,6847],{"class":1956},[198,16854,12733],{"class":1960},[198,16856,7597],{"class":1383},[198,16858,12308],{"class":1960},[198,16860,1964],{"class":1383},[198,16862,16863,16865,16867,16869,16871,16873,16875,16877,16879,16881,16883,16885],{"class":200,"line":11445},[198,16864,6736],{"class":1956},[198,16866,6792],{"class":1956},[198,16868,12917],{"class":1387},[198,16870,2221],{"class":2220},[198,16872,12587],{"class":1960},[198,16874,10386],{"class":1383},[198,16876,12926],{"class":1387},[198,16878,8929],{"class":1383},[198,16880,5912],{"class":1417},[198,16882,8934],{"class":1383},[198,16884,11275],{"class":1417},[198,16886,12937],{"class":1383},[198,16888,16889,16891,16893,16895,16897,16899,16901],{"class":200,"line":11477},[198,16890,12833],{"class":1956},[198,16892,10683],{"class":1387},[198,16894,12839],{"class":1956},[198,16896,6021],{"class":1417},[198,16898,12844],{"class":1383},[198,16900,11275],{"class":1417},[198,16902,1964],{"class":1383},[198,16904,16905,16907,16909,16911,16913,16915,16917,16919,16921],{"class":200,"line":11495},[198,16906,12958],{"class":1387},[198,16908,12961],{"class":1383},[198,16910,10692],{"class":1387},[198,16912,6945],{"class":1383},[198,16914,1421],{"class":2220},[198,16916,12970],{"class":1387},[198,16918,41],{"class":1383},[198,16920,12749],{"class":2202},[198,16922,2244],{"class":1383},[198,16924,16925],{"class":200,"line":11500},[198,16926,2447],{"class":1383},[198,16928,16929],{"class":200,"line":11505},[198,16930,12985],{"class":1387},[198,16932,16933],{"class":200,"line":11511},[198,16934,1613],{"class":1383},[198,16936,16937],{"class":200,"line":11544},[198,16938,217],{"emptyLinePlaceholder":216},[198,16940,16941],{"class":200,"line":11550},[198,16942,16440],{"class":1383},[198,16944,16945,16947,16949,16951],{"class":200,"line":11561},[198,16946,8151],{"class":1956},[198,16948,8154],{"class":1956},[198,16950,14915],{"class":1960},[198,16952,1964],{"class":1383},[198,16954,16955,16958,16960,16962,16964,16966],{"class":200,"line":11567},[198,16956,16957],{"class":1387},"    test_objects",[198,16959,2998],{"class":1383},[198,16961,7541],{"class":1960},[198,16963,1384],{"class":1383},[198,16965,13178],{"class":1960},[198,16967,12664],{"class":1383},[198,16969,16970],{"class":200,"line":11589},[198,16971,1613],{"class":1383},[198,16973,16974],{"class":200,"line":11594},[198,16975,217],{"emptyLinePlaceholder":216},[198,16977,16978],{"class":200,"line":11629},[198,16979,16440],{"class":1383},[198,16981,16982,16984,16986],{"class":200,"line":11668},[198,16983,7236],{"class":1956},[198,16985,14915],{"class":1960},[198,16987,1964],{"class":1383},[198,16989,16990],{"class":200,"line":11673},[198,16991,16992],{"class":1383},"    #[wasm_bindgen(constructor)]\n",[198,16994,16995,16998,17000,17002,17004,17006],{"class":200,"line":11679},[198,16996,16997],{"class":1956},"    pub",[198,16999,9316],{"class":1956},[198,17001,2341],{"class":2202},[198,17003,15013],{"class":1383},[198,17005,7600],{"class":1960},[198,17007,1964],{"class":1383},[198,17009,17010,17012],{"class":200,"line":11685},[198,17011,7607],{"class":1960},[198,17013,1964],{"class":1383},[198,17015,17016,17019,17021,17023,17025,17027],{"class":200,"line":11703},[198,17017,17018],{"class":1387},"            test_objects",[198,17020,2998],{"class":1383},[198,17022,7541],{"class":1960},[198,17024,5252],{"class":1383},[198,17026,6778],{"class":2202},[198,17028,10983],{"class":1383},[198,17030,17031],{"class":200,"line":11708},[198,17032,2442],{"class":1383},[198,17034,17035],{"class":200,"line":11714},[198,17036,2447],{"class":1383},[198,17038,17039],{"class":200,"line":11722},[198,17040,217],{"emptyLinePlaceholder":216},[198,17042,17043],{"class":200,"line":11740},[198,17044,17045],{"class":1383},"    #[wasm_bindgen]\n",[198,17047,17048,17050,17052,17054,17056,17058,17060,17062,17064,17066,17068],{"class":200,"line":11755},[198,17049,16997],{"class":1956},[198,17051,9316],{"class":1956},[198,17053,15079],{"class":2202},[198,17055,6844],{"class":1383},[198,17057,6847],{"class":1956},[198,17059,7278],{"class":1960},[198,17061,2764],{"class":1383},[198,17063,13193],{"class":1387},[198,17065,2998],{"class":1383},[198,17067,15094],{"class":1960},[198,17069,2212],{"class":1383},[198,17071,17072,17074,17076,17078,17080,17082,17084,17086],{"class":200,"line":11760},[198,17073,7394],{"class":1956},[198,17075,6792],{"class":1956},[198,17077,12970],{"class":1387},[198,17079,2221],{"class":2220},[198,17081,12345],{"class":1960},[198,17083,5252],{"class":1383},[198,17085,13036],{"class":2202},[198,17087,2244],{"class":1383},[198,17089,17090],{"class":200,"line":11783},[198,17091,17092],{"class":1930},"        \u002F\u002F Get the current time in ms\n",[198,17094,17095,17097,17100,17102,17104,17106,17108,17110,17112,17114,17116],{"class":200,"line":11788},[198,17096,7448],{"class":1960},[198,17098,17099],{"class":1383},".test_objects ",[198,17101,1421],{"class":2220},[198,17103,6825],{"class":1960},[198,17105,5252],{"class":1383},[198,17107,12822],{"class":2202},[198,17109,2206],{"class":1383},[198,17111,13193],{"class":1387},[198,17113,14201],{"class":1956},[198,17115,15797],{"class":1960},[198,17117,2280],{"class":1383},[198,17119,17120],{"class":200,"line":11794},[198,17121,217],{"emptyLinePlaceholder":216},[198,17123,17124,17127,17129,17131,17133,17135,17137],{"class":200,"line":11817},[198,17125,17126],{"class":1956},"        for",[198,17128,12836],{"class":1387},[198,17130,12839],{"class":1956},[198,17132,6021],{"class":1417},[198,17134,12844],{"class":1383},[198,17136,13193],{"class":1387},[198,17138,1964],{"class":1383},[198,17140,17141,17143,17146,17148,17150,17152],{"class":200,"line":11848},[198,17142,7972],{"class":1960},[198,17144,17145],{"class":1383},".test_objects.",[198,17147,12858],{"class":2202},[198,17149,2206],{"class":1383},[198,17151,13178],{"class":1960},[198,17153,1964],{"class":1383},[198,17155,17156,17159,17161,17163,17165,17167,17169,17171,17173],{"class":200,"line":11854},[198,17157,17158],{"class":1387},"                path",[198,17160,2998],{"class":1383},[198,17162,13236],{"class":2202},[198,17164,6844],{"class":1383},[198,17166,6847],{"class":1956},[198,17168,12970],{"class":1387},[198,17170,2764],{"class":1383},[198,17172,10854],{"class":1417},[198,17174,9915],{"class":1383},[198,17176,17177,17180,17182,17184],{"class":200,"line":11877},[198,17178,17179],{"class":1387},"                stats",[198,17181,2998],{"class":1383},[198,17183,12674],{"class":1960},[198,17185,1964],{"class":1383},[198,17187,17188,17191,17193,17195,17197,17199,17201],{"class":200,"line":11910},[198,17189,17190],{"class":1387},"                    owner_id",[198,17192,2998],{"class":1383},[198,17194,13269],{"class":2202},[198,17196,6844],{"class":1383},[198,17198,6847],{"class":1956},[198,17200,12970],{"class":1387},[198,17202,9915],{"class":1383},[198,17204,17205,17208,17210,17212,17214,17216,17218],{"class":200,"line":11921},[198,17206,17207],{"class":1387},"                    group_id",[198,17209,2998],{"class":1383},[198,17211,13269],{"class":2202},[198,17213,6844],{"class":1383},[198,17215,6847],{"class":1956},[198,17217,12970],{"class":1387},[198,17219,9915],{"class":1383},[198,17221,17222,17225,17227,17229,17231,17233,17235],{"class":200,"line":11929},[198,17223,17224],{"class":1387},"                    size",[198,17226,2998],{"class":1383},[198,17228,13269],{"class":2202},[198,17230,6844],{"class":1383},[198,17232,6847],{"class":1956},[198,17234,12970],{"class":1387},[198,17236,9915],{"class":1383},[198,17238,17239,17242,17244,17246,17248,17250,17252],{"class":200,"line":11954},[198,17240,17241],{"class":1387},"                    compressed_size",[198,17243,2998],{"class":1383},[198,17245,13269],{"class":2202},[198,17247,6844],{"class":1383},[198,17249,6847],{"class":1956},[198,17251,12970],{"class":1387},[198,17253,9915],{"class":1383},[198,17255,17256,17259,17261,17263,17265,17267,17269],{"class":200,"line":11960},[198,17257,17258],{"class":1387},"                    last_read",[198,17260,2998],{"class":1383},[198,17262,13269],{"class":2202},[198,17264,6844],{"class":1383},[198,17266,6847],{"class":1956},[198,17268,12970],{"class":1387},[198,17270,9915],{"class":1383},[198,17272,17273,17276,17278,17280,17282,17284,17286],{"class":200,"line":11965},[198,17274,17275],{"class":1387},"                    last_modified",[198,17277,2998],{"class":1383},[198,17279,13269],{"class":2202},[198,17281,6844],{"class":1383},[198,17283,6847],{"class":1956},[198,17285,12970],{"class":1387},[198,17287,9915],{"class":1383},[198,17289,17290,17293,17295,17297,17299,17301,17303],{"class":200,"line":11970},[198,17291,17292],{"class":1387},"                    created",[198,17294,2998],{"class":1383},[198,17296,13269],{"class":2202},[198,17298,6844],{"class":1383},[198,17300,6847],{"class":1956},[198,17302,12970],{"class":1387},[198,17304,9915],{"class":1383},[198,17306,17307,17310,17312,17314,17316,17318,17320],{"class":200,"line":11988},[198,17308,17309],{"class":1387},"                    mode",[198,17311,2998],{"class":1383},[198,17313,13269],{"class":2202},[198,17315,6844],{"class":1383},[198,17317,6847],{"class":1956},[198,17319,12970],{"class":1387},[198,17321,9915],{"class":1383},[198,17323,17324,17327,17329,17331,17333,17335,17337],{"class":200,"line":12010},[198,17325,17326],{"class":1387},"                    dev",[198,17328,2998],{"class":1383},[198,17330,13269],{"class":2202},[198,17332,6844],{"class":1383},[198,17334,6847],{"class":1956},[198,17336,12970],{"class":1387},[198,17338,9915],{"class":1383},[198,17340,17341,17344,17346,17348,17350,17352,17354],{"class":200,"line":12015},[198,17342,17343],{"class":1387},"                    rdev",[198,17345,2998],{"class":1383},[198,17347,13269],{"class":2202},[198,17349,6844],{"class":1383},[198,17351,6847],{"class":1956},[198,17353,12970],{"class":1387},[198,17355,9915],{"class":1383},[198,17357,17358,17361,17363,17365,17367,17369,17371],{"class":200,"line":13554},[198,17359,17360],{"class":1387},"                    ino",[198,17362,2998],{"class":1383},[198,17364,13269],{"class":2202},[198,17366,6844],{"class":1383},[198,17368,6847],{"class":1956},[198,17370,12970],{"class":1387},[198,17372,9915],{"class":1383},[198,17374,17375,17378,17380,17382,17384,17386,17388],{"class":200,"line":13559},[198,17376,17377],{"class":1387},"                    nlink",[198,17379,2998],{"class":1383},[198,17381,13269],{"class":2202},[198,17383,6844],{"class":1383},[198,17385,6847],{"class":1956},[198,17387,12970],{"class":1387},[198,17389,9915],{"class":1383},[198,17391,17392],{"class":200,"line":13585},[198,17393,17394],{"class":1383},"                },\n",[198,17396,17397,17400,17402,17404],{"class":200,"line":13606},[198,17398,17399],{"class":1387},"                chunks",[198,17401,2998],{"class":1383},[198,17403,13479],{"class":2202},[198,17405,13482],{"class":1383},[198,17407,17408,17411,17413,17415,17417],{"class":200,"line":13615},[198,17409,17410],{"class":2202},"                    generate_random_sha256",[198,17412,6844],{"class":1383},[198,17414,6847],{"class":1956},[198,17416,12970],{"class":1387},[198,17418,9915],{"class":1383},[198,17420,17421,17423,17425,17427,17429],{"class":200,"line":13624},[198,17422,17410],{"class":2202},[198,17424,6844],{"class":1383},[198,17426,6847],{"class":1956},[198,17428,12970],{"class":1387},[198,17430,9915],{"class":1383},[198,17432,17433,17435,17437,17439,17441],{"class":200,"line":13630},[198,17434,17410],{"class":2202},[198,17436,6844],{"class":1383},[198,17438,6847],{"class":1956},[198,17440,12970],{"class":1387},[198,17442,9915],{"class":1383},[198,17444,17445],{"class":200,"line":13652},[198,17446,17447],{"class":1383},"                ],\n",[198,17449,17450,17453,17455,17457,17459,17461,17463],{"class":200,"line":13657},[198,17451,17452],{"class":1387},"                sha256",[198,17454,2998],{"class":1383},[198,17456,13534],{"class":2202},[198,17458,6844],{"class":1383},[198,17460,6847],{"class":1956},[198,17462,12970],{"class":1387},[198,17464,9915],{"class":1383},[198,17466,17467],{"class":200,"line":13662},[198,17468,1220],{"class":1383},[198,17470,17471],{"class":200,"line":13684},[198,17472,2442],{"class":1383},[198,17474,17475],{"class":200,"line":13690},[198,17476,2447],{"class":1383},[198,17478,17479],{"class":200,"line":13697},[198,17480,217],{"emptyLinePlaceholder":216},[198,17482,17483,17486,17488],{"class":200,"line":13705},[198,17484,17485],{"class":1383},"    #[wasm_bindgen(js_name ",[198,17487,1421],{"class":2220},[198,17489,17490],{"class":1383}," toString)]\n",[198,17492,17493,17495,17497,17499,17501,17503,17505,17507],{"class":200,"line":13730},[198,17494,16997],{"class":1956},[198,17496,9316],{"class":1956},[198,17498,15842],{"class":2202},[198,17500,6844],{"class":1383},[198,17502,8002],{"class":1960},[198,17504,7597],{"class":1383},[198,17506,15851],{"class":1960},[198,17508,1964],{"class":1383},[198,17510,17511,17514],{"class":200,"line":13736},[198,17512,17513],{"class":2202},"        format!",[198,17515,2775],{"class":1383},[198,17517,17518,17521],{"class":200,"line":13742},[198,17519,17520],{"class":1424},"            \"TestObjectWrapper {{ test_objects: {} }}\"",[198,17522,1757],{"class":1383},[198,17524,17525,17527,17529,17531],{"class":200,"line":13749},[198,17526,7972],{"class":1960},[198,17528,17145],{"class":1383},[198,17530,7353],{"class":2202},[198,17532,9519],{"class":1383},[198,17534,17535],{"class":200,"line":13757},[198,17536,17537],{"class":1383},"        )\n",[198,17539,17540],{"class":200,"line":13782},[198,17541,2447],{"class":1383},[198,17543,17544],{"class":200,"line":13787},[198,17545,1613],{"class":1383},[11,17547,17548,17549,41],{},"Pour utiliser notre module dans Node.JS, nous devons importer le module ",[165,17550,17551],{},"wasm-bindgen",[190,17553,17555],{"className":388,"code":17554,"language":390,"meta":59,"style":59},"const { webcrypto } = require('node:crypto')\nglobal.crypto = webcrypto\n\nconst wasm = require('..\u002Fpkg\u002Ftest_rust_was.js');\nconst filesize = require(\"filesize.js\");\n\nglobal.gc();\nconst memoryBefore = process.memoryUsage().rss;\n\nconst time = Date.now();\n\nconst nbObjects = 1300000;\nconst testArray = new wasm.TestObjectWrapper();\ntestArray.fill(nbObjects);\n\nconsole.log(\"Creation time: \", Date.now() - time);\n\nglobal.gc();\nconst memoryAfter = process.memoryUsage().rss;\n\nconsole.log(\"Memory consumption in JS: \", filesize.default(memoryAfter - memoryBefore));\nconsole.log(\"Memory consumption calculated by head: \", filesize.default(432));\nconsole.log(\"Memory consumption by objects: \", filesize.default((memoryAfter - memoryBefore) \u002F nbObjects));\n  \nconsole.log(testArray.toString());\n",[165,17556,17557,17579,17593,17597,17615,17631,17635,17645,17666,17670,17686,17690,17703,17721,17735,17739,17767,17771,17781,17801,17805,17836,17864,17900,17905],{"__ignoreMap":59},[198,17558,17559,17561,17563,17566,17568,17570,17572,17574,17577],{"class":200,"line":201},[198,17560,10558],{"class":1956},[198,17562,10386],{"class":1383},[198,17564,17565],{"class":1960},"webcrypto",[198,17567,10613],{"class":1383},[198,17569,1421],{"class":2220},[198,17571,10566],{"class":2202},[198,17573,2206],{"class":1383},[198,17575,17576],{"class":1424},"'node:crypto'",[198,17578,2845],{"class":1383},[198,17580,17581,17583,17585,17588,17590],{"class":200,"line":207},[198,17582,11329],{"class":1960},[198,17584,41],{"class":1383},[198,17586,17587],{"class":1387},"crypto",[198,17589,2221],{"class":2220},[198,17591,17592],{"class":1387}," webcrypto\n",[198,17594,17595],{"class":200,"line":213},[198,17596,217],{"emptyLinePlaceholder":216},[198,17598,17599,17601,17604,17606,17608,17610,17613],{"class":200,"line":220},[198,17600,10558],{"class":1956},[198,17602,17603],{"class":1960}," wasm",[198,17605,2221],{"class":2220},[198,17607,10566],{"class":2202},[198,17609,2206],{"class":1383},[198,17611,17612],{"class":1424},"'..\u002Fpkg\u002Ftest_rust_was.js'",[198,17614,2280],{"class":1383},[198,17616,17617,17619,17621,17623,17625,17627,17629],{"class":200,"line":254},[198,17618,10558],{"class":1956},[198,17620,10561],{"class":1960},[198,17622,2221],{"class":2220},[198,17624,10566],{"class":2202},[198,17626,2206],{"class":1383},[198,17628,10571],{"class":1424},[198,17630,2280],{"class":1383},[198,17632,17633],{"class":200,"line":260},[198,17634,217],{"emptyLinePlaceholder":216},[198,17636,17637,17639,17641,17643],{"class":200,"line":266},[198,17638,11329],{"class":1960},[198,17640,41],{"class":1383},[198,17642,11334],{"class":2202},[198,17644,2244],{"class":1383},[198,17646,17647,17649,17651,17653,17655,17657,17659,17661,17664],{"class":200,"line":272},[198,17648,10558],{"class":1956},[198,17650,11348],{"class":1960},[198,17652,2221],{"class":2220},[198,17654,11353],{"class":1960},[198,17656,41],{"class":1383},[198,17658,11358],{"class":2202},[198,17660,8010],{"class":1383},[198,17662,17663],{"class":1387},"rss",[198,17665,2008],{"class":1383},[198,17667,17668],{"class":200,"line":278},[198,17669,217],{"emptyLinePlaceholder":216},[198,17671,17672,17674,17676,17678,17680,17682,17684],{"class":200,"line":283},[198,17673,10558],{"class":1956},[198,17675,11377],{"class":1960},[198,17677,2221],{"class":2220},[198,17679,11382],{"class":1960},[198,17681,41],{"class":1383},[198,17683,11387],{"class":2202},[198,17685,2244],{"class":1383},[198,17687,17688],{"class":200,"line":288},[198,17689,217],{"emptyLinePlaceholder":216},[198,17691,17692,17694,17696,17698,17701],{"class":200,"line":450},[198,17693,10558],{"class":1956},[198,17695,11413],{"class":1960},[198,17697,2221],{"class":2220},[198,17699,17700],{"class":1417}," 1300000",[198,17702,2008],{"class":1383},[198,17704,17705,17707,17709,17711,17713,17715,17717,17719],{"class":200,"line":456},[198,17706,10558],{"class":1956},[198,17708,11428],{"class":1960},[198,17710,2221],{"class":2220},[198,17712,2341],{"class":1956},[198,17714,17603],{"class":1960},[198,17716,41],{"class":1383},[198,17718,14973],{"class":2202},[198,17720,2244],{"class":1383},[198,17722,17723,17725,17727,17729,17731,17733],{"class":200,"line":462},[198,17724,16085],{"class":1960},[198,17726,41],{"class":1383},[198,17728,16090],{"class":2202},[198,17730,2206],{"class":1383},[198,17732,11440],{"class":1387},[198,17734,2280],{"class":1383},[198,17736,17737],{"class":200,"line":468},[198,17738,217],{"emptyLinePlaceholder":216},[198,17740,17741,17743,17745,17747,17749,17751,17753,17755,17757,17759,17761,17763,17765],{"class":200,"line":473},[198,17742,11514],{"class":1960},[198,17744,41],{"class":1383},[198,17746,11519],{"class":2202},[198,17748,2206],{"class":1383},[198,17750,11524],{"class":1424},[198,17752,2764],{"class":1383},[198,17754,11529],{"class":1960},[198,17756,41],{"class":1383},[198,17758,11387],{"class":2202},[198,17760,2484],{"class":1383},[198,17762,6053],{"class":2220},[198,17764,11377],{"class":1387},[198,17766,2280],{"class":1383},[198,17768,17769],{"class":200,"line":478},[198,17770,217],{"emptyLinePlaceholder":216},[198,17772,17773,17775,17777,17779],{"class":200,"line":484},[198,17774,11329],{"class":1960},[198,17776,41],{"class":1383},[198,17778,11334],{"class":2202},[198,17780,2244],{"class":1383},[198,17782,17783,17785,17787,17789,17791,17793,17795,17797,17799],{"class":200,"line":490},[198,17784,10558],{"class":1956},[198,17786,11572],{"class":1960},[198,17788,2221],{"class":2220},[198,17790,11353],{"class":1960},[198,17792,41],{"class":1383},[198,17794,11358],{"class":2202},[198,17796,8010],{"class":1383},[198,17798,17663],{"class":1387},[198,17800,2008],{"class":1383},[198,17802,17803],{"class":200,"line":1068},[198,17804,217],{"emptyLinePlaceholder":216},[198,17806,17807,17809,17811,17813,17815,17818,17820,17822,17824,17826,17828,17830,17832,17834],{"class":200,"line":1074},[198,17808,11514],{"class":1960},[198,17810,41],{"class":1383},[198,17812,11519],{"class":2202},[198,17814,2206],{"class":1383},[198,17816,17817],{"class":1424},"\"Memory consumption in JS: \"",[198,17819,2764],{"class":1383},[198,17821,11610],{"class":1960},[198,17823,41],{"class":1383},[198,17825,11615],{"class":2202},[198,17827,2206],{"class":1383},[198,17829,11620],{"class":1387},[198,17831,5111],{"class":2220},[198,17833,11348],{"class":1387},[198,17835,2528],{"class":1383},[198,17837,17838,17840,17842,17844,17846,17849,17851,17853,17855,17857,17859,17862],{"class":200,"line":1080},[198,17839,11514],{"class":1960},[198,17841,41],{"class":1383},[198,17843,11519],{"class":2202},[198,17845,2206],{"class":1383},[198,17847,17848],{"class":1424},"\"Memory consumption calculated by head: \"",[198,17850,2764],{"class":1383},[198,17852,11610],{"class":1960},[198,17854,41],{"class":1383},[198,17856,11615],{"class":2202},[198,17858,2206],{"class":1383},[198,17860,17861],{"class":1417},"432",[198,17863,2528],{"class":1383},[198,17865,17866,17868,17870,17872,17874,17876,17878,17880,17882,17884,17886,17888,17890,17892,17894,17896,17898],{"class":200,"line":1086},[198,17867,11514],{"class":1960},[198,17869,41],{"class":1383},[198,17871,11519],{"class":2202},[198,17873,2206],{"class":1383},[198,17875,11640],{"class":1424},[198,17877,2764],{"class":1383},[198,17879,11610],{"class":1960},[198,17881,41],{"class":1383},[198,17883,11615],{"class":2202},[198,17885,11651],{"class":1383},[198,17887,11620],{"class":1387},[198,17889,5111],{"class":2220},[198,17891,11348],{"class":1387},[198,17893,8484],{"class":1383},[198,17895,5347],{"class":2220},[198,17897,11413],{"class":1387},[198,17899,2528],{"class":1383},[198,17901,17902],{"class":200,"line":1092},[198,17903,17904],{"class":1383},"  \n",[198,17906,17907,17909,17911,17913,17915,17917,17919,17921],{"class":200,"line":1098},[198,17908,11514],{"class":1960},[198,17910,41],{"class":1383},[198,17912,11519],{"class":2202},[198,17914,2206],{"class":1383},[198,17916,16085],{"class":1960},[198,17918,41],{"class":1383},[198,17920,16236],{"class":2202},[198,17922,5414],{"class":1383},[11,17924,17925],{},"Nous n'oublions pas de compiler notre module en mode release et avec la target nodejs.",[11,17927,17928],{},"Le résultat est alors le suivant :",[6106,17930,17931,17939],{},[6109,17932,17933],{},[6112,17934,17935,17937],{},[6115,17936],{},[6115,17938],{},[6128,17940,17941,17947,17954,17961],{},[6112,17942,17943,17945],{},[6133,17944,12047],{},[6133,17946,12050],{},[6112,17948,17949,17951],{},[6133,17950,12055],{},[6133,17952,17953],{},"42 secondes",[6112,17955,17956,17958],{},[6133,17957,12063],{},[6133,17959,17960],{},"450,6 Mo",[6112,17962,17963,17965],{},[6133,17964,12071],{},[6133,17966,17967],{},"363.5 octets",[11,17969,17970],{},"Wasm permet d'améliorer la consommation mémoire. Sur mon exemple, le temps de création n'est pas très impressionnant\nmais est, je crois, lié à la génération des nombres aléatoires.",[11,17972,17973],{},"L'utilisation de WASM pourrait être une bonne alternative.",[11,17975,17976],{},"Quand utiliser WASM et quand faire un module node ? L'avantage de faire du Wasm, c'est que le module peut tourner\négalement côté navigateur. L'autre avantage est que le module n'a pas besoin d'être recompilé en cas de changement de\nplateforme (Linux, Windows, ... ; x86, ARM, ...).",[11,17978,17979],{},"D'un autre côté, un module node natif a l'avantage d'être plus simple (moins de bindings) et sera sûrement plus rapide\nà l'exécution.",[72,17981,1620],{"id":1619},[11,17983,17984],{},"Pour améliorer les performances de notre application, nous allons donc écrire un module natif en Rust avec N-API.",[11,17986,17987,17988,41],{},"Vous pouvez retrouver le code source de cet article sur mon dépôt ",[15,17989,17992],{"href":17990,"rel":17991},"https:\u002F\u002Fgogs.shadoware.org\u002FShadowareOrg\u002Fblog_compare_js_rust_wasm",[24],"Gitea",[1660,17994,17995],{},"html pre.shiki code .seHd6, html code.shiki .seHd6{--shiki-default:#C678DD}html pre.shiki code .sU0A5, html code.shiki .sU0A5{--shiki-default:#E5C07B}html pre.shiki code .sjrmR, html code.shiki .sjrmR{--shiki-default:#56B6C2}html pre.shiki code .sVbv2, html code.shiki .sVbv2{--shiki-default:#61AFEF}html pre.shiki code .sn6KH, html code.shiki .sn6KH{--shiki-default:#ABB2BF}html pre.shiki code .subq3, html code.shiki .subq3{--shiki-default:#98C379}html pre.shiki code .sV9Aq, html code.shiki .sV9Aq{--shiki-default:#7F848E;--shiki-default-font-style:italic}html pre.shiki code .s_ZVi, html code.shiki .s_ZVi{--shiki-default:#E06C75;--shiki-default-font-style:italic}html pre.shiki code .sVyAn, html code.shiki .sVyAn{--shiki-default:#E06C75}html pre.shiki code .sVC51, html code.shiki .sVC51{--shiki-default:#D19A66}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":59,"searchDepth":207,"depth":207,"links":17997},[17998,17999,18000,18001,18002,18003,18005],{"id":10534,"depth":207,"text":10535},{"id":10544,"depth":207,"text":10545},{"id":12107,"depth":207,"text":12108},{"id":12294,"depth":207,"text":12295},{"id":14294,"depth":207,"text":14295},{"id":16285,"depth":207,"text":18004},"Conclusion - Wasm",{"id":1619,"depth":207,"text":1620},"2023-05-10",{"type":8,"value":18008},[18009,18011,18013],[72,18010,10535],{"id":10534},[11,18012,10538],{},[11,18014,10541],{},{"planet":216},"\u002Fpost\u002Fwoodstock_rust",{"title":10529,"description":59},"woodstock_rust","posts\u002FWoodstock\u002F2023-05-10_woodstock_rust",[10523,10524,10525,1705,6327],"RXnKX2dJmrksM5sZOeN70MXCyeSAMu1H3Jj5D3fie28",1777849582747]