Skip to content

Instantly share code, notes, and snippets.

@DemonQilin
Created July 22, 2023 01:12
Show Gist options
  • Save DemonQilin/639d8fb3ad78446ba9165b1014bbdb93 to your computer and use it in GitHub Desktop.
Save DemonQilin/639d8fb3ad78446ba9165b1014bbdb93 to your computer and use it in GitHub Desktop.
Replicate highlights

Copy and paste in the console:

localStorage.setItem('mdbook-quiz:highlights', `[{"startMeta":{"parentTagName":"P","parentIndex":8,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":8,"textOffset":178},"text":"The code associated with each arm is an expression, and the resultant value of\\nthe expression in the matching arm is the value that gets returned for the\\nentire match expression.","id":"498e97b1-e299-4c93-ac79-075956de4376","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch06-02-match.html\\",\\"domHash\\":\\"1b9da7f53674515d0e768aa92591bb9c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":26,"textOffset":54},"endMeta":{"parentTagName":"P","parentIndex":26,"textOffset":101},"text":"the arms’ patterns must\\ncover all possibilities","id":"5a62a9b3-e67f-4b54-b976-0e12849b8783","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch06-02-match.html\\",\\"domHash\\":\\"e7bcee9137a2c52f169517c4ef551a3a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":28,"textOffset":93},"endMeta":{"parentTagName":"P","parentIndex":28,"textOffset":198},"text":"Matches in Rust are exhaustive: we must exhaust every last\\npossibility in order for the code to be valid.","id":"7b59e4d3-fbe5-45a9-a959-ccd4b1151742","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch06-02-match.html\\",\\"domHash\\":\\"5b1800bfda2a8cf476d3a4987ec6b660\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":31,"textOffset":161},"endMeta":{"parentTagName":"P","parentIndex":31,"textOffset":452},"text":"This catch-all pattern meets the requirement that match must be\\nexhaustive. Note that we have to put the catch-all arm last because the\\npatterns are evaluated in order. If we put the catch-all arm earlier, the other\\narms would never run, so Rust will warn us if we add arms after a catch-all","id":"184c491d-c5e0-4ce1-b3ce-30139c783d2d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch06-02-match.html\\",\\"domHash\\":\\"0feb27d7e86e2c9113409b8d93603115\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":1,"textOffset":179},"endMeta":{"parentTagName":"P","parentIndex":1,"textOffset":355},"text":"A package can contain multiple binary crates and\\noptionally one library crate. As a package grows, you can extract parts into\\nseparate crates that become external dependencies.","id":"d69d55a0-40d8-4bb7-8f71-71decf4d73f0","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html\\",\\"domHash\\":\\"3cbcffcc285e5bc20dd91ead2b88c60e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":1,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":1,"textOffset":81},"text":"A crate is the smallest amount of code that the Rust compiler considers at a\\ntime","id":"faff95d5-b16a-42c2-a889-11ca4f09478a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-01-packages-and-crates.html\\",\\"domHash\\":\\"6743b9fcc57cf1b169fb4ef6c7a955d2\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":2,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":2,"textOffset":71},"text":"A crate can come in one of two forms: a binary crate or a library crate","id":"5ae6eebd-9fed-4ca6-951c-e5b3352e4bc1","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-01-packages-and-crates.html\\",\\"domHash\\":\\"d8d77437a6929d480e6559e56c025289\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":1,"textOffset":301},"endMeta":{"parentTagName":"P","parentIndex":1,"textOffset":445},"text":"Crates\\ncan contain modules, and the modules may be defined in other files that get\\ncompiled with the crate, as we’ll see in the coming sections.","id":"d87f63fe-e08d-4c71-860f-944e97b1af81","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-01-packages-and-crates.html\\",\\"domHash\\":\\"6712de4fbadaddc80701675fa0ee5499\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":14,"textOffset":287},"text":"Items in a parent module can’t use the private items inside child modules, but\\nitems in child modules can use the items in their ancestor modules. This is\\nbecause child modules wrap and hide their implementation details, but the child\\nmodules can see the context in which they’re defined","id":"9b6de79f-7b74-468d-a72d-2437bfacc19b","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html\\",\\"domHash\\":\\"9e8fffa3b24ab67d7f676d198bed5d0c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":22,"textOffset":76},"endMeta":{"parentTagName":"P","parentIndex":22,"textOffset":160},"text":"The privacy rules apply to structs, enums, functions, and methods as well as\\nmodules","id":"243c442f-0426-4aed-87a8-c118d0b37401","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html\\",\\"domHash\\":\\"c83fcd5d371d0464ec7115475e37f0d1\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":0,"textOffset":277},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":451},"text":"Fortunately, there’s a\\nway to simplify this process: we can create a shortcut to a path with the use\\nkeyword once, and then use the shorter name everywhere else in the scope.","id":"7f5a901e-20e8-415b-a751-fef804f9710a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html\\",\\"domHash\\":\\"b7ebfccd6038d976b3f71452debb274c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":5,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":5,"textOffset":88},"text":"Note that use only creates the shortcut for the particular scope in which the\\nuse occurs","id":"d8199e2c-633c-45b8-963b-4124b91c92f1","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html\\",\\"domHash\\":\\"8098689f8b16acd77646fda216deaa25\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":4,"textOffset":268},"endMeta":{"parentTagName":"P","parentIndex":4,"textOffset":342},"text":"Paths brought into scope with use\\nalso check privacy, like any other paths","id":"6c6b3b3d-d56b-4e67-9ccf-6318d21000e9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html\\",\\"domHash\\":\\"8217c1ddb716df6640a4962c4052511f\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":13,"textOffset":137},"endMeta":{"parentTagName":"P","parentIndex":13,"textOffset":263},"text":"Bringing the\\nfunction’s parent module into scope with use means we have to specify the\\nparent module when calling the function","id":"5de04340-152b-47bb-b61e-6b0809b04c29","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html\\",\\"domHash\\":\\"c4221076fb4abbf00f01a2a5181b348b\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":14,"textOffset":117},"text":"On the other hand, when bringing in structs, enums, and other items with use,\\nit’s idiomatic to specify the full path","id":"6bae4f56-e69b-4f65-bf83-99d832a9187f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html\\",\\"domHash\\":\\"95753036a7c4d13c00430ffb0f2c6ede\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":18,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":18,"textOffset":141},"text":"The exception to this idiom is if we’re bringing two items with the same name\\ninto scope with use statements, because Rust doesn’t allow that","id":"a724ccb8-c852-4e3a-84ab-b5b59da28a6d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html\\",\\"domHash\\":\\"3e701e8ca24fb7ef0e6527ad969c07ed\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":22,"textOffset":109},"endMeta":{"parentTagName":"P","parentIndex":22,"textOffset":187},"text":"after the path, we can specify as and a new\\nlocal name, or alias, for the type","id":"114ed12b-c16f-457b-ba7d-52a2e8ebc369","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html\\",\\"domHash\\":\\"bdfb41d67bd8dd0086651dc99eba4e5c\\"}"},{"startMeta":{"parentTagName":"LI","parentIndex":137,"textOffset":17},"endMeta":{"parentTagName":"LI","parentIndex":137,"textOffset":176},"text":"is the full path starting from a crate root; for code\\nfrom an external crate, the absolute path begins with the crate name, and for\\ncode from the current crate","id":"c5c31eaa-6899-4014-9d67-6bf27878911f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html\\",\\"domHash\\":\\"20661e0eca565fd81540eb75dc422567\\"}"},{"startMeta":{"parentTagName":"LI","parentIndex":138,"textOffset":16},"endMeta":{"parentTagName":"LI","parentIndex":138,"textOffset":107},"text":"starts from the current module and uses self, super, or\\nan identifier in the current module","id":"19f8fc3f-19c0-4386-9528-511d6891a4a4","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html\\",\\"domHash\\":\\"185141c9b67851d2c28090c79057102e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":10,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":10,"textOffset":232},"text":"Choosing whether to use a relative or absolute path is a decision you’ll make\\nbased on your project, and depends on whether you’re more likely to move item\\ndefinition code separately from or together with the code that uses the item","id":"c85d2eb7-ef53-407c-ade4-7c89e2865b8f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html\\",\\"domHash\\":\\"0d31bc3b2c8605b9c1c814e4aa9896f7\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":8,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":8,"textOffset":87},"text":"Note that you only need to load a file using a mod declaration once in your\\nmodule tree","id":"5152811e-4f55-4797-83d5-314b4d4f6359","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-05-separating-modules-into-different-files.html\\",\\"domHash\\":\\"c602636f6db3c2e8fb4c59b6520100a2\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":8,"textOffset":246},"endMeta":{"parentTagName":"P","parentIndex":8,"textOffset":350},"text":"other files in your project should refer to the loaded file’s code\\nusing a path to where it was declared","id":"2d1258d9-5523-43e4-b81b-ba26e08f75a3","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-05-separating-modules-into-different-files.html\\",\\"domHash\\":\\"1cb61ba7500a92a18c0e3b2e6b9f1e34\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":26,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":26,"textOffset":101},"text":"When we bring a name into scope with the use keyword, the name available in\\nthe new scope is private.","id":"eb067631-1578-4b41-b613-3e1e21b3d292","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html\\",\\"domHash\\":\\"03697c9bf9fb27048e3751a245a1281c\\"}"},{"startMeta":{"parentTagName":"LI","parentIndex":147,"textOffset":19},"endMeta":{"parentTagName":"LI","parentIndex":147,"textOffset":85},"text":"Code within a module is private from its parent\\nmodules by default","id":"41df3b28-ff07-44b4-ae91-cec92600012c","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-02-defining-modules-to-control-scope-and-privacy.html\\",\\"domHash\\":\\"aac1b0fe6421f5e08ddde3ca34a82280\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":29,"textOffset":60},"endMeta":{"parentTagName":"CODE","parentIndex":98,"textOffset":4},"text":"the compiler\\ncan coerce the &String argument into a &str","id":"e3316856-4d78-4f9f-a384-c80ba5b035d9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch08-02-strings.html\\",\\"domHash\\":\\"67b06f87533a7b5ad721da96774c9088\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":16,"textOffset":202},"endMeta":{"parentTagName":"P","parentIndex":16,"textOffset":319},"text":"Debug symbols are enabled by\\ndefault when using cargo build or cargo run without the --release flag,\\nas we have here.","id":"52b5a627-9040-4a8c-91c2-a822cb9398e6","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-01-unrecoverable-errors-with-panic.html\\",\\"domHash\\":\\"a80816e9279364dd09d45fdafeb10f48\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":16,"textOffset":121},"endMeta":{"parentTagName":"P","parentIndex":16,"textOffset":319},"text":"In order to get backtraces with this\\ninformation, debug symbols must be enabled. Debug symbols are enabled by\\ndefault when using cargo build or cargo run without the --release flag,\\nas we have here.","id":"6951bb3d-15ec-4aa9-bcda-8c659e590508","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-01-unrecoverable-errors-with-panic.html\\",\\"domHash\\":\\"33b7262e213bf12afcce2565d118baec\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":0,"textOffset":359},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":451},"text":"By default, these panics will\\nprint a failure message, unwind, clean up the stack, and quit.","id":"ad691386-df4f-44d3-8c13-fdf78d341cb7","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-01-unrecoverable-errors-with-panic.html\\",\\"domHash\\":\\"0e5a1c67cff51e479cf3d8759b536386\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":315},"endMeta":{"parentTagName":"P","parentIndex":14,"textOffset":513},"text":"Backtraces in Rust work as they do in other languages: the\\nkey to reading the backtrace is to start from the top and read until you see\\nfiles you wrote. That’s the spot where the problem originated.","id":"0cc2ecd5-6482-4eee-b004-a3afc683af0c","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-01-unrecoverable-errors-with-panic.html\\",\\"domHash\\":\\"9b04a272c6b38f698156775e7bdb3dd5\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":48,"textOffset":108},"endMeta":{"parentTagName":"P","parentIndex":48,"textOffset":300},"text":"error values that have the ? operator called\\non them go through the from function, defined in the From trait in the\\nstandard library, which is used to convert values from one type into another","id":"1eef3c91-82fa-4906-893c-eee26bf34f44","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"bc69c11a5fcb0a8c569e2024c6053193\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":48,"textOffset":456},"endMeta":{"parentTagName":"P","parentIndex":48,"textOffset":611},"text":"This is useful when a function returns one error type to represent\\nall the ways a function might fail, even if parts might fail for many different\\nreasons.","id":"24cec4b3-439f-4cac-8ce9-df6002b4124a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"a16cfb43ce76e6ad5e8c3989aeff3853\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":51,"textOffset":0},"endMeta":{"parentTagName":"CODE","parentIndex":223,"textOffset":1},"text":"The ? operator eliminates a lot of boilerplate and makes this function’s\\nimplementation simpler. We could even shorten this code further by chaining\\nmethod calls immediately after the ?","id":"77ac80a2-dee4-474a-a0ae-b7f67ed581ce","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":59,"textOffset":384},"endMeta":{"parentTagName":"CODE","parentIndex":253,"textOffset":6},"text":"The return type of the function has to be a Result so that\\nit’s compatible with this return","id":"ffcf84ee-2a72-4d55-9d61-acf115808325","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"d5fb386d1ab48d559db32123bf356684\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":59,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":59,"textOffset":108},"text":"The ? operator can only be used in functions whose return type is compatible\\nwith the value the ? is used on","id":"54d04311-87c9-4431-9f94-a8ef2796d049","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":64,"textOffset":27},"endMeta":{"parentTagName":"CODE","parentIndex":271,"textOffset":12},"text":"we’re only allowed to use the ? operator in a\\nfunction that returns Result, Option, or another type that implements\\nFromResidual","id":"b8e2c6a4-df9f-4a6c-9c99-581d4a8962fe","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"6e2623097d141975c191126b7a4910d5\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":65,"textOffset":213},"endMeta":{"parentTagName":"P","parentIndex":65,"textOffset":344},"text":"The other technique is\\nto use a match or one of the Result<T, E> methods to handle the Result<T, E> in whatever way is appropriate.","id":"ac42d75e-232c-4f73-b8f6-701037fafa2f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"22af9306cee2673c72892e9e8f26d41d\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":66,"textOffset":177},"endMeta":{"parentTagName":"P","parentIndex":66,"textOffset":497},"text":"The behavior of the ? operator when called\\non an Option<T> is similar to its behavior when called on a Result<T, E>:\\nif the value is None, the None will be returned early from the function at\\nthat point. If the value is Some, the value inside the Some is the\\nresulting value of the expression and the function continues.","id":"04f92445-393c-459a-8152-80acb849f6c5","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"c8c13df784cb7b683da324a800fde5ba\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":68,"textOffset":131},"endMeta":{"parentTagName":"P","parentIndex":68,"textOffset":266},"text":"This code takes the\\ntext string slice argument and calls the lines method on it, which returns\\nan iterator over the lines in the string","id":"767b94b0-899a-4a18-b025-6fc4b6629f45","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"669de3b7eb48d33de2a8f00082274419\\"}"},{"startMeta":{"parentTagName":"CODE","parentIndex":327,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":70,"textOffset":397},"text":"ok method on Result or the ok_or method on\\nOption to do the conversion explicitl","id":"b4100c6b-4485-4cfc-80e6-7efa2c0af792","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"444bcb3a3fcf8389296c49467f27e1d6\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":71,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":71,"textOffset":240},"text":"So far, all the main functions we’ve used return (). The main function is\\nspecial because it’s the entry and exit point of executable programs, and there\\nare restrictions on what its return type can be for the programs to behave as\\nexpected","id":"e33dedc5-7502-41dd-8995-7b729b7239f4","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"9575bc7beeb48eef70d754472e7f8190\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":75,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":75,"textOffset":175},"text":"When a main function returns a Result<(), E>, the executable will\\nexit with a value of 0 if main returns Ok(()) and will exit with a\\nnonzero value if main returns an Err value","id":"24eafe69-3993-484a-8679-cada80ee6f83","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"0b8cc449d00d272cd1332e8e1dde07b6\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":76,"textOffset":0},"endMeta":{"parentTagName":"CODE","parentIndex":367,"textOffset":8},"text":"The main function may return any types that implement the\\nstd::process::Termination trait, which contains\\na function report that returns an ExitCode","id":"6f210bc1-7a38-4fa4-94a8-2757fca11a38","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-02-recoverable-errors-with-result.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":3,"textOffset":51},"endMeta":{"parentTagName":"P","parentIndex":3,"textOffset":158},"text":"we aren’t inserting any\\nvalues into this vector, Rust doesn’t know what kind of elements we intend to\\nstore","id":"18f27b8e-5feb-4a47-91a4-c3dbbdfd6cda","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch08-01-vectors.html\\",\\"domHash\\":\\"1a9f5db713d89d0cf6c695d1c7617b3e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":15,"textOffset":217},"endMeta":{"parentTagName":"P","parentIndex":15,"textOffset":364},"text":"Rust does give\\nyou the option to expose inner parts of child modules’ code to outer ancestor\\nmodules by using the pub keyword to make an item publi","id":"89b983e7-9eb0-4d29-959d-cf3cad604799","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html\\",\\"domHash\\":\\"e1b38eb36c16a71f91f61cbc04711a45\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":2,"textOffset":134},"endMeta":{"parentTagName":"P","parentIndex":2,"textOffset":298},"text":"In\\nexamples, it’s understood that a call to a method like unwrap that could\\npanic is meant as a placeholder for the way you’d want your application to\\nhandle errors","id":"f30b6698-00d4-4e48-9136-a40f133f0af2","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"97d1f0b8cdf0a200143748f1ec4dd7bd\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":3,"textOffset":11},"endMeta":{"parentTagName":"P","parentIndex":3,"textOffset":124},"text":"the unwrap and expect methods are very handy when prototyping,\\nbefore you’re ready to decide how to handle errors","id":"544c13ca-4dd0-4921-b33e-a1ff07a397da","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"e3eb16afdbabab150c5da0ade825a14d\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":4,"textOffset":125},"endMeta":{"parentTagName":"P","parentIndex":4,"textOffset":233},"text":"Because panic! is how a test\\nis marked as a failure, calling unwrap or expect is exactly what should\\nhappen.","id":"933271f4-fd82-4aa1-8fe5-7b4aff5a3ac7","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"0c4c118be0e11c0281725506d1800b8f\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":5,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":5,"textOffset":186},"text":"It would also be appropriate to call unwrap or expect when you have some\\nother logic that ensures the Result will have an Ok value, but the logic\\nisn’t something the compiler understands","id":"1b8186f5-b4cb-4c05-b2cc-ae5b15cddd55","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"1a48308d64154effe80343c21af16b7a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":7,"textOffset":39},"endMeta":{"parentTagName":"P","parentIndex":7,"textOffset":205},"text":"when it’s possible that your code\\ncould end up in a bad state. In this context, a bad state is when some\\nassumption, guarantee, contract, or invariant has been broken","id":"16979239-701e-4da5-abf3-764cb47d8888","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"6093dac744516e5ce134151bddb4fb4d\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":8,"textOffset":193},"endMeta":{"parentTagName":"P","parentIndex":8,"textOffset":247},"text":"in cases where continuing could be\\ninsecure or harmful","id":"4ae9c824-18ea-43c7-b25e-aed3507a1f55","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"4da73ab09bb8aab91daaf7f60b759fa7\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":9,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":9,"textOffset":102},"text":"However, when failure is expected, it’s more appropriate to return a Result\\nthan to make a panic! call","id":"dec144e5-011e-494d-a5ab-4eb92d1421c8","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"45744f06b42ca13994e09322c8484df9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":10,"textOffset":24},"endMeta":{"parentTagName":"P","parentIndex":10,"textOffset":191},"text":"an operation that could put a user at risk if it’s\\ncalled using invalid values, your code should verify the values are valid first\\nand panic if the values aren’t valid","id":"95637675-e075-4dad-999a-af1c431b0d2d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"5a07bcad2796dd98337113448b7180d1\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":10,"textOffset":639},"endMeta":{"parentTagName":"P","parentIndex":10,"textOffset":745},"text":" when the contract is violated makes sense because a\\ncontract violation always indicates a caller-side bug","id":"8cd47a3d-dbbd-49d2-b74e-52f2ea659e4e","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"8fbee07c9c2abe449c79ba54fd21f5dc\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":11,"textOffset":106},"endMeta":{"parentTagName":"P","parentIndex":11,"textOffset":219},"text":"you can use Rust’s type system (and thus the type\\nchecking done by the compiler) to do many of the checks for you","id":"6da7290f-1b6c-49fa-9bd3-db5b133f0150","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"d97378a51c7e94d1779edda123e24fba\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":11,"textOffset":219},"endMeta":{"parentTagName":"P","parentIndex":11,"textOffset":383},"text":". If your\\nfunction has a particular type as a parameter, you can proceed with your code’s\\nlogic knowing that the compiler has already ensured you have a valid value","id":"baacd190-c95a-42bd-902e-3d0550e3374d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"879a3881b83b08f2468cf7673cdd3c86\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":16,"textOffset":7},"endMeta":{"parentTagName":"P","parentIndex":16,"textOffset":152},"text":", we can make a new type and put the validations in a function to create\\nan instance of the type rather than repeating the validations everywhere","id":"616112f7-4939-40cc-a3f9-0263716835de","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"ffc8cc9e7db07414e6a1e0439ed9f766\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":20,"textOffset":323},"endMeta":{"parentTagName":"CODE","parentIndex":89,"textOffset":5},"text":"It’s important that the value field be private so code\\nusing the Guess struct is not allowed to set value","id":"8eb4a458-ef58-47e6-9167-435276a92020","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch09-03-to-panic-or-not-to-panic.html\\",\\"domHash\\":\\"5164f0949a63ee5813559f03021cf912\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":2,"textOffset":210},"endMeta":{"parentTagName":"CODE","parentIndex":5,"textOffset":2},"text":"To change a function\\ninto a test function, add #[test] on the line before fn","id":"0c721c9a-3d58-4b98-8307-4294d56ede2a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"7cc9420b696a73122d42f7936fd6b994\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":11,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":11,"textOffset":52},"text":"The cargo test command runs all tests in our project","id":"bb18e9e8-34f9-4b69-abce-8b89ea65bfe5","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":13,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":13,"textOffset":356},"text":"Cargo compiled and ran the test. We see the line running 1 test. The next\\nline shows the name of the generated test function, called it_works, and that\\nthe result of running that test is ok. The overall summary test result: ok.\\nmeans that all the tests passed, and the portion that reads 1 passed; 0 failed totals the number of tests that passed or failed.","id":"f73dcf07-1108-42b4-97ee-b7bb14f12df3","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"75d7b0958610ac3035755528eb32f76e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":255},"endMeta":{"parentTagName":"EM","parentIndex":1,"textOffset":9},"text":"We can also pass an\\nargument to the cargo test command to run only tests whose name matches a\\nstring; this is called filtering","id":"8c9784e6-6b41-4812-a77b-eb25b839e743","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"87fb71ea8f04866370b45af27ca0167c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":20,"textOffset":72},"endMeta":{"parentTagName":"P","parentIndex":20,"textOffset":248},"text":"Tests\\nfail when something in the test function panics. Each test is run in a new\\nthread, and when the main thread sees that a test thread has died, the test is\\nmarked as failed","id":"63a61811-9ece-41ab-9e67-ec69d6ec5789","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"0542cc3cad2f61377301541edba80dd0\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":28,"textOffset":136},"endMeta":{"parentTagName":"P","parentIndex":28,"textOffset":341},"text":"We give the\\nassert! macro an argument that evaluates to a Boolean. If the value is\\ntrue, nothing happens and the test passes. If the value is false, the\\nassert! macro calls panic! to cause the test to fail","id":"d08da490-591c-4461-9e8b-e70ff04d7176","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"cc0e7ee4699bbf9f1349e5bb729f8bf0\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":35,"textOffset":242},"endMeta":{"parentTagName":"P","parentIndex":35,"textOffset":474},"text":"Because the tests module is an inner module, we need to bring the\\ncode under test in the outer module into the scope of the inner module. We use\\na glob here so anything we define in the outer module is available to this\\ntests module","id":"2bd4a283-2cdb-4230-8199-d52e80b841bc","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"3a4d082928c94977e7d3cfa3ffe6ad6a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":43,"textOffset":242},"endMeta":{"parentTagName":"P","parentIndex":43,"textOffset":580},"text":"However, this is such a common test that the standard library\\nprovides a pair of macros—assert_eq! and assert_ne!—to perform this test\\nmore conveniently. These macros compare two arguments for equality or\\ninequality, respectively. They’ll also print the two values if the assertion\\nfails, which makes it easier to see why the test failed;","id":"95cad75b-85bc-4619-acb0-e7e9e08348e5","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"c8d7a6ecfd81edd3d231192f19a1dd92\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":53,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":53,"textOffset":229},"text":"The assert_ne! macro will pass if the two values we give it are not equal and\\nfail if they’re equal. This macro is most useful for cases when we’re not sure\\nwhat a value will be, but we know what the value definitely shouldn’t be","id":"476a4ac5-a870-47d8-98b1-542e96520bec","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":55,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":55,"textOffset":144},"text":"You can also add a custom message to be printed with the failure message as\\noptional arguments to the assert!, assert_eq!, and assert_ne! macros","id":"f22ac977-5488-41de-8d36-a607e72a645c","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"bd2856d8bcc348e928a0fe22c5f9e04c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":55,"textOffset":437},"endMeta":{"parentTagName":"P","parentIndex":55,"textOffset":586},"text":"Custom messages are useful for documenting\\nwhat an assertion means; when a test fails, you’ll have a better idea of what\\nthe problem is with the code","id":"e3f364df-2d85-4f22-b8eb-5987e22ecb44","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"c57cbfea6377ebf5b43e5dd5cdd3bedd\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":65,"textOffset":14},"endMeta":{"parentTagName":"P","parentIndex":65,"textOffset":186},"text":"adding the attribute should_panic to our test function. The\\ntest passes if the code inside the function panics; the test fails if the code\\ninside the function doesn’t panic","id":"b561e9c1-4fe8-443e-ab58-b6a5248f667d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"4536089a9a2d4dd91b22ed568acd10c5\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":69,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":69,"textOffset":110},"text":"We place the #[should_panic] attribute after the #[test] attribute and\\nbefore the test function it applies to.","id":"a520a96d-e150-4d09-b8c3-d03e9d3f0d9d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"46756f20e41df80fa0466287dc9c8eb0\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":73,"textOffset":156},"endMeta":{"parentTagName":"P","parentIndex":73,"textOffset":268},"text":"To make should_panic tests more precise, we can add an optional\\nexpected parameter to the should_panic attribute","id":"1716aeb8-1767-4643-9a11-4e3321d91594","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"7ec8c49a8f93ae038d02d0123165019c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":82,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":82,"textOffset":226},"text":"Writing tests so they return a Result<T, E> enables you to use the question\\nmark operator in the body of tests, which can be a convenient way to write\\ntests that should fail if any operation within them returns an Err variant.","id":"d1ccbdb4-2837-483f-baf1-bb705837c753","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"b4dbd936a95f325503b7dcc278acd984\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":81,"textOffset":137},"endMeta":{"parentTagName":"P","parentIndex":81,"textOffset":226},"text":"we return\\nOk(()) when the test passes and an Err with a String inside when the test\\nfails","id":"c2099e17-6746-45d3-b2cf-4e81628cdd2b","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"c47edb9208f9f2eb9cd247d6e68beb74\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":1,"textOffset":86},"endMeta":{"parentTagName":"P","parentIndex":1,"textOffset":247},"text":"To separate these two types of arguments, you list the arguments that\\ngo to cargo test followed by the separator -- and then the ones that go to\\nthe test binary.","id":"54876c42-1c95-47fb-99eb-d86fb82e28cc","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"79bcfa2c24d3ba8686c1330ae51c7856\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":0,"textOffset":152},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":244},"text":"The default behavior of the binary produced by cargo test is to run\\nall the tests in paralle","id":"6586a033-cf7c-4e4a-9716-aa66e108a414","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"16ed6aa3bfb8925cc7e4e219aed7440e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":2,"textOffset":189},"endMeta":{"parentTagName":"P","parentIndex":2,"textOffset":268},"text":"you must make sure your tests don’t depend\\non each other or on any shared state","id":"99a3e691-5cce-40f4-b333-7972dfae84ae","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"d1e25576065df14ddc90b96969c8c65a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":4,"textOffset":121},"endMeta":{"parentTagName":"P","parentIndex":4,"textOffset":218},"text":"you can send the --test-threads flag\\nand the number of threads you want to use to the test binary","id":"f0b9fd77-a24c-4241-9461-951d4f1a73aa","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"69da9611c0645275ff935fbd21052f21\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":5,"textOffset":3},"endMeta":{"parentTagName":"P","parentIndex":5,"textOffset":86},"text":"set the number of test threads to 1, telling the program not to use any\\nparallelism","id":"ea81fd0f-33b8-4cc2-bb3f-2dc6d135804e","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"0d7766f3f0fe02d628ff00d218017eb2\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":6,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":6,"textOffset":94},"text":"By default, if a test passes, Rust’s test library captures anything printed to\\nstandard output","id":"60fcf25b-0772-44ef-8eec-e9127e9d07c8","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"14b63c25e802f87d89e48abb846fe774\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":6,"textOffset":266},"endMeta":{"parentTagName":"P","parentIndex":6,"textOffset":369},"text":"If a test fails, we’ll see whatever was\\nprinted to standard output with the rest of the failure message","id":"b40c4e06-3142-464d-9a34-80a83f8078f2","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"934642bb941158e121b8fc635c4fc49d\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":12,"textOffset":0},"endMeta":{"parentTagName":"CODE","parentIndex":20,"textOffset":13},"text":"If we want to see printed values for passing tests as well, we can tell Rust\\nto also show the output of successful tests with --show-output","id":"3a88e5b4-f4b1-424d-9cdb-46dcb58f88eb","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"ea6357f691a8746286175fe56cbd7c59\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":169},"endMeta":{"parentTagName":"P","parentIndex":14,"textOffset":288},"text":"You can choose which tests to run by passing cargo test the name\\nor names of the test(s) you want to run as an argument","id":"df8bc16e-b04e-41ad-874f-c48f359f3d09","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"b1360ec4bfb11cc74e5cf2266d9398b8\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":19,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":19,"textOffset":62},"text":"We can pass the name of any test function to cargo test to run","id":"0adcf3d4-186d-4ca5-a297-80504b4a3945","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"36528240bd57a2696f62e6ffbe60d90b\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":21,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":21,"textOffset":111},"text":"We can’t specify the names of multiple tests in this way; only the first value\\ngiven to cargo test will be used","id":"442b9825-2a93-441e-8ab8-e7cb222b6891","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"db639fb9f35ea086f3aa2ba3d319d29c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":23,"textOffset":108},"endMeta":{"parentTagName":"P","parentIndex":23,"textOffset":249},"text":"the module in which a test appears becomes\\npart of the test’s name, so we can run all the tests in a module by filtering\\non the module’s name","id":"761e9f67-5ffc-4311-b75c-d781d954cead","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"765521929b8bfd6e690769b98ffffeef\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":27,"textOffset":50},"endMeta":{"parentTagName":"CODE","parentIndex":48,"textOffset":23},"text":"If we want to run only\\nthe ignored tests, we can use cargo test -- --ignored","id":"d5b6680a-0bc8-44a4-b3fa-87f04bab8337","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"808e481d13507bdf8273c4191d607a91\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":28,"textOffset":262},"endMeta":{"parentTagName":"CODE","parentIndex":53,"textOffset":31},"text":"If you want to run all tests whether they’re\\nignored or not, you can run cargo test -- --include-ignored","id":"dd6049fc-0b9c-4379-97c6-68073e86149a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"95c9f1d2bcd37f587c61beea624e4dc0\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":19,"textOffset":57},"endMeta":{"parentTagName":"P","parentIndex":19,"textOffset":77},"text":"o run only that test","id":"9605aed0-857b-445c-a2e7-425d039034af","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"38dbdebb56fef096e133ca8861d1e12a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":26,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":26,"textOffset":70},"text":"After #[test] we add the #[ignore] line to the test we want to exclude","id":"58a7a8d1-df87-4bc9-b87b-7366bdf410a3","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-02-running-tests.html\\",\\"domHash\\":\\"96fec156ad0b85bb5b9a81e636550fd6\\"}"},{"startMeta":{"parentTagName":"EM","parentIndex":0,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":566},"text":"Unit tests are small and more focused, testing one module in isolation\\nat a time, and can test private interfaces. Integration tests are entirely\\nexternal to your library and use your code in the same way any other external\\ncode would, using only the public interface and potentially exercising multiple\\nmodules per test.","id":"224b4f70-af61-4543-bb34-f48576225089","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"0e0d1adfc22bf78673bcf59bec4daaf9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":2,"textOffset":251},"endMeta":{"parentTagName":"CODE","parentIndex":1,"textOffset":9},"text":"The convention is to create a module named tests\\nin each file to contain the test functions and to annotate the module with\\ncfg(test)","id":"0c5ea562-723e-483d-94e5-c1cf736d3942","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"2327bf3ce1942a3e4f0d512b5a720990\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":3,"textOffset":0},"endMeta":{"parentTagName":"CODE","parentIndex":5,"textOffset":11},"text":"The #[cfg(test)] annotation on the tests module tells Rust to compile and run\\nthe test code only when you run cargo test, not when you run cargo build","id":"0b0b63e9-0066-4f77-ad40-7402d5157dc8","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":6,"textOffset":305},"endMeta":{"parentTagName":"CODE","parentIndex":14,"textOffset":7},"text":"By using the cfg attribute, Cargo compiles our test code only\\nif we actively run the tests with cargo test. This includes any helper\\nfunctions that might be within this module, in addition to the functions\\nannotated with #[test]","id":"44254521-9d85-4774-aad0-c70e42a2cfaf","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"72252778aaec8a21f142b8987e60be6c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":7,"textOffset":241},"endMeta":{"parentTagName":"P","parentIndex":7,"textOffset":300},"text":"Rust’s privacy rules do allow you to test private functions","id":"a5111804-a6f2-4d6c-9921-2ea33e91f637","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"85193d7a1197ba703b9772a30b2387f1\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":12,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":12,"textOffset":262},"text":"We create a tests directory at the top level of our project directory, next\\nto src. Cargo knows to look for integration test files in this directory. We\\ncan then make as many test files as we want, and Cargo will compile each of the\\nfiles as an individual crate.","id":"e8b83e51-15f3-4e23-be3a-6b87360929fe","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"d47fb9bfafc69414eb6679e7e100407b\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":17,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":17,"textOffset":114},"text":"Each file in the tests directory is a separate crate, so we need to bring our\\nlibrary into each test crate’s scope","id":"28de1cce-b365-45dc-957a-416c2c12254d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"4c1010d19b8dc1febc45d8673bbd7643\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":18,"textOffset":0},"endMeta":{"parentTagName":"CODE","parentIndex":30,"textOffset":10},"text":"We don’t need to annotate any code in tests/integration_test.rs with\\n#[cfg(test)]. Cargo treats the tests directory specially and compiles files\\nin this directory only when we run cargo test","id":"d5d0f62a-1182-4ea3-9f0d-93da64bc84f9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"6a434c5ea0a8e3c3d569cb476cf9f57e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":19,"textOffset":94},"endMeta":{"parentTagName":"P","parentIndex":19,"textOffset":174},"text":"Note that if any test in a section fails, the following sections\\nwill not be run","id":"5f40da5e-a453-45f8-9e0c-6041d4e0f26f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"4965be21766fd9244a3cecbeb63b292a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":31,"textOffset":382},"endMeta":{"parentTagName":"P","parentIndex":31,"textOffset":502},"text":"Files in subdirectories of the tests\\ndirectory don’t get compiled as separate crates or have sections in the test\\noutput","id":"b31e28ca-1f94-4c7b-8de9-01ada7961f3f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"63426949b888451e5eed8ee44aab28d8\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":35,"textOffset":107},"endMeta":{"parentTagName":"P","parentIndex":35,"textOffset":247},"text":"we can’t create integration tests in the\\ntests directory and bring functions defined in the src/main.rs file into\\nscope with a use statement","id":"9257f7bf-2b68-4065-bae8-d0e7e2f9ccea","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"48480aeca52bc422b4f2bebbe331320a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":36,"textOffset":155},"endMeta":{"parentTagName":"P","parentIndex":36,"textOffset":277},"text":"Using that structure, integration tests can test the\\nlibrary crate with use to make the important functionality available.","id":"5690e013-0d08-4212-9183-fa716e5685a7","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-03-test-organization.html\\",\\"domHash\\":\\"acb7d29c02c6359bf257a0b99bbf96b1\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":0,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":146},"text":"We use generics to create definitions for items like function signatures or\\nstructs, which we can then use with many different concrete data types","id":"9ed93d2c-2fc7-4893-bfb6-aeee9d8b74ac","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"f840126c2ea38a9f75574b8cdabad96d\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":6,"textOffset":142},"endMeta":{"parentTagName":"P","parentIndex":6,"textOffset":347},"text":"You can use\\nany identifier as a type parameter name. But we’ll use T because, by\\nconvention, type parameter names in Rust are short, often just a letter, and\\nRust’s type-naming convention is UpperCamelCase","id":"5e2e9b8b-3804-40f2-9738-c433130246bb","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"9d0cd76ae101035ba104aa19a75e3902\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":7,"textOffset":323},"endMeta":{"parentTagName":"P","parentIndex":7,"textOffset":434},"text":"place type name declarations inside angle brackets, <>,\\nbetween the name of the function and the parameter list","id":"a79c2eff-a7a5-4692-a652-626ded00d2ff","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"e5ac875df0385f6a60919a04f5415b08\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":7,"textOffset":162},"endMeta":{"parentTagName":"P","parentIndex":7,"textOffset":281},"text":" when we use a type parameter name in a function signature, we have\\nto declare the type parameter name before we use it","id":"a7bf7ec2-233d-4cea-b542-d6f943085f4a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"1a6bc0e73d405c1056b01feab6eb9644\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":16,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":16,"textOffset":100},"text":"We can also define structs to use a generic type parameter in one or more\\nfields using the <> syntax","id":"823a3193-c4ab-47cd-ab7f-84508d5a8b33","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"154b21638e4f919a7d3c53cd94d7b883\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":19,"textOffset":108},"endMeta":{"parentTagName":"P","parentIndex":19,"textOffset":313},"text":"we declare the name of the type parameter inside\\nangle brackets just after the name of the struct. Then we use the generic type\\nin the struct definition where we would otherwise specify concrete data types","id":"f4b7ae0b-8f6d-40a2-bc53-8b567d4a2dbe","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"8b85a74dbf750983036a9a259a7a9793\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":24,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":24,"textOffset":133},"text":"To define a Point struct where x and y are both generics but could have\\ndifferent types, we can use multiple generic type parameters.","id":"c1f6280b-a1a3-4ff0-9d02-cb3ec15bdf36","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"4be6a422e5e13a8721e7b4774aad9a33\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":27,"textOffset":50},"endMeta":{"parentTagName":"P","parentIndex":27,"textOffset":315},"text":"You can use as many generic\\ntype parameters in a definition as you want, but using more than a few makes\\nyour code hard to read. If you're finding you need lots of generic types in\\nyour code, it could indicate that your code needs restructuring into smaller\\npieces.","id":"d5318005-770f-4a95-811b-8b6da66e3e7c","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"c0fd74dfc6b076d961fd096b15242b9c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":38,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":38,"textOffset":82},"text":"We can also specify constraints on generic types when defining methods on the\\ntype","id":"3b70bce1-64a6-4b4a-90d3-f69fb7bc8506","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"6dfbe41d89b508b8d8f9134e22e63cc9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":37,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":37,"textOffset":117},"text":"Note that we have to declare T just after impl so we can use T to specify\\nthat we’re implementing methods on the type","id":"071f4a4b-8989-44aa-bc4d-76afe7b5913d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"11fd149ae2ba78e2f556b84c69e27d33\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":42,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":42,"textOffset":90},"text":"You cannot simultaneously implement specific and generic methods of the same name this way","id":"4345b32c-155e-4543-af10-d241666560d5","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"c19efcba177a4ce0882814993155037d\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":42,"textOffset":371},"endMeta":{"parentTagName":"P","parentIndex":42,"textOffset":491},"text":"Rust does not have inheritance-like mechanisms for specializing methods as you might find in an object-oriented language","id":"ee7dc210-83ec-4c87-933a-b75ac9b029a0","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"ca152ad21240387da93f8a94dfd15b62\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":43,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":43,"textOffset":126},"text":"Generic type parameters in a struct definition aren’t always the same as those\\nyou use in that same struct’s method signatures","id":"a5614c08-9974-4b25-aee9-ae8e95a38471","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"09efa4bca1a88a42e557a1dd66415783\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":49,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":49,"textOffset":233},"text":"Rust accomplishes this by performing monomorphization of the code using\\ngenerics at compile time. Monomorphization is the process of turning generic\\ncode into specific code by filling in the concrete types that are used when\\ncompiled","id":"43a529aa-9251-409f-8ede-bb117a185285","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"105eadb4f5dd4d916a6a920661516859\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":54,"textOffset":89},"endMeta":{"parentTagName":"P","parentIndex":54,"textOffset":312},"text":"Because Rust compiles generic code into code that specifies the\\ntype in each instance, we pay no runtime cost for using generics. When the code\\nruns, it performs just as it would if we had duplicated each definition by\\nhand","id":"33a1faf0-e414-46a6-9d4d-57039846519c","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"8a735c15f351becfcb55a8efce8472d6\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":54,"textOffset":269},"endMeta":{"parentTagName":"P","parentIndex":54,"textOffset":550},"text":"All primitive types and most of\\nthe standard library types implement these traits. For structs and enums that\\nyou define yourself, you’ll need to implement PartialEq to assert equality of\\nthose types. You’ll also need to implement Debug to print the values when the\\nassertion fails","id":"a9f22477-71dc-4d04-a93d-9569aef2a309","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"539c799340e6952e80569c9a9ec345f9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":54,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":54,"textOffset":268},"text":"Under the surface, the assert_eq! and assert_ne! macros use the operators\\n== and !=, respectively. When the assertions fail, these macros print their\\narguments using debug formatting, which means the values being compared must\\nimplement the PartialEq and Debug traits.","id":"81661154-2917-43fa-b162-8a33493390f9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch11-01-writing-tests.html\\",\\"domHash\\":\\"8dba4ad1e9eb73b16383a3a1f188aaa0\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":28,"textOffset":24},"endMeta":{"parentTagName":"P","parentIndex":28,"textOffset":88},"text":"we can define enums to hold generic data types in their\\nvariants","id":"055d7b9a-96d1-45a6-8a51-09eeb341a7a7","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"1b4f7f6c630ae1ecafa66c440f3ff36c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":32,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":32,"textOffset":195},"text":"When you recognize situations in your code with multiple struct or enum\\ndefinitions that differ only in the types of the values they hold, you can\\navoid duplication by using generic types instead","id":"2a3c3dd0-7b80-4d27-beba-a0224f2ce415","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-01-syntax.html\\",\\"domHash\\":\\"96cc66be45552b101c0301c56b873736\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":0,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":244},"text":"A trait defines functionality a particular type has and can share with other\\ntypes. We can use traits to define shared behavior in an abstract way. We can\\nuse trait bounds to specify that a generic type can be any type that has\\ncertain behavior","id":"cf49c28c-327c-4b8b-bb98-ac093e5822db","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"6743b9fcc57cf1b169fb4ef6c7a955d2\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":2,"textOffset":163},"endMeta":{"parentTagName":"P","parentIndex":2,"textOffset":292},"text":"Trait definitions are a way to group method signatures together to\\ndefine a set of behaviors necessary to accomplish some purpose","id":"fbcd9ea7-487b-44d9-92e3-79291f252b3f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"486efb13c5949a75fc747093fcce6161\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":8,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":8,"textOffset":207},"text":"After the method signature, instead of providing an implementation within curly\\nbrackets, we use a semicolon. Each type implementing this trait must provide\\nits own custom behavior for the body of the method","id":"0adb09c9-8b35-45c3-86a6-f4d1699cbd1c","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"2fc0c153b40bade378e70fc894108bef\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":9,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":9,"textOffset":127},"text":"A trait can have multiple methods in its body: the method signatures are listed\\none per line and each line ends in a semicolon.","id":"87ddbac0-c772-4eca-8afd-09a43c8c5ac5","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"667410a44ff1e93f70c64c76d25b6ac9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":13,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":13,"textOffset":544},"text":"Implementing a trait on a type is similar to implementing regular methods. The\\ndifference is that after impl, we put the trait name we want to implement,\\nthen use the for keyword, and then specify the name of the type we want to\\nimplement the trait for. Within the impl block, we put the method signatures\\nthat the trait definition has defined. Instead of adding a semicolon after each\\nsignature, we use curly brackets and fill in the method body with the specific\\nbehavior that we want the methods of the trait to have for the particular type.","id":"292c2d37-81c1-4620-9acc-e9640a50b4d8","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"3950b8719de05c619fd46a45ea717916\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":181},"endMeta":{"parentTagName":"P","parentIndex":14,"textOffset":295},"text":"we call regular methods. The only\\ndifference is that the user must bring the trait into scope as well as the\\ntypes","id":"3a7fa981-4dfc-484f-b864-b2be8aca9a4f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"61eee8558cdc5f111a3306d04e832d30\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":16,"textOffset":134},"endMeta":{"parentTagName":"P","parentIndex":16,"textOffset":268},"text":"One restriction to\\nnote is that we can implement a trait on a type only if at least one of the\\ntrait or the type is local to our crate","id":"ac49234b-f6dd-4e4c-b6ab-5b728038bf70","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"3d614f480d62e4706c62a650787b82b8\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":17,"textOffset":256},"endMeta":{"parentTagName":"P","parentIndex":17,"textOffset":613},"text":" This restriction is part of a property\\ncalled coherence, and more specifically the orphan rule, so named because\\nthe parent type is not present. This rule ensures that other people’s code\\ncan’t break your code and vice versa. Without the rule, two crates could\\nimplement the same trait for the same type, and Rust wouldn’t know which\\nimplementation to use.","id":"76889a56-e7ac-4f97-8378-62200716e6b1","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"05af47a3f8903336ba67957ce367e94c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":25,"textOffset":154},"endMeta":{"parentTagName":"P","parentIndex":25,"textOffset":305},"text":"the syntax for overriding a default implementation is the same as the syntax\\nfor implementing a trait method that doesn’t have a default implementation","id":"a7afe89b-cfd0-4bdc-b736-cd024fccbe16","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"213c1cad3aea53276ccc78abc82d66e2\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":26,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":26,"textOffset":129},"text":"Default implementations can call other methods in the same trait, even if those\\nother methods don’t have a default implementation","id":"083791ab-652c-49fc-8fe3-4889dadc857d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"63fc74a9948b9251e7f3c032a2d05a53\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":22,"textOffset":71},"endMeta":{"parentTagName":"P","parentIndex":22,"textOffset":101},"text":"we\\nspecify an empty impl block","id":"0d82ac89-02d6-4d23-85f1-8b572a6dc983","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"66ff7a1a2c51f037d80499ad573e8c36\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":30,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":30,"textOffset":117},"text":"Note that it isn’t possible to call the default implementation from an\\noverriding implementation of that same method.","id":"e2fcdeca-c2c6-46f7-9ce2-b6b1c91fb58d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"1eaf0ad501642deaf7fdd32c0ad620d7\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":42,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":42,"textOffset":166},"text":"Instead of a concrete type for the item parameter, we specify the impl\\nkeyword and the trait name. This parameter accepts any type that implements the\\nspecified trait","id":"18107e0f-4c5b-418a-a4b1-d29e3c163883","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"47599a448ef4f6182ead71bc9d81dfe0\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":44,"textOffset":0},"endMeta":{"parentTagName":"EM","parentIndex":5,"textOffset":11},"text":"The impl Trait syntax works for straightforward cases but is actually syntax\\nsugar for a longer form known as a trait bound","id":"6081d973-77c0-4e6f-9fba-8df098aae1d3","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":49,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":49,"textOffset":45},"text":"We can also specify more than one trait bound","id":"88a907e4-4869-42e4-938a-0695b0611cac","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"9b1fd70ed6ba7273c176de2fe8345cdb\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":49,"textOffset":211},"endMeta":{"parentTagName":"P","parentIndex":49,"textOffset":242},"text":"We can do\\nso using the + syntax","id":"7ab67c3e-0a0d-4895-9bad-673b18ab1ae3","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"8cca3ee961a77902b889b2e6016b8d2e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":50,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":50,"textOffset":61},"text":"The + syntax is also valid with trait bounds on generic types","id":"f9fb191d-5b6e-4bf0-b409-17b3b55a86b4","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":52,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":52,"textOffset":45},"text":"Using too many trait bounds has its downsides","id":"8b9fe473-1441-44e5-ab61-f7754d086dbe","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"e5b98ec62b425059995dc25c525c1969\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":52,"textOffset":277},"endMeta":{"parentTagName":"P","parentIndex":52,"textOffset":398},"text":"For this reason, Rust has alternate\\nsyntax for specifying trait bounds inside a where clause after the function\\nsignature","id":"cc14da81-1d23-4f45-9787-88119603b056","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"bb7415b1d8f59e61a02af8b832662505\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":55,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":55,"textOffset":115},"text":"We can also use the impl Trait syntax in the return position to return a\\nvalue of some type that implements a trait","id":"c47348cd-de24-4f6f-8810-bdb69c3af432","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"96b8ad14f5e77ce749840e500f1d8681\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":58,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":58,"textOffset":70},"text":"However, you can only use impl Trait if you’re returning a single type","id":"03648ab9-f2c3-4e52-9dd1-83816b01120a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"faf1b73ddcdee89170767095dd3cfd36\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":18,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":18,"textOffset":265},"text":"Sometimes it’s useful to have default behavior for some or all of the methods\\nin a trait instead of requiring implementations for all methods on every type.\\nThen, as we implement the trait on a particular type, we can keep or override\\neach method’s default behavior","id":"838d0d33-16df-429e-9cdb-c60fd4a32cf8","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"a198f133b59239df4b657a4e61ba583f\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":60,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":60,"textOffset":161},"text":"By using a trait bound with an impl block that uses generic type parameters,\\nwe can implement methods conditionally for types that implement the specified\\ntraits","id":"aa9d7c32-effe-4d7e-9590-f7f4998e4be8","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"94ec97fe0e2dad45abdff7a508c91c98\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":63,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":63,"textOffset":248},"text":"We can also conditionally implement a trait for any type that implements\\nanother trait. Implementations of a trait on any type that satisfies the trait\\nbounds are called blanket implementations and are extensively used in the\\nRust standard library.","id":"9173312c-6e13-40da-a088-16dbdc61b178","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"c3964fc2ca609bcf3d4ceb1042fa87d9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":66,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":66,"textOffset":328},"text":"Traits and trait bounds let us write code that uses generic type parameters to\\nreduce duplication but also specify to the compiler that we want the generic\\ntype to have particular behavior. The compiler can then use the trait bound\\ninformation to check that all the concrete types used with our code provide the\\ncorrect behavior","id":"a5d36009-dd4c-4d45-8c1b-c260013cc6e9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-02-traits.html\\",\\"domHash\\":\\"0974abc04cd5dc2b2dbc2be31158442c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":0,"textOffset":69},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":200},"text":"Rather\\nthan ensuring that a type has the behavior we want, lifetimes ensure that\\nreferences are valid as long as we need them to be","id":"49d22a9b-460e-4a5a-ad0b-4566bc931938","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"90347ee7f04eefb39dc5b909670a2c9b\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":3,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":3,"textOffset":147},"text":"The main aim of lifetimes is to prevent dangling references, which cause a\\nprogram to reference data other than the data it’s intended to reference","id":"46c20dfe-41e9-456e-a6c8-154ed98796ef","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"3bcc9d1dc71869a84e18738252737e37\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":11,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":11,"textOffset":435},"text":"Here, we’ve annotated the lifetime of r with 'a and the lifetime of x\\nwith 'b. As you can see, the inner 'b block is much smaller than the outer\\n'a lifetime block. At compile time, Rust compares the size of the two\\nlifetimes and sees that r has a lifetime of 'a but that it refers to memory\\nwith a lifetime of 'b. The program is rejected because 'b is shorter than\\n'a: the subject of the reference doesn’t live as long as the reference","id":"3078850c-3f7d-45d2-b1a6-3c10a09e3b2c","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"409409b2aeb04359b6b3e882b561609a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":1,"textOffset":315},"endMeta":{"parentTagName":"P","parentIndex":1,"textOffset":651},"text":"We only must annotate types\\nwhen multiple types are possible. In a similar way, we must annotate lifetimes\\nwhen the lifetimes of references could be related in a few different ways. Rust\\nrequires us to annotate the relationships using generic lifetime parameters to\\nensure the actual references used at runtime will definitely be valid.","id":"bf41ca8d-0254-45ee-8102-f39ec169c9e9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"46fa55673a82c10f57e6633708bfbf33\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":24,"textOffset":31},"endMeta":{"parentTagName":"P","parentIndex":24,"textOffset":151},"text":"return type needs a generic lifetime parameter\\non it because Rust can’t tell whether the reference being returned refers","id":"64df876a-8328-459f-8060-316025f41ede","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"df389a192d6b283cc175248d16626918\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":25,"textOffset":542},"endMeta":{"parentTagName":"P","parentIndex":25,"textOffset":697},"text":"To fix this error, we’ll add generic lifetime parameters that\\ndefine the relationship between the references so the borrow checker can\\nperform its analysis","id":"959544ea-c6b4-489b-98e6-32a0487955ee","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"b3d05128f7bb99c0e04235721ae4c5fb\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":26,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":26,"textOffset":196},"text":"Lifetime annotations don’t change how long any of the references live. Rather,\\nthey describe the relationships of the lifetimes of multiple references to each\\nother without affecting the lifetimes","id":"4e01d40e-495a-4908-aa20-4f86e2f4ea7a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"f3457d17f8c1eb23977b3761a35b66ef\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":27,"textOffset":53},"endMeta":{"parentTagName":"P","parentIndex":27,"textOffset":164},"text":"the names of lifetime\\nparameters must start with an apostrophe (') and are usually all lowercase\\nand very short","id":"8f9accce-586c-42f6-8191-f7e89265a95e","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"11068f520e5dde3520c66ed6b7129236\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":27,"textOffset":249},"endMeta":{"parentTagName":"P","parentIndex":27,"textOffset":383},"text":"We place lifetime parameter annotations after the & of a\\nreference, using a space to separate the annotation from the reference’s type","id":"3b974b51-638d-4918-898c-568728f04902","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"35d39c62905b24503dca373ffd94546c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":29,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":29,"textOffset":183},"text":"One lifetime annotation by itself doesn’t have much meaning, because the\\nannotations are meant to tell Rust how generic lifetime parameters of multiple\\nreferences relate to each other","id":"f38f47fa-f2cd-48b6-9621-a1029dfdbb03","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"486f1a56c5e61eb5e7a120037ce6487f\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":30,"textOffset":52},"endMeta":{"parentTagName":"P","parentIndex":30,"textOffset":173},"text":"we need to declare the\\ngeneric lifetime parameters inside angle brackets between the function name\\nand the parameter list","id":"9581c724-a86b-47a8-b0c3-56a420a098cf","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"67b36a2c2450f0d7175c79f61363b304\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":31,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":31,"textOffset":219},"text":"We want the signature to express the following constraint: the returned\\nreference will be valid as long as both the parameters are valid. This is the\\nrelationship between lifetimes of the parameters and the return value","id":"032f3e73-a698-446f-95ee-1529bc4d9444","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"d1253fdfeb633f3679d73444b4dad7d2\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":36,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":36,"textOffset":260},"text":"Remember, when we specify the lifetime parameters in this function signature,\\nwe’re not changing the lifetimes of any values passed in or returned. Rather,\\nwe’re specifying that the borrow checker should reject any values that don’t\\nadhere to these constraints","id":"7de356bf-4a54-4c44-9358-5a4502ded18f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"4df560579f8140c2252fddf3ed2e45e9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":37,"textOffset":40},"endMeta":{"parentTagName":"P","parentIndex":37,"textOffset":333},"text":"the annotations go in the function\\nsignature, not in the function body. The lifetime annotations become part of\\nthe contract of the function, much like the types in the signature. Having\\nfunction signatures contain the lifetime contract means the analysis the Rust\\ncompiler does can be simpler","id":"b0ed0256-f817-45ba-bdcf-a579dbc190dd","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"9c3319db35ca21360485d757903f12d8\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":57,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":57,"textOffset":96},"text":"The way in which you need to specify lifetime parameters depends on what your\\nfunction is doing.","id":"809e6462-fe62-4e3d-90e5-d89c8ac01e6b","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"40e372dc61516871b36f72f0053dbe22\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":60,"textOffset":152},"endMeta":{"parentTagName":"P","parentIndex":60,"textOffset":384},"text":"If\\nthe reference returned does not refer to one of the parameters, it must refer\\nto a value created within this function. However, this would be a dangling\\nreference because the value will go out of scope at the end of the function.","id":"29bbd727-1d05-4624-803e-e908a17fb9e1","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"0f5eee2a7a1a58b0ca02dcf2b9596ec7\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":64,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":64,"textOffset":294},"text":"Ultimately, lifetime syntax is about connecting the lifetimes of various\\nparameters and return values of functions. Once they’re connected, Rust has\\nenough information to allow memory-safe operations and disallow operations that\\nwould create dangling pointers or otherwise violate memory safety","id":"e703632f-1ef0-4999-b0f6-259c64a5596f","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"4006cc1aeeb7cd6c144bc0b2a724cb21\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":65,"textOffset":56},"endMeta":{"parentTagName":"P","parentIndex":65,"textOffset":203},"text":"We can define structs to\\nhold references, but in that case we would need to add a lifetime annotation on\\nevery reference in the struct’s definition","id":"31ca5e04-5ba1-43d3-8ded-181f7e02d2ec","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"30a73ee636c528d5e6d77dbf1d130277\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":68,"textOffset":87},"endMeta":{"parentTagName":"P","parentIndex":68,"textOffset":293},"text":"As with generic data types, we declare the name of the generic\\nlifetime parameter inside angle brackets after the name of the struct so we can\\nuse the lifetime parameter in the body of the struct definition","id":"1dd29e9d-283e-43c5-a795-20e7def914ea","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"ab1c2f78b30218d1ad9b714cf012dceb\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":74,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":74,"textOffset":236},"text":"After writing a lot of Rust code, the Rust team found that Rust programmers\\nwere entering the same lifetime annotations over and over in particular\\nsituations. These situations were predictable and followed a few deterministic\\npatterns.","id":"84819347-b905-4c46-a409-d6fcf64081a3","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"ae7920fbee693d012ffb1ce1259a6a76\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":76,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":76,"textOffset":295},"text":"The patterns programmed into Rust’s analysis of references are called the\\nlifetime elision rules. These aren’t rules for programmers to follow; they’re\\na set of particular cases that the compiler will consider, and if your code\\nfits these cases, you don’t need to write the lifetimes explicitly.","id":"3b21a105-1115-4e4b-8c6c-32b050329194","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"e646d48c320a9064442b917c23dd7894\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":77,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":77,"textOffset":46},"text":"The elision rules don’t provide full inference","id":"5b050bb4-28c8-4533-9e27-a1792cc963e0","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"4b2a20d26b9a1ab348d92b8ed091b76e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":78,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":78,"textOffset":130},"text":"Lifetimes on function or method parameters are called input lifetimes, and\\nlifetimes on return values are called output lifetimes.","id":"f5e442d4-42c4-4c27-91b4-2e8731218ede","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"c24db1e59979a01cfe5c2d02988977a9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":79,"textOffset":216},"endMeta":{"parentTagName":"P","parentIndex":79,"textOffset":376},"text":" If the\\ncompiler gets to the end of the three rules and there are still references for\\nwhich it can’t figure out lifetimes, the compiler will stop with an error","id":"919a87f6-3948-4129-9041-9accc4811eef","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"94d698abd3ff2df486c65dfd6f4b70ec\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":80,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":80,"textOffset":110},"text":"The first rule is that the compiler assigns a different lifetime parameter to each lifetime in each input type","id":"e87ae790-7c64-4226-b5ab-f893f840fcc9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"b7eb94d1236aa659466e6c131fc1f3ee\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":81,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":81,"textOffset":134},"text":"The second rule is that, if there is exactly one input lifetime parameter, that\\nlifetime is assigned to all output lifetime parameters","id":"86f29e22-8253-4152-ba67-1da190543ae9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"3cd18766dbb3fa8a2512305aba1e3993\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":82,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":82,"textOffset":203},"text":"The third rule is that, if there are multiple input lifetime parameters, but\\none of them is &self or &mut self because this is a method, the lifetime of\\nself is assigned to all output lifetime parameters","id":"ba7f5fd2-3495-4d5c-aac6-14a565b780df","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch10-03-lifetime-syntax.html\\",\\"domHash\\":\\"8f493e50554a559b3a515bdb28393f44\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":20,"textOffset":206},"endMeta":{"parentTagName":"P","parentIndex":20,"textOffset":372},"text":"But for now, it’s okay to copy a few\\nstrings to continue making progress because you’ll make these copies only\\nonce and your file path and query string are very small","id":"6d8a1f73-ea70-401f-9a7f-2adf1444209d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch12-03-improving-error-handling-and-modularity.html\\",\\"domHash\\":\\"9aab519cb335de7524241d07d5239adf\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":45,"textOffset":308},"endMeta":{"parentTagName":"P","parentIndex":45,"textOffset":439},"text":" A nonzero exit status is a convention to signal to the process that\\ncalled our program that the program exited with an error state","id":"b8bb5185-a76b-4c6b-963c-42c2d418a3ab","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch12-03-improving-error-handling-and-modularity.html\\",\\"domHash\\":\\"555b1803032ca61f9116768ec5dc2ed2\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":48,"textOffset":145},"endMeta":{"parentTagName":"CODE","parentIndex":168,"textOffset":14},"text":"Using unwrap_or_else allows us to define some custom, non-panic! error\\nhandling. If the Result is an Ok value, this method’s behavior is similar\\nto unwrap: it returns the inner value Ok is wrapping. However, if the value\\nis an Err value, this method calls the code in the closure, which is an\\nanonymous function we define and pass as an argument to unwrap_or_else","id":"38effa26-cb19-4ea5-8ff5-aae580f68d2d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch12-03-improving-error-handling-and-modularity.html\\",\\"domHash\\":\\"a6dd56e1d8a8a1e615bb9e9488d6136f\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":20,"textOffset":0},"endMeta":{"parentTagName":"CODE","parentIndex":31,"textOffset":5},"text":"Rust has a helpful method to handle line-by-line iteration of strings,\\nconveniently named lines","id":"60effa6e-e394-4a4c-8fef-0fb94168476b","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch12-04-testing-the-librarys-functionality.html\\",\\"domHash\\":\\"f0e617083b4b6d4570a328c02bf50f7f\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":18,"textOffset":217},"endMeta":{"parentTagName":"P","parentIndex":18,"textOffset":338},"text":"Then\\nwe’ll use the var function from the env module to check to see if any value\\nhas been set for an environment variable","id":"d8417335-3bf8-4e6e-8cf4-70d3f7236140","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch12-05-working-with-environment-variables.html\\",\\"domHash\\":\\"102766d424ab13690326783f94a762e5\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":21,"textOffset":154},"endMeta":{"parentTagName":"P","parentIndex":21,"textOffset":403},"text":"The env::var function returns a Result that will be the\\nsuccessful Ok variant that contains the value of the environment variable if\\nthe environment variable is set to any value. It will return the Err variant\\nif the environment variable is not set.","id":"4a89f2d5-50e5-4772-8d7c-abd4eb2559a1","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch12-05-working-with-environment-variables.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":1,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":1,"textOffset":221},"text":"Rust’s closures are anonymous functions you can save in a variable or pass as\\narguments to other functions. You can create the closure in one place and then\\ncall the closure elsewhere to evaluate it in a different context","id":"916c105c-0c90-4261-a9c4-4d4f22eb87be","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"dedaf661775e5a64a1ef92e22897edc9\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":8,"textOffset":343},"endMeta":{"parentTagName":"P","parentIndex":8,"textOffset":792},"text":"The unwrap_or_else method on\\nOption<T> is defined by the standard library.\\nIt takes one argument: a closure without any arguments that returns a value T\\n(the same type stored in the Some variant of the Option<T>, in this case\\nShirtColor). If the Option<T> is the Some variant, unwrap_or_else\\nreturns the value from within the Some. If the Option<T> is the None\\nvariant, unwrap_or_else calls the closure and returns the value returned by\\nthe closure.","id":"351d660d-f569-4979-9df3-705f0f609266","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":11,"textOffset":273},"endMeta":{"parentTagName":"P","parentIndex":11,"textOffset":501},"text":"The closure captures an\\nimmutable reference to the self Inventory instance and passes it with the\\ncode we specify to the unwrap_or_else method. Functions, on the other hand,\\nare not able to capture their environment in this way.","id":"4acf7a8b-7446-4f42-b526-eac1946e49a5","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"4501ed4597464e57e3d57ade215c5a8f\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":12,"textOffset":59},"endMeta":{"parentTagName":"P","parentIndex":12,"textOffset":174},"text":"Closures don’t\\nusually require you to annotate the types of the parameters or the return value\\nlike fn functions do","id":"555da691-02e8-457d-97b7-274db58b3a6d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"e4ba4de9e5c2927ef468f5a9be3b91bc\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":12,"textOffset":426},"endMeta":{"parentTagName":"P","parentIndex":12,"textOffset":600},"text":"Closures, on the other hand, aren’t used\\nin an exposed interface like this: they’re stored in variables and used without\\nnaming them and exposing them to users of our library","id":"45bcbc90-894f-4923-9dd1-b3fa36085d31","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"5e537b1aa49f425789020696c3c90368\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":13,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":13,"textOffset":109},"text":"Closures are typically short and relevant only within a narrow context rather\\nthan in any arbitrary scenario.","id":"efbbb769-61f5-4770-8d17-8240d8046c62","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"e8355413142535be5bffcbd7701a3c2c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":14,"textOffset":155},"text":"As with variables, we can add type annotations if we want to increase\\nexplicitness and clarity at the cost of being more verbose than is strictly\\nnecessary","id":"f72bfda1-184f-42bd-a105-5115f03070dd","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"24fa94fb8c872471ad8577d9f6f3bdfe\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":18,"textOffset":389},"endMeta":{"parentTagName":"P","parentIndex":18,"textOffset":535},"text":"The\\nadd_one_v3 and add_one_v4 lines require the closures to be evaluated to be\\nable to compile because the types will be inferred from their usage","id":"7cec24fb-964f-4d23-be4a-95381dc52c8b","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"4cc79ff6318ecedb45a283b92c656f96\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":19,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":19,"textOffset":122},"text":"For closure definitions, the compiler will infer one concrete type for each of\\ntheir parameters and for their return value","id":"2aa2c98c-0c73-4ef3-8b5a-2c69de55676e","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"cd22c1014b1d5832fd18dbedac4dd9fb\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":32,"textOffset":88},"endMeta":{"parentTagName":"P","parentIndex":32,"textOffset":311},"text":"the three ways a function can take a parameter: borrowing\\nimmutably, borrowing mutably, and taking ownership. The closure will decide\\nwhich of these to use based on what the body of the function does with the\\ncaptured value","id":"1fbe163d-2269-42d6-98dd-0f9d4f086ca9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"2295883374254fb200f12ccdd50f8910\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":43,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":43,"textOffset":215},"text":"If you want to force the closure to take ownership of the values it uses in the\\nenvironment even though the body of the closure doesn’t strictly need\\nownership, you can use the move keyword before the parameter list","id":"3357a275-a391-4245-91ab-f98b21f5de17","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"d664521d2fe37b4e3d7387bdbaadf1a5\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":44,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":44,"textOffset":124},"text":"This technique is mostly useful when passing a closure to a new thread to move\\nthe data so that it’s owned by the new thread","id":"966cc99f-f7d8-4e78-836f-2e7e3af5debf","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-01-closures.html\\",\\"domHash\\":\\"8c7eeaf718b2ab8fb939abe0b0063e89\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":0,"textOffset":85},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":200},"text":"An iterator is responsible for the logic of iterating over each item and\\ndetermining when the sequence has finished","id":"d06cfa5d-5741-43db-be91-eb77dc8921b2","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"07ac70218a46318c255bd3c2e21d7bfa\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":1,"textOffset":1},"endMeta":{"parentTagName":"P","parentIndex":1,"textOffset":118},"text":"n Rust, iterators are lazy, meaning they have no effect until you call\\nmethods that consume the iterator to use it up","id":"3b109ac1-c939-4e4b-9a8a-b5493d4cac01","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"c6069936482bd1658631e18a59ecd874\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":8,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":8,"textOffset":86},"text":"All iterators implement a trait named Iterator that is defined in the\\nstandard library","id":"6b9fb5e5-57cf-4fd7-977c-abf45d65a0da","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"ed3bdc2ea8621c746c0bb0d1e69a1a4c\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":9,"textOffset":193},"endMeta":{"parentTagName":"P","parentIndex":9,"textOffset":452},"text":"all you need to know is that\\nthis code says implementing the Iterator trait requires that you also define\\nan Item type, and this Item type is used in the return type of the next\\nmethod. In other words, the Item type will be the type returned from the\\niterator","id":"2d2a4e35-44d6-44fb-a96b-5e3542616a48","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"2278b11786238915331b66e72f7edab5\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":10,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":10,"textOffset":192},"text":"The Iterator trait only requires implementors to define one method: the\\nnext method, which returns one item of the iterator at a time wrapped in\\nSome and, when iteration is over, returns None.","id":"21746b4e-b4c5-4593-aff4-b7de8c6c7cb8","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":45},"endMeta":{"parentTagName":"P","parentIndex":14,"textOffset":236},"text":"calling the next method on an\\niterator changes internal state that the iterator uses to keep track of where\\nit is in the sequence. In other words, this code consumes, or uses up, the\\niterator","id":"b89a5a34-cd72-42a8-ae0a-0f3667d3e36b","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"c5b23f4a68cc044cf49848618eee530a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":14,"textOffset":330},"endMeta":{"parentTagName":"P","parentIndex":14,"textOffset":435},"text":"when we used a for loop because the loop took\\nownership of v1_iter and made it mutable behind the scenes.","id":"30241a84-23c7-4609-bacb-07116cefab65","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"54374ce176be6a6cb748f2067e4cd580\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":15,"textOffset":0},"endMeta":{"parentTagName":"CODE","parentIndex":42,"textOffset":4},"text":"Also note that the values we get from the calls to next are immutable\\nreferences to the values in the vector. The iter method produces an iterator\\nover immutable references. If we want to create an iterator that takes\\nownership of v1 and returns owned values, we can call into_iter instead of\\niter. Similarly, if we want to iterate over mutable references, we can call\\niter_mut instead of iter","id":"62343832-ad61-4555-98e5-99f1871bbf22","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"b28028637849cd1bfd18bb2421e228c5\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":17,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":17,"textOffset":95},"text":"Methods that call next are called consuming adaptors, because calling them\\nuses up the iterator","id":"819baa90-143b-44b4-8bdb-b1e0fbc6b505","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"aac8ec464f700afff91302ae335574f2\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":16,"textOffset":230},"endMeta":{"parentTagName":"P","parentIndex":16,"textOffset":388},"text":"Some of these methods call the next method in their definition, which\\nis why you’re required to implement the next method when implementing the\\nIterator trait","id":"f33e5164-bd31-46cc-a20d-75098b63252b","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"195db03cac3036fbd7b4eb829a74336f\\"}"},{"startMeta":{"parentTagName":"EM","parentIndex":4,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":21,"textOffset":184},"text":"Iterator adaptors are methods defined on the Iterator trait that don’t\\nconsume the iterator. Instead, they produce different iterators by changing\\nsome aspect of the original iterator.","id":"cdd6048c-5399-44c3-bed3-db428f36563d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"693b39af540d308b781f81386ccbbbfa\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":26,"textOffset":122},"endMeta":{"parentTagName":"P","parentIndex":26,"textOffset":190},"text":"iterator adaptors are lazy, and\\nwe need to consume the iterator here","id":"d93a39e4-a0ff-4aca-8405-61fcd2021df3","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"7af63ace215f722ff7d58c9b14e0d849\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":32,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":32,"textOffset":232},"text":"You can chain multiple calls to iterator adaptors to perform complex actions in\\na readable way. But because all iterators are lazy, you have to call one of the\\nconsuming adaptor methods to get results from calls to iterator adaptors","id":"752b2f1a-e923-4125-b1da-faa37a8e31fa","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"d0aeda481698704f3e8ec1b7ca44bb4a\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":33,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":33,"textOffset":172},"text":"Many iterator adapters take closures as arguments, and commonly the closures\\nwe’ll specify as arguments to iterator adapters will be closures that capture\\ntheir environment","id":"fd5dfb50-a139-4257-b2e1-a6ac402ba56a","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-02-iterators.html\\",\\"domHash\\":\\"112e156be9dc5e64277b24f1a1c6ca52\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":18,"textOffset":0},"endMeta":{"parentTagName":"CODE","parentIndex":47,"textOffset":9},"text":"We’ve updated the signature of the Config::build function so the parameter\\nargs has a generic type with the trait bounds impl Iterator<Item = String>\\ninstead of &[String]","id":"95334487-22df-4145-bd8a-56fbfbbef468","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-03-improving-our-io-project.html\\",\\"domHash\\":\\"b7c470e5d7a376bbd4499cfd414c6ee1\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":27,"textOffset":151},"endMeta":{"parentTagName":"P","parentIndex":27,"textOffset":427},"text":"The\\nfunctional programming style prefers to minimize the amount of mutable state to\\nmake code clearer. Removing the mutable state might enable a future enhancement\\nto make searching happen in parallel, because we wouldn’t have to manage\\nconcurrent access to the results vector","id":"89f0bf36-1ab7-436d-a79c-8a45b43f101c","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-03-improving-our-io-project.html\\",\\"domHash\\":\\"9c278f570f47ed814d7b7a0914c94380\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":3,"textOffset":221},"endMeta":{"parentTagName":"P","parentIndex":3,"textOffset":492},"text":"\\niterators, although a high-level abstraction, get compiled down to roughly the\\nsame code as if you’d written the lower-level code yourself. Iterators are one\\nof Rust’s zero-cost abstractions, by which we mean using the abstraction\\nimposes no additional runtime overhead.","id":"61f33de9-7722-4b29-a562-21372b0ef5f0","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-04-performance.html\\",\\"domHash\\":\\"3adc86307695429824ad7e2c654c10a8\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":7,"textOffset":312},"endMeta":{"parentTagName":"P","parentIndex":7,"textOffset":619},"text":"There’s no loop at all corresponding to the iteration over the values in\\ncoefficients: Rust knows that there are 12 iterations, so it “unrolls” the\\nloop. Unrolling is an optimization that removes the overhead of the loop\\ncontrolling code and instead generates repetitive code for each iteration of\\nthe loop.","id":"db4d07ef-745a-47ee-a7cf-4ad138ae21db","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-04-performance.html\\",\\"domHash\\":\\"7f3fd4825447746cfc98f8d35c2fccd7\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":8,"textOffset":275},"endMeta":{"parentTagName":"P","parentIndex":8,"textOffset":427},"text":"you can use iterators and closures\\nwithout fear! They make code seem like it’s higher level but don’t impose a\\nruntime performance penalty for doing so.","id":"4aae908f-9e58-4e46-ac4e-cea7e6e13877","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch13-04-performance.html\\",\\"domHash\\":\\"2229f3836c2af58b117d93f208d41eb2\\"}"},{"startMeta":{"parentTagName":"EM","parentIndex":0,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":181},"text":"release profiles are predefined and customizable profiles with\\ndifferent configurations that allow a programmer to have more control over\\nvarious options for compiling code","id":"5b190602-160b-4dc8-9ced-d7fc5353ad18","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-01-release-profiles.html\\",\\"domHash\\":\\"f9bd7994fcdda9bdebebf3bd53052a69\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":4,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":4,"textOffset":155},"text":"Cargo has default settings for each of the profiles that apply when you haven't\\nexplicitly added any [profile.*] sections in the project’s Cargo.toml file.","id":"c3760f96-c381-42fe-a5b6-11f09b3daf18","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-01-release-profiles.html\\",\\"domHash\\":\\"472b71c97ad3ebfce1f7a9b301ab17fd\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":6,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":6,"textOffset":111},"text":"The opt-level setting controls the number of optimizations Rust will apply to\\nyour code, with a range of 0 to 3","id":"dbc6d853-3e80-437a-a5f8-1ce549d6f0c2","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-01-release-profiles.html\\",\\"domHash\\":\\"02edd93949f6d3c57d9822691b59f649\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":7,"textOffset":0},"endMeta":{"parentTagName":"EM","parentIndex":2,"textOffset":10},"text":"You can override a default setting by adding a different value for it in\\nCargo.toml","id":"0a0c347e-7c3b-4e28-8cd8-53e8ffb3a240","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-01-release-profiles.html\\",\\"domHash\\":\\"e10e256df674bb8364976849b5ea08b3\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":0,"textOffset":151},"endMeta":{"parentTagName":"P","parentIndex":0,"textOffset":276},"text":"The crate registry at\\ncrates.io distributes the source code of\\nyour packages, so it primarily hosts code that is open source.","id":"cbdea7c3-8387-4454-8aa6-368351086f9d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"0f20834fc807c80465400303bc937ed7\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":2,"textOffset":222},"endMeta":{"parentTagName":"P","parentIndex":2,"textOffset":561},"text":"Rust also has\\na particular kind of comment for documentation, known conveniently as a\\ndocumentation comment, that will generate HTML documentation. The HTML\\ndisplays the contents of documentation comments for public API items intended\\nfor programmers interested in knowing how to use your crate as opposed to how\\nyour crate is implemented.","id":"c78f4ad3-279e-4cb7-8d16-148a0244f5c7","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"7cb07fdf2cc69373750ab042097ddea5\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":3,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":3,"textOffset":187},"text":"Documentation comments use three slashes, ///, instead of two and support\\nMarkdown notation for formatting the text. Place documentation comments just\\nbefore the item they’re documenting.","id":"2927f158-b129-4a5b-9176-ac31a27d4c19","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"a839bfdc716ca4135f9fe7884a3b25fa\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":6,"textOffset":179},"endMeta":{"parentTagName":"P","parentIndex":6,"textOffset":398},"text":"We can generate the HTML documentation from\\nthis documentation comment by running cargo doc. This command runs the\\nrustdoc tool distributed with Rust and puts the generated HTML documentation\\nin the target/doc directory","id":"9f432647-fa70-4ec8-bb24-c8f29c52a9de","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"7a0f1911a66c5a3c3ee30c50dd945903\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":7,"textOffset":17},"endMeta":{"parentTagName":"P","parentIndex":7,"textOffset":205},"text":"running cargo doc --open will build the HTML for your\\ncurrent crate’s documentation (as well as the documentation for all of your\\ncrate’s dependencies) and open the result in a web browser","id":"b195ad22-649a-4f20-9fda-aa79f3418475","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"b3be2b82088561aff417a4fd11e854c1\\"}"},{"startMeta":{"parentTagName":"LI","parentIndex":137,"textOffset":8},"endMeta":{"parentTagName":"LI","parentIndex":137,"textOffset":72},"text":"The scenarios in which the function being documented could\\npanic","id":"4f79f1ad-0096-4ac3-a3a9-a38dd51e6b55","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"d98f62a4cd3d354bf87f75a71c9c1141\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":9,"textOffset":129},"endMeta":{"parentTagName":"P","parentIndex":9,"textOffset":175},"text":"other sections that crate\\nauthors commonly use","id":"d643e43b-7e5b-46aa-8da0-1fc9c23726ac","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"10d9d305b07d8a8e146599ac036ab99c\\"}"},{"startMeta":{"parentTagName":"LI","parentIndex":138,"textOffset":8},"endMeta":{"parentTagName":"LI","parentIndex":138,"textOffset":134},"text":"If the function returns a Result, describing the kinds of\\nerrors that might occur and what conditions might cause those errors","id":"50fad8f8-e694-4828-bd50-1da0737658c1","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"007093d3ba24c7afd3bcb11827e33c78\\"}"},{"startMeta":{"parentTagName":"LI","parentIndex":139,"textOffset":8},"endMeta":{"parentTagName":"LI","parentIndex":139,"textOffset":41},"text":"If the function is unsafe to call","id":"91e3195c-8cb1-485d-9c98-63894353a0d2","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"8969bad07ac860cd7cf29d4c6294c08b\\"}"},{"startMeta":{"parentTagName":"LI","parentIndex":139,"textOffset":79},"endMeta":{"parentTagName":"LI","parentIndex":139,"textOffset":142},"text":"there should be a section explaining why the function is unsafe","id":"3e21ee62-4522-487d-ad02-b45588d98fe2","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"b43da8e13cb651013ce4b3c91e8b650e\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":10,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":10,"textOffset":174},"text":"Most documentation comments don’t need all of these sections, but this is a\\ngood checklist to remind you of the aspects of your code users will be\\ninterested in knowing about","id":"07027787-7ecb-4515-b3dd-908e1950e9c3","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"ee867161e99a024bb74f6b3fef883a89\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":11,"textOffset":142},"endMeta":{"parentTagName":"P","parentIndex":11,"textOffset":219},"text":"running cargo test will run the code examples in your documentation as tests!","id":"eba6c9ac-8896-408f-baec-89a312383079","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"b3be2b82088561aff417a4fd11e854c1\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":11,"textOffset":276},"endMeta":{"parentTagName":"P","parentIndex":11,"textOffset":387},"text":"nothing is worse than examples\\nthat don’t work because the code has changed since the documentation was\\nwritten","id":"0137551c-12d8-4764-90a5-54cc882a3db7","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"58f9ffcc25e9b1903ff9f9aa751a06bb\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":13,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":13,"textOffset":291},"text":"The style of doc comment //! adds documentation to the item that contains the\\ncomments rather than to the items following the comments. We typically use\\nthese doc comments inside the crate root file (src/lib.rs by convention) or\\ninside a module to document the crate or the module as a whole","id":"475f6ffb-bd87-41b6-a732-6f7cda0be2a0","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"4ac07d2d1661429b104c986cb0238eb3\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":20,"textOffset":0},"endMeta":{"parentTagName":"P","parentIndex":20,"textOffset":204},"text":"Documentation comments within items are useful for describing crates and\\nmodules especially. Use them to explain the overall purpose of the container to\\nhelp your users understand the crate’s organization","id":"8ec9a2b9-fd2e-4e4f-a8b5-2b519cb840bb","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"ea74ef2609de23f0b02bc1f65be9f775\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":29,"textOffset":83},"endMeta":{"parentTagName":"P","parentIndex":29,"textOffset":220},"text":"People who use your crate are less familiar with the structure than you\\nare and might have difficulty finding the pieces they want to use","id":"d60ae26d-b870-4f6d-8c06-7c65d4951d3d","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"2109b78664c6abbf36ea6ca045949316\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":30,"textOffset":133},"endMeta":{"parentTagName":"P","parentIndex":30,"textOffset":246},"text":"the structure that\\nmakes sense to you while you’re developing a crate might not be very convenient\\nfor your users","id":"25120409-e965-4e88-b562-f975afddadfd","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"8c0b54c07c7ae83e77f4c05befd01720\\"}"},{"startMeta":{"parentTagName":"P","parentIndex":31,"textOffset":161},"endMeta":{"parentTagName":"P","parentIndex":31,"textOffset":417},"text":"you can re-export items to make a public structure that’s different\\nfrom your private structure by using pub use. Re-exporting takes a public\\nitem in one location and makes it public in another location, as if it were\\ndefined in the other location instead.","id":"0160fe78-0282-4aee-99a4-1dc2f61c38b9","__isHighlightSource":{},"extra":"{\\"text\\":\\"\\",\\"page\\":\\"/ch14-02-publishing-to-crates-io.html\\",\\"domHash\\":\\"b3d0790125bb2d67ca460dd9e02091ec\\"}"}]`)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment