A simple CPU rendered GUI IDE experience.
semblance of intellisense; needs work
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | complete_ | 4168 | ||||
| -rw-r--r-- | src/com.rs | 244 | ||||
| -rw-r--r-- | src/hov.rs | 2 | ||||
| -rw-r--r-- | src/lsp.rs | 190 | ||||
| -rw-r--r-- | src/main.rs | 196 | ||||
| -rw-r--r-- | src/text.rs | 107 |
7 files changed, 2333 insertions, 2576 deletions
@@ -48,6 +48,8 @@ papaya = "0.2.3" markdown = "1.0.0" itertools = "0.14.0" pin-project = "1.1.10" +replace_with = "0.1.8" +nucleo = "0.5.0" [build-dependencies] cc = "*" @@ -1,2410 +1,1758 @@ -Some( - List( - CompletionList { - is_incomplete: true, - items: [ - CompletionItem { - label: "HighlightEvent::", - label_details: None, - kind: Some( - Enum, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "HighlightEvent::", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "HighlightEvent::", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "NamedKey::", - label_details: None, - kind: Some( - Enum, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "NamedKey::", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "NamedKey::", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "implicit_fn", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "A macro that adds support for implicit closures to Rust.\n\nThis provides a concise alternative to regular closure syntax\nfor when each parameter is used at most once\nand is not deeply nested.\n\nThis feature [has been suggested before](https://github.com/rust-lang/rfcs/issues/2554),\nbut this macro mostly exists for fun.\n\n# Examples\n\nUsing implicit closures to concisely sum a list:\n\n```rust\n#[implicit_fn]\nfn main() {\n let n = [1, 2, 3].into_iter().fold(0, _ + _);\n assert_eq!(n, 6);\n}\n```\n\nCopying all the elements of an array:\n\n```rust\n#[implicit_fn]\nfn main() {\n let array: [&u32; 3] = [&1, &2, &3];\n let array: [u32; 3] = array.map(*_);\n assert_eq!(array, [1, 2, 3]);\n}\n```\n\nRunning a fallible function in an iterator:\n\n```rust\n#[implicit_fn]\nfn main() -> Result<(), Box<dyn Error>> {\n let names = fs::read_dir(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/src\"))?\n .map(_?.file_name().into_string().map_err(|_| \"file not UTF-8\")?)\n .collect::<Result<Vec<_>, Box<dyn Error>>>()?;\n assert_eq!(names, [\"lib.rs\"]);\n Ok(())\n}\n```\n\nRunning a match on an array of options:\n\n```rust\n#[implicit_fn]\nfn main() {\n let options = [Some(16), None, Some(2)];\n let numbers = options.map(match _ {\n Some(x) => x + 1,\n None => 0,\n });\n assert_eq!(numbers, [17, 0, 3]);\n}\n```\n\nPrinting the elements of an iterator:\n\n```rust\n#[implicit_fn]\nfn main() {\n [1, 2, 3].into_iter().for_each(println!(\"{}\", _));\n}\n```", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "implicit_fn", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "implicit_fn", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "semantic", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "semantic", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "semantic", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "core", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "# The Rust Core Library\n\nThe Rust Core Library is the dependency-free[^free] foundation of [The\nRust Standard Library](../std/index.html). It is the portable glue\nbetween the language and its libraries, defining the intrinsic and\nprimitive building blocks of all Rust code. It links to no\nupstream libraries, no system libraries, and no libc.\n\n[^free]: Strictly speaking, there are some symbols which are needed but\n they aren't always necessary.\n\nThe core library is *minimal*: it isn't even aware of heap allocation,\nnor does it provide concurrency or I/O. These things require\nplatform integration, and this library is platform-agnostic.\n\n# How to use the core library\n\nPlease note that all of these details are currently not considered stable.\n\nThis library is built on the assumption of a few existing symbols:\n\n* `memcpy`, `memmove`, `memset`, `memcmp`, `bcmp`, `strlen` - These are core memory routines\n which are generated by Rust codegen backends. Additionally, this library can make explicit\n calls to `strlen`. Their signatures are the same as found in C, but there are extra\n assumptions about their semantics: For `memcpy`, `memmove`, `memset`, `memcmp`, and `bcmp`, if\n the `n` parameter is 0, the function is assumed to not be UB, even if the pointers are NULL or\n dangling. (Note that making extra assumptions about these functions is common among compilers:\n [clang](https://reviews.llvm.org/D86993) and [GCC](https://gcc.gnu.org/onlinedocs/gcc/Standards.html#C-Language) do the same.)\n These functions are often provided by the system libc, but can also be provided by the\n [compiler-builtins crate](https://crates.io/crates/compiler_builtins).\n Note that the library does not guarantee that it will always make these assumptions, so Rust\n user code directly calling the C functions should follow the C specification! The advice for\n Rust user code is to call the functions provided by this library instead (such as\n `ptr::copy`).\n\n* Panic handler - This function takes one argument, a `&panic::PanicInfo`. It is up to consumers of this core\n library to define this panic function; it is only required to never\n return. You should mark your implementation using `#[panic_handler]`.\n\n* `rust_eh_personality` - is used by the failure mechanisms of the\n compiler. This is often mapped to GCC's personality function, but crates\n which do not trigger a panic can be assured that this function is never\n called. The `lang` attribute is called `eh_personality`.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "core", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "core", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "std", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "# The Rust Standard Library\n\nThe Rust Standard Library is the foundation of portable Rust software, a\nset of minimal and battle-tested shared abstractions for the [broader Rust\necosystem][crates.io]. It offers core types, like [`Vec<T>`] and\n[`Option<T>`], library-defined [operations on language\nprimitives](#primitives), [standard macros](#macros), [I/O] and\n[multithreading], among [many other things][other].\n\n`std` is available to all Rust crates by default. Therefore, the\nstandard library can be accessed in [`use`] statements through the path\n`std`, as in [`use std::env`].\n\n# How to read this documentation\n\nIf you already know the name of what you are looking for, the fastest way to\nfind it is to use the <a href=\"#\" onclick=\"window.searchState.focus();\">search\nbutton</a> at the top of the page.\n\nOtherwise, you may want to jump to one of these useful sections:\n\n* [`std::*` modules](#modules)\n* [Primitive types](#primitives)\n* [Standard macros](#macros)\n* [The Rust Prelude]\n\nIf this is your first time, the documentation for the standard library is\nwritten to be casually perused. Clicking on interesting things should\ngenerally lead you to interesting places. Still, there are important bits\nyou don't want to miss, so read on for a tour of the standard library and\nits documentation!\n\nOnce you are familiar with the contents of the standard library you may\nbegin to find the verbosity of the prose distracting. At this stage in your\ndevelopment you may want to press the\n\"<svg style=\"width:0.75rem;height:0.75rem\" viewBox=\"0 0 12 12\" stroke=\"currentColor\" fill=\"none\"><path d=\"M2,2l4,4l4,-4M2,6l4,4l4,-4\"/></svg> Summary\"\nbutton near the top of the page to collapse it into a more skimmable view.\n\nWhile you are looking at the top of the page, also notice the\n\"Source\" link. Rust's API documentation comes with the source\ncode and you are encouraged to read it. The standard library source is\ngenerally high quality and a peek behind the curtains is\noften enlightening.\n\n# What is in the standard library documentation?\n\nFirst of all, The Rust Standard Library is divided into a number of focused\nmodules, [all listed further down this page](#modules). These modules are\nthe bedrock upon which all of Rust is forged, and they have mighty names\nlike [`std::slice`] and [`std::cmp`]. Modules' documentation typically\nincludes an overview of the module along with examples, and are a smart\nplace to start familiarizing yourself with the library.\n\nSecond, implicit methods on [primitive types] are documented here. This can\nbe a source of confusion for two reasons:\n\n1. While primitives are implemented by the compiler, the standard library\n implements methods directly on the primitive types (and it is the only\n library that does so), which are [documented in the section on\n primitives](#primitives).\n2. The standard library exports many modules *with the same name as\n primitive types*. These define additional items related to the primitive\n type, but not the all-important methods.\n\nSo for example there is a [page for the primitive type\n`char`](primitive::char) that lists all the methods that can be called on\ncharacters (very useful), and there is a [page for the module\n`std::char`](crate::char) that documents iterator and error types created by these methods\n(rarely useful).\n\nNote the documentation for the primitives [`str`] and [`[T]`][prim@slice] (also\ncalled 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually\ncalls to methods on [`str`] and [`[T]`][prim@slice] respectively, via [deref\ncoercions][deref-coercions].\n\nThird, the standard library defines [The Rust Prelude], a small collection\nof items - mostly traits - that are imported into every module of every\ncrate. The traits in the prelude are pervasive, making the prelude\ndocumentation a good entry point to learning about the library.\n\nAnd finally, the standard library exports a number of standard macros, and\n[lists them on this page](#macros) (technically, not all of the standard\nmacros are defined by the standard library - some are defined by the\ncompiler - but they are documented here the same). Like the prelude, the\nstandard macros are imported by default into all crates.\n\n# Contributing changes to the documentation\n\nCheck out the Rust contribution guidelines [here](\nhttps://rustc-dev-guide.rust-lang.org/contributing.html#writing-documentation).\nThe source for this documentation can be found on\n[GitHub](https://github.com/rust-lang/rust) in the 'library/std/' directory.\nTo contribute changes, make sure you read the guidelines first, then submit\npull-requests for your suggested changes.\n\nContributions are appreciated! If you see a part of the docs that can be\nimproved, submit a PR, or chat with us first on [Zulip][rust-zulip]\n#docs.\n\n# A Tour of The Rust Standard Library\n\nThe rest of this crate documentation is dedicated to pointing out notable\nfeatures of The Rust Standard Library.\n\n## Containers and collections\n\nThe [`option`] and [`result`] modules define optional and error-handling\ntypes, [`Option<T>`] and [`Result<T, E>`]. The [`iter`] module defines\nRust's iterator trait, [`Iterator`], which works with the [`for`] loop to\naccess collections.\n\nThe standard library exposes three common ways to deal with contiguous\nregions of memory:\n\n* [`Vec<T>`] - A heap-allocated *vector* that is resizable at runtime.\n* [`[T; N]`][prim@array] - An inline *array* with a fixed size at compile time.\n* [`[T]`][prim@slice] - A dynamically sized *slice* into any other kind of contiguous\n storage, whether heap-allocated or not.\n\nSlices can only be handled through some kind of *pointer*, and as such come\nin many flavors such as:\n\n* `&[T]` - *shared slice*\n* `&mut [T]` - *mutable slice*\n* [`Box<[T]>`][owned slice] - *owned slice*\n\n[`str`], a UTF-8 string slice, is a primitive type, and the standard library\ndefines many methods for it. Rust [`str`]s are typically accessed as\nimmutable references: `&str`. Use the owned [`String`] for building and\nmutating strings.\n\nFor converting to strings use the [`format!`] macro, and for converting from\nstrings use the [`FromStr`] trait.\n\nData may be shared by placing it in a reference-counted box or the [`Rc`]\ntype, and if further contained in a [`Cell`] or [`RefCell`], may be mutated\nas well as shared. Likewise, in a concurrent setting it is common to pair an\natomically-reference-counted box, [`Arc`], with a [`Mutex`] to get the same\neffect.\n\nThe [`collections`] module defines maps, sets, linked lists and other\ntypical collection types, including the common [`HashMap<K, V>`].\n\n## Platform abstractions and I/O\n\nBesides basic data types, the standard library is largely concerned with\nabstracting over differences in common platforms, most notably Windows and\nUnix derivatives.\n\nCommon types of I/O, including [files], [TCP], and [UDP], are defined in\nthe [`io`], [`fs`], and [`net`] modules.\n\nThe [`thread`] module contains Rust's threading abstractions. [`sync`]\ncontains further primitive shared memory types, including [`atomic`], [`mpmc`] and\n[`mpsc`], which contains the channel types for message passing.\n\n# Use before and after `main()`\n\nMany parts of the standard library are expected to work before and after `main()`;\nbut this is not guaranteed or ensured by tests. It is recommended that you write your own tests\nand run them on each platform you wish to support.\nThis means that use of `std` before/after main, especially of features that interact with the\nOS or global state, is exempted from stability and portability guarantees and instead only\nprovided on a best-effort basis. Nevertheless bug reports are appreciated.\n\nOn the other hand `core` and `alloc` are most likely to work in such environments with\nthe caveat that any hookable behavior such as panics, oom handling or allocators will also\ndepend on the compatibility of the hooks.\n\nSome features may also behave differently outside main, e.g. stdio could become unbuffered,\nsome panics might turn into aborts, backtraces might not get symbolicated or similar.\n\nNon-exhaustive list of known limitations:\n\n- after-main use of thread-locals, which also affects additional features:\n - [`thread::current()`]\n- under UNIX, before main, file descriptors 0, 1, and 2 may be unchanged\n (they are guaranteed to be open during main,\n and are opened to /dev/null O_RDWR if they weren't open on program start)\n\n\n[I/O]: io\n[TCP]: net::TcpStream\n[The Rust Prelude]: prelude\n[UDP]: net::UdpSocket\n[`Arc`]: sync::Arc\n[owned slice]: boxed\n[`Cell`]: cell::Cell\n[`FromStr`]: str::FromStr\n[`HashMap<K, V>`]: collections::HashMap\n[`Mutex`]: sync::Mutex\n[`Option<T>`]: option::Option\n[`Rc`]: rc::Rc\n[`RefCell`]: cell::RefCell\n[`Result<T, E>`]: result::Result\n[`Vec<T>`]: vec::Vec\n[`atomic`]: sync::atomic\n[`for`]: ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for\n[`str`]: prim@str\n[`mpmc`]: sync::mpmc\n[`mpsc`]: sync::mpsc\n[`std::cmp`]: cmp\n[`std::slice`]: mod@slice\n[`use std::env`]: env/index.html\n[`use`]: ../book/ch07-02-defining-modules-to-control-scope-and-privacy.html\n[crates.io]: https://crates.io\n[deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods\n[files]: fs::File\n[multithreading]: thread\n[other]: #what-is-in-the-standard-library-documentation\n[primitive types]: ../book/ch03-02-data-types.html\n[rust-zulip]: https://rust-lang.zulipchat.com/\n[array]: prim@array\n[slice]: prim@slice", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "std", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "std", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "array_chunks", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "Adds `array_chunks` on stable.\nThis used to be a nightly feature, now its a crate.\n\nThis is just a wrapper so you dont have to write `x.as_chunks::<N>().0.into_iter()`.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "array_chunks", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "array_chunks", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "atools", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "a collection of useful features for working with arrays", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "atools", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "atools", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "car", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "provides some ([`map`](array::map) and [`from_fn`](core::array::from_fn)) [`core::array`] fn related functions as const macros.\n```rust\nconst X: [usize; 6] = car::map!(car::from_fn!(|x| x), |x| x * 24);\n```", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "car", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "car", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "lower", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "a lil macro crate.\n\nprovides a handy macro for converting `a + b` to `a.add(b)` for when you cant easily overload the `Add` trait,\nand some traits that provide [`f*_algebraic`](algebraic::math) and [`f*_fast`](fast::math) implementations. (requires nightly)", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "lower", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "lower", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "fimg", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "# fimg\n\nProvides fast image operations, such as rotation, flipping, and overlaying.\n\n## Organization\n\nImage types:\n\n- [`Image`]: the main image type.\n- [`DynImage`]: This is the image type you use when, say, loading a png. You should immediately convert this into a\n- [`ImageCloner`]: This is... a [`Image`], but about to be cloned. It just allows some simple out-of-place optimizations, that `.clone().op()` dont allow. (produce with [`Image::cloner`])\n- [`uninit::Image`]: A uninitialized image. Used for performance optimization.\n\n### Operations\n\nAffine:\n- [`Image::rot_90`]\n- [`Image::rot_180`]\n- [`Image::rot_270`]\n- [`Image::flip_h`]\n- [`Image::flip_v`]\n\nDrawing:\n- [`Image::box`], [`Image::filled_box`], [`Image::stroked_box`]\n- [`Image::circle`], [`Image::border_circle`]\n- [`Image::line`], [`Image::thick_line`]\n- [`Image::points`]\n- [`Image::quad`]\n- [`Image::poly`], [`Image::border_poly`]\n- [`Image::tri`]\n- [`Image::text`]\n\nScaling: [`Image::scale`]\n\nMisc image ops:\n- [`Image::repeated`]\n- [`Image::overlay`](Overlay), [`Image::overlay_at`](OverlayAt), [`Image::overlay_blended`](BlendingOverlay)\n- [`Image::blur`]\n- [`Image::crop`]\n\n## feature flags\n\n- `scale`: enables the [`scale`] module.\n- `save`: enables [`Image::save`], via the [`png`](https://crates.io/crates/png) crate.\n- `text`: enables [`Image::text`], via the [`fontdue`](https://crates.io/crates/fontdue) crate.\n- `blur`: enables [`Image::blur`], via the [`stackblur`](https://crates.io/crates/stackblur-iter) crate.\n- `real-show`: [`Image::show`], if the `save` feature is enabled, will, by default, simply open the appropriate image viewing program.\nif, for some reason, this is inadequate/you dont have a good image viewer, enable the `real-show` feature to make [`Image::show`] open up a window of its own.\nwithout the `real-show` feature, [`Image::show`] will save itself to your temp directory, which you may not want.\n- `term`: [`term::print`]. this enables printing images directly to the terminal, if you don't want to open a window or something. supports `{iterm2, kitty, sixel, fallback}` graphics.\n- `default`: \\[`save`, `scale`\\].", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "fimg", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "fimg", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "itertools", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "Extra iterator adaptors, functions and macros.\n\nTo extend [`Iterator`] with methods in this crate, import\nthe [`Itertools`] trait:\n\n```rust\nuse itertools::Itertools;\n```\n\nNow, new methods like [`interleave`](Itertools::interleave)\nare available on all iterators:\n\n```rust\nuse itertools::Itertools;\n\nlet it = (1..3).interleave(vec![-1, -2]);\nitertools::assert_equal(it, vec![1, -1, 2, -2]);\n```\n\nMost iterator methods are also provided as functions (with the benefit\nthat they convert parameters using [`IntoIterator`]):\n\n```rust\nuse itertools::interleave;\n\nfor elt in interleave(&[1, 2, 3], &[2, 3, 4]) {\n /* loop body */\n}\n```\n\n## Crate Features\n\n- `use_std`\n - Enabled by default.\n - Disable to compile itertools using `#![no_std]`. This disables\n any item that depend on allocations (see the `use_alloc` feature)\n and hash maps (like `unique`, `counts`, `into_grouping_map` and more).\n- `use_alloc`\n - Enabled by default.\n - Enables any item that depend on allocations (like `chunk_by`,\n `kmerge`, `join` and many more).\n\n## Rust Version\n\nThis version of itertools requires Rust 1.63.0 or later.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "itertools", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "itertools", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "swash", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "\nFont introspection, complex text shaping and glyph rendering.\n\nFor a comprehensive list of features provided by this crate, please check out\nthe [readme](https://github.com/dfrg/swash/blob/main/README.md) on GitHub.\n\n# Note\n\nThis is a low level library focusing on implementations of OpenType and\nvarious related Unicode specifications for building high quality, high performance\ntext layout and rendering components with minimal overhead.\n\nIf you're looking for something higher level, please stay tuned-- work is in\nprogress.\n\n# Usage\n\nThe primary currency in this crate is the [`FontRef`] struct so you'll want to\nstart there to learn how to construct and use fonts.\n\nDocumentation for [shaping](shape) and [scaling](scale) is provided in\nthe respective modules.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "swash", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "swash", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "dsb", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "dsb", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "dsb", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "memchr", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "\nThis library provides heavily optimized routines for string search primitives.\n\n# Overview\n\nThis section gives a brief high level overview of what this crate offers.\n\n* The top-level module provides routines for searching for 1, 2 or 3 bytes\n in the forward or reverse direction. When searching for more than one byte,\n positions are considered a match if the byte at that position matches any\n of the bytes.\n* The [`memmem`] sub-module provides forward and reverse substring search\n routines.\n\nIn all such cases, routines operate on `&[u8]` without regard to encoding. This\nis exactly what you want when searching either UTF-8 or arbitrary bytes.\n\n# Example: using `memchr`\n\nThis example shows how to use `memchr` to find the first occurrence of `z` in\na haystack:\n\n```rust\nuse memchr::memchr;\n\nlet haystack = b\"foo bar baz quuz\";\nassert_eq!(Some(10), memchr(b'z', haystack));\n```\n\n# Example: matching one of three possible bytes\n\nThis examples shows how to use `memrchr3` to find occurrences of `a`, `b` or\n`c`, starting at the end of the haystack.\n\n```rust\nuse memchr::memchr3_iter;\n\nlet haystack = b\"xyzaxyzbxyzc\";\n\nlet mut it = memchr3_iter(b'a', b'b', b'c', haystack).rev();\nassert_eq!(Some(11), it.next());\nassert_eq!(Some(7), it.next());\nassert_eq!(Some(3), it.next());\nassert_eq!(None, it.next());\n```\n\n# Example: iterating over substring matches\n\nThis example shows how to use the [`memmem`] sub-module to find occurrences of\na substring in a haystack.\n\n```rust\nuse memchr::memmem;\n\nlet haystack = b\"foo bar foo baz foo\";\n\nlet mut it = memmem::find_iter(haystack, \"foo\");\nassert_eq!(Some(0), it.next());\nassert_eq!(Some(8), it.next());\nassert_eq!(Some(16), it.next());\nassert_eq!(None, it.next());\n```\n\n# Example: repeating a search for the same needle\n\nIt may be possible for the overhead of constructing a substring searcher to be\nmeasurable in some workloads. In cases where the same needle is used to search\nmany haystacks, it is possible to do construction once and thus to avoid it for\nsubsequent searches. This can be done with a [`memmem::Finder`]:\n\n```rust\nuse memchr::memmem;\n\nlet finder = memmem::Finder::new(\"foo\");\n\nassert_eq!(Some(4), finder.find(b\"baz foo quux\"));\nassert_eq!(None, finder.find(b\"quux baz bar\"));\n```\n\n# Why use this crate?\n\nAt first glance, the APIs provided by this crate might seem weird. Why provide\na dedicated routine like `memchr` for something that could be implemented\nclearly and trivially in one line:\n\n```rust\nfn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {\n haystack.iter().position(|&b| b == needle)\n}\n```\n\nOr similarly, why does this crate provide substring search routines when Rust's\ncore library already provides them?\n\n```rust\nfn search(haystack: &str, needle: &str) -> Option<usize> {\n haystack.find(needle)\n}\n```\n\nThe primary reason for both of them to exist is performance. When it comes to\nperformance, at a high level at least, there are two primary ways to look at\nit:\n\n* **Throughput**: For this, think about it as, \"given some very large haystack\n and a byte that never occurs in that haystack, how long does it take to\n search through it and determine that it, in fact, does not occur?\"\n* **Latency**: For this, think about it as, \"given a tiny haystack---just a\n few bytes---how long does it take to determine if a byte is in it?\"\n\nThe `memchr` routine in this crate has _slightly_ worse latency than the\nsolution presented above, however, its throughput can easily be over an\norder of magnitude faster. This is a good general purpose trade off to make.\nYou rarely lose, but often gain big.\n\n**NOTE:** The name `memchr` comes from the corresponding routine in `libc`. A\nkey advantage of using this library is that its performance is not tied to its\nquality of implementation in the `libc` you happen to be using, which can vary\ngreatly from platform to platform.\n\nBut what about substring search? This one is a bit more complicated. The\nprimary reason for its existence is still indeed performance, but it's also\nuseful because Rust's core library doesn't actually expose any substring\nsearch routine on arbitrary bytes. The only substring search routine that\nexists works exclusively on valid UTF-8.\n\nSo if you have valid UTF-8, is there a reason to use this over the standard\nlibrary substring search routine? Yes. This routine is faster on almost every\nmetric, including latency. The natural question then, is why isn't this\nimplementation in the standard library, even if only for searching on UTF-8?\nThe reason is that the implementation details for using SIMD in the standard\nlibrary haven't quite been worked out yet.\n\n**NOTE:** Currently, only `x86_64`, `wasm32` and `aarch64` targets have vector\naccelerated implementations of `memchr` (and friends) and `memmem`.\n\n# Crate features\n\n* **std** - When enabled (the default), this will permit features specific to\nthe standard library. Currently, the only thing used from the standard library\nis runtime SIMD CPU feature detection. This means that this feature must be\nenabled to get AVX2 accelerated routines on `x86_64` targets without enabling\nthe `avx2` feature at compile time, for example. When `std` is not enabled,\nthis crate will still attempt to use SSE2 accelerated routines on `x86_64`. It\nwill also use AVX2 accelerated routines when the `avx2` feature is enabled at\ncompile time. In general, enable this feature if you can.\n* **alloc** - When enabled (the default), APIs in this crate requiring some\nkind of allocation will become available. For example, the\n[`memmem::Finder::into_owned`](crate::memmem::Finder::into_owned) API and the\n[`arch::all::shiftor`](crate::arch::all::shiftor) substring search\nimplementation. Otherwise, this crate is designed from the ground up to be\nusable in core-only contexts, so the `alloc` feature doesn't add much\ncurrently. Notably, disabling `std` but enabling `alloc` will **not** result\nin the use of AVX2 on `x86_64` targets unless the `avx2` feature is enabled\nat compile time. (With `std` enabled, AVX2 can be used even without the `avx2`\nfeature enabled at compile time by way of runtime CPU feature detection.)\n* **logging** - When enabled (disabled by default), the `log` crate is used\nto emit log messages about what kinds of `memchr` and `memmem` algorithms\nare used. Namely, both `memchr` and `memmem` have a number of different\nimplementation choices depending on the target and CPU, and the log messages\ncan help show what specific implementations are being used. Generally, this is\nuseful for debugging performance issues.\n* **libc** - **DEPRECATED**. Previously, this enabled the use of the target's\n`memchr` function from whatever `libc` was linked into the program. This\nfeature is now a no-op because this crate's implementation of `memchr` should\nnow be sufficiently fast on a number of platforms that `libc` should no longer\nbe needed. (This feature is somewhat of a holdover from this crate's origins.\nOriginally, this crate was literally just a safe wrapper function around the\n`memchr` function from `libc`.)", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "memchr", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "memchr", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "log", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "A lightweight logging facade.\n\nThe `log` crate provides a single logging API that abstracts over the\nactual logging implementation. Libraries can use the logging API provided\nby this crate, and the consumer of those libraries can choose the logging\nimplementation that is most suitable for its use case.\n\nIf no logging implementation is selected, the facade falls back to a \"noop\"\nimplementation that ignores all log messages. The overhead in this case\nis very small - just an integer load, comparison and jump.\n\nA log request consists of a _target_, a _level_, and a _body_. A target is a\nstring which defaults to the module path of the location of the log request,\nthough that default may be overridden. Logger implementations typically use\nthe target to filter requests based on some user configuration.\n\n# Usage\n\nThe basic use of the log crate is through the five logging macros: [`error!`],\n[`warn!`], [`info!`], [`debug!`] and [`trace!`]\nwhere `error!` represents the highest-priority log messages\nand `trace!` the lowest. The log messages are filtered by configuring\nthe log level to exclude messages with a lower priority.\nEach of these macros accept format strings similarly to [`println!`].\n\n\n[`error!`]: ./macro.error.html\n[`warn!`]: ./macro.warn.html\n[`info!`]: ./macro.info.html\n[`debug!`]: ./macro.debug.html\n[`trace!`]: ./macro.trace.html\n[`println!`]: https://doc.rust-lang.org/stable/std/macro.println.html\n\nAvoid writing expressions with side-effects in log statements. They may not be evaluated.\n\n## In libraries\n\nLibraries should link only to the `log` crate, and use the provided\nmacros to log whatever information will be useful to downstream consumers.\n\n### Examples\n\n```rust\nuse log::{info, warn};\n\npub fn shave_the_yak(yak: &mut Yak) {\n info!(target: \"yak_events\", \"Commencing yak shaving for {yak:?}\");\n\n loop {\n match find_a_razor() {\n Ok(razor) => {\n info!(\"Razor located: {razor}\");\n yak.shave(razor);\n break;\n }\n Err(err) => {\n warn!(\"Unable to locate a razor: {err}, retrying\");\n }\n }\n }\n}\n```\n\n## In executables\n\nExecutables should choose a logging implementation and initialize it early in the\nruntime of the program. Logging implementations will typically include a\nfunction to do this. Any log messages generated before\nthe implementation is initialized will be ignored.\n\nThe executable itself may use the `log` crate to log as well.\n\n### Warning\n\nThe logging system may only be initialized once.\n\n## Structured logging\n\nIf you enable the `kv` feature you can associate structured values\nwith your log records. If we take the example from before, we can include\nsome additional context besides what's in the formatted message:\n\n```rust\nuse log::{info, warn};\n\npub fn shave_the_yak(yak: &mut Yak) {\n info!(target: \"yak_events\", yak:serde; \"Commencing yak shaving\");\n\n loop {\n match find_a_razor() {\n Ok(razor) => {\n info!(razor; \"Razor located\");\n yak.shave(razor);\n break;\n }\n Err(e) => {\n warn!(e:err; \"Unable to locate a razor, retrying\");\n }\n }\n }\n}\n```\n\nSee the [`kv`] module documentation for more details.\n\n# Available logging implementations\n\nIn order to produce log output executables have to use\na logger implementation compatible with the facade.\nThere are many available implementations to choose from,\nhere are some of the most popular ones:\n\n* Simple minimal loggers:\n * [env_logger]\n * [colog]\n * [simple_logger]\n * [simplelog]\n * [pretty_env_logger]\n * [stderrlog]\n * [flexi_logger]\n * [call_logger]\n * [structured-logger]\n * [clang_log]\n * [ftail]\n* Complex configurable frameworks:\n * [log4rs]\n * [logforth]\n * [fern]\n * [spdlog-rs]\n* Adaptors for other facilities:\n * [syslog]\n * [slog-stdlog]\n * [systemd-journal-logger]\n * [android_log]\n * [win_dbg_logger]\n * [db_logger]\n * [log-to-defmt]\n * [logcontrol-log]\n* For WebAssembly binaries:\n * [console_log]\n* For dynamic libraries:\n * You may need to construct an FFI-safe wrapper over `log` to initialize in your libraries\n* Utilities:\n * [log_err]\n * [log-reload]\n\n# Implementing a Logger\n\nLoggers implement the [`Log`] trait. Here's a very basic example that simply\nlogs all messages at the [`Error`][level_link], [`Warn`][level_link] or\n[`Info`][level_link] levels to stdout:\n\n```rust\nuse log::{Record, Level, Metadata};\n\nstruct SimpleLogger;\n\nimpl log::Log for SimpleLogger {\n fn enabled(&self, metadata: &Metadata) -> bool {\n metadata.level() <= Level::Info\n }\n\n fn log(&self, record: &Record) {\n if self.enabled(record.metadata()) {\n println!(\"{} - {}\", record.level(), record.args());\n }\n }\n\n fn flush(&self) {}\n}\n\n```\n\nLoggers are installed by calling the [`set_logger`] function. The maximum\nlog level also needs to be adjusted via the [`set_max_level`] function. The\nlogging facade uses this as an optimization to improve performance of log\nmessages at levels that are disabled. It's important to set it, as it\ndefaults to [`Off`][filter_link], so no log messages will ever be captured!\nIn the case of our example logger, we'll want to set the maximum log level\nto [`Info`][filter_link], since we ignore any [`Debug`][level_link] or\n[`Trace`][level_link] level log messages. A logging implementation should\nprovide a function that wraps a call to [`set_logger`] and\n[`set_max_level`], handling initialization of the logger:\n\n```rust\nuse log::{SetLoggerError, LevelFilter};\n\nstatic LOGGER: SimpleLogger = SimpleLogger;\n\npub fn init() -> Result<(), SetLoggerError> {\n log::set_logger(&LOGGER)\n .map(|()| log::set_max_level(LevelFilter::Info))\n}\n```\n\nImplementations that adjust their configurations at runtime should take care\nto adjust the maximum log level as well.\n\n# Use with `std`\n\n`set_logger` requires you to provide a `&'static Log`, which can be hard to\nobtain if your logger depends on some runtime configuration. The\n`set_boxed_logger` function is available with the `std` Cargo feature. It is\nidentical to `set_logger` except that it takes a `Box<Log>` rather than a\n`&'static Log`:\n\n```rust\npub fn init() -> Result<(), SetLoggerError> {\n log::set_boxed_logger(Box::new(SimpleLogger))\n .map(|()| log::set_max_level(LevelFilter::Info))\n}\n```\n\n# Compile time filters\n\nLog levels can be statically disabled at compile time by enabling one of these Cargo features:\n\n* `max_level_off`\n* `max_level_error`\n* `max_level_warn`\n* `max_level_info`\n* `max_level_debug`\n* `max_level_trace`\n\nLog invocations at disabled levels will be skipped and will not even be present in the\nresulting binary. These features control the value of the `STATIC_MAX_LEVEL` constant. The\nlogging macros check this value before logging a message. By default, no levels are disabled.\n\nIt is possible to override this level for release builds only with the following features:\n\n* `release_max_level_off`\n* `release_max_level_error`\n* `release_max_level_warn`\n* `release_max_level_info`\n* `release_max_level_debug`\n* `release_max_level_trace`\n\nLibraries should avoid using the max level features because they're global and can't be changed\nonce they're set.\n\nFor example, a crate can disable trace level logs in debug builds and trace, debug, and info\nlevel logs in release builds with the following configuration:\n\n```toml\n[dependencies]\nlog = { version = \"0.4\", features = [\"max_level_debug\", \"release_max_level_warn\"] }\n```\n# Crate Feature Flags\n\nThe following crate feature flags are available in addition to the filters. They are\nconfigured in your `Cargo.toml`.\n\n* `std` allows use of `std` crate instead of the default `core`. Enables using `std::error` and\n `set_boxed_logger` functionality.\n* `serde` enables support for serialization and deserialization of `Level` and `LevelFilter`.\n\n```toml\n[dependencies]\nlog = { version = \"0.4\", features = [\"std\", \"serde\"] }\n```\n\n# Version compatibility\n\nThe 0.3 and 0.4 versions of the `log` crate are almost entirely compatible. Log messages\nmade using `log` 0.3 will forward transparently to a logger implementation using `log` 0.4. Log\nmessages made using `log` 0.4 will forward to a logger implementation using `log` 0.3, but the\nmodule path and file name information associated with the message will unfortunately be lost.\n\n[`Log`]: trait.Log.html\n[level_link]: enum.Level.html\n[filter_link]: enum.LevelFilter.html\n[`set_logger`]: fn.set_logger.html\n[`set_max_level`]: fn.set_max_level.html\n[`try_set_logger_raw`]: fn.try_set_logger_raw.html\n[`shutdown_logger_raw`]: fn.shutdown_logger_raw.html\n[env_logger]: https://docs.rs/env_logger/*/env_logger/\n[colog]: https://docs.rs/colog/*/colog/\n[simple_logger]: https://github.com/borntyping/rust-simple_logger\n[simplelog]: https://github.com/drakulix/simplelog.rs\n[pretty_env_logger]: https://docs.rs/pretty_env_logger/*/pretty_env_logger/\n[stderrlog]: https://docs.rs/stderrlog/*/stderrlog/\n[flexi_logger]: https://docs.rs/flexi_logger/*/flexi_logger/\n[call_logger]: https://docs.rs/call_logger/*/call_logger/\n[syslog]: https://docs.rs/syslog/*/syslog/\n[slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/\n[log4rs]: https://docs.rs/log4rs/*/log4rs/\n[logforth]: https://docs.rs/logforth/*/logforth/\n[fern]: https://docs.rs/fern/*/fern/\n[spdlog-rs]: https://docs.rs/spdlog-rs/*/spdlog/\n[systemd-journal-logger]: https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/\n[android_log]: https://docs.rs/android_log/*/android_log/\n[win_dbg_logger]: https://docs.rs/win_dbg_logger/*/win_dbg_logger/\n[db_logger]: https://docs.rs/db_logger/*/db_logger/\n[log-to-defmt]: https://docs.rs/log-to-defmt/*/log_to_defmt/\n[console_log]: https://docs.rs/console_log/*/console_log/\n[structured-logger]: https://docs.rs/structured-logger/latest/structured_logger/\n[logcontrol-log]: https://docs.rs/logcontrol-log/*/logcontrol_log/\n[log_err]: https://docs.rs/log_err/*/log_err/\n[log-reload]: https://docs.rs/log-reload/*/log_reload/\n[clang_log]: https://docs.rs/clang_log/latest/clang_log\n[ftail]: https://docs.rs/ftail/latest/ftail", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "log", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "log", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "ropey", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "Ropey is a utf8 text rope for Rust. It is fast, robust, and can handle\nhuge texts and memory-incoherent edits with ease.\n\nRopey's atomic unit of text is Unicode scalar values (or `char`s in Rust)\nencoded as utf8. All of Ropey's editing and slicing operations are done\nin terms of char indices, which prevents accidental creation of invalid\nutf8 data.\n\nThe library is made up of four main components:\n\n- [`Rope`]: the main rope type.\n- [`RopeSlice`]: an immutable view into part of a\n `Rope`.\n- [`iter`]: iterators over `Rope`/`RopeSlice` data.\n- [`RopeBuilder`]: an efficient incremental\n `Rope` builder.\n\n\n# A Basic Example\n\nLet's say we want to open up a text file, replace the 516th line (the\nwriting was terrible!), and save it back to disk. It's contrived, but will\ngive a good sampling of the APIs and how they work together.\n\n```rust\nuse std::fs::File;\nuse std::io::{BufReader, BufWriter};\nuse ropey::Rope;\n\n// Load a text file.\nlet mut text = Rope::from_reader(\n BufReader::new(File::open(\"my_great_book.txt\")?)\n)?;\n\n// Print the 516th line (zero-indexed) to see the terrible\n// writing.\nprintln!(\"{}\", text.line(515));\n\n// Get the start/end char indices of the line.\nlet start_idx = text.line_to_char(515);\nlet end_idx = text.line_to_char(516);\n\n// Remove the line...\ntext.remove(start_idx..end_idx);\n\n// ...and replace it with something better.\ntext.insert(start_idx, \"The flowers are... so... dunno.\\n\");\n\n// Print the changes, along with the previous few lines for context.\nlet start_idx = text.line_to_char(511);\nlet end_idx = text.line_to_char(516);\nprintln!(\"{}\", text.slice(start_idx..end_idx));\n\n// Write the file back out to disk.\ntext.write_to(\n BufWriter::new(File::create(\"my_great_book.txt\")?)\n)?;\n```\n\nMore examples can be found in the `examples` directory of the git\nrepository. Many of those examples demonstrate doing non-trivial things\nwith Ropey such as grapheme handling, search-and-replace, and streaming\nloading of non-utf8 text files.\n\n\n# Low-level APIs\n\nRopey also provides access to some of its low-level APIs, enabling client\ncode to efficiently work with a `Rope`'s data and implement new\nfunctionality. The most important of those API's are:\n\n- The [`chunk_at_*()`](Rope::chunk_at_byte)\n chunk-fetching methods of `Rope` and `RopeSlice`.\n- The [`Chunks`](iter::Chunks) iterator.\n- The functions in [`str_utils`] for operating on\n `&str` slices.\n\nInternally, each `Rope` stores text as a segemented collection of utf8\nstrings. The chunk-fetching methods and `Chunks` iterator provide direct\naccess to those strings (or \"chunks\") as `&str` slices, allowing client\ncode to work directly with the underlying utf8 data.\n\nThe chunk-fetching methods and `str_utils` functions are the basic\nbuilding blocks that Ropey itself uses to build much of its functionality.\nFor example, the [`Rope::byte_to_char()`]\nmethod can be reimplemented as a free function like this:\n\n```rust\nuse ropey::{\n Rope,\n str_utils::byte_to_char_idx\n};\n\nfn byte_to_char(rope: &Rope, byte_idx: usize) -> usize {\n let (chunk, b, c, _) = rope.chunk_at_byte(byte_idx);\n c + byte_to_char_idx(chunk, byte_idx - b)\n}\n```\n\nAnd this will be just as efficient as Ropey's implementation.\n\nThe chunk-fetching methods in particular are among the fastest functions\nthat Ropey provides, generally operating in the sub-hundred nanosecond\nrange for medium-sized (~200kB) documents on recent-ish computer systems.\n\n\n# A Note About Line Breaks\n\nSome of Ropey's APIs use the concept of line breaks or lines of text.\n\nRopey considers the start of the rope and positions immediately\n_after_ line breaks to be the start of new lines. And it treats\nline breaks as being a part of the lines they mark the end of.\n\nFor example, the rope `\"Hello\"` has a single line: `\"Hello\"`. The\nrope `\"Hello\\nworld\"` has two lines: `\"Hello\\n\"` and `\"world\"`. And\nthe rope `\"Hello\\nworld\\n\"` has three lines: `\"Hello\\n\"`,\n`\"world\\n\"`, and `\"\"`.\n\nRopey can be configured at build time via feature flags to recognize\ndifferent line breaks. Ropey always recognizes:\n\n- `U+000A` — LF (Line Feed)\n- `U+000D` `U+000A` — CRLF (Carriage Return + Line Feed)\n\nWith the `cr_lines` feature, the following are also recognized:\n\n- `U+000D` — CR (Carriage Return)\n\nWith the `unicode_lines` feature, in addition to all of the\nabove, the following are also recognized (bringing Ropey into\nconformance with\n[Unicode Annex #14](https://www.unicode.org/reports/tr14/#BK)):\n\n- `U+000B` — VT (Vertical Tab)\n- `U+000C` — FF (Form Feed)\n- `U+0085` — NEL (Next Line)\n- `U+2028` — Line Separator\n- `U+2029` — Paragraph Separator\n\n(Note: `unicode_lines` is enabled by default, and always implies\n`cr_lines`.)\n\nCRLF pairs are always treated as a single line break, and are never split\nacross chunks. Note, however, that slicing can still split them.\n\n\n# A Note About SIMD Acceleration\n\nRopey has a `simd` feature flag (enabled by default) that enables\nexplicit SIMD on supported platforms to improve performance.\n\nThere is a bit of a footgun here: if you disable default features to\nconfigure line break behavior (as per the section above) then SIMD\nwill also get disabled, and performance will suffer. So be careful\nto explicitly re-enable the `simd` feature flag (if desired) when\ndoing that.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "ropey", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "ropey", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "regex_cursor", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "\nThis crate provides routines for searching **discontiguous strings** for matches\nof a regular expression (aka \"regex\"). It is based on regex-automata and\nmost of the code is adapted from the various crates in the\n[regex](https://github.com/rust-lang/regex) repository.\n\nIt is intended as a prototype for upstream support for \"streaming regex\". The\ncursor based API in this crate is very similar to the API already exposed by\n`regex`/`regex-automata`. To that end a generic `Cursor` trait is provided that\ncollections can implement.\n\nA sketch of the cursor API is shown below. The string is yielded in multiple\nbyte chunks. Calling advance moves the cursor to the next chunk. Calling\nbacktrack moves the cursor a chunk back. Backtracking is required by this\ncrate. That makes it unsuitable for searching fully unbuffered streams like\nbytes send over a TCP connection.\n\n```rust_ignore\npub trait Cursor {\n fn chunk(&self) -> &[u8] { .. }\n fn advance(&mut self) -> bool { .. }\n fn bracktrack(&mut self) -> bool { .. }\n}\n```\n\nWorking on this crate showed me that regex backtracks a lot more than expected\nwith most functionality fundamentally requiring backtracking. For network\nusecases that do not buffer their input the primary usecase would likely be\ndetecting a match (without necessarily requiring the matched byte range).\nSuch usecases can be covered by manually feeding bytes into the hybrid and DFA\nengines from the regex-automata crate. This approach also has the advantage\nof allowing the caller to pause the match (async) while waiting for more data\nallowing the caller to drive the search instead of the engine itself.\n\nThe only part of this crate that could be applied to the fully streaming case is\nthe streaming PikeVM implementation. However, there are some limitations:\n* only a single search can be run since the PikeVM may look ahead multiple bytes\nto disambiguate alternative matches\n* Prefilters longer than one byte can not work\n* utf-8 mode can not be supported (empty matches may occur between unicode\nboundaries)\n\nCurrently, the PikeVM implementation is not written with this use case in mind\nand may call backtrack unnecessarily, but that could be addressed in the future,\nbut especially the first point is very limiting. The pikevm also does not allow\nthe user to drive the search and would block on network calls for example (no\nasync).", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "regex_cursor", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "regex_cursor", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "anyhow", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "[![github]](https://github.com/dtolnay/anyhow) [![crates-io]](https://crates.io/crates/anyhow) [![docs-rs]](https://docs.rs/anyhow)\n\n[github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github\n[crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust\n[docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs\n\n<br>\n\nThis library provides [`anyhow::Error`][Error], a trait object based error\ntype for easy idiomatic error handling in Rust applications.\n\n<br>\n\n# Details\n\n- Use `Result<T, anyhow::Error>`, or equivalently `anyhow::Result<T>`, as\n the return type of any fallible function.\n\n Within the function, use `?` to easily propagate any error that implements\n the [`std::error::Error`] trait.\n\n ```\n # pub trait Deserialize {}\n #\n # mod serde_json {\n # use super::Deserialize;\n # use std::io;\n #\n # pub fn from_str<T: Deserialize>(json: &str) -> io::Result<T> {\n # unimplemented!()\n # }\n # }\n #\n # struct ClusterMap;\n #\n # impl Deserialize for ClusterMap {}\n #\n use anyhow::Result;\n\n fn get_cluster_info() -> Result<ClusterMap> {\n let config = std::fs::read_to_string(\"cluster.json\")?;\n let map: ClusterMap = serde_json::from_str(&config)?;\n Ok(map)\n }\n #\n # fn main() {}\n ```\n\n- Attach context to help the person troubleshooting the error understand\n where things went wrong. A low-level error like \"No such file or\n directory\" can be annoying to debug without more context about what higher\n level step the application was in the middle of.\n\n ```\n # struct It;\n #\n # impl It {\n # fn detach(&self) -> Result<()> {\n # unimplemented!()\n # }\n # }\n #\n use anyhow::{Context, Result};\n\n fn main() -> Result<()> {\n # return Ok(());\n #\n # const _: &str = stringify! {\n ...\n # };\n #\n # let it = It;\n # let path = \"./path/to/instrs.json\";\n #\n it.detach().context(\"Failed to detach the important thing\")?;\n\n let content = std::fs::read(path)\n .with_context(|| format!(\"Failed to read instrs from {}\", path))?;\n #\n # const _: &str = stringify! {\n ...\n # };\n #\n # Ok(())\n }\n ```\n\n ```console\n Error: Failed to read instrs from ./path/to/instrs.json\n\n Caused by:\n No such file or directory (os error 2)\n ```\n\n- Downcasting is supported and can be by value, by shared reference, or by\n mutable reference as needed.\n\n ```\n # use anyhow::anyhow;\n # use std::fmt::{self, Display};\n # use std::task::Poll;\n #\n # #[derive(Debug)]\n # enum DataStoreError {\n # Censored(()),\n # }\n #\n # impl Display for DataStoreError {\n # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\n # unimplemented!()\n # }\n # }\n #\n # impl std::error::Error for DataStoreError {}\n #\n # const REDACTED_CONTENT: () = ();\n #\n # let error = anyhow!(\"...\");\n # let root_cause = &error;\n #\n # let ret =\n // If the error was caused by redaction, then return a\n // tombstone instead of the content.\n match root_cause.downcast_ref::<DataStoreError>() {\n Some(DataStoreError::Censored(_)) => Ok(Poll::Ready(REDACTED_CONTENT)),\n None => Err(error),\n }\n # ;\n ```\n\n- If using Rust ≥ 1.65, a backtrace is captured and printed with the\n error if the underlying error type does not already provide its own. In\n order to see backtraces, they must be enabled through the environment\n variables described in [`std::backtrace`]:\n\n - If you want panics and errors to both have backtraces, set\n `RUST_BACKTRACE=1`;\n - If you want only errors to have backtraces, set `RUST_LIB_BACKTRACE=1`;\n - If you want only panics to have backtraces, set `RUST_BACKTRACE=1` and\n `RUST_LIB_BACKTRACE=0`.\n\n [`std::backtrace`]: std::backtrace#environment-variables\n\n- Anyhow works with any error type that has an impl of `std::error::Error`,\n including ones defined in your crate. We do not bundle a `derive(Error)`\n macro but you can write the impls yourself or use a standalone macro like\n [thiserror].\n\n [thiserror]: https://github.com/dtolnay/thiserror\n\n ```\n use thiserror::Error;\n\n #[derive(Error, Debug)]\n pub enum FormatError {\n #[error(\"Invalid header (expected {expected:?}, got {found:?})\")]\n InvalidHeader {\n expected: String,\n found: String,\n },\n #[error(\"Missing attribute: {0}\")]\n MissingAttribute(String),\n }\n ```\n\n- One-off error messages can be constructed using the `anyhow!` macro, which\n supports string interpolation and produces an `anyhow::Error`.\n\n ```\n # use anyhow::{anyhow, Result};\n #\n # fn demo() -> Result<()> {\n # let missing = \"...\";\n return Err(anyhow!(\"Missing attribute: {}\", missing));\n # Ok(())\n # }\n ```\n\n A `bail!` macro is provided as a shorthand for the same early return.\n\n ```\n # use anyhow::{bail, Result};\n #\n # fn demo() -> Result<()> {\n # let missing = \"...\";\n bail!(\"Missing attribute: {}\", missing);\n # Ok(())\n # }\n ```\n\n<br>\n\n# No-std support\n\nIn no_std mode, almost all of the same API is available and works the same\nway. To depend on Anyhow in no_std mode, disable our default enabled \"std\"\nfeature in Cargo.toml. A global allocator is required.\n\n```toml\n[dependencies]\nanyhow = { version = \"1.0\", default-features = false }\n```\n\nWith versions of Rust older than 1.81, no_std mode may require an additional\n`.map_err(Error::msg)` when working with a non-Anyhow error type inside a\nfunction that returns Anyhow's error type, as the trait that `?`-based error\nconversions are defined by is only available in std in those old versions.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "anyhow", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "anyhow", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "serde_derive", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "This crate provides Serde's two derive macros.\n\n```rust\n#[derive(Serialize, Deserialize)]\n```\n\nPlease refer to [https://serde.rs/derive.html] for how to set this up.\n\n[https://serde.rs/derive.html]: https://serde.rs/derive.html", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "serde_derive", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "serde_derive", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "serde", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "# Serde\n\nSerde is a framework for ***ser***ializing and ***de***serializing Rust data\nstructures efficiently and generically.\n\nThe Serde ecosystem consists of data structures that know how to serialize\nand deserialize themselves along with data formats that know how to\nserialize and deserialize other things. Serde provides the layer by which\nthese two groups interact with each other, allowing any supported data\nstructure to be serialized and deserialized using any supported data format.\n\nSee the Serde website <https://serde.rs> for additional documentation and\nusage examples.\n\n## Design\n\nWhere many other languages rely on runtime reflection for serializing data,\nSerde is instead built on Rust's powerful trait system. A data structure\nthat knows how to serialize and deserialize itself is one that implements\nSerde's `Serialize` and `Deserialize` traits (or uses Serde's derive\nattribute to automatically generate implementations at compile time). This\navoids any overhead of reflection or runtime type information. In fact in\nmany situations the interaction between data structure and data format can\nbe completely optimized away by the Rust compiler, leaving Serde\nserialization to perform the same speed as a handwritten serializer for the\nspecific selection of data structure and data format.\n\n## Data formats\n\nThe following is a partial list of data formats that have been implemented\nfor Serde by the community.\n\n- [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.\n- [Postcard], a no\\_std and embedded-systems friendly compact binary format.\n- [CBOR], a Concise Binary Object Representation designed for small message\n size without the need for version negotiation.\n- [YAML], a self-proclaimed human-friendly configuration language that ain't\n markup language.\n- [MessagePack], an efficient binary format that resembles a compact JSON.\n- [TOML], a minimal configuration format used by [Cargo].\n- [Pickle], a format common in the Python world.\n- [RON], a Rusty Object Notation.\n- [BSON], the data storage and network transfer format used by MongoDB.\n- [Avro], a binary format used within Apache Hadoop, with support for schema\n definition.\n- [JSON5], a superset of JSON including some productions from ES5.\n- [URL] query strings, in the x-www-form-urlencoded format.\n- [Starlark], the format used for describing build targets by the Bazel and\n Buck build systems. *(serialization only)*\n- [Envy], a way to deserialize environment variables into Rust structs.\n *(deserialization only)*\n- [Envy Store], a way to deserialize [AWS Parameter Store] parameters into\n Rust structs. *(deserialization only)*\n- [S-expressions], the textual representation of code and data used by the\n Lisp language family.\n- [D-Bus]'s binary wire format.\n- [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy\n serialization format.\n- [Bencode], a simple binary format used in the BitTorrent protocol.\n- [Token streams], for processing Rust procedural macro input.\n *(deserialization only)*\n- [DynamoDB Items], the format used by [rusoto_dynamodb] to transfer data to\n and from DynamoDB.\n- [Hjson], a syntax extension to JSON designed around human reading and\n editing. *(deserialization only)*\n- [CSV], Comma-separated values is a tabular text file format.\n\n[JSON]: https://github.com/serde-rs/json\n[Postcard]: https://github.com/jamesmunns/postcard\n[CBOR]: https://github.com/enarx/ciborium\n[YAML]: https://github.com/dtolnay/serde-yaml\n[MessagePack]: https://github.com/3Hren/msgpack-rust\n[TOML]: https://docs.rs/toml\n[Pickle]: https://github.com/birkenfeld/serde-pickle\n[RON]: https://github.com/ron-rs/ron\n[BSON]: https://github.com/mongodb/bson-rust\n[Avro]: https://docs.rs/apache-avro\n[JSON5]: https://github.com/callum-oakley/json5-rs\n[URL]: https://docs.rs/serde_qs\n[Starlark]: https://github.com/dtolnay/serde-starlark\n[Envy]: https://github.com/softprops/envy\n[Envy Store]: https://github.com/softprops/envy-store\n[Cargo]: https://doc.rust-lang.org/cargo/reference/manifest.html\n[AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html\n[S-expressions]: https://github.com/rotty/lexpr-rs\n[D-Bus]: https://docs.rs/zvariant\n[FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers\n[Bencode]: https://github.com/P3KI/bendy\n[Token streams]: https://github.com/oxidecomputer/serde_tokenstream\n[DynamoDB Items]: https://docs.rs/serde_dynamo\n[rusoto_dynamodb]: https://docs.rs/rusoto_dynamodb\n[Hjson]: https://github.com/Canop/deser-hjson\n[CSV]: https://docs.rs/csv", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "serde", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "serde", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "arc_swap", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "Making [`Arc`][Arc] itself atomic\n\nThe [`ArcSwap`] type is a container for an `Arc` that can be changed atomically. Semantically,\nit is similar to something like `Atomic<Arc<T>>` (if there was such a thing) or\n`RwLock<Arc<T>>` (but without the need for the locking). It is optimized for read-mostly\nscenarios, with consistent performance characteristics.\n\n# Motivation\n\nThere are many situations in which one might want to have some data structure that is often\nread and seldom updated. Some examples might be a configuration of a service, routing tables,\nsnapshot of some data that is renewed every few minutes, etc.\n\nIn all these cases one needs:\n* Being able to read the current value of the data structure, fast, often and concurrently from\n many threads.\n* Using the same version of the data structure over longer period of time ‒ a query should be\n answered by a consistent version of data, a packet should be routed either by an old or by a\n new version of the routing table but not by a combination, etc.\n* Perform an update without disrupting the processing.\n\nThe first idea would be to use [`RwLock<T>`][RwLock] and keep a read-lock for the whole time of\nprocessing. Update would, however, pause all processing until done.\n\nBetter option would be to have [`RwLock<Arc<T>>`][RwLock]. Then one would lock, clone the [Arc]\nand unlock. This suffers from CPU-level contention (on the lock and on the reference count of\nthe [Arc]) which makes it relatively slow. Depending on the implementation, an update may be\nblocked for arbitrary long time by a steady inflow of readers.\n\n```rust\nstatic ROUTING_TABLE: Lazy<RwLock<Arc<RoutingTable>>> = Lazy::new(|| {\n RwLock::new(Arc::new(RoutingTable))\n});\n\nfn process_packet(packet: Packet) {\n let table = Arc::clone(&ROUTING_TABLE.read().unwrap());\n table.route(packet);\n}\n```\n\nThe [ArcSwap] can be used instead, which solves the above problems and has better performance\ncharacteristics than the [RwLock], both in contended and non-contended scenarios.\n\n```rust\nstatic ROUTING_TABLE: Lazy<ArcSwap<RoutingTable>> = Lazy::new(|| {\n ArcSwap::from_pointee(RoutingTable)\n});\n\nfn process_packet(packet: Packet) {\n let table = ROUTING_TABLE.load();\n table.route(packet);\n}\n```\n\n# Crate contents\n\nAt the heart of the crate there are [`ArcSwap`] and [`ArcSwapOption`] types, containers for an\n[`Arc`] and [`Option<Arc>`][Option].\n\nTechnically, these are type aliases for partial instantiations of the [`ArcSwapAny`] type. The\n[`ArcSwapAny`] is more flexible and allows tweaking of many things (can store other things than\n[`Arc`]s, can configure the locking [`Strategy`]). For details about the tweaking, see the\ndocumentation of the [`strategy`] module and the [`RefCnt`] trait.\n\nThe [`cache`] module provides means for speeding up read access of the contained data at the\ncost of delayed reclamation.\n\nThe [`access`] module can be used to do projections into the contained data to separate parts\nof application from each other (eg. giving a component access to only its own part of\nconfiguration while still having it reloaded as a whole).\n\n# Before using\n\nThe data structure is a bit niche. Before using, please check the\n[limitations and common pitfalls][docs::limitations] and the [performance\ncharacteristics][docs::performance], including choosing the right [read\noperation][docs::performance#read-operations].\n\nYou can also get an inspiration about what's possible in the [common patterns][docs::patterns]\nsection.\n\n# Examples\n\n```rust\nuse std::sync::Arc;\n\nuse arc_swap::ArcSwap;\nuse crossbeam_utils::thread;\n\nlet config = ArcSwap::from(Arc::new(String::default()));\nthread::scope(|scope| {\n scope.spawn(|_| {\n let new_conf = Arc::new(\"New configuration\".to_owned());\n config.store(new_conf);\n });\n for _ in 0..10 {\n scope.spawn(|_| {\n loop {\n let cfg = config.load();\n if !cfg.is_empty() {\n assert_eq!(**cfg, \"New configuration\");\n return;\n }\n }\n });\n }\n}).unwrap();\n```\n\n[RwLock]: https://doc.rust-lang.org/std/sync/struct.RwLock.html", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "arc_swap", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "arc_swap", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "regex", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "\nThis crate provides routines for searching strings for matches of a [regular\nexpression] (aka \"regex\"). The regex syntax supported by this crate is similar\nto other regex engines, but it lacks several features that are not known how to\nimplement efficiently. This includes, but is not limited to, look-around and\nbackreferences. In exchange, all regex searches in this crate have worst case\n`O(m * n)` time complexity, where `m` is proportional to the size of the regex\nand `n` is proportional to the size of the string being searched.\n\n[regular expression]: https://en.wikipedia.org/wiki/Regular_expression\n\nIf you just want API documentation, then skip to the [`Regex`] type. Otherwise,\nhere's a quick example showing one way of parsing the output of a grep-like\nprogram:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?m)^([^:]+):([0-9]+):(.+)$\").unwrap();\nlet hay = \"\\\npath/to/foo:54:Blue Harvest\npath/to/bar:90:Something, Something, Something, Dark Side\npath/to/baz:3:It's a Trap!\n\";\n\nlet mut results = vec![];\nfor (_, [path, lineno, line]) in re.captures_iter(hay).map(|c| c.extract()) {\n results.push((path, lineno.parse::<u64>()?, line));\n}\nassert_eq!(results, vec![\n (\"path/to/foo\", 54, \"Blue Harvest\"),\n (\"path/to/bar\", 90, \"Something, Something, Something, Dark Side\"),\n (\"path/to/baz\", 3, \"It's a Trap!\"),\n]);\n```\n\n# Overview\n\nThe primary type in this crate is a [`Regex`]. Its most important methods are\nas follows:\n\n* [`Regex::new`] compiles a regex using the default configuration. A\n[`RegexBuilder`] permits setting a non-default configuration. (For example,\ncase insensitive matching, verbose mode and others.)\n* [`Regex::is_match`] reports whether a match exists in a particular haystack.\n* [`Regex::find`] reports the byte offsets of a match in a haystack, if one\nexists. [`Regex::find_iter`] returns an iterator over all such matches.\n* [`Regex::captures`] returns a [`Captures`], which reports both the byte\noffsets of a match in a haystack and the byte offsets of each matching capture\ngroup from the regex in the haystack.\n[`Regex::captures_iter`] returns an iterator over all such matches.\n\nThere is also a [`RegexSet`], which permits searching for multiple regex\npatterns simultaneously in a single search. However, it currently only reports\nwhich patterns match and *not* the byte offsets of a match.\n\nOtherwise, this top-level crate documentation is organized as follows:\n\n* [Usage](#usage) shows how to add the `regex` crate to your Rust project.\n* [Examples](#examples) provides a limited selection of regex search examples.\n* [Performance](#performance) provides a brief summary of how to optimize regex\nsearching speed.\n* [Unicode](#unicode) discusses support for non-ASCII patterns.\n* [Syntax](#syntax) enumerates the specific regex syntax supported by this\ncrate.\n* [Untrusted input](#untrusted-input) discusses how this crate deals with regex\npatterns or haystacks that are untrusted.\n* [Crate features](#crate-features) documents the Cargo features that can be\nenabled or disabled for this crate.\n* [Other crates](#other-crates) links to other crates in the `regex` family.\n\n# Usage\n\nThe `regex` crate is [on crates.io](https://crates.io/crates/regex) and can be\nused by adding `regex` to your dependencies in your project's `Cargo.toml`.\nOr more simply, just run `cargo add regex`.\n\nHere is a complete example that creates a new Rust project, adds a dependency\non `regex`, creates the source code for a regex search and then runs the\nprogram.\n\nFirst, create the project in a new directory:\n\n```text\n$ mkdir regex-example\n$ cd regex-example\n$ cargo init\n```\n\nSecond, add a dependency on `regex`:\n\n```text\n$ cargo add regex\n```\n\nThird, edit `src/main.rs`. Delete what's there and replace it with this:\n\n```rust\nuse regex::Regex;\n\nfn main() {\n let re = Regex::new(r\"Hello (?<name>\\w+)!\").unwrap();\n let Some(caps) = re.captures(\"Hello Murphy!\") else {\n println!(\"no match!\");\n return;\n };\n println!(\"The name is: {}\", &caps[\"name\"]);\n}\n```\n\nFourth, run it with `cargo run`:\n\n```text\n$ cargo run\n Compiling memchr v2.5.0\n Compiling regex-syntax v0.7.1\n Compiling aho-corasick v1.0.1\n Compiling regex v1.8.1\n Compiling regex-example v0.1.0 (/tmp/regex-example)\n Finished dev [unoptimized + debuginfo] target(s) in 4.22s\n Running `target/debug/regex-example`\nThe name is: Murphy\n```\n\nThe first time you run the program will show more output like above. But\nsubsequent runs shouldn't have to re-compile the dependencies.\n\n# Examples\n\nThis section provides a few examples, in tutorial style, showing how to\nsearch a haystack with a regex. There are more examples throughout the API\ndocumentation.\n\nBefore starting though, it's worth defining a few terms:\n\n* A **regex** is a Rust value whose type is `Regex`. We use `re` as a\nvariable name for a regex.\n* A **pattern** is the string that is used to build a regex. We use `pat` as\na variable name for a pattern.\n* A **haystack** is the string that is searched by a regex. We use `hay` as a\nvariable name for a haystack.\n\nSometimes the words \"regex\" and \"pattern\" are used interchangeably.\n\nGeneral use of regular expressions in this crate proceeds by compiling a\n**pattern** into a **regex**, and then using that regex to search, split or\nreplace parts of a **haystack**.\n\n### Example: find a middle initial\n\nWe'll start off with a very simple example: a regex that looks for a specific\nname but uses a wildcard to match a middle initial. Our pattern serves as\nsomething like a template that will match a particular name with *any* middle\ninitial.\n\n```rust\nuse regex::Regex;\n\n// We use 'unwrap()' here because it would be a bug in our program if the\n// pattern failed to compile to a regex. Panicking in the presence of a bug\n// is okay.\nlet re = Regex::new(r\"Homer (.)\\. Simpson\").unwrap();\nlet hay = \"Homer J. Simpson\";\nlet Some(caps) = re.captures(hay) else { return };\nassert_eq!(\"J\", &caps[1]);\n```\n\nThere are a few things worth noticing here in our first example:\n\n* The `.` is a special pattern meta character that means \"match any single\ncharacter except for new lines.\" (More precisely, in this crate, it means\n\"match any UTF-8 encoding of any Unicode scalar value other than `\\n`.\")\n* We can match an actual `.` literally by escaping it, i.e., `\\.`.\n* We use Rust's [raw strings] to avoid needing to deal with escape sequences in\nboth the regex pattern syntax and in Rust's string literal syntax. If we didn't\nuse raw strings here, we would have had to use `\\\\.` to match a literal `.`\ncharacter. That is, `r\"\\.\"` and `\"\\\\.\"` are equivalent patterns.\n* We put our wildcard `.` instruction in parentheses. These parentheses have a\nspecial meaning that says, \"make whatever part of the haystack matches within\nthese parentheses available as a capturing group.\" After finding a match, we\naccess this capture group with `&caps[1]`.\n\n[raw strings]: https://doc.rust-lang.org/stable/reference/tokens.html#raw-string-literals\n\nOtherwise, we execute a search using `re.captures(hay)` and return from our\nfunction if no match occurred. We then reference the middle initial by asking\nfor the part of the haystack that matched the capture group indexed at `1`.\n(The capture group at index 0 is implicit and always corresponds to the entire\nmatch. In this case, that's `Homer J. Simpson`.)\n\n### Example: named capture groups\n\nContinuing from our middle initial example above, we can tweak the pattern\nslightly to give a name to the group that matches the middle initial:\n\n```rust\nuse regex::Regex;\n\n// Note that (?P<middle>.) is a different way to spell the same thing.\nlet re = Regex::new(r\"Homer (?<middle>.)\\. Simpson\").unwrap();\nlet hay = \"Homer J. Simpson\";\nlet Some(caps) = re.captures(hay) else { return };\nassert_eq!(\"J\", &caps[\"middle\"]);\n```\n\nGiving a name to a group can be useful when there are multiple groups in\na pattern. It makes the code referring to those groups a bit easier to\nunderstand.\n\n### Example: validating a particular date format\n\nThis examples shows how to confirm whether a haystack, in its entirety, matches\na particular date format:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"^\\d{4}-\\d{2}-\\d{2}$\").unwrap();\nassert!(re.is_match(\"2010-03-14\"));\n```\n\nNotice the use of the `^` and `$` anchors. In this crate, every regex search is\nrun with an implicit `(?s:.)*?` at the beginning of its pattern, which allows\nthe regex to match anywhere in a haystack. Anchors, as above, can be used to\nensure that the full haystack matches a pattern.\n\nThis crate is also Unicode aware by default, which means that `\\d` might match\nmore than you might expect it to. For example:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"^\\d{4}-\\d{2}-\\d{2}$\").unwrap();\nassert!(re.is_match(\"𝟚𝟘𝟙𝟘-𝟘𝟛-𝟙𝟜\"));\n```\n\nTo only match an ASCII decimal digit, all of the following are equivalent:\n\n* `[0-9]`\n* `(?-u:\\d)`\n* `[[:digit:]]`\n* `[\\d&&\\p{ascii}]`\n\n### Example: finding dates in a haystack\n\nIn the previous example, we showed how one might validate that a haystack,\nin its entirety, corresponded to a particular date format. But what if we wanted\nto extract all things that look like dates in a specific format from a haystack?\nTo do this, we can use an iterator API to find all matches (notice that we've\nremoved the anchors and switched to looking for ASCII-only digits):\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"[0-9]{4}-[0-9]{2}-[0-9]{2}\").unwrap();\nlet hay = \"What do 1865-04-14, 1881-07-02, 1901-09-06 and 1963-11-22 have in common?\";\n// 'm' is a 'Match', and 'as_str()' returns the matching part of the haystack.\nlet dates: Vec<&str> = re.find_iter(hay).map(|m| m.as_str()).collect();\nassert_eq!(dates, vec![\n \"1865-04-14\",\n \"1881-07-02\",\n \"1901-09-06\",\n \"1963-11-22\",\n]);\n```\n\nWe can also iterate over [`Captures`] values instead of [`Match`] values, and\nthat in turn permits accessing each component of the date via capturing groups:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?<y>[0-9]{4})-(?<m>[0-9]{2})-(?<d>[0-9]{2})\").unwrap();\nlet hay = \"What do 1865-04-14, 1881-07-02, 1901-09-06 and 1963-11-22 have in common?\";\n// 'm' is a 'Match', and 'as_str()' returns the matching part of the haystack.\nlet dates: Vec<(&str, &str, &str)> = re.captures_iter(hay).map(|caps| {\n // The unwraps are okay because every capture group must match if the whole\n // regex matches, and in this context, we know we have a match.\n //\n // Note that we use `caps.name(\"y\").unwrap().as_str()` instead of\n // `&caps[\"y\"]` because the lifetime of the former is the same as the\n // lifetime of `hay` above, but the lifetime of the latter is tied to the\n // lifetime of `caps` due to how the `Index` trait is defined.\n let year = caps.name(\"y\").unwrap().as_str();\n let month = caps.name(\"m\").unwrap().as_str();\n let day = caps.name(\"d\").unwrap().as_str();\n (year, month, day)\n}).collect();\nassert_eq!(dates, vec![\n (\"1865\", \"04\", \"14\"),\n (\"1881\", \"07\", \"02\"),\n (\"1901\", \"09\", \"06\"),\n (\"1963\", \"11\", \"22\"),\n]);\n```\n\n### Example: simpler capture group extraction\n\nOne can use [`Captures::extract`] to make the code from the previous example a\nbit simpler in this case:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"([0-9]{4})-([0-9]{2})-([0-9]{2})\").unwrap();\nlet hay = \"What do 1865-04-14, 1881-07-02, 1901-09-06 and 1963-11-22 have in common?\";\nlet dates: Vec<(&str, &str, &str)> = re.captures_iter(hay).map(|caps| {\n let (_, [year, month, day]) = caps.extract();\n (year, month, day)\n}).collect();\nassert_eq!(dates, vec![\n (\"1865\", \"04\", \"14\"),\n (\"1881\", \"07\", \"02\"),\n (\"1901\", \"09\", \"06\"),\n (\"1963\", \"11\", \"22\"),\n]);\n```\n\n`Captures::extract` works by ensuring that the number of matching groups match\nthe number of groups requested via the `[year, month, day]` syntax. If they do,\nthen the substrings for each corresponding capture group are automatically\nreturned in an appropriately sized array. Rust's syntax for pattern matching\narrays does the rest.\n\n### Example: replacement with named capture groups\n\nBuilding on the previous example, perhaps we'd like to rearrange the date\nformats. This can be done by finding each match and replacing it with\nsomething different. The [`Regex::replace_all`] routine provides a convenient\nway to do this, including by supporting references to named groups in the\nreplacement string:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?<y>\\d{4})-(?<m>\\d{2})-(?<d>\\d{2})\").unwrap();\nlet before = \"1973-01-05, 1975-08-25 and 1980-10-18\";\nlet after = re.replace_all(before, \"$m/$d/$y\");\nassert_eq!(after, \"01/05/1973, 08/25/1975 and 10/18/1980\");\n```\n\nThe replace methods are actually polymorphic in the replacement, which\nprovides more flexibility than is seen here. (See the documentation for\n[`Regex::replace`] for more details.)\n\n### Example: verbose mode\n\nWhen your regex gets complicated, you might consider using something other\nthan regex. But if you stick with regex, you can use the `x` flag to enable\ninsignificant whitespace mode or \"verbose mode.\" In this mode, whitespace\nis treated as insignificant and one may write comments. This may make your\npatterns easier to comprehend.\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?x)\n (?P<y>\\d{4}) # the year, including all Unicode digits\n -\n (?P<m>\\d{2}) # the month, including all Unicode digits\n -\n (?P<d>\\d{2}) # the day, including all Unicode digits\n\").unwrap();\n\nlet before = \"1973-01-05, 1975-08-25 and 1980-10-18\";\nlet after = re.replace_all(before, \"$m/$d/$y\");\nassert_eq!(after, \"01/05/1973, 08/25/1975 and 10/18/1980\");\n```\n\nIf you wish to match against whitespace in this mode, you can still use `\\s`,\n`\\n`, `\\t`, etc. For escaping a single space character, you can escape it\ndirectly with `\\ `, use its hex character code `\\x20` or temporarily disable\nthe `x` flag, e.g., `(?-x: )`.\n\n### Example: match multiple regular expressions simultaneously\n\nThis demonstrates how to use a [`RegexSet`] to match multiple (possibly\noverlapping) regexes in a single scan of a haystack:\n\n```rust\nuse regex::RegexSet;\n\nlet set = RegexSet::new(&[\n r\"\\w+\",\n r\"\\d+\",\n r\"\\pL+\",\n r\"foo\",\n r\"bar\",\n r\"barfoo\",\n r\"foobar\",\n]).unwrap();\n\n// Iterate over and collect all of the matches. Each match corresponds to the\n// ID of the matching pattern.\nlet matches: Vec<_> = set.matches(\"foobar\").into_iter().collect();\nassert_eq!(matches, vec![0, 2, 3, 4, 6]);\n\n// You can also test whether a particular regex matched:\nlet matches = set.matches(\"foobar\");\nassert!(!matches.matched(5));\nassert!(matches.matched(6));\n```\n\n# Performance\n\nThis section briefly discusses a few concerns regarding the speed and resource\nusage of regexes.\n\n### Only ask for what you need\n\nWhen running a search with a regex, there are generally three different types\nof information one can ask for:\n\n1. Does a regex match in a haystack?\n2. Where does a regex match in a haystack?\n3. Where do each of the capturing groups match in a haystack?\n\nGenerally speaking, this crate could provide a function to answer only #3,\nwhich would subsume #1 and #2 automatically. However, it can be significantly\nmore expensive to compute the location of capturing group matches, so it's best\nnot to do it if you don't need to.\n\nTherefore, only ask for what you need. For example, don't use [`Regex::find`]\nif you only need to test if a regex matches a haystack. Use [`Regex::is_match`]\ninstead.\n\n### Unicode can impact memory usage and search speed\n\nThis crate has first class support for Unicode and it is **enabled by default**.\nIn many cases, the extra memory required to support it will be negligible and\nit typically won't impact search speed. But it can in some cases.\n\nWith respect to memory usage, the impact of Unicode principally manifests\nthrough the use of Unicode character classes. Unicode character classes\ntend to be quite large. For example, `\\w` by default matches around 140,000\ndistinct codepoints. This requires additional memory, and tends to slow down\nregex compilation. While a `\\w` here and there is unlikely to be noticed,\nwriting `\\w{100}` will for example result in quite a large regex by default.\nIndeed, `\\w` is considerably larger than its ASCII-only version, so if your\nrequirements are satisfied by ASCII, it's probably a good idea to stick to\nASCII classes. The ASCII-only version of `\\w` can be spelled in a number of\nways. All of the following are equivalent:\n\n* `[0-9A-Za-z_]`\n* `(?-u:\\w)`\n* `[[:word:]]`\n* `[\\w&&\\p{ascii}]`\n\nWith respect to search speed, Unicode tends to be handled pretty well, even when\nusing large Unicode character classes. However, some of the faster internal\nregex engines cannot handle a Unicode aware word boundary assertion. So if you\ndon't need Unicode-aware word boundary assertions, you might consider using\n`(?-u:\\b)` instead of `\\b`, where the former uses an ASCII-only definition of\na word character.\n\n### Literals might accelerate searches\n\nThis crate tends to be quite good at recognizing literals in a regex pattern\nand using them to accelerate a search. If it is at all possible to include\nsome kind of literal in your pattern, then it might make search substantially\nfaster. For example, in the regex `\\w+@\\w+`, the engine will look for\noccurrences of `@` and then try a reverse match for `\\w+` to find the start\nposition.\n\n### Avoid re-compiling regexes, especially in a loop\n\nIt is an anti-pattern to compile the same pattern in a loop since regex\ncompilation is typically expensive. (It takes anywhere from a few microseconds\nto a few **milliseconds** depending on the size of the pattern.) Not only is\ncompilation itself expensive, but this also prevents optimizations that reuse\nallocations internally to the regex engine.\n\nIn Rust, it can sometimes be a pain to pass regular expressions around if\nthey're used from inside a helper function. Instead, we recommend using\n[`std::sync::LazyLock`], or the [`once_cell`] crate,\nif you can't use the standard library.\n\nThis example shows how to use `std::sync::LazyLock`:\n\n```rust\nuse std::sync::LazyLock;\n\nuse regex::Regex;\n\nfn some_helper_function(haystack: &str) -> bool {\n static RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r\"...\").unwrap());\n RE.is_match(haystack)\n}\n\nfn main() {\n assert!(some_helper_function(\"abc\"));\n assert!(!some_helper_function(\"ac\"));\n}\n```\n\nSpecifically, in this example, the regex will be compiled when it is used for\nthe first time. On subsequent uses, it will reuse the previously built `Regex`.\nNotice how one can define the `Regex` locally to a specific function.\n\n[`std::sync::LazyLock`]: https://doc.rust-lang.org/std/sync/struct.LazyLock.html\n[`once_cell`]: https://crates.io/crates/once_cell\n\n### Sharing a regex across threads can result in contention\n\nWhile a single `Regex` can be freely used from multiple threads simultaneously,\nthere is a small synchronization cost that must be paid. Generally speaking,\none shouldn't expect to observe this unless the principal task in each thread\nis searching with the regex *and* most searches are on short haystacks. In this\ncase, internal contention on shared resources can spike and increase latency,\nwhich in turn may slow down each individual search.\n\nOne can work around this by cloning each `Regex` before sending it to another\nthread. The cloned regexes will still share the same internal read-only portion\nof its compiled state (it's reference counted), but each thread will get\noptimized access to the mutable space that is used to run a search. In general,\nthere is no additional cost in memory to doing this. The only cost is the added\ncode complexity required to explicitly clone the regex. (If you share the same\n`Regex` across multiple threads, each thread still gets its own mutable space,\nbut accessing that space is slower.)\n\n# Unicode\n\nThis section discusses what kind of Unicode support this regex library has.\nBefore showing some examples, we'll summarize the relevant points:\n\n* This crate almost fully implements \"Basic Unicode Support\" (Level 1) as\nspecified by the [Unicode Technical Standard #18][UTS18]. The full details\nof what is supported are documented in [UNICODE.md] in the root of the regex\ncrate repository. There is virtually no support for \"Extended Unicode Support\"\n(Level 2) from UTS#18.\n* The top-level [`Regex`] runs searches *as if* iterating over each of the\ncodepoints in the haystack. That is, the fundamental atom of matching is a\nsingle codepoint.\n* [`bytes::Regex`], in contrast, permits disabling Unicode mode for part of all\nof your pattern in all cases. When Unicode mode is disabled, then a search is\nrun *as if* iterating over each byte in the haystack. That is, the fundamental\natom of matching is a single byte. (A top-level `Regex` also permits disabling\nUnicode and thus matching *as if* it were one byte at a time, but only when\ndoing so wouldn't permit matching invalid UTF-8.)\n* When Unicode mode is enabled (the default), `.` will match an entire Unicode\nscalar value, even when it is encoded using multiple bytes. When Unicode mode\nis disabled (e.g., `(?-u:.)`), then `.` will match a single byte in all cases.\n* The character classes `\\w`, `\\d` and `\\s` are all Unicode-aware by default.\nUse `(?-u:\\w)`, `(?-u:\\d)` and `(?-u:\\s)` to get their ASCII-only definitions.\n* Similarly, `\\b` and `\\B` use a Unicode definition of a \"word\" character.\nTo get ASCII-only word boundaries, use `(?-u:\\b)` and `(?-u:\\B)`. This also\napplies to the special word boundary assertions. (That is, `\\b{start}`,\n`\\b{end}`, `\\b{start-half}`, `\\b{end-half}`.)\n* `^` and `$` are **not** Unicode-aware in multi-line mode. Namely, they only\nrecognize `\\n` (assuming CRLF mode is not enabled) and not any of the other\nforms of line terminators defined by Unicode.\n* Case insensitive searching is Unicode-aware and uses simple case folding.\n* Unicode general categories, scripts and many boolean properties are available\nby default via the `\\p{property name}` syntax.\n* In all cases, matches are reported using byte offsets. Or more precisely,\nUTF-8 code unit offsets. This permits constant time indexing and slicing of the\nhaystack.\n\n[UTS18]: https://unicode.org/reports/tr18/\n[UNICODE.md]: https://github.com/rust-lang/regex/blob/master/UNICODE.md\n\nPatterns themselves are **only** interpreted as a sequence of Unicode scalar\nvalues. This means you can use Unicode characters directly in your pattern:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?i)Δ+\").unwrap();\nlet m = re.find(\"ΔδΔ\").unwrap();\nassert_eq!((0, 6), (m.start(), m.end()));\n// alternatively:\nassert_eq!(0..6, m.range());\n```\n\nAs noted above, Unicode general categories, scripts, script extensions, ages\nand a smattering of boolean properties are available as character classes. For\nexample, you can match a sequence of numerals, Greek or Cherokee letters:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"[\\pN\\p{Greek}\\p{Cherokee}]+\").unwrap();\nlet m = re.find(\"abcΔᎠβⅠᏴγδⅡxyz\").unwrap();\nassert_eq!(3..23, m.range());\n```\n\nWhile not specific to Unicode, this library also supports character class set\noperations. Namely, one can nest character classes arbitrarily and perform set\noperations on them. Those set operations are union (the default), intersection,\ndifference and symmetric difference. These set operations tend to be most\nuseful with Unicode character classes. For example, to match any codepoint\nthat is both in the `Greek` script and in the `Letter` general category:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"[\\p{Greek}&&\\pL]+\").unwrap();\nlet subs: Vec<&str> = re.find_iter(\"ΔδΔ𐅌ΔδΔ\").map(|m| m.as_str()).collect();\nassert_eq!(subs, vec![\"ΔδΔ\", \"ΔδΔ\"]);\n\n// If we just matches on Greek, then all codepoints would match!\nlet re = Regex::new(r\"\\p{Greek}+\").unwrap();\nlet subs: Vec<&str> = re.find_iter(\"ΔδΔ𐅌ΔδΔ\").map(|m| m.as_str()).collect();\nassert_eq!(subs, vec![\"ΔδΔ𐅌ΔδΔ\"]);\n```\n\n### Opt out of Unicode support\n\nThe [`bytes::Regex`] type that can be used to search `&[u8]` haystacks. By\ndefault, haystacks are conventionally treated as UTF-8 just like it is with the\nmain `Regex` type. However, this behavior can be disabled by turning off the\n`u` flag, even if doing so could result in matching invalid UTF-8. For example,\nwhen the `u` flag is disabled, `.` will match any byte instead of any Unicode\nscalar value.\n\nDisabling the `u` flag is also possible with the standard `&str`-based `Regex`\ntype, but it is only allowed where the UTF-8 invariant is maintained. For\nexample, `(?-u:\\w)` is an ASCII-only `\\w` character class and is legal in an\n`&str`-based `Regex`, but `(?-u:\\W)` will attempt to match *any byte* that\nisn't in `(?-u:\\w)`, which in turn includes bytes that are invalid UTF-8.\nSimilarly, `(?-u:\\xFF)` will attempt to match the raw byte `\\xFF` (instead of\n`U+00FF`), which is invalid UTF-8 and therefore is illegal in `&str`-based\nregexes.\n\nFinally, since Unicode support requires bundling large Unicode data\ntables, this crate exposes knobs to disable the compilation of those\ndata tables, which can be useful for shrinking binary size and reducing\ncompilation times. For details on how to do that, see the section on [crate\nfeatures](#crate-features).\n\n# Syntax\n\nThe syntax supported in this crate is documented below.\n\nNote that the regular expression parser and abstract syntax are exposed in\na separate crate, [`regex-syntax`](https://docs.rs/regex-syntax).\n\n### Matching one character\n\n<pre class=\"rust\">\n. any character except new line (includes new line with s flag)\n[0-9] any ASCII digit\n\\d digit (\\p{Nd})\n\\D not digit\n\\pX Unicode character class identified by a one-letter name\n\\p{Greek} Unicode character class (general category or script)\n\\PX Negated Unicode character class identified by a one-letter name\n\\P{Greek} negated Unicode character class (general category or script)\n</pre>\n\n### Character classes\n\n<pre class=\"rust\">\n[xyz] A character class matching either x, y or z (union).\n[^xyz] A character class matching any character except x, y and z.\n[a-z] A character class matching any character in range a-z.\n[[:alpha:]] ASCII character class ([A-Za-z])\n[[:^alpha:]] Negated ASCII character class ([^A-Za-z])\n[x[^xyz]] Nested/grouping character class (matching any character except y and z)\n[a-y&&xyz] Intersection (matching x or y)\n[0-9&&[^4]] Subtraction using intersection and negation (matching 0-9 except 4)\n[0-9--4] Direct subtraction (matching 0-9 except 4)\n[a-g~~b-h] Symmetric difference (matching `a` and `h` only)\n[\\[\\]] Escaping in character classes (matching [ or ])\n[a&&b] An empty character class matching nothing\n</pre>\n\nAny named character class may appear inside a bracketed `[...]` character\nclass. For example, `[\\p{Greek}[:digit:]]` matches any ASCII digit or any\ncodepoint in the `Greek` script. `[\\p{Greek}&&\\pL]` matches Greek letters.\n\nPrecedence in character classes, from most binding to least:\n\n1. Ranges: `[a-cd]` == `[[a-c]d]`\n2. Union: `[ab&&bc]` == `[[ab]&&[bc]]`\n3. Intersection, difference, symmetric difference. All three have equivalent\nprecedence, and are evaluated in left-to-right order. For example,\n`[\\pL--\\p{Greek}&&\\p{Uppercase}]` == `[[\\pL--\\p{Greek}]&&\\p{Uppercase}]`.\n4. Negation: `[^a-z&&b]` == `[^[a-z&&b]]`.\n\n### Composites\n\n<pre class=\"rust\">\nxy concatenation (x followed by y)\nx|y alternation (x or y, prefer x)\n</pre>\n\nThis example shows how an alternation works, and what it means to prefer a\nbranch in the alternation over subsequent branches.\n\n```rust\nuse regex::Regex;\n\nlet haystack = \"samwise\";\n// If 'samwise' comes first in our alternation, then it is\n// preferred as a match, even if the regex engine could\n// technically detect that 'sam' led to a match earlier.\nlet re = Regex::new(r\"samwise|sam\").unwrap();\nassert_eq!(\"samwise\", re.find(haystack).unwrap().as_str());\n// But if 'sam' comes first, then it will match instead.\n// In this case, it is impossible for 'samwise' to match\n// because 'sam' is a prefix of it.\nlet re = Regex::new(r\"sam|samwise\").unwrap();\nassert_eq!(\"sam\", re.find(haystack).unwrap().as_str());\n```\n\n### Repetitions\n\n<pre class=\"rust\">\nx* zero or more of x (greedy)\nx+ one or more of x (greedy)\nx? zero or one of x (greedy)\nx*? zero or more of x (ungreedy/lazy)\nx+? one or more of x (ungreedy/lazy)\nx?? zero or one of x (ungreedy/lazy)\nx{n,m} at least n x and at most m x (greedy)\nx{n,} at least n x (greedy)\nx{n} exactly n x\nx{n,m}? at least n x and at most m x (ungreedy/lazy)\nx{n,}? at least n x (ungreedy/lazy)\nx{n}? exactly n x\n</pre>\n\n### Empty matches\n\n<pre class=\"rust\">\n^ the beginning of a haystack (or start-of-line with multi-line mode)\n$ the end of a haystack (or end-of-line with multi-line mode)\n\\A only the beginning of a haystack (even with multi-line mode enabled)\n\\z only the end of a haystack (even with multi-line mode enabled)\n\\b a Unicode word boundary (\\w on one side and \\W, \\A, or \\z on other)\n\\B not a Unicode word boundary\n\\b{start}, \\< a Unicode start-of-word boundary (\\W|\\A on the left, \\w on the right)\n\\b{end}, \\> a Unicode end-of-word boundary (\\w on the left, \\W|\\z on the right))\n\\b{start-half} half of a Unicode start-of-word boundary (\\W|\\A on the left)\n\\b{end-half} half of a Unicode end-of-word boundary (\\W|\\z on the right)\n</pre>\n\nThe empty regex is valid and matches the empty string. For example, the\nempty regex matches `abc` at positions `0`, `1`, `2` and `3`. When using the\ntop-level [`Regex`] on `&str` haystacks, an empty match that splits a codepoint\nis guaranteed to never be returned. However, such matches are permitted when\nusing a [`bytes::Regex`]. For example:\n\n```rust\nlet re = regex::Regex::new(r\"\").unwrap();\nlet ranges: Vec<_> = re.find_iter(\"💩\").map(|m| m.range()).collect();\nassert_eq!(ranges, vec![0..0, 4..4]);\n\nlet re = regex::bytes::Regex::new(r\"\").unwrap();\nlet ranges: Vec<_> = re.find_iter(\"💩\".as_bytes()).map(|m| m.range()).collect();\nassert_eq!(ranges, vec![0..0, 1..1, 2..2, 3..3, 4..4]);\n```\n\nNote that an empty regex is distinct from a regex that can never match.\nFor example, the regex `[a&&b]` is a character class that represents the\nintersection of `a` and `b`. That intersection is empty, which means the\ncharacter class is empty. Since nothing is in the empty set, `[a&&b]` matches\nnothing, not even the empty string.\n\n### Grouping and flags\n\n<pre class=\"rust\">\n(exp) numbered capture group (indexed by opening parenthesis)\n(?P<name>exp) named (also numbered) capture group (names must be alpha-numeric)\n(?<name>exp) named (also numbered) capture group (names must be alpha-numeric)\n(?:exp) non-capturing group\n(?flags) set flags within current group\n(?flags:exp) set flags for exp (non-capturing)\n</pre>\n\nCapture group names must be any sequence of alpha-numeric Unicode codepoints,\nin addition to `.`, `_`, `[` and `]`. Names must start with either an `_` or\nan alphabetic codepoint. Alphabetic codepoints correspond to the `Alphabetic`\nUnicode property, while numeric codepoints correspond to the union of the\n`Decimal_Number`, `Letter_Number` and `Other_Number` general categories.\n\nFlags are each a single character. For example, `(?x)` sets the flag `x`\nand `(?-x)` clears the flag `x`. Multiple flags can be set or cleared at\nthe same time: `(?xy)` sets both the `x` and `y` flags and `(?x-y)` sets\nthe `x` flag and clears the `y` flag.\n\nAll flags are by default disabled unless stated otherwise. They are:\n\n<pre class=\"rust\">\ni case-insensitive: letters match both upper and lower case\nm multi-line mode: ^ and $ match begin/end of line\ns allow . to match \\n\nR enables CRLF mode: when multi-line mode is enabled, \\r\\n is used\nU swap the meaning of x* and x*?\nu Unicode support (enabled by default)\nx verbose mode, ignores whitespace and allow line comments (starting with `#`)\n</pre>\n\nNote that in verbose mode, whitespace is ignored everywhere, including within\ncharacter classes. To insert whitespace, use its escaped form or a hex literal.\nFor example, `\\ ` or `\\x20` for an ASCII space.\n\nFlags can be toggled within a pattern. Here's an example that matches\ncase-insensitively for the first part but case-sensitively for the second part:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?i)a+(?-i)b+\").unwrap();\nlet m = re.find(\"AaAaAbbBBBb\").unwrap();\nassert_eq!(m.as_str(), \"AaAaAbb\");\n```\n\nNotice that the `a+` matches either `a` or `A`, but the `b+` only matches\n`b`.\n\nMulti-line mode means `^` and `$` no longer match just at the beginning/end of\nthe input, but also at the beginning/end of lines:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?m)^line \\d+\").unwrap();\nlet m = re.find(\"line one\\nline 2\\n\").unwrap();\nassert_eq!(m.as_str(), \"line 2\");\n```\n\nNote that `^` matches after new lines, even at the end of input:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?m)^\").unwrap();\nlet m = re.find_iter(\"test\\n\").last().unwrap();\nassert_eq!((m.start(), m.end()), (5, 5));\n```\n\nWhen both CRLF mode and multi-line mode are enabled, then `^` and `$` will\nmatch either `\\r` or `\\n`, but never in the middle of a `\\r\\n`:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?mR)^foo$\").unwrap();\nlet m = re.find(\"\\r\\nfoo\\r\\n\").unwrap();\nassert_eq!(m.as_str(), \"foo\");\n```\n\nUnicode mode can also be selectively disabled, although only when the result\n*would not* match invalid UTF-8. One good example of this is using an ASCII\nword boundary instead of a Unicode word boundary, which might make some regex\nsearches run faster:\n\n```rust\nuse regex::Regex;\n\nlet re = Regex::new(r\"(?-u:\\b).+(?-u:\\b)\").unwrap();\nlet m = re.find(\"$$abc$$\").unwrap();\nassert_eq!(m.as_str(), \"abc\");\n```\n\n### Escape sequences\n\nNote that this includes all possible escape sequences, even ones that are\ndocumented elsewhere.\n\n<pre class=\"rust\">\n\\* literal *, applies to all ASCII except [0-9A-Za-z<>]\n\\a bell (\\x07)\n\\f form feed (\\x0C)\n\\t horizontal tab\n\\n new line\n\\r carriage return\n\\v vertical tab (\\x0B)\n\\A matches at the beginning of a haystack\n\\z matches at the end of a haystack\n\\b word boundary assertion\n\\B negated word boundary assertion\n\\b{start}, \\< start-of-word boundary assertion\n\\b{end}, \\> end-of-word boundary assertion\n\\b{start-half} half of a start-of-word boundary assertion\n\\b{end-half} half of a end-of-word boundary assertion\n\\123 octal character code, up to three digits (when enabled)\n\\x7F hex character code (exactly two digits)\n\\x{10FFFF} any hex character code corresponding to a Unicode code point\n\\u007F hex character code (exactly four digits)\n\\u{7F} any hex character code corresponding to a Unicode code point\n\\U0000007F hex character code (exactly eight digits)\n\\U{7F} any hex character code corresponding to a Unicode code point\n\\p{Letter} Unicode character class\n\\P{Letter} negated Unicode character class\n\\d, \\s, \\w Perl character class\n\\D, \\S, \\W negated Perl character class\n</pre>\n\n### Perl character classes (Unicode friendly)\n\nThese classes are based on the definitions provided in\n[UTS#18](https://www.unicode.org/reports/tr18/#Compatibility_Properties):\n\n<pre class=\"rust\">\n\\d digit (\\p{Nd})\n\\D not digit\n\\s whitespace (\\p{White_Space})\n\\S not whitespace\n\\w word character (\\p{Alphabetic} + \\p{M} + \\d + \\p{Pc} + \\p{Join_Control})\n\\W not word character\n</pre>\n\n### ASCII character classes\n\nThese classes are based on the definitions provided in\n[UTS#18](https://www.unicode.org/reports/tr18/#Compatibility_Properties):\n\n<pre class=\"rust\">\n[[:alnum:]] alphanumeric ([0-9A-Za-z])\n[[:alpha:]] alphabetic ([A-Za-z])\n[[:ascii:]] ASCII ([\\x00-\\x7F])\n[[:blank:]] blank ([\\t ])\n[[:cntrl:]] control ([\\x00-\\x1F\\x7F])\n[[:digit:]] digits ([0-9])\n[[:graph:]] graphical ([!-~])\n[[:lower:]] lower case ([a-z])\n[[:print:]] printable ([ -~])\n[[:punct:]] punctuation ([!-/:-@\\[-`{-~])\n[[:space:]] whitespace ([\\t\\n\\v\\f\\r ])\n[[:upper:]] upper case ([A-Z])\n[[:word:]] word characters ([0-9A-Za-z_])\n[[:xdigit:]] hex digit ([0-9A-Fa-f])\n</pre>\n\n# Untrusted input\n\nThis crate is meant to be able to run regex searches on untrusted haystacks\nwithout fear of [ReDoS]. This crate also, to a certain extent, supports\nuntrusted patterns.\n\n[ReDoS]: https://en.wikipedia.org/wiki/ReDoS\n\nThis crate differs from most (but not all) other regex engines in that it\ndoesn't use unbounded backtracking to run a regex search. In those cases,\none generally cannot use untrusted patterns *or* untrusted haystacks because\nit can be very difficult to know whether a particular pattern will result in\ncatastrophic backtracking or not.\n\nWe'll first discuss how this crate deals with untrusted inputs and then wrap\nit up with a realistic discussion about what practice really looks like.\n\n### Panics\n\nOutside of clearly documented cases, most APIs in this crate are intended to\nnever panic regardless of the inputs given to them. For example, `Regex::new`,\n`Regex::is_match`, `Regex::find` and `Regex::captures` should never panic. That\nis, it is an API promise that those APIs will never panic no matter what inputs\nare given to them. With that said, regex engines are complicated beasts, and\nproviding a rock solid guarantee that these APIs literally never panic is\nessentially equivalent to saying, \"there are no bugs in this library.\" That is\na bold claim, and not really one that can be feasibly made with a straight\nface.\n\nDon't get the wrong impression here. This crate is extensively tested, not just\nwith unit and integration tests, but also via fuzz testing. For example, this\ncrate is part of the [OSS-fuzz project]. Panics should be incredibly rare, but\nit is possible for bugs to exist, and thus possible for a panic to occur. If\nyou need a rock solid guarantee against panics, then you should wrap calls into\nthis library with [`std::panic::catch_unwind`].\n\nIt's also worth pointing out that this library will *generally* panic when\nother regex engines would commit undefined behavior. When undefined behavior\noccurs, your program might continue as if nothing bad has happened, but it also\nmight mean your program is open to the worst kinds of exploits. In contrast,\nthe worst thing a panic can do is a denial of service.\n\n[OSS-fuzz project]: https://android.googlesource.com/platform/external/oss-fuzz/+/refs/tags/android-t-preview-1/projects/rust-regex/\n[`std::panic::catch_unwind`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html\n\n### Untrusted patterns\n\nThe principal way this crate deals with them is by limiting their size by\ndefault. The size limit can be configured via [`RegexBuilder::size_limit`]. The\nidea of a size limit is that compiling a pattern into a `Regex` will fail if it\nbecomes \"too big.\" Namely, while *most* resources consumed by compiling a regex\nare approximately proportional (albeit with some high constant factors in some\ncases, such as with Unicode character classes) to the length of the pattern\nitself, there is one particular exception to this: counted repetitions. Namely,\nthis pattern:\n\n```text\na{5}{5}{5}{5}{5}{5}\n```\n\nIs equivalent to this pattern:\n\n```text\na{15625}\n```\n\nIn both of these cases, the actual pattern string is quite small, but the\nresulting `Regex` value is quite large. Indeed, as the first pattern shows,\nit isn't enough to locally limit the size of each repetition because they can\nbe stacked in a way that results in exponential growth.\n\nTo provide a bit more context, a simplified view of regex compilation looks\nlike this:\n\n* The pattern string is parsed into a structured representation called an AST.\nCounted repetitions are not expanded and Unicode character classes are not\nlooked up in this stage. That is, the size of the AST is proportional to the\nsize of the pattern with \"reasonable\" constant factors. In other words, one\ncan reasonably limit the memory used by an AST by limiting the length of the\npattern string.\n* The AST is translated into an HIR. Counted repetitions are still *not*\nexpanded at this stage, but Unicode character classes are embedded into the\nHIR. The memory usage of a HIR is still proportional to the length of the\noriginal pattern string, but the constant factors---mostly as a result of\nUnicode character classes---can be quite high. Still though, the memory used by\nan HIR can be reasonably limited by limiting the length of the pattern string.\n* The HIR is compiled into a [Thompson NFA]. This is the stage at which\nsomething like `\\w{5}` is rewritten to `\\w\\w\\w\\w\\w`. Thus, this is the stage\nat which [`RegexBuilder::size_limit`] is enforced. If the NFA exceeds the\nconfigured size, then this stage will fail.\n\n[Thompson NFA]: https://en.wikipedia.org/wiki/Thompson%27s_construction\n\nThe size limit helps avoid two different kinds of exorbitant resource usage:\n\n* It avoids permitting exponential memory usage based on the size of the\npattern string.\n* It avoids long search times. This will be discussed in more detail in the\nnext section, but worst case search time *is* dependent on the size of the\nregex. So keeping regexes limited to a reasonable size is also a way of keeping\nsearch times reasonable.\n\nFinally, it's worth pointing out that regex compilation is guaranteed to take\nworst case `O(m)` time, where `m` is proportional to the size of regex. The\nsize of the regex here is *after* the counted repetitions have been expanded.\n\n**Advice for those using untrusted regexes**: limit the pattern length to\nsomething small and expand it as needed. Configure [`RegexBuilder::size_limit`]\nto something small and then expand it as needed.\n\n### Untrusted haystacks\n\nThe main way this crate guards against searches from taking a long time is by\nusing algorithms that guarantee a `O(m * n)` worst case time and space bound.\nNamely:\n\n* `m` is proportional to the size of the regex, where the size of the regex\nincludes the expansion of all counted repetitions. (See the previous section on\nuntrusted patterns.)\n* `n` is proportional to the length, in bytes, of the haystack.\n\nIn other words, if you consider `m` to be a constant (for example, the regex\npattern is a literal in the source code), then the search can be said to run\nin \"linear time.\" Or equivalently, \"linear time with respect to the size of the\nhaystack.\"\n\nBut the `m` factor here is important not to ignore. If a regex is\nparticularly big, the search times can get quite slow. This is why, in part,\n[`RegexBuilder::size_limit`] exists.\n\n**Advice for those searching untrusted haystacks**: As long as your regexes\nare not enormous, you should expect to be able to search untrusted haystacks\nwithout fear. If you aren't sure, you should benchmark it. Unlike backtracking\nengines, if your regex is so big that it's likely to result in slow searches,\nthis is probably something you'll be able to observe regardless of what the\nhaystack is made up of.\n\n### Iterating over matches\n\nOne thing that is perhaps easy to miss is that the worst case time\ncomplexity bound of `O(m * n)` applies to methods like [`Regex::is_match`],\n[`Regex::find`] and [`Regex::captures`]. It does **not** apply to\n[`Regex::find_iter`] or [`Regex::captures_iter`]. Namely, since iterating over\nall matches can execute many searches, and each search can scan the entire\nhaystack, the worst case time complexity for iterators is `O(m * n^2)`.\n\nOne example of where this occurs is when a pattern consists of an alternation,\nwhere an earlier branch of the alternation requires scanning the entire\nhaystack only to discover that there is no match. It also requires a later\nbranch of the alternation to have matched at the beginning of the search. For\nexample, consider the pattern `.*[^A-Z]|[A-Z]` and the haystack `AAAAA`. The\nfirst search will scan to the end looking for matches of `.*[^A-Z]` even though\na finite automata engine (as in this crate) knows that `[A-Z]` has already\nmatched the first character of the haystack. This is due to the greedy nature\nof regex searching. That first search will report a match at the first `A` only\nafter scanning to the end to discover that no other match exists. The next\nsearch then begins at the second `A` and the behavior repeats.\n\nThere is no way to avoid this. This means that if both patterns and haystacks\nare untrusted and you're iterating over all matches, you're susceptible to\nworst case quadratic time complexity. One possible way to mitigate this\nis to drop down to the lower level `regex-automata` crate and use its\n`meta::Regex` iterator APIs. There, you can configure the search to operate\nin \"earliest\" mode by passing a `Input::new(haystack).earliest(true)` to\n`meta::Regex::find_iter` (for example). By enabling this mode, you give up\nthe normal greedy match semantics of regex searches and instead ask the regex\nengine to immediately stop as soon as a match has been found. Enabling this\nmode will thus restore the worst case `O(m * n)` time complexity bound, but at\nthe cost of different semantics.\n\n### Untrusted inputs in practice\n\nWhile providing a `O(m * n)` worst case time bound on all searches goes a long\nway toward preventing [ReDoS], that doesn't mean every search you can possibly\nrun will complete without burning CPU time. In general, there are a few ways\nfor the `m * n` time bound to still bite you:\n\n* You are searching an exceptionally long haystack. No matter how you slice\nit, a longer haystack will take more time to search. This crate may often make\nvery quick work of even long haystacks because of its literal optimizations,\nbut those aren't available for all regexes.\n* Unicode character classes can cause searches to be quite slow in some cases.\nThis is especially true when they are combined with counted repetitions. While\nthe regex size limit above will protect you from the most egregious cases,\nthe default size limit still permits pretty big regexes that can execute more\nslowly than one might expect.\n* While routines like [`Regex::find`] and [`Regex::captures`] guarantee\nworst case `O(m * n)` search time, routines like [`Regex::find_iter`] and\n[`Regex::captures_iter`] actually have worst case `O(m * n^2)` search time.\nThis is because `find_iter` runs many searches, and each search takes worst\ncase `O(m * n)` time. Thus, iteration of all matches in a haystack has\nworst case `O(m * n^2)`. A good example of a pattern that exhibits this is\n`(?:A+){1000}|` or even `.*[^A-Z]|[A-Z]`.\n\nIn general, untrusted haystacks are easier to stomach than untrusted patterns.\nUntrusted patterns give a lot more control to the caller to impact the\nperformance of a search. In many cases, a regex search will actually execute in\naverage case `O(n)` time (i.e., not dependent on the size of the regex), but\nthis can't be guaranteed in general. Therefore, permitting untrusted patterns\nmeans that your only line of defense is to put a limit on how big `m` (and\nperhaps also `n`) can be in `O(m * n)`. `n` is limited by simply inspecting\nthe length of the haystack while `m` is limited by *both* applying a limit to\nthe length of the pattern *and* a limit on the compiled size of the regex via\n[`RegexBuilder::size_limit`].\n\nIt bears repeating: if you're accepting untrusted patterns, it would be a good\nidea to start with conservative limits on `m` and `n`, and then carefully\nincrease them as needed.\n\n# Crate features\n\nBy default, this crate tries pretty hard to make regex matching both as fast\nas possible and as correct as it can be. This means that there is a lot of\ncode dedicated to performance, the handling of Unicode data and the Unicode\ndata itself. Overall, this leads to more dependencies, larger binaries and\nlonger compile times. This trade off may not be appropriate in all cases, and\nindeed, even when all Unicode and performance features are disabled, one is\nstill left with a perfectly serviceable regex engine that will work well in\nmany cases. (Note that code is not arbitrarily reducible, and for this reason,\nthe [`regex-lite`](https://docs.rs/regex-lite) crate exists to provide an even\nmore minimal experience by cutting out Unicode and performance, but still\nmaintaining the linear search time bound.)\n\nThis crate exposes a number of features for controlling that trade off. Some\nof these features are strictly performance oriented, such that disabling them\nwon't result in a loss of functionality, but may result in worse performance.\nOther features, such as the ones controlling the presence or absence of Unicode\ndata, can result in a loss of functionality. For example, if one disables the\n`unicode-case` feature (described below), then compiling the regex `(?i)a`\nwill fail since Unicode case insensitivity is enabled by default. Instead,\ncallers must use `(?i-u)a` to disable Unicode case folding. Stated differently,\nenabling or disabling any of the features below can only add or subtract from\nthe total set of valid regular expressions. Enabling or disabling a feature\nwill never modify the match semantics of a regular expression.\n\nMost features below are enabled by default. Features that aren't enabled by\ndefault are noted.\n\n### Ecosystem features\n\n* **std** -\n When enabled, this will cause `regex` to use the standard library. In terms\n of APIs, `std` causes error types to implement the `std::error::Error`\n trait. Enabling `std` will also result in performance optimizations,\n including SIMD and faster synchronization primitives. Notably, **disabling\n the `std` feature will result in the use of spin locks**. To use a regex\n engine without `std` and without spin locks, you'll need to drop down to\n the [`regex-automata`](https://docs.rs/regex-automata) crate.\n* **logging** -\n When enabled, the `log` crate is used to emit messages about regex\n compilation and search strategies. This is **disabled by default**. This is\n typically only useful to someone working on this crate's internals, but might\n be useful if you're doing some rabbit hole performance hacking. Or if you're\n just interested in the kinds of decisions being made by the regex engine.\n\n### Performance features\n\n**Note**:\n To get performance benefits offered by the SIMD, `std` must be enabled.\n None of the `perf-*` features will enable `std` implicitly.\n\n* **perf** -\n Enables all performance related features except for `perf-dfa-full`. This\n feature is enabled by default is intended to cover all reasonable features\n that improve performance, even if more are added in the future.\n* **perf-dfa** -\n Enables the use of a lazy DFA for matching. The lazy DFA is used to compile\n portions of a regex to a very fast DFA on an as-needed basis. This can\n result in substantial speedups, usually by an order of magnitude on large\n haystacks. The lazy DFA does not bring in any new dependencies, but it can\n make compile times longer.\n* **perf-dfa-full** -\n Enables the use of a full DFA for matching. Full DFAs are problematic because\n they have worst case `O(2^n)` construction time. For this reason, when this\n feature is enabled, full DFAs are only used for very small regexes and a\n very small space bound is used during determinization to avoid the DFA\n from blowing up. This feature is not enabled by default, even as part of\n `perf`, because it results in fairly sizeable increases in binary size and\n compilation time. It can result in faster search times, but they tend to be\n more modest and limited to non-Unicode regexes.\n* **perf-onepass** -\n Enables the use of a one-pass DFA for extracting the positions of capture\n groups. This optimization applies to a subset of certain types of NFAs and\n represents the fastest engine in this crate for dealing with capture groups.\n* **perf-backtrack** -\n Enables the use of a bounded backtracking algorithm for extracting the\n positions of capture groups. This usually sits between the slowest engine\n (the PikeVM) and the fastest engine (one-pass DFA) for extracting capture\n groups. It's used whenever the regex is not one-pass and is small enough.\n* **perf-inline** -\n Enables the use of aggressive inlining inside match routines. This reduces\n the overhead of each match. The aggressive inlining, however, increases\n compile times and binary size.\n* **perf-literal** -\n Enables the use of literal optimizations for speeding up matches. In some\n cases, literal optimizations can result in speedups of _several_ orders of\n magnitude. Disabling this drops the `aho-corasick` and `memchr` dependencies.\n* **perf-cache** -\n This feature used to enable a faster internal cache at the cost of using\n additional dependencies, but this is no longer an option. A fast internal\n cache is now used unconditionally with no additional dependencies. This may\n change in the future.\n\n### Unicode features\n\n* **unicode** -\n Enables all Unicode features. This feature is enabled by default, and will\n always cover all Unicode features, even if more are added in the future.\n* **unicode-age** -\n Provide the data for the\n [Unicode `Age` property](https://www.unicode.org/reports/tr44/tr44-24.html#Character_Age).\n This makes it possible to use classes like `\\p{Age:6.0}` to refer to all\n codepoints first introduced in Unicode 6.0\n* **unicode-bool** -\n Provide the data for numerous Unicode boolean properties. The full list\n is not included here, but contains properties like `Alphabetic`, `Emoji`,\n `Lowercase`, `Math`, `Uppercase` and `White_Space`.\n* **unicode-case** -\n Provide the data for case insensitive matching using\n [Unicode's \"simple loose matches\" specification](https://www.unicode.org/reports/tr18/#Simple_Loose_Matches).\n* **unicode-gencat** -\n Provide the data for\n [Unicode general categories](https://www.unicode.org/reports/tr44/tr44-24.html#General_Category_Values).\n This includes, but is not limited to, `Decimal_Number`, `Letter`,\n `Math_Symbol`, `Number` and `Punctuation`.\n* **unicode-perl** -\n Provide the data for supporting the Unicode-aware Perl character classes,\n corresponding to `\\w`, `\\s` and `\\d`. This is also necessary for using\n Unicode-aware word boundary assertions. Note that if this feature is\n disabled, the `\\s` and `\\d` character classes are still available if the\n `unicode-bool` and `unicode-gencat` features are enabled, respectively.\n* **unicode-script** -\n Provide the data for\n [Unicode scripts and script extensions](https://www.unicode.org/reports/tr24/).\n This includes, but is not limited to, `Arabic`, `Cyrillic`, `Hebrew`,\n `Latin` and `Thai`.\n* **unicode-segment** -\n Provide the data necessary to provide the properties used to implement the\n [Unicode text segmentation algorithms](https://www.unicode.org/reports/tr29/).\n This enables using classes like `\\p{gcb=Extend}`, `\\p{wb=Katakana}` and\n `\\p{sb=ATerm}`.\n\n# Other crates\n\nThis crate has two required dependencies and several optional dependencies.\nThis section briefly describes them with the goal of raising awareness of how\ndifferent components of this crate may be used independently.\n\nIt is somewhat unusual for a regex engine to have dependencies, as most regex\nlibraries are self contained units with no dependencies other than a particular\nenvironment's standard library. Indeed, for other similarly optimized regex\nengines, most or all of the code in the dependencies of this crate would\nnormally just be inseparable or coupled parts of the crate itself. But since\nRust and its tooling ecosystem make the use of dependencies so easy, it made\nsense to spend some effort de-coupling parts of this crate and making them\nindependently useful.\n\nWe only briefly describe each crate here.\n\n* [`regex-lite`](https://docs.rs/regex-lite) is not a dependency of `regex`,\nbut rather, a standalone zero-dependency simpler version of `regex` that\nprioritizes compile times and binary size. In exchange, it eschews Unicode\nsupport and performance. Its match semantics are as identical as possible to\nthe `regex` crate, and for the things it supports, its APIs are identical to\nthe APIs in this crate. In other words, for a lot of use cases, it is a drop-in\nreplacement.\n* [`regex-syntax`](https://docs.rs/regex-syntax) provides a regular expression\nparser via `Ast` and `Hir` types. It also provides routines for extracting\nliterals from a pattern. Folks can use this crate to do analysis, or even to\nbuild their own regex engine without having to worry about writing a parser.\n* [`regex-automata`](https://docs.rs/regex-automata) provides the regex engines\nthemselves. One of the downsides of finite automata based regex engines is that\nthey often need multiple internal engines in order to have similar or better\nperformance than an unbounded backtracking engine in practice. `regex-automata`\nin particular provides public APIs for a PikeVM, a bounded backtracker, a\none-pass DFA, a lazy DFA, a fully compiled DFA and a meta regex engine that\ncombines all them together. It also has native multi-pattern support and\nprovides a way to compile and serialize full DFAs such that they can be loaded\nand searched in a no-std no-alloc environment. `regex-automata` itself doesn't\neven have a required dependency on `regex-syntax`!\n* [`memchr`](https://docs.rs/memchr) provides low level SIMD vectorized\nroutines for quickly finding the location of single bytes or even substrings\nin a haystack. In other words, it provides fast `memchr` and `memmem` routines.\nThese are used by this crate in literal optimizations.\n* [`aho-corasick`](https://docs.rs/aho-corasick) provides multi-substring\nsearch. It also provides SIMD vectorized routines in the case where the number\nof substrings to search for is relatively small. The `regex` crate also uses\nthis for literal optimizations.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "regex", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "regex", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "tree_house", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "tree_house", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "tree_house", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "helix_loader", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "helix_loader", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "helix_loader", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "parking_lot", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "This library provides implementations of `Mutex`, `RwLock`, `Condvar` and\n`Once` that are smaller, faster and more flexible than those in the Rust\nstandard library. It also provides a `ReentrantMutex` type.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "parking_lot", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "parking_lot", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "serde_json", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "# Serde JSON\n\nJSON is a ubiquitous open-standard format that uses human-readable text to\ntransmit data objects consisting of key-value pairs.\n\n```json\n{\n \"name\": \"John Doe\",\n \"age\": 43,\n \"address\": {\n \"street\": \"10 Downing Street\",\n \"city\": \"London\"\n },\n \"phones\": [\n \"+44 1234567\",\n \"+44 2345678\"\n ]\n}\n```\n\nThere are three common ways that you might find yourself needing to work\nwith JSON data in Rust.\n\n - **As text data.** An unprocessed string of JSON data that you receive on\n an HTTP endpoint, read from a file, or prepare to send to a remote\n server.\n - **As an untyped or loosely typed representation.** Maybe you want to\n check that some JSON data is valid before passing it on, but without\n knowing the structure of what it contains. Or you want to do very basic\n manipulations like insert a key in a particular spot.\n - **As a strongly typed Rust data structure.** When you expect all or most\n of your data to conform to a particular structure and want to get real\n work done without JSON's loosey-goosey nature tripping you up.\n\nSerde JSON provides efficient, flexible, safe ways of converting data\nbetween each of these representations.\n\n# Operating on untyped JSON values\n\nAny valid JSON data can be manipulated in the following recursive enum\nrepresentation. This data structure is [`serde_json::Value`][value].\n\n```rust\nenum Value {\n Null,\n Bool(bool),\n Number(Number),\n String(String),\n Array(Vec<Value>),\n Object(Map<String, Value>),\n}\n```\n\nA string of JSON data can be parsed into a `serde_json::Value` by the\n[`serde_json::from_str`][from_str] function. There is also [`from_slice`]\nfor parsing from a byte slice `&[u8]` and [`from_reader`] for parsing from\nany `io::Read` like a File or a TCP stream.\n\n```rust\nuse serde_json::{Result, Value};\n\nfn untyped_example() -> Result<()> {\n // Some JSON input data as a &str. Maybe this comes from the user.\n let data = r#\"\n {\n \"name\": \"John Doe\",\n \"age\": 43,\n \"phones\": [\n \"+44 1234567\",\n \"+44 2345678\"\n ]\n }\"#;\n\n // Parse the string of data into serde_json::Value.\n let v: Value = serde_json::from_str(data)?;\n\n // Access parts of the data by indexing with square brackets.\n println!(\"Please call {} at the number {}\", v[\"name\"], v[\"phones\"][0]);\n\n Ok(())\n}\n```\n\nThe result of square bracket indexing like `v[\"name\"]` is a borrow of the\ndata at that index, so the type is `&Value`. A JSON map can be indexed with\nstring keys, while a JSON array can be indexed with integer keys. If the\ntype of the data is not right for the type with which it is being indexed,\nor if a map does not contain the key being indexed, or if the index into a\nvector is out of bounds, the returned element is `Value::Null`.\n\nWhen a `Value` is printed, it is printed as a JSON string. So in the code\nabove, the output looks like `Please call \"John Doe\" at the number \"+44\n1234567\"`. The quotation marks appear because `v[\"name\"]` is a `&Value`\ncontaining a JSON string and its JSON representation is `\"John Doe\"`.\nPrinting as a plain string without quotation marks involves converting from\na JSON string to a Rust string with [`as_str()`] or avoiding the use of\n`Value` as described in the following section.\n\n[`as_str()`]: crate::Value::as_str\n\nThe `Value` representation is sufficient for very basic tasks but can be\ntedious to work with for anything more significant. Error handling is\nverbose to implement correctly, for example imagine trying to detect the\npresence of unrecognized fields in the input data. The compiler is powerless\nto help you when you make a mistake, for example imagine typoing `v[\"name\"]`\nas `v[\"nmae\"]` in one of the dozens of places it is used in your code.\n\n# Parsing JSON as strongly typed data structures\n\nSerde provides a powerful way of mapping JSON data into Rust data structures\nlargely automatically.\n\n```rust\nuse serde::{Deserialize, Serialize};\nuse serde_json::Result;\n\n#[derive(Serialize, Deserialize)]\nstruct Person {\n name: String,\n age: u8,\n phones: Vec<String>,\n}\n\nfn typed_example() -> Result<()> {\n // Some JSON input data as a &str. Maybe this comes from the user.\n let data = r#\"\n {\n \"name\": \"John Doe\",\n \"age\": 43,\n \"phones\": [\n \"+44 1234567\",\n \"+44 2345678\"\n ]\n }\"#;\n\n // Parse the string of data into a Person object. This is exactly the\n // same function as the one that produced serde_json::Value above, but\n // now we are asking it for a Person as output.\n let p: Person = serde_json::from_str(data)?;\n\n // Do things just like with any other Rust data structure.\n println!(\"Please call {} at the number {}\", p.name, p.phones[0]);\n\n Ok(())\n}\n```\n\nThis is the same `serde_json::from_str` function as before, but this time we\nassign the return value to a variable of type `Person` so Serde will\nautomatically interpret the input data as a `Person` and produce informative\nerror messages if the layout does not conform to what a `Person` is expected\nto look like.\n\nAny type that implements Serde's `Deserialize` trait can be deserialized\nthis way. This includes built-in Rust standard library types like `Vec<T>`\nand `HashMap<K, V>`, as well as any structs or enums annotated with\n`#[derive(Deserialize)]`.\n\nOnce we have `p` of type `Person`, our IDE and the Rust compiler can help us\nuse it correctly like they do for any other Rust code. The IDE can\nautocomplete field names to prevent typos, which was impossible in the\n`serde_json::Value` representation. And the Rust compiler can check that\nwhen we write `p.phones[0]`, then `p.phones` is guaranteed to be a\n`Vec<String>` so indexing into it makes sense and produces a `String`.\n\n# Constructing JSON values\n\nSerde JSON provides a [`json!` macro][macro] to build `serde_json::Value`\nobjects with very natural JSON syntax.\n\n```rust\nuse serde_json::json;\n\nfn main() {\n // The type of `john` is `serde_json::Value`\n let john = json!({\n \"name\": \"John Doe\",\n \"age\": 43,\n \"phones\": [\n \"+44 1234567\",\n \"+44 2345678\"\n ]\n });\n\n println!(\"first phone number: {}\", john[\"phones\"][0]);\n\n // Convert to a string of JSON and print it out\n println!(\"{}\", john.to_string());\n}\n```\n\nThe `Value::to_string()` function converts a `serde_json::Value` into a\n`String` of JSON text.\n\nOne neat thing about the `json!` macro is that variables and expressions can\nbe interpolated directly into the JSON value as you are building it. Serde\nwill check at compile time that the value you are interpolating is able to\nbe represented as JSON.\n\n```rust\nlet full_name = \"John Doe\";\nlet age_last_year = 42;\n\n// The type of `john` is `serde_json::Value`\nlet john = json!({\n \"name\": full_name,\n \"age\": age_last_year + 1,\n \"phones\": [\n format!(\"+44 {}\", random_phone())\n ]\n});\n```\n\nThis is amazingly convenient, but we have the problem we had before with\n`Value`: the IDE and Rust compiler cannot help us if we get it wrong. Serde\nJSON provides a better way of serializing strongly-typed data structures\ninto JSON text.\n\n# Creating JSON by serializing data structures\n\nA data structure can be converted to a JSON string by\n[`serde_json::to_string`][to_string]. There is also\n[`serde_json::to_vec`][to_vec] which serializes to a `Vec<u8>` and\n[`serde_json::to_writer`][to_writer] which serializes to any `io::Write`\nsuch as a File or a TCP stream.\n\n```rust\nuse serde::{Deserialize, Serialize};\nuse serde_json::Result;\n\n#[derive(Serialize, Deserialize)]\nstruct Address {\n street: String,\n city: String,\n}\n\nfn print_an_address() -> Result<()> {\n // Some data structure.\n let address = Address {\n street: \"10 Downing Street\".to_owned(),\n city: \"London\".to_owned(),\n };\n\n // Serialize it to a JSON string.\n let j = serde_json::to_string(&address)?;\n\n // Print, write to a file, or send to an HTTP server.\n println!(\"{}\", j);\n\n Ok(())\n}\n```\n\nAny type that implements Serde's `Serialize` trait can be serialized this\nway. This includes built-in Rust standard library types like `Vec<T>` and\n`HashMap<K, V>`, as well as any structs or enums annotated with\n`#[derive(Serialize)]`.\n\n# No-std support\n\nAs long as there is a memory allocator, it is possible to use serde_json\nwithout the rest of the Rust standard library. Disable the default \"std\"\nfeature and enable the \"alloc\" feature:\n\n```toml\n[dependencies]\nserde_json = { version = \"1.0\", default-features = false, features = [\"alloc\"] }\n```\n\nFor JSON support in Serde without a memory allocator, please see the\n[`serde-json-core`] crate.\n\n[value]: crate::value::Value\n[from_str]: crate::de::from_str\n[from_slice]: crate::de::from_slice\n[from_reader]: crate::de::from_reader\n[to_string]: crate::ser::to_string\n[to_vec]: crate::ser::to_vec\n[to_writer]: crate::ser::to_writer\n[macro]: crate::json\n[`serde-json-core`]: https://github.com/rust-embedded-community/serde-json-core", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "serde_json", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "serde_json", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "url", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "\n\nrust-url is an implementation of the [URL Standard](http://url.spec.whatwg.org/)\nfor the [Rust](http://rust-lang.org/) programming language.\n\n\n# URL parsing and data structures\n\nFirst, URL parsing may fail for various reasons and therefore returns a `Result`.\n\n```rust\nuse url::{Url, ParseError};\n\nassert!(Url::parse(\"http://[:::1]\") == Err(ParseError::InvalidIpv6Address))\n```\n\nLet’s parse a valid URL and look at its components.\n\n```rust\nuse url::{Url, Host, Position};\nlet issue_list_url = Url::parse(\n \"https://github.com/rust-lang/rust/issues?labels=E-easy&state=open\"\n)?;\n\n\nassert!(issue_list_url.scheme() == \"https\");\nassert!(issue_list_url.username() == \"\");\nassert!(issue_list_url.password() == None);\nassert!(issue_list_url.host_str() == Some(\"github.com\"));\nassert!(issue_list_url.host() == Some(Host::Domain(\"github.com\")));\nassert!(issue_list_url.port() == None);\nassert!(issue_list_url.path() == \"/rust-lang/rust/issues\");\nassert!(issue_list_url.path_segments().map(|c| c.collect::<Vec<_>>()) ==\n Some(vec![\"rust-lang\", \"rust\", \"issues\"]));\nassert!(issue_list_url.query() == Some(\"labels=E-easy&state=open\"));\nassert!(&issue_list_url[Position::BeforePath..] == \"/rust-lang/rust/issues?labels=E-easy&state=open\");\nassert!(issue_list_url.fragment() == None);\nassert!(!issue_list_url.cannot_be_a_base());\n```\n\nSome URLs are said to be *cannot-be-a-base*:\nthey don’t have a username, password, host, or port,\nand their \"path\" is an arbitrary string rather than slash-separated segments:\n\n```rust\nuse url::Url;\n\nlet data_url = Url::parse(\"data:text/plain,Hello?World#\")?;\n\nassert!(data_url.cannot_be_a_base());\nassert!(data_url.scheme() == \"data\");\nassert!(data_url.path() == \"text/plain,Hello\");\nassert!(data_url.path_segments().is_none());\nassert!(data_url.query() == Some(\"World\"));\nassert!(data_url.fragment() == Some(\"\"));\n```\n\n## Default Features\n\nVersions `<= 2.5.2` of the crate have no default features. Versions `> 2.5.2` have the default feature 'std'.\nIf you are upgrading across this boundary and you have specified `default-features = false`, then\nyou will need to add the 'std' feature or the 'alloc' feature to your dependency.\nThe 'std' feature has the same behavior as the previous versions. The 'alloc' feature\nprovides no_std support.\n\n## Serde\n\nEnable the `serde` feature to include `Deserialize` and `Serialize` implementations for `url::Url`.\n\n# Base URL\n\nMany contexts allow URL *references* that can be relative to a *base URL*:\n\n```html\n<link rel=\"stylesheet\" href=\"../main.css\">\n```\n\nSince parsed URLs are absolute, giving a base is required for parsing relative URLs:\n\n```rust\nuse url::{Url, ParseError};\n\nassert!(Url::parse(\"../main.css\") == Err(ParseError::RelativeUrlWithoutBase))\n```\n\nUse the `join` method on an `Url` to use it as a base URL:\n\n```rust\nuse url::Url;\n\nlet this_document = Url::parse(\"http://servo.github.io/rust-url/url/index.html\")?;\nlet css_url = this_document.join(\"../main.css\")?;\nassert_eq!(css_url.as_str(), \"http://servo.github.io/rust-url/main.css\");\n```\n\n# Feature: `serde`\n\nIf you enable the `serde` feature, [`Url`](struct.Url.html) will implement\n[`serde::Serialize`](https://docs.rs/serde/1/serde/trait.Serialize.html) and\n[`serde::Deserialize`](https://docs.rs/serde/1/serde/trait.Deserialize.html).\nSee [serde documentation](https://serde.rs) for more information.\n\n```toml\nurl = { version = \"2\", features = [\"serde\"] }\n```\n\n# Feature: `debugger_visualizer`\n\nIf you enable the `debugger_visualizer` feature, the `url` crate will include\na [natvis file](https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects)\nfor [Visual Studio](https://www.visualstudio.com/) that allows you to view\n[`Url`](struct.Url.html) objects in the debugger.\n\nThis feature requires Rust 1.71 or later.\n\n```toml\nurl = { version = \"2\", features = [\"debugger_visualizer\"] }\n```", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "url", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "url", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "helix_core", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "helix_core", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "helix_core", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "lsp_types", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "\n\nLanguage Server Protocol types for Rust.\n\nBased on: <https://microsoft.github.io/language-server-protocol/specification>\n\nThis library uses the URL crate for parsing URIs. Note that there is\nsome confusion on the meaning of URLs vs URIs:\n<http://stackoverflow.com/a/28865728/393898>. According to that\ninformation, on the classical sense of \"URLs\", \"URLs\" are a subset of\nURIs, But on the modern/new meaning of URLs, they are the same as\nURIs. The important take-away aspect is that the URL crate should be\nable to parse any URI, such as `urn:isbn:0451450523`.\n", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "lsp_types", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "lsp_types", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "lsp_server", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "A language server scaffold, exposing a synchronous crossbeam-channel based API.\nThis crate handles protocol handshaking and parsing messages, while you\ncontrol the message dispatch loop yourself.\n\nRun with `RUST_LOG=lsp_server=debug` to see all the messages.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "lsp_server", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "lsp_server", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "rust_fsm", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "\n[![Documentation][docs-badge]][docs-link]\n[![Latest Version][crate-badge]][crate-link]\n\nThe `rust-fsm` crate provides a simple and universal framework for building\nstate machines in Rust with minimum effort.\n\nThe essential part of this crate is the\n[`StateMachineImpl`](trait.StateMachineImpl.html) trait. This trait allows a\ndeveloper to provide a strict state machine definition, e.g. specify its:\n\n* An input alphabet - a set of entities that the state machine takes as\n inputs and performs state transitions based on them.\n* Possible states - a set of states this machine could be in.\n* An output alphabet - a set of entities that the state machine may output\n as results of its work.\n* A transition function - a function that changes the state of the state\n machine based on its current state and the provided input.\n* An output function - a function that outputs something from the output\n alphabet based on the current state and the provided inputs.\n* The initial state of the machine.\n\nNote that on the implementation level such abstraction allows build any type\nof state machines:\n\n* A classical state machine by providing only an input alphabet, a set of\n states and a transition function.\n* A Mealy machine by providing all entities listed above.\n* A Moore machine by providing an output function that do not depend on the\n provided inputs.\n\n## Feature flags\n\n### Default\n\n- `std` - implement features that require the `std` environment. See below.\n- `dsl` - re-export `rust-fsm-dsl` from `rust-fsm`. Recommended to leave this on\n for the best development experience.\n\n### Non-default\n\n- `diagram` - generate Mermaid state diagrams in the doc strings. See below.\n\n## Usage in `no_std` environments\n\nThis library has the feature named `std` which is enabled by default. You\nmay want to import this library as\n`rust-fsm = { version = \"0.8\", default-features = false, features = [\"dsl\"] }`\nto use it in a `no_std` environment. This only affects error types (the `Error`\ntrait is only available in `std`).\n\nThe DSL implementation re-export is gated by the feature named `dsl` which is\nalso enabled by default.\n\n## Use\n\nInitially this library was designed to build an easy to use DSL for defining\nstate machines on top of it. Using the DSL will require to connect an\nadditional crate `rust-fsm-dsl` (this is due to limitation of the procedural\nmacros system).\n\n### Using the DSL for defining state machines\n\nThe DSL is parsed by the `state_machine` macro. Here is a little example.\n\n```rust\nuse rust_fsm::*;\n\nstate_machine! {\n #[derive(Debug)]\n #[repr(C)]\n /// A Circuit Breaker state machine.\n circuit_breaker(Closed)\n\n Closed(Unsuccessful) => Open [SetupTimer],\n Open(TimerTriggered) => HalfOpen,\n HalfOpen => {\n Successful => Closed,\n Unsuccessful => Open [SetupTimer]\n }\n}\n```\n\nThis code sample:\n\n* Defines a state machine called `circuit_breaker`;\n* Derives the `Debug` trait for it. All attributes you use here (like\n `#[repr(C)]`) will be applied to all types generated by this macro. If you\n want to apply attributes or a docstring to the `mod` generated by this macro,\n just put it before the macro invocation.\n* Sets the initial state of this state machine to `Closed`;\n* Defines state transitions. For example: on receiving the `Successful`\n input when in the `HalfOpen` state, the machine must move to the `Closed`\n state;\n* Defines outputs. For example: on receiving `Unsuccessful` in the\n `Closed` state, the machine must output `SetupTimer`.\n\nThis state machine can be used as follows:\n\n```rust\n// Initialize the state machine. The state is `Closed` now.\nlet mut machine = circuit_breaker::StateMachine::new();\n// Consume the `Successful` input. No state transition is performed.\nlet _ = machine.consume(circuit_breaker::Input::Successful);\n// Consume the `Unsuccesful` input. The machine is moved to the `Open`\n// state. The output is `SetupTimer`.\nlet output = machine.consume(circuit_breaker::Input::Unsuccessful).unwrap();\n// Check the output\nif let Some(circuit_breaker::Output::SetupTimer) = output {\n // Set up the timer...\n}\n// Check the state\nif let circuit_breaker::State::Open = machine.state() {\n // Do something...\n}\n```\n\nThe following entities are generated:\n\n* An empty structure `circuit_breaker::Impl` that implements the\n `StateMachineImpl` trait.\n* Enums `circuit_breaker::State`, `circuit_breaker::Input` and\n `circuit_breaker::Output` that represent the state, the input alphabet and the\n output alphabet respectively.\n* Type alias `circuit_breaker::StateMachine` that expands to\n `StateMachine<circuit_breaker::Impl>`.\n\nNote that if there is no outputs in the specification, the output alphabet is an\nempty enum and due to technical limitations of many Rust attributes, no\nattributes (e.g. `derive`, `repr`) are applied to it.\n\nWithin the `state_machine` macro you must define at least one state\ntransition.\n\n#### Visibility\n\nYou can specify visibility like this:\n\n```rust\nuse rust_fsm::*;\n\nstate_machine! {\n pub CircuitBreaker: Closed => Result => Action\n\n Closed => Unsuccessful => Open [SetupTimer],\n Open => TimerTriggered => HalfOpen,\n HalfOpen => {\n Successful => Closed,\n Unsuccessful => Open [SetupTimer]\n }\n}\n```\n\nThe default visibility is private.\n\n#### Custom alphabet types\n\nYou can supply your own types to use as input, output or state. All of them are\noptional: you can use only one of them or all of them at once if you want to.\nThe current limitation is that you have to supply a fully qualified type path.\n\n```rust\nuse rust_fsm::*;\n\npub enum Input {\n Successful,\n Unsuccessful,\n TimerTriggered,\n}\n\npub enum State {\n Closed,\n HalfOpen,\n Open,\n}\n\npub enum Output {\n SetupTimer,\n}\n\nstate_machine! {\n #[state_machine(input(crate::Input), state(crate::State), output(crate::Output))]\n circuit_breaker(Closed)\n\n Closed(Unsuccessful) => Open [SetupTimer],\n Open(TimerTriggered) => HalfOpen,\n HalfOpen => {\n Successful => Closed,\n Unsuccessful => Open [SetupTimer]\n }\n}\n```\n\n#### Diagrams\n\n`state_machine` macro can document your state machines with diagrams. This is\ncontrolled by the `diagram` feature, which is non-default. The diagrams are\ngenerated in the [Mermaid][mermaid] format. This feature includes the Mermaid\nscript into the documentation page.\n\nTo see this in action, download the repository and run:\n\n```bash\ncargo doc -p doc-example --open\n```\n\n\n\n### Without DSL\n\nThe `state_machine` macro has limited capabilities (for example, a state\ncannot carry any additional data), so in certain complex cases a user might\nwant to write a more complex state machine by hand.\n\nAll you need to do to build a state machine is to implement the\n`StateMachineImpl` trait and use it in conjuctions with some of the provided\nwrappers (for now there is only `StateMachine`).\n\nYou can see an example of the Circuit Breaker state machine in the\n[project repository][repo].\n\n[repo]: https://github.com/eugene-babichenko/rust-fsm\n[docs-badge]: https://docs.rs/rust-fsm/badge.svg\n[docs-link]: https://docs.rs/rust-fsm\n[crate-badge]: https://img.shields.io/crates/v/rust-fsm.svg\n[crate-link]: https://crates.io/crates/rust-fsm\n[mermaid]: https://mermaid.js.org/", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "rust_fsm", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "rust_fsm", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "amap", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "amap", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "amap", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "clipp", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "simple possibly cross platform clipboard crate\n\n```rust\nclipp::copy(\"wow such clipboard\");\nassert_eq!(clipp::paste(), \"wow such clipboard\");\n```", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "clipp", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "clipp", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "crossbeam", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "Tools for concurrent programming.\n\n## Atomics\n\n* [`AtomicCell`], a thread-safe mutable memory location.\n* [`AtomicConsume`], for reading from primitive atomic types with \"consume\" ordering.\n\n## Data structures\n\n* [`deque`], work-stealing deques for building task schedulers.\n* [`ArrayQueue`], a bounded MPMC queue that allocates a fixed-capacity buffer on construction.\n* [`SegQueue`], an unbounded MPMC queue that allocates small buffers, segments, on demand.\n\n## Memory management\n\n* [`epoch`], an epoch-based garbage collector.\n\n## Thread synchronization\n\n* [`channel`], multi-producer multi-consumer channels for message passing.\n* [`Parker`], a thread parking primitive.\n* [`ShardedLock`], a sharded reader-writer lock with fast concurrent reads.\n* [`WaitGroup`], for synchronizing the beginning or end of some computation.\n\n## Utilities\n\n* [`Backoff`], for exponential backoff in spin loops.\n* [`CachePadded`], for padding and aligning a value to the length of a cache line.\n* [`scope`], for spawning threads that borrow local variables from the stack.\n\n[`AtomicCell`]: atomic::AtomicCell\n[`AtomicConsume`]: atomic::AtomicConsume\n[`ArrayQueue`]: queue::ArrayQueue\n[`SegQueue`]: queue::SegQueue\n[`Parker`]: sync::Parker\n[`ShardedLock`]: sync::ShardedLock\n[`WaitGroup`]: sync::WaitGroup\n[`Backoff`]: utils::Backoff\n[`CachePadded`]: utils::CachePadded", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "crossbeam", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "crossbeam", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "diff_match_patch_rs", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "diff_match_patch_rs", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "diff_match_patch_rs", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "env_logger", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "A simple logger that can be configured via environment variables, for use\nwith the logging facade exposed by the [`log` crate][log-crate-url].\n\nDespite having \"env\" in its name, **`env_logger`** can also be configured by\nother means besides environment variables. See [the examples][gh-repo-examples]\nin the source repository for more approaches.\n\nBy default, `env_logger` writes logs to `stderr`, but can be configured to\ninstead write them to `stdout`.\n\n## Example\n\n```rust\nuse log::{debug, error, log_enabled, info, Level};\n\nenv_logger::init();\n\ndebug!(\"this is a debug {}\", \"message\");\nerror!(\"this is printed by default\");\n\nif log_enabled!(Level::Info) {\n let x = 3 * 4; // expensive computation\n info!(\"the answer was: {}\", x);\n}\n```\n\nAssumes the binary is `main`:\n\n```console\n$ RUST_LOG=error ./main\n[2017-11-09T02:12:24Z ERROR main] this is printed by default\n```\n\n```console\n$ RUST_LOG=info ./main\n[2017-11-09T02:12:24Z ERROR main] this is printed by default\n[2017-11-09T02:12:24Z INFO main] the answer was: 12\n```\n\n```console\n$ RUST_LOG=debug ./main\n[2017-11-09T02:12:24Z DEBUG main] this is a debug message\n[2017-11-09T02:12:24Z ERROR main] this is printed by default\n[2017-11-09T02:12:24Z INFO main] the answer was: 12\n```\n\nYou can also set the log level on a per module basis:\n\n```console\n$ RUST_LOG=main=info ./main\n[2017-11-09T02:12:24Z ERROR main] this is printed by default\n[2017-11-09T02:12:24Z INFO main] the answer was: 12\n```\n\nAnd enable all logging:\n\n```console\n$ RUST_LOG=main ./main\n[2017-11-09T02:12:24Z DEBUG main] this is a debug message\n[2017-11-09T02:12:24Z ERROR main] this is printed by default\n[2017-11-09T02:12:24Z INFO main] the answer was: 12\n```\n\nIf the binary name contains hyphens, you will need to replace\nthem with underscores:\n\n```console\n$ RUST_LOG=my_app ./my-app\n[2017-11-09T02:12:24Z DEBUG my_app] this is a debug message\n[2017-11-09T02:12:24Z ERROR my_app] this is printed by default\n[2017-11-09T02:12:24Z INFO my_app] the answer was: 12\n```\n\nThis is because Rust modules and crates cannot contain hyphens\nin their name, although `cargo` continues to accept them.\n\nSee the documentation for the [`log` crate][log-crate-url] for more\ninformation about its API.\n\n## Enabling logging\n\n**By default all logging is disabled except for the `error` level**\n\nThe **`RUST_LOG`** environment variable controls logging with the syntax:\n```console\nRUST_LOG=[target][=][level][,...]\n```\nOr in other words, its a comma-separated list of directives.\nDirectives can filter by **target**, by **level**, or both (using `=`).\n\nFor example,\n```console\nRUST_LOG=data=debug,hardware=debug\n```\n\n**target** is typically the path of the module the message\nin question originated from, though it can be overridden.\nThe path is rooted in the name of the crate it was compiled for, so if\nyour program is in a file called, for example, `hello.rs`, the path would\nsimply be `hello`.\n\nFurthermore, the log can be filtered using prefix-search based on the\nspecified log target.\n\nFor example, `RUST_LOG=example` would match the following targets:\n- `example`\n- `example::test`\n- `example::test::module::submodule`\n- `examples::and_more_examples`\n\nWhen providing the crate name or a module path, explicitly specifying the\nlog level is optional. If omitted, all logging for the item will be\nenabled.\n\n**level** is the maximum [`log::Level`][level-enum] to be shown and includes:\n- `error`\n- `warn`\n- `info`\n- `debug`\n- `trace`\n- `off` (pseudo level to disable all logging for the target)\n\nLogging level names are case-insensitive; e.g.,\n`debug`, `DEBUG`, and `dEbuG` all represent the same logging level. For\nconsistency, our convention is to use the lower case names. Where our docs\ndo use other forms, they do so in the context of specific examples, so you\nwon't be surprised if you see similar usage in the wild.\n\nSome examples of valid values of `RUST_LOG` are:\n\n- `RUST_LOG=hello` turns on all logging for the `hello` module\n- `RUST_LOG=trace` turns on all logging for the application, regardless of its name\n- `RUST_LOG=TRACE` turns on all logging for the application, regardless of its name (same as previous)\n- `RUST_LOG=info` turns on all info logging\n- `RUST_LOG=INFO` turns on all info logging (same as previous)\n- `RUST_LOG=hello=debug` turns on debug logging for `hello`\n- `RUST_LOG=hello=DEBUG` turns on debug logging for `hello` (same as previous)\n- `RUST_LOG=hello,std::option` turns on `hello`, and std's option logging\n- `RUST_LOG=error,hello=warn` turn on global error logging and also warn for `hello`\n- `RUST_LOG=error,hello=off` turn on global error logging, but turn off logging for `hello`\n- `RUST_LOG=off` turns off all logging for the application\n- `RUST_LOG=OFF` turns off all logging for the application (same as previous)\n\n## Filtering results\n\nA `RUST_LOG` directive may include a regex filter. The syntax is to append `/`\nfollowed by a regex. Each message is checked against the regex, and is only\nlogged if it matches. Note that the matching is done after formatting the\nlog string but before adding any logging meta-data. There is a single filter\nfor all modules.\n\nSome examples:\n\n* `hello/foo` turns on all logging for the 'hello' module where the log\n message includes 'foo'.\n* `info/f.o` turns on all info logging where the log message includes 'foo',\n 'f1o', 'fao', etc.\n* `hello=debug/foo*foo` turns on debug logging for 'hello' where the log\n message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.\n* `error,hello=warn/[0-9]scopes` turn on global error logging and also\n warn for hello. In both cases the log message must include a single digit\n number followed by 'scopes'.\n\n## Capturing logs in tests\n\nRecords logged during `cargo test` will not be captured by the test harness by default.\nThe [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured:\n\n```rust\n#[cfg(test)]\nmod tests {\n use log::info;\n\n fn init() {\n let _ = env_logger::builder().is_test(true).try_init();\n }\n\n #[test]\n fn it_works() {\n init();\n\n info!(\"This record will be captured by `cargo test`\");\n\n assert_eq!(2, 1 + 1);\n }\n}\n```\n\nEnabling test capturing comes at the expense of color and other style support\nand may have performance implications.\n\n## Disabling colors\n\nColors and other styles can be configured with the `RUST_LOG_STYLE`\nenvironment variable. It accepts the following values:\n\n* `auto` (default) will attempt to print style characters, but don't force the issue.\n If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors.\n* `always` will always print style characters even if they aren't supported by the terminal.\n This includes emitting ANSI colors on Windows if the console API is unavailable.\n* `never` will never print style characters.\n\n## Tweaking the default format\n\nParts of the default format can be excluded from the log output using the [`Builder`].\nThe following example excludes the timestamp from the log output:\n\n```rust\nenv_logger::builder()\n .format_timestamp(None)\n .init();\n```\n\n### Stability of the default format\n\nThe default format won't optimise for long-term stability, and explicitly makes no\nguarantees about the stability of its output across major, minor or patch version\nbumps during `0.x`.\n\nIf you want to capture or interpret the output of `env_logger` programmatically\nthen you should use a custom format.\n\n### Using a custom format\n\nCustom formats can be provided as closures to the [`Builder`].\nThese closures take a [`Formatter`][crate::fmt::Formatter] and `log::Record` as arguments:\n\n```rust\nuse std::io::Write;\n\nenv_logger::builder()\n .format(|buf, record| {\n writeln!(buf, \"{}: {}\", record.level(), record.args())\n })\n .init();\n```\n\nSee the [`fmt`] module for more details about custom formats.\n\n## Specifying defaults for environment variables\n\n`env_logger` can read configuration from environment variables.\nIf these variables aren't present, the default value to use can be tweaked with the [`Env`] type.\nThe following example defaults to log `warn` and above if the `RUST_LOG` environment variable\nisn't set:\n\n```rust\nuse env_logger::Env;\n\nenv_logger::Builder::from_env(Env::default().default_filter_or(\"warn\")).init();\n```\n\n[gh-repo-examples]: https://github.com/rust-cli/env_logger/tree/main/examples\n[level-enum]: https://docs.rs/log/latest/log/enum.Level.html\n[log-crate-url]: https://docs.rs/log", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "env_logger", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "env_logger", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "markdown", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "Public API of `markdown-rs`.\n\nThis module exposes primarily [`to_html()`][].\nIt also exposes [`to_html_with_options()`][] and [`to_mdast()`][].\n\n* [`to_html()`][]\n — safe way to transform (untrusted?) markdown into HTML\n* [`to_html_with_options()`][]\n — like `to_html` but lets you configure how markdown is turned into\n HTML, such as allowing dangerous HTML or turning on/off different\n constructs (GFM, MDX, and the like)\n* [`to_mdast()`][]\n — turn markdown into a syntax tree\n\n## Features\n\n* **`default`**\n — nothing is enabled by default\n* **`log`**\n — enable logging (includes `dep:log`);\n you can show logs with `RUST_LOG=debug`\n* **`serde`**\n — enable serde to serialize ASTs and configuration (includes `dep:serde`)", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "markdown", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "markdown", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "papaya", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "A fast and ergonomic concurrent hash-table for read-heavy workloads.\n\n# Features\n\n- An ergonomic lock-free API — no more deadlocks!\n- Powerful atomic operations.\n- Seamless usage in async contexts.\n- Extremely scalable, low-latency reads (see [performance](#performance)).\n- Predictable latency across all operations.\n- Efficient memory usage, with garbage collection powered by [`seize`].\n\n# Overview\n\nThe top-level crate documentation is organized as follows:\n\n- [Usage](#usage) shows how to interact with the concurrent `HashMap`.\n- [Consistency](#consistency) describes the guarantees of concurrent operations.\n- [Atomic Operations](#atomic-operations) shows how to perform dynamic operations atomically.\n- [Async Support](#async-support) shows how to use the map in an async context.\n- [Advanced Lifetimes](#advanced-lifetimes) explains how to use guards when working with nested types.\n- [Performance](#performance) provides details of expected performance characteristics.\n\n# Usage\n\n`papaya` aims to provide an ergonomic API without sacrificing performance. [`HashMap`] exposes a lock-free API, enabling it to hand out direct references to objects in the map without the need for wrapper types that are clunky and prone to deadlocks. However, you can't hold on to references forever due to concurrent removals. Because of this, the `HashMap` API is structured around *pinning*. Through a pin you can access the map just like a standard `HashMap`. A pin is similar to a lock guard, so any references that are returned will be tied to the lifetime of the guard. Unlike a lock however, pinning is cheap and can never cause deadlocks.\n\n```rust\nuse papaya::HashMap;\n\n// Create a map.\nlet map = HashMap::new();\n\n// Pin the map.\nlet map = map.pin();\n\n// Use the map as normal.\nmap.insert('A', 1);\nassert_eq!(map.get(&'A'), Some(&1));\nassert_eq!(map.len(), 1);\n```\n\nAs expected of a concurrent `HashMap`, all operations take a shared reference. This allows the map to be freely pinned and accessed from multiple threads:\n\n```rust\nuse papaya::HashMap;\n\n// Use a map from multiple threads.\nlet map = HashMap::new();\nstd::thread::scope(|s| {\n // Insert some values.\n s.spawn(|| {\n let map = map.pin();\n for i in 'A'..='Z' {\n map.insert(i, 1);\n }\n });\n\n // Remove the values.\n s.spawn(|| {\n let map = map.pin();\n for i in 'A'..='Z' {\n map.remove(&i);\n }\n });\n\n // Read the values.\n s.spawn(|| {\n for (key, value) in map.pin().iter() {\n println!(\"{key}: {value}\");\n }\n });\n});\n```\n\nIt is important to note that as long as you are holding on to a guard, you are preventing the map from performing garbage collection. Pinning and unpinning the table is relatively cheap but not free, similar to the cost of locking and unlocking an uncontended or lightly contended `Mutex`. Thus guard reuse is encouraged, within reason. See the [`seize`] crate for advanced usage and specifics of the garbage collection algorithm.\n\n# Consistency\n\nDue to the concurrent nature of the map, read and write operations may overlap in time. There is no support for locking the entire table nor individual keys to prevent concurrent access, except through external fine-grained locking. As such, read operations (such as `get`) reflect the results of the *most-recent* write. More formally, a read establishes a *happens-before* relationship with the corresponding write.\n\nAggregate operations, such as iterators, rely on a weak snapshot of the table and return results reflecting the state of the table at or some point after the creation of the iterator. This means that they may, but are not guaranteed to, reflect concurrent modifications to the table that occur during iteration. Similarly, operations such as `clear` and `clone` rely on iteration and may not produce \"perfect\" results if the map is being concurrently modified.\n\nNote that to obtain a stable snapshot of the table, aggregate table operations require completing any in-progress resizes. If you rely heavily on iteration or similar operations you should consider configuring [`ResizeMode::Blocking`].\n\n# Atomic Operations\n\nAs mentioned above, `papaya` does not support locking keys to prevent access, which makes performing complex operations more challenging. Instead, `papaya` exposes a number of atomic operations. The most basic of these is [`HashMap::update`], which can be used to update an existing value in the map using a closure:\n\n```rust\nlet map = papaya::HashMap::new();\nmap.pin().insert(\"poneyland\", 42);\nassert_eq!(map.pin().update(\"poneyland\", |e| e + 1), Some(&43));\n```\n\nNote that in the event that the entry is concurrently modified during an `update`, the closure may be called multiple times to retry the operation. For this reason, update operations are intended to be quick and *pure*, as they may be retried or internally memoized.\n\n`papaya` also exposes more powerful atomic operations that serve as a replacement for the [standard entry API](std::collections::hash_map::Entry). These include:\n\n- [`HashMap::update`]\n- [`HashMap::update_or_insert`]\n- [`HashMap::update_or_insert_with`]\n- [`HashMap::get_or_insert`]\n- [`HashMap::get_or_insert_with`]\n- [`HashMap::compute`]\n\nFor example, with a standard `HashMap`, `Entry::and_modify` is often paired with `Entry::or_insert`:\n\n```rust\nuse std::collections::HashMap;\n\nlet mut map = HashMap::new();\n// Insert `poneyland` with the value `42` if it doesn't exist,\n// otherwise increment it's value.\nmap.entry(\"poneyland\")\n .and_modify(|e| { *e += 1 })\n .or_insert(42);\n```\n\nHowever, implementing this with a concurrent `HashMap` is tricky as the entry may be modified in-between operations. Instead, you can write the above operation using [`HashMap::update_or_insert`]:\n\n```rust\nuse papaya::HashMap;\n\nlet map = HashMap::new();\n// Insert `poneyland` with the value `42` if it doesn't exist,\n// otherwise increment it's value.\nmap.pin().update_or_insert(\"poneyland\", |e| e + 1, 42);\n```\n\nAtomic operations are extremely powerful but also easy to misuse. They may be less efficient than update mechanisms tailored for the specific type of data in the map. For example, concurrent counters should avoid using `update` and instead use `AtomicUsize`. Entries that are frequently modified may also benefit from fine-grained locking.\n\n# Async Support\n\nBy default, a pinned map guard does not implement `Send` as it is tied to the current thread, similar to a lock guard. This leads to an issue in work-stealing schedulers as guards are not valid across `.await` points.\n\nTo overcome this, you can use an *owned* guard.\n\n```rust\nuse papaya::HashMap;\n\nasync fn run(map: Arc<HashMap<i32, String>>) {\n tokio::spawn(async move {\n // Pin the map with an owned guard.\n let map = map.pin_owned();\n\n // Hold references across await points.\n let value = map.get(&37);\n tokio::fs::write(\"db.txt\", format!(\"{value:?}\")).await;\n println!(\"{value:?}\");\n });\n}\n```\n\nNote that owned guards are more expensive to create than regular guards, so they should only be used if necessary. In the above example, you could instead drop the reference and call `get` a second time after the asynchronous call. A more fitting example involves asynchronous iteration:\n\n```rust\nuse papaya::HashMap;\n\nasync fn run(map: Arc<HashMap<i32, String>>) {\n tokio::spawn(async move {\n for (key, value) in map.pin_owned().iter() {\n tokio::fs::write(\"db.txt\", format!(\"{key}: {value}\\n\")).await;\n }\n });\n}\n```\n\n# Advanced Lifetimes\n\nYou may run into issues when you try to return a reference to a map contained within an outer type. For example:\n\n```rust\npub struct Metrics {\n map: papaya::HashMap<String, Vec<u64>>\n}\n\nimpl Metrics {\n pub fn get(&self, name: &str) -> Option<&[u64]> {\n // error[E0515]: cannot return value referencing temporary value\n Some(self.map.pin().get(name)?.as_slice())\n }\n}\n```\n\nThe solution is to accept a guard in the method directly, tying the lifetime to the caller's stack frame:\n\n```rust\nuse papaya::Guard;\n\npub struct Metrics {\n map: papaya::HashMap<String, Vec<u64>>\n}\n\nimpl Metrics {\n pub fn guard(&self) -> impl Guard + '_ {\n self.map.guard()\n }\n\n pub fn get<'guard>(&self, name: &str, guard: &'guard impl Guard) -> Option<&'guard [u64]> {\n Some(self.map.get(name, guard)?.as_slice())\n }\n}\n```\n\nThe `Guard` trait supports both local and owned guards. Note the `'guard` lifetime that ties the guard to the returned reference. No wrapper types or guard mapping is necessary.\n\n# Performance\n\n`papaya` is built with read-heavy workloads in mind. As such, read operations are extremely high throughput and provide consistent performance that scales with concurrency, meaning `papaya` will excel in workloads where reads are more common than writes. In write heavy workloads, `papaya` will still provide competitive performance despite not being it's primary use case. See the [benchmarks] for details.\n\n`papaya` aims to provide predictable and consistent latency across all operations. Most operations are lock-free, and those that aren't only block under rare and constrained conditions. `papaya` also features [incremental resizing](ResizeMode). Predictable latency is an important part of performance that doesn't often show up in benchmarks, but has significant implications for real-world usage.\n\n[benchmarks]: https://github.com/ibraheemdev/papaya/blob/master/BENCHMARKS.md", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "papaya", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "papaya", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "pin_project", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "\n<!-- Note: Document from sync-markdown-to-rustdoc:start through sync-markdown-to-rustdoc:end\n is synchronized from README.md. Any changes to that range are not preserved. -->\n<!-- tidy:sync-markdown-to-rustdoc:start -->\n\nA crate for safe and ergonomic [pin-projection].\n\n## Usage\n\nAdd this to your `Cargo.toml`:\n\n```toml\n[dependencies]\npin-project = \"1\"\n```\n\n## Examples\n\n[`#[pin_project]`][`pin_project`] attribute creates projection types\ncovering all the fields of struct or enum.\n\n```rust\nuse std::pin::Pin;\n\nuse pin_project::pin_project;\n\n#[pin_project]\nstruct Struct<T, U> {\n #[pin]\n pinned: T,\n unpinned: U,\n}\n\nimpl<T, U> Struct<T, U> {\n fn method(self: Pin<&mut Self>) {\n let this = self.project();\n let _: Pin<&mut T> = this.pinned; // Pinned reference to the field\n let _: &mut U = this.unpinned; // Normal reference to the field\n }\n}\n```\n\n[*code like this will be generated*][struct-default-expanded]\n\nTo use `#[pin_project]` on enums, you need to name the projection type\nreturned from the method.\n\n```rust\nuse std::pin::Pin;\n\nuse pin_project::pin_project;\n\n#[pin_project(project = EnumProj)]\nenum Enum<T, U> {\n Pinned(#[pin] T),\n Unpinned(U),\n}\n\nimpl<T, U> Enum<T, U> {\n fn method(self: Pin<&mut Self>) {\n match self.project() {\n EnumProj::Pinned(x) => {\n let _: Pin<&mut T> = x;\n }\n EnumProj::Unpinned(y) => {\n let _: &mut U = y;\n }\n }\n }\n}\n```\n\n[*code like this will be generated*][enum-default-expanded]\n\nSee [`#[pin_project]`][`pin_project`] attribute for more details, and\nsee [examples] directory for more examples and generated code.\n\n## Related Projects\n\n- [pin-project-lite]: A lightweight version of pin-project written with declarative macros.\n\n[enum-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/enum-default-expanded.rs\n[examples]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/README.md\n[pin-project-lite]: https://github.com/taiki-e/pin-project-lite\n[pin-projection]: https://doc.rust-lang.org/std/pin/index.html#projections-and-structural-pinning\n[struct-default-expanded]: https://github.com/taiki-e/pin-project/blob/HEAD/examples/struct-default-expanded.rs\n\n<!-- tidy:sync-markdown-to-rustdoc:end -->", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "pin_project", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "pin_project", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "run", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "crate that only bendn will ever use", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "run", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "run", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "softbuffer", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "softbuffer", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "softbuffer", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "test_log", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "A crate providing a replacement #[[macro@test]] attribute that\ninitializes logging and/or tracing infrastructure before running\ntests.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "test_log", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "test_log", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "tokio", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: "A runtime for writing reliable network applications without compromising speed.\n\nTokio is an event-driven, non-blocking I/O platform for writing asynchronous\napplications with the Rust programming language. At a high level, it\nprovides a few major components:\n\n* Tools for [working with asynchronous tasks][tasks], including\n [synchronization primitives and channels][sync] and [timeouts, sleeps, and\n intervals][time].\n* APIs for [performing asynchronous I/O][io], including [TCP and UDP][net] sockets,\n [filesystem][fs] operations, and [process] and [signal] management.\n* A [runtime] for executing asynchronous code, including a task scheduler,\n an I/O driver backed by the operating system's event queue (`epoll`, `kqueue`,\n `IOCP`, etc...), and a high performance timer.\n\nGuide level documentation is found on the [website].\n\n[tasks]: #working-with-tasks\n[sync]: crate::sync\n[time]: crate::time\n[io]: #asynchronous-io\n[net]: crate::net\n[fs]: crate::fs\n[process]: crate::process\n[signal]: crate::signal\n[fs]: crate::fs\n[runtime]: crate::runtime\n[website]: https://tokio.rs/tokio/tutorial\n\n# A Tour of Tokio\n\nTokio consists of a number of modules that provide a range of functionality\nessential for implementing asynchronous applications in Rust. In this\nsection, we will take a brief tour of Tokio, summarizing the major APIs and\ntheir uses.\n\nThe easiest way to get started is to enable all features. Do this by\nenabling the `full` feature flag:\n\n```toml\ntokio = { version = \"1\", features = [\"full\"] }\n```\n\n### Authoring applications\n\nTokio is great for writing applications and most users in this case shouldn't\nworry too much about what features they should pick. If you're unsure, we suggest\ngoing with `full` to ensure that you don't run into any road blocks while you're\nbuilding your application.\n\n#### Example\n\nThis example shows the quickest way to get started with Tokio.\n\n```toml\ntokio = { version = \"1\", features = [\"full\"] }\n```\n\n### Authoring libraries\n\nAs a library author your goal should be to provide the lightest weight crate\nthat is based on Tokio. To achieve this you should ensure that you only enable\nthe features you need. This allows users to pick up your crate without having\nto enable unnecessary features.\n\n#### Example\n\nThis example shows how you may want to import features for a library that just\nneeds to `tokio::spawn` and use a `TcpStream`.\n\n```toml\ntokio = { version = \"1\", features = [\"rt\", \"net\"] }\n```\n\n## Working With Tasks\n\nAsynchronous programs in Rust are based around lightweight, non-blocking\nunits of execution called [_tasks_][tasks]. The [`tokio::task`] module provides\nimportant tools for working with tasks:\n\n* The [`spawn`] function and [`JoinHandle`] type, for scheduling a new task\n on the Tokio runtime and awaiting the output of a spawned task, respectively,\n* Functions for [running blocking operations][blocking] in an asynchronous\n task context.\n\nThe [`tokio::task`] module is present only when the \"rt\" feature flag\nis enabled.\n\n[tasks]: task/index.html#what-are-tasks\n[`tokio::task`]: crate::task\n[`spawn`]: crate::task::spawn()\n[`JoinHandle`]: crate::task::JoinHandle\n[blocking]: task/index.html#blocking-and-yielding\n\nThe [`tokio::sync`] module contains synchronization primitives to use when\nneeding to communicate or share data. These include:\n\n* channels ([`oneshot`], [`mpsc`], [`watch`], and [`broadcast`]), for sending values\n between tasks,\n* a non-blocking [`Mutex`], for controlling access to a shared, mutable\n value,\n* an asynchronous [`Barrier`] type, for multiple tasks to synchronize before\n beginning a computation.\n\nThe `tokio::sync` module is present only when the \"sync\" feature flag is\nenabled.\n\n[`tokio::sync`]: crate::sync\n[`Mutex`]: crate::sync::Mutex\n[`Barrier`]: crate::sync::Barrier\n[`oneshot`]: crate::sync::oneshot\n[`mpsc`]: crate::sync::mpsc\n[`watch`]: crate::sync::watch\n[`broadcast`]: crate::sync::broadcast\n\nThe [`tokio::time`] module provides utilities for tracking time and\nscheduling work. This includes functions for setting [timeouts][timeout] for\ntasks, [sleeping][sleep] work to run in the future, or [repeating an operation at an\ninterval][interval].\n\nIn order to use `tokio::time`, the \"time\" feature flag must be enabled.\n\n[`tokio::time`]: crate::time\n[sleep]: crate::time::sleep()\n[interval]: crate::time::interval()\n[timeout]: crate::time::timeout()\n\nFinally, Tokio provides a _runtime_ for executing asynchronous tasks. Most\napplications can use the [`#[tokio::main]`][main] macro to run their code on the\nTokio runtime. However, this macro provides only basic configuration options. As\nan alternative, the [`tokio::runtime`] module provides more powerful APIs for configuring\nand managing runtimes. You should use that module if the `#[tokio::main]` macro doesn't\nprovide the functionality you need.\n\nUsing the runtime requires the \"rt\" or \"rt-multi-thread\" feature flags, to\nenable the current-thread [single-threaded scheduler][rt] and the [multi-thread\nscheduler][rt-multi-thread], respectively. See the [`runtime` module\ndocumentation][rt-features] for details. In addition, the \"macros\" feature\nflag enables the `#[tokio::main]` and `#[tokio::test]` attributes.\n\n[main]: attr.main.html\n[`tokio::runtime`]: crate::runtime\n[`Builder`]: crate::runtime::Builder\n[`Runtime`]: crate::runtime::Runtime\n[rt]: runtime/index.html#current-thread-scheduler\n[rt-multi-thread]: runtime/index.html#multi-thread-scheduler\n[rt-features]: runtime/index.html#runtime-scheduler\n\n## CPU-bound tasks and blocking code\n\nTokio is able to concurrently run many tasks on a few threads by repeatedly\nswapping the currently running task on each thread. However, this kind of\nswapping can only happen at `.await` points, so code that spends a long time\nwithout reaching an `.await` will prevent other tasks from running. To\ncombat this, Tokio provides two kinds of threads: Core threads and blocking threads.\n\nThe core threads are where all asynchronous code runs, and Tokio will by default\nspawn one for each CPU core. You can use the environment variable `TOKIO_WORKER_THREADS`\nto override the default value.\n\nThe blocking threads are spawned on demand, can be used to run blocking code\nthat would otherwise block other tasks from running and are kept alive when\nnot used for a certain amount of time which can be configured with [`thread_keep_alive`].\nSince it is not possible for Tokio to swap out blocking tasks, like it\ncan do with asynchronous code, the upper limit on the number of blocking\nthreads is very large. These limits can be configured on the [`Builder`].\n\nTo spawn a blocking task, you should use the [`spawn_blocking`] function.\n\n[`Builder`]: crate::runtime::Builder\n[`spawn_blocking`]: crate::task::spawn_blocking()\n[`thread_keep_alive`]: crate::runtime::Builder::thread_keep_alive()\n\n```rust\n#[tokio::main]\nasync fn main() {\n // This is running on a core thread.\n\n let blocking_task = tokio::task::spawn_blocking(|| {\n // This is running on a blocking thread.\n // Blocking here is ok.\n });\n\n // We can wait for the blocking task like this:\n // If the blocking task panics, the unwrap below will propagate the\n // panic.\n blocking_task.await.unwrap();\n}\n```\n\nIf your code is CPU-bound and you wish to limit the number of threads used\nto run it, you should use a separate thread pool dedicated to CPU bound tasks.\nFor example, you could consider using the [rayon] library for CPU-bound\ntasks. It is also possible to create an extra Tokio runtime dedicated to\nCPU-bound tasks, but if you do this, you should be careful that the extra\nruntime runs _only_ CPU-bound tasks, as IO-bound tasks on that runtime\nwill behave poorly.\n\nHint: If using rayon, you can use a [`oneshot`] channel to send the result back\nto Tokio when the rayon task finishes.\n\n[rayon]: https://docs.rs/rayon\n[`oneshot`]: crate::sync::oneshot\n\n## Asynchronous IO\n\nAs well as scheduling and running tasks, Tokio provides everything you need\nto perform input and output asynchronously.\n\nThe [`tokio::io`] module provides Tokio's asynchronous core I/O primitives,\nthe [`AsyncRead`], [`AsyncWrite`], and [`AsyncBufRead`] traits. In addition,\nwhen the \"io-util\" feature flag is enabled, it also provides combinators and\nfunctions for working with these traits, forming as an asynchronous\ncounterpart to [`std::io`].\n\nTokio also includes APIs for performing various kinds of I/O and interacting\nwith the operating system asynchronously. These include:\n\n* [`tokio::net`], which contains non-blocking versions of [TCP], [UDP], and\n [Unix Domain Sockets][UDS] (enabled by the \"net\" feature flag),\n* [`tokio::fs`], similar to [`std::fs`] but for performing filesystem I/O\n asynchronously (enabled by the \"fs\" feature flag),\n* [`tokio::signal`], for asynchronously handling Unix and Windows OS signals\n (enabled by the \"signal\" feature flag),\n* [`tokio::process`], for spawning and managing child processes (enabled by\n the \"process\" feature flag).\n\n[`tokio::io`]: crate::io\n[`AsyncRead`]: crate::io::AsyncRead\n[`AsyncWrite`]: crate::io::AsyncWrite\n[`AsyncBufRead`]: crate::io::AsyncBufRead\n[`std::io`]: std::io\n[`tokio::net`]: crate::net\n[TCP]: crate::net::tcp\n[UDP]: crate::net::UdpSocket\n[UDS]: crate::net::unix\n[`tokio::fs`]: crate::fs\n[`std::fs`]: std::fs\n[`tokio::signal`]: crate::signal\n[`tokio::process`]: crate::process\n\n# Examples\n\nA simple TCP echo server:\n\n```rust\nuse tokio::net::TcpListener;\nuse tokio::io::{AsyncReadExt, AsyncWriteExt};\n\n#[tokio::main]\nasync fn main() -> Result<(), Box<dyn std::error::Error>> {\n let listener = TcpListener::bind(\"127.0.0.1:8080\").await?;\n\n loop {\n let (mut socket, _) = listener.accept().await?;\n\n tokio::spawn(async move {\n let mut buf = [0; 1024];\n\n // In a loop, read data from the socket and write the data back.\n loop {\n let n = match socket.read(&mut buf).await {\n // socket closed\n Ok(0) => return,\n Ok(n) => n,\n Err(e) => {\n eprintln!(\"failed to read from socket; err = {:?}\", e);\n return;\n }\n };\n\n // Write the data back\n if let Err(e) = socket.write_all(&buf[0..n]).await {\n eprintln!(\"failed to write to socket; err = {:?}\", e);\n return;\n }\n }\n });\n }\n}\n```\n\n# Feature flags\n\nTokio uses a set of [feature flags] to reduce the amount of compiled code. It\nis possible to just enable certain features over others. By default, Tokio\ndoes not enable any features but allows one to enable a subset for their use\ncase. Below is a list of the available feature flags. You may also notice\nabove each function, struct and trait there is listed one or more feature flags\nthat are required for that item to be used. If you are new to Tokio it is\nrecommended that you use the `full` feature flag which will enable all public APIs.\nBeware though that this will pull in many extra dependencies that you may not\nneed.\n\n- `full`: Enables all features listed below except `test-util` and `tracing`.\n- `rt`: Enables `tokio::spawn`, the current-thread scheduler,\n and non-scheduler utilities.\n- `rt-multi-thread`: Enables the heavier, multi-threaded, work-stealing scheduler.\n- `io-util`: Enables the IO based `Ext` traits.\n- `io-std`: Enable `Stdout`, `Stdin` and `Stderr` types.\n- `net`: Enables `tokio::net` types such as `TcpStream`, `UnixStream` and\n `UdpSocket`, as well as (on Unix-like systems) `AsyncFd` and (on\n FreeBSD) `PollAio`.\n- `time`: Enables `tokio::time` types and allows the schedulers to enable\n the built in timer.\n- `process`: Enables `tokio::process` types.\n- `macros`: Enables `#[tokio::main]` and `#[tokio::test]` macros.\n- `sync`: Enables all `tokio::sync` types.\n- `signal`: Enables all `tokio::signal` types.\n- `fs`: Enables `tokio::fs` types.\n- `test-util`: Enables testing based infrastructure for the Tokio runtime.\n- `parking_lot`: As a potential optimization, use the `_parking_lot_` crate's\n synchronization primitives internally. Also, this\n dependency is necessary to construct some of our primitives\n in a `const` context. `MSRV` may increase according to the\n `_parking_lot_` release in use.\n\n_Note: `AsyncRead` and `AsyncWrite` traits do not require any features and are\nalways available._\n\n## Unstable features\n\nSome feature flags are only available when specifying the `tokio_unstable` flag:\n\n- `tracing`: Enables tracing events.\n\nLikewise, some parts of the API are only available with the same flag:\n\n- [`task::Builder`]\n- Some methods on [`task::JoinSet`]\n- [`runtime::RuntimeMetrics`]\n- [`runtime::Builder::on_task_spawn`]\n- [`runtime::Builder::on_task_terminate`]\n- [`runtime::Builder::unhandled_panic`]\n- [`runtime::TaskMeta`]\n\nThis flag enables **unstable** features. The public API of these features\nmay break in 1.x releases. To enable these features, the `--cfg\ntokio_unstable` argument must be passed to `rustc` when compiling. This\nserves to explicitly opt-in to features which may break semver conventions,\nsince Cargo [does not yet directly support such opt-ins][unstable features].\n\nYou can specify it in your project's `.cargo/config.toml` file:\n\n```toml\n[build]\nrustflags = [\"--cfg\", \"tokio_unstable\"]\n```\n\n<div class=\"warning\">\nThe <code>[build]</code> section does <strong>not</strong> go in a\n<code>Cargo.toml</code> file. Instead it must be placed in the Cargo config\nfile <code>.cargo/config.toml</code>.\n</div>\n\nAlternatively, you can specify it with an environment variable:\n\n```sh\n## Many *nix shells:\nexport RUSTFLAGS=\"--cfg tokio_unstable\"\ncargo build\n```\n\n```powershell\n## Windows PowerShell:\n$Env:RUSTFLAGS=\"--cfg tokio_unstable\"\ncargo build\n```\n\n[unstable features]: https://internals.rust-lang.org/t/feature-request-unstable-opt-in-non-transitive-crate-features/16193#why-not-a-crate-feature-2\n[feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section\n\n# Supported platforms\n\nTokio currently guarantees support for the following platforms:\n\n * Linux\n * Windows\n * Android (API level 21)\n * macOS\n * iOS\n * FreeBSD\n\nTokio will continue to support these platforms in the future. However,\nfuture releases may change requirements such as the minimum required libc\nversion on Linux, the API level on Android, or the supported FreeBSD\nrelease.\n\nBeyond the above platforms, Tokio is intended to work on all platforms\nsupported by the mio crate. You can find a longer list [in mio's\ndocumentation][mio-supported]. However, these additional platforms may\nbecome unsupported in the future.\n\nNote that Wine is considered to be a different platform from Windows. See\nmio's documentation for more information on Wine support.\n\n[mio-supported]: https://crates.io/crates/mio#platforms\n\n## `WASM` support\n\nTokio has some limited support for the `WASM` platform. Without the\n`tokio_unstable` flag, the following features are supported:\n\n * `sync`\n * `macros`\n * `io-util`\n * `rt`\n * `time`\n\nEnabling any other feature (including `full`) will cause a compilation\nfailure.\n\nThe `time` module will only work on `WASM` platforms that have support for\ntimers (e.g. wasm32-wasi). The timing functions will panic if used on a `WASM`\nplatform that does not support timers.\n\nNote also that if the runtime becomes indefinitely idle, it will panic\nimmediately instead of blocking forever. On platforms that don't support\ntime, this means that the runtime can never be idle in any way.\n\n## Unstable `WASM` support\n\nTokio also has unstable support for some additional `WASM` features. This\nrequires the use of the `tokio_unstable` flag.\n\nUsing this flag enables the use of `tokio::net` on the wasm32-wasi target.\nHowever, not all methods are available on the networking types as `WASI`\ncurrently does not support the creation of new sockets from within `WASM`.\nBecause of this, sockets must currently be created via the `FromRawFd`\ntrait.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "tokio", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "tokio", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "tree_sitter", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "tree_sitter", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "tree_sitter", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "winit", - label_details: None, - kind: Some( - Module, - ), - detail: None, - documentation: Some( - MarkupContent( - MarkupContent { - kind: Markdown, - value: " Winit is a cross-platform window creation and event loop management library.\n\n # Building windows\n\n Before you can create a [`Window`], you first need to build an [`EventLoop`]. This is done with\n the [`EventLoop::new()`] function.\n\n ```no_run\n use winit::event_loop::EventLoop;\n\n # // Intentionally use `fn main` for clarity\n fn main() {\n let event_loop = EventLoop::new().unwrap();\n // ...\n }\n ```\n\n Then you create a [`Window`] with [`create_window`].\n\n # Event handling\n\n Once a [`Window`] has been created, it will generate different *events*. A [`Window`] object can\n generate [`WindowEvent`]s when certain input events occur, such as a cursor moving over the\n window or a key getting pressed while the window is focused. Devices can generate\n [`DeviceEvent`]s, which contain unfiltered event data that isn't specific to a certain window.\n Some user activity, like mouse movement, can generate both a [`WindowEvent`] *and* a\n [`DeviceEvent`]. You can also create and handle your own custom [`Event::UserEvent`]s, if\n desired.\n\n You can retrieve events by calling [`EventLoop::run_app()`]. This function will\n dispatch events for every [`Window`] that was created with that particular [`EventLoop`], and\n will run until [`exit()`] is used, at which point [`Event::LoopExiting`].\n\n Winit no longer uses a `EventLoop::poll_events() -> impl Iterator<Event>`-based event loop\n model, since that can't be implemented properly on some platforms (e.g web, iOS) and works\n poorly on most other platforms. However, this model can be re-implemented to an extent with\n[`EventLoopExtPumpEvents::pump_app_events()`][platform::pump_events::EventLoopExtPumpEvents::pump_app_events()]\n [^1]. See that method's documentation for more reasons about why\n it's discouraged beyond compatibility reasons.\n\n\n ```no_run\n use winit::application::ApplicationHandler;\n use winit::event::WindowEvent;\n use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};\n use winit::window::{Window, WindowId};\n\n #[derive(Default)]\n struct App {\n window: Option<Window>,\n }\n\n impl ApplicationHandler for App {\n fn resumed(&mut self, event_loop: &ActiveEventLoop) {\n self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap());\n }\n\n fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {\n match event {\n WindowEvent::CloseRequested => {\n println!(\"The close button was pressed; stopping\");\n event_loop.exit();\n },\n WindowEvent::RedrawRequested => {\n // Redraw the application.\n //\n // It's preferable for applications that do not render continuously to render in\n // this event rather than in AboutToWait, since rendering in here allows\n // the program to gracefully handle redraws requested by the OS.\n\n // Draw.\n\n // Queue a RedrawRequested event.\n //\n // You only need to call this if you've determined that you need to redraw in\n // applications which do not always need to. Applications that redraw continuously\n // can render here instead.\n self.window.as_ref().unwrap().request_redraw();\n }\n _ => (),\n }\n }\n }\n\n # // Intentionally use `fn main` for clarity\n fn main() {\n let event_loop = EventLoop::new().unwrap();\n\n // ControlFlow::Poll continuously runs the event loop, even if the OS hasn't\n // dispatched any events. This is ideal for games and similar applications.\n event_loop.set_control_flow(ControlFlow::Poll);\n\n // ControlFlow::Wait pauses the event loop if no events are available to process.\n // This is ideal for non-game applications that only update in response to user\n // input, and uses significantly less power/CPU time than ControlFlow::Poll.\n event_loop.set_control_flow(ControlFlow::Wait);\n\n let mut app = App::default();\n event_loop.run_app(&mut app);\n }\n ```\n\n [`WindowEvent`] has a [`WindowId`] member. In multi-window environments, it should be\n compared to the value returned by [`Window::id()`] to determine which [`Window`]\n dispatched the event.\n\n # Drawing on the window\n\n Winit doesn't directly provide any methods for drawing on a [`Window`]. However, it allows you\n to retrieve the raw handle of the window and display (see the [`platform`] module and/or the\n [`raw_window_handle`] and [`raw_display_handle`] methods), which in turn allows\n you to create an OpenGL/Vulkan/DirectX/Metal/etc. context that can be used to render graphics.\n\n Note that many platforms will display garbage data in the window's client area if the\n application doesn't render anything to the window by the time the desktop compositor is ready to\n display the window to the user. If you notice this happening, you should create the window with\n [`visible` set to `false`][crate::window::WindowAttributes::with_visible] and explicitly make\n the window visible only once you're ready to render into it.\n\n # UI scaling\n\n UI scaling is important, go read the docs for the [`dpi`] crate for an\n introduction.\n\n All of Winit's functions return physical types, but can take either logical or physical\n coordinates as input, allowing you to use the most convenient coordinate system for your\n particular application.\n\n Winit will dispatch a [`ScaleFactorChanged`] event whenever a window's scale factor has changed.\n This can happen if the user drags their window from a standard-resolution monitor to a high-DPI\n monitor or if the user changes their DPI settings. This allows you to rescale your application's\n UI elements and adjust how the platform changes the window's size to reflect the new scale\n factor. If a window hasn't received a [`ScaleFactorChanged`] event, its scale factor\n can be found by calling [`window.scale_factor()`].\n\n [`ScaleFactorChanged`]: event::WindowEvent::ScaleFactorChanged\n [`window.scale_factor()`]: window::Window::scale_factor\n\n # Cargo Features\n\n Winit provides the following Cargo features:\n\n * `x11` (enabled by default): On Unix platforms, enables the X11 backend.\n * `wayland` (enabled by default): On Unix platforms, enables the Wayland backend.\n * `rwh_04`: Implement `raw-window-handle v0.4` traits.\n * `rwh_05`: Implement `raw-window-handle v0.5` traits.\n * `rwh_06`: Implement `raw-window-handle v0.6` traits.\n * `serde`: Enables serialization/deserialization of certain types with [Serde](https://crates.io/crates/serde).\n * `mint`: Enables mint (math interoperability standard types) conversions.\n\n See the [`platform`] module for documentation on platform-specific cargo\n features.\n\n [`EventLoop`]: event_loop::EventLoop\n [`EventLoop::new()`]: event_loop::EventLoop::new\n [`EventLoop::run_app()`]: event_loop::EventLoop::run_app\n [`exit()`]: event_loop::ActiveEventLoop::exit\n [`Window`]: window::Window\n [`WindowId`]: window::WindowId\n [`WindowAttributes`]: window::WindowAttributes\n [`create_window`]: event_loop::ActiveEventLoop::create_window\n [`Window::id()`]: window::Window::id\n [`WindowEvent`]: event::WindowEvent\n [`DeviceEvent`]: event::DeviceEvent\n [`Event::UserEvent`]: event::Event::UserEvent\n [`Event::LoopExiting`]: event::Event::LoopExiting\n [`raw_window_handle`]: ./window/struct.Window.html#method.raw_window_handle\n [`raw_display_handle`]: ./window/struct.Window.html#method.raw_display_handle\n [^1]: `EventLoopExtPumpEvents::pump_app_events()` is only available on Windows, macOS, Android, X11 and Wayland.", - }, - ), - ), - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "winit", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "winit", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "self::", - label_details: None, - kind: Some( - Keyword, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "self::", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "self::", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "crate::", - label_details: None, - kind: Some( - Keyword, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "crate::", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "crate::", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - CompletionItem { - label: "super::", - label_details: None, - kind: Some( - Keyword, - ), - detail: None, - documentation: None, - deprecated: None, - preselect: Some( - true, - ), - sort_text: Some( - "7fffffff", - ), - filter_text: Some( - "super::", - ), - insert_text: None, - insert_text_format: None, - insert_text_mode: None, - text_edit: Some( - Edit( - TextEdit { - range: Range { - start: Position { - line: 13, - character: 4, - }, - end: Position { - line: 13, - character: 8, - }, - }, - new_text: "super::", - }, - ), - ), - additional_text_edits: None, - command: None, - commit_characters: None, - data: None, - tags: None, - }, - ], - }, - ), -)
\ No newline at end of file +{ + "isIncomplete": true, + "items": [ + { + "label": "new", + "kind": 3, + "detail": "pub const fn new() -> String", + "documentation": { + "kind": "markdown", + "value": "Creates a new empty `String`.\n\nGiven that the `String` is empty, this will not allocate any initial\nbuffer. While that means that this initial operation is very\ninexpensive, it may cause excessive allocation later when you add\ndata. If you have an idea of how much data the `String` will hold,\nconsider the [`with_capacity`] method to prevent excessive\nre-allocation.\n\n[`with_capacity`]: String::with_capacity\n\n# Examples\n\n```rust\nlet s = String::new();\n```" + }, + "preselect": true, + "sortText": "7ffffff0", + "filterText": "new", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "new" + } + }, + { + "label": "with_capacity", + "kind": 3, + "detail": "pub fn with_capacity(capacity: usize) -> String", + "documentation": { + "kind": "markdown", + "value": "Creates a new empty `String` with at least the specified capacity.\n\n`String`s have an internal buffer to hold their data. The capacity is\nthe length of that buffer, and can be queried with the [`capacity`]\nmethod. This method creates an empty `String`, but one with an initial\nbuffer that can hold at least `capacity` bytes. This is useful when you\nmay be appending a bunch of data to the `String`, reducing the number of\nreallocations it needs to do.\n\n[`capacity`]: String::capacity\n\nIf the given capacity is `0`, no allocation will occur, and this method\nis identical to the [`new`] method.\n\n[`new`]: String::new\n\n# Examples\n\n```rust\nlet mut s = String::with_capacity(10);\n\n// The String contains no chars, even though it has capacity for more\nassert_eq!(s.len(), 0);\n\n// These are all done without reallocating...\nlet cap = s.capacity();\nfor _ in 0..10 {\n s.push('a');\n}\n\nassert_eq!(s.capacity(), cap);\n\n// ...but this may make the string reallocate\ns.push('a');\n```" + }, + "sortText": "7ffffff1", + "filterText": "with_capacity", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "with_capacity" + } + }, + { + "label": "try_with_capacity", + "kind": 3, + "detail": "pub fn try_with_capacity(capacity: usize) -> Result<String, TryReserveError>", + "documentation": { + "kind": "markdown", + "value": "Creates a new empty `String` with at least the specified capacity.\n\n# Errors\n\nReturns [`Err`] if the capacity exceeds `isize::MAX` bytes,\nor if the memory allocator reports failure." + }, + "sortText": "7ffffffb", + "filterText": "try_with_capacity", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "try_with_capacity" + } + }, + { + "label": "from_utf8", + "kind": 3, + "detail": "pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>", + "documentation": { + "kind": "markdown", + "value": "Converts a vector of bytes to a `String`.\n\nA string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes\n([`Vec<u8>`]) is made of bytes, so this function converts between the\ntwo. Not all byte slices are valid `String`s, however: `String`\nrequires that it is valid UTF-8. `from_utf8()` checks to ensure that\nthe bytes are valid UTF-8, and then does the conversion.\n\nIf you are sure that the byte slice is valid UTF-8, and you don't want\nto incur the overhead of the validity check, there is an unsafe version\nof this function, [`from_utf8_unchecked`], which has the same behavior\nbut skips the check.\n\nThis method will take care to not copy the vector, for efficiency's\nsake.\n\nIf you need a [`&str`] instead of a `String`, consider\n[`str::from_utf8`].\n\nThe inverse of this method is [`into_bytes`].\n\n# Errors\n\nReturns [`Err`] if the slice is not UTF-8 with a description as to why the\nprovided bytes are not UTF-8. The vector you moved in is also included.\n\n# Examples\n\nBasic usage:\n\n```rust\n// some bytes, in a vector\nlet sparkle_heart = vec![240, 159, 146, 150];\n\n// We know these bytes are valid, so we'll use `unwrap()`.\nlet sparkle_heart = String::from_utf8(sparkle_heart).unwrap();\n\nassert_eq!(\"💖\", sparkle_heart);\n```\n\nIncorrect bytes:\n\n```rust\n// some invalid bytes, in a vector\nlet sparkle_heart = vec![0, 159, 146, 150];\n\nassert!(String::from_utf8(sparkle_heart).is_err());\n```\n\nSee the docs for [`FromUtf8Error`] for more details on what you can do\nwith this error.\n\n[`from_utf8_unchecked`]: String::from_utf8_unchecked\n[`Vec<u8>`]: crate::vec::Vec \"Vec\"\n[`&str`]: prim@str \"&str\"\n[`into_bytes`]: String::into_bytes" + }, + "sortText": "7ffffffb", + "filterText": "from_utf8", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf8" + } + }, + { + "label": "from_utf8_lossy", + "kind": 3, + "detail": "pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str>", + "documentation": { + "kind": "markdown", + "value": "Converts a slice of bytes to a string, including invalid characters.\n\nStrings are made of bytes ([`u8`]), and a slice of bytes\n([`&[u8]`][byteslice]) is made of bytes, so this function converts\nbetween the two. Not all byte slices are valid strings, however: strings\nare required to be valid UTF-8. During this conversion,\n`from_utf8_lossy()` will replace any invalid UTF-8 sequences with\n[`U+FFFD REPLACEMENT CHARACTER`][U+FFFD], which looks like this: �\n\n[byteslice]: prim@slice\n[U+FFFD]: core::char::REPLACEMENT_CHARACTER\n\nIf you are sure that the byte slice is valid UTF-8, and you don't want\nto incur the overhead of the conversion, there is an unsafe version\nof this function, [`from_utf8_unchecked`], which has the same behavior\nbut skips the checks.\n\n[`from_utf8_unchecked`]: String::from_utf8_unchecked\n\nThis function returns a [`Cow<'a, str>`]. If our byte slice is invalid\nUTF-8, then we need to insert the replacement characters, which will\nchange the size of the string, and hence, require a `String`. But if\nit's already valid UTF-8, we don't need a new allocation. This return\ntype allows us to handle both cases.\n\n[`Cow<'a, str>`]: crate::borrow::Cow \"borrow::Cow\"\n\n# Examples\n\nBasic usage:\n\n```rust\n// some bytes, in a vector\nlet sparkle_heart = vec![240, 159, 146, 150];\n\nlet sparkle_heart = String::from_utf8_lossy(&sparkle_heart);\n\nassert_eq!(\"💖\", sparkle_heart);\n```\n\nIncorrect bytes:\n\n```rust\n// some invalid bytes\nlet input = b\"Hello \\xF0\\x90\\x80World\";\nlet output = String::from_utf8_lossy(input);\n\nassert_eq!(\"Hello �World\", output);\n```" + }, + "sortText": "7fffffff", + "filterText": "from_utf8_lossy", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf8_lossy" + } + }, + { + "label": "from_utf8_lossy_owned", + "kind": 3, + "detail": "pub fn from_utf8_lossy_owned(v: Vec<u8>) -> String", + "documentation": { + "kind": "markdown", + "value": "Converts a [`Vec<u8>`] to a `String`, substituting invalid UTF-8\nsequences with replacement characters.\n\nSee [`from_utf8_lossy`] for more details.\n\n[`from_utf8_lossy`]: String::from_utf8_lossy\n\nNote that this function does not guarantee reuse of the original `Vec`\nallocation.\n\n# Examples\n\nBasic usage:\n\n```rust\n#![feature(string_from_utf8_lossy_owned)]\n// some bytes, in a vector\nlet sparkle_heart = vec![240, 159, 146, 150];\n\nlet sparkle_heart = String::from_utf8_lossy_owned(sparkle_heart);\n\nassert_eq!(String::from(\"💖\"), sparkle_heart);\n```\n\nIncorrect bytes:\n\n```rust\n#![feature(string_from_utf8_lossy_owned)]\n// some invalid bytes\nlet input: Vec<u8> = b\"Hello \\xF0\\x90\\x80World\".into();\nlet output = String::from_utf8_lossy_owned(input);\n\nassert_eq!(String::from(\"Hello �World\"), output);\n```" + }, + "sortText": "7ffffff1", + "filterText": "from_utf8_lossy_owned", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf8_lossy_owned" + } + }, + { + "label": "from_utf16", + "kind": 3, + "detail": "pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error>", + "documentation": { + "kind": "markdown", + "value": "Decode a native endian UTF-16–encoded vector `v` into a `String`,\nreturning [`Err`] if `v` contains any invalid data.\n\n# Examples\n\n```rust\n// 𝄞music\nlet v = &[0xD834, 0xDD1E, 0x006d, 0x0075,\n 0x0073, 0x0069, 0x0063];\nassert_eq!(String::from(\"𝄞music\"),\n String::from_utf16(v).unwrap());\n\n// 𝄞mu<invalid>ic\nlet v = &[0xD834, 0xDD1E, 0x006d, 0x0075,\n 0xD800, 0x0069, 0x0063];\nassert!(String::from_utf16(v).is_err());\n```" + }, + "sortText": "7ffffffb", + "filterText": "from_utf16", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf16" + } + }, + { + "label": "from_utf16_lossy", + "kind": 3, + "detail": "pub fn from_utf16_lossy(v: &[u16]) -> String", + "documentation": { + "kind": "markdown", + "value": "Decode a native endian UTF-16–encoded slice `v` into a `String`,\nreplacing invalid data with [the replacement character (`U+FFFD`)][U+FFFD].\n\nUnlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],\n`from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8\nconversion requires a memory allocation.\n\n[`from_utf8_lossy`]: String::from_utf8_lossy\n[`Cow<'a, str>`]: crate::borrow::Cow \"borrow::Cow\"\n[U+FFFD]: core::char::REPLACEMENT_CHARACTER\n\n# Examples\n\n```rust\n// 𝄞mus<invalid>ic<invalid>\nlet v = &[0xD834, 0xDD1E, 0x006d, 0x0075,\n 0x0073, 0xDD1E, 0x0069, 0x0063,\n 0xD834];\n\nassert_eq!(String::from(\"𝄞mus\\u{FFFD}ic\\u{FFFD}\"),\n String::from_utf16_lossy(v));\n```" + }, + "sortText": "7ffffff1", + "filterText": "from_utf16_lossy", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf16_lossy" + } + }, + { + "label": "from_utf16le", + "kind": 3, + "detail": "pub fn from_utf16le(v: &[u8]) -> Result<String, FromUtf16Error>", + "documentation": { + "kind": "markdown", + "value": "Decode a UTF-16LE–encoded vector `v` into a `String`,\nreturning [`Err`] if `v` contains any invalid data.\n\n# Examples\n\nBasic usage:\n\n```rust\n#![feature(str_from_utf16_endian)]\n// 𝄞music\nlet v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,\n 0x73, 0x00, 0x69, 0x00, 0x63, 0x00];\nassert_eq!(String::from(\"𝄞music\"),\n String::from_utf16le(v).unwrap());\n\n// 𝄞mu<invalid>ic\nlet v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,\n 0x00, 0xD8, 0x69, 0x00, 0x63, 0x00];\nassert!(String::from_utf16le(v).is_err());\n```" + }, + "sortText": "7ffffffb", + "filterText": "from_utf16le", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf16le" + } + }, + { + "label": "from_utf16le_lossy", + "kind": 3, + "detail": "pub fn from_utf16le_lossy(v: &[u8]) -> String", + "documentation": { + "kind": "markdown", + "value": "Decode a UTF-16LE–encoded slice `v` into a `String`, replacing\ninvalid data with [the replacement character (`U+FFFD`)][U+FFFD].\n\nUnlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],\n`from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8\nconversion requires a memory allocation.\n\n[`from_utf8_lossy`]: String::from_utf8_lossy\n[`Cow<'a, str>`]: crate::borrow::Cow \"borrow::Cow\"\n[U+FFFD]: core::char::REPLACEMENT_CHARACTER\n\n# Examples\n\nBasic usage:\n\n```rust\n#![feature(str_from_utf16_endian)]\n// 𝄞mus<invalid>ic<invalid>\nlet v = &[0x34, 0xD8, 0x1E, 0xDD, 0x6d, 0x00, 0x75, 0x00,\n 0x73, 0x00, 0x1E, 0xDD, 0x69, 0x00, 0x63, 0x00,\n 0x34, 0xD8];\n\nassert_eq!(String::from(\"𝄞mus\\u{FFFD}ic\\u{FFFD}\"),\n String::from_utf16le_lossy(v));\n```" + }, + "sortText": "7ffffff1", + "filterText": "from_utf16le_lossy", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf16le_lossy" + } + }, + { + "label": "from_utf16be", + "kind": 3, + "detail": "pub fn from_utf16be(v: &[u8]) -> Result<String, FromUtf16Error>", + "documentation": { + "kind": "markdown", + "value": "Decode a UTF-16BE–encoded vector `v` into a `String`,\nreturning [`Err`] if `v` contains any invalid data.\n\n# Examples\n\nBasic usage:\n\n```rust\n#![feature(str_from_utf16_endian)]\n// 𝄞music\nlet v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,\n 0x00, 0x73, 0x00, 0x69, 0x00, 0x63];\nassert_eq!(String::from(\"𝄞music\"),\n String::from_utf16be(v).unwrap());\n\n// 𝄞mu<invalid>ic\nlet v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,\n 0xD8, 0x00, 0x00, 0x69, 0x00, 0x63];\nassert!(String::from_utf16be(v).is_err());\n```" + }, + "sortText": "7ffffffb", + "filterText": "from_utf16be", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf16be" + } + }, + { + "label": "from_utf16be_lossy", + "kind": 3, + "detail": "pub fn from_utf16be_lossy(v: &[u8]) -> String", + "documentation": { + "kind": "markdown", + "value": "Decode a UTF-16BE–encoded slice `v` into a `String`, replacing\ninvalid data with [the replacement character (`U+FFFD`)][U+FFFD].\n\nUnlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],\n`from_utf16le_lossy` returns a `String` since the UTF-16 to UTF-8\nconversion requires a memory allocation.\n\n[`from_utf8_lossy`]: String::from_utf8_lossy\n[`Cow<'a, str>`]: crate::borrow::Cow \"borrow::Cow\"\n[U+FFFD]: core::char::REPLACEMENT_CHARACTER\n\n# Examples\n\nBasic usage:\n\n```rust\n#![feature(str_from_utf16_endian)]\n// 𝄞mus<invalid>ic<invalid>\nlet v = &[0xD8, 0x34, 0xDD, 0x1E, 0x00, 0x6d, 0x00, 0x75,\n 0x00, 0x73, 0xDD, 0x1E, 0x00, 0x69, 0x00, 0x63,\n 0xD8, 0x34];\n\nassert_eq!(String::from(\"𝄞mus\\u{FFFD}ic\\u{FFFD}\"),\n String::from_utf16be_lossy(v));\n```" + }, + "sortText": "7ffffff1", + "filterText": "from_utf16be_lossy", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf16be_lossy" + } + }, + { + "label": "into_raw_parts", + "kind": 2, + "detail": "pub fn into_raw_parts(self) -> (*mut u8, usize, usize)", + "documentation": { + "kind": "markdown", + "value": "Decomposes a `String` into its raw components: `(pointer, length, capacity)`.\n\nReturns the raw pointer to the underlying data, the length of\nthe string (in bytes), and the allocated capacity of the data\n(in bytes). These are the same arguments in the same order as\nthe arguments to [`from_raw_parts`].\n\nAfter calling this function, the caller is responsible for the\nmemory previously managed by the `String`. The only way to do\nthis is to convert the raw pointer, length, and capacity back\ninto a `String` with the [`from_raw_parts`] function, allowing\nthe destructor to perform the cleanup.\n\n[`from_raw_parts`]: String::from_raw_parts\n\n# Examples\n\n```rust\n#![feature(vec_into_raw_parts)]\nlet s = String::from(\"hello\");\n\nlet (ptr, len, cap) = s.into_raw_parts();\n\nlet rebuilt = unsafe { String::from_raw_parts(ptr, len, cap) };\nassert_eq!(rebuilt, \"hello\");\n```" + }, + "sortText": "7fffffff", + "filterText": "into_raw_parts", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "into_raw_parts" + } + }, + { + "label": "from_raw_parts", + "kind": 3, + "detail": "pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String", + "documentation": { + "kind": "markdown", + "value": "Creates a new `String` from a pointer, a length and a capacity.\n\n# Safety\n\nThis is highly unsafe, due to the number of invariants that aren't\nchecked:\n\n* all safety requirements for [`Vec::<u8>::from_raw_parts`].\n* all safety requirements for [`String::from_utf8_unchecked`].\n\nViolating these may cause problems like corrupting the allocator's\ninternal data structures. For example, it is normally **not** safe to\nbuild a `String` from a pointer to a C `char` array containing UTF-8\n_unless_ you are certain that array was originally allocated by the\nRust standard library's allocator.\n\nThe ownership of `buf` is effectively transferred to the\n`String` which may then deallocate, reallocate or change the\ncontents of memory pointed to by the pointer at will. Ensure\nthat nothing else uses the pointer after calling this\nfunction.\n\n# Examples\n\n```rust\nuse std::mem;\n\nunsafe {\n let s = String::from(\"hello\");\n\n // Prevent automatically dropping the String's data\n let mut s = mem::ManuallyDrop::new(s);\n\n let ptr = s.as_mut_ptr();\n let len = s.len();\n let capacity = s.capacity();\n\n let s = String::from_raw_parts(ptr, len, capacity);\n\n assert_eq!(String::from(\"hello\"), s);\n}\n```" + }, + "sortText": "7ffffff1", + "filterText": "from_raw_parts", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_raw_parts" + } + }, + { + "label": "from_utf8_unchecked", + "kind": 3, + "detail": "pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String", + "documentation": { + "kind": "markdown", + "value": "Converts a vector of bytes to a `String` without checking that the\nstring contains valid UTF-8.\n\nSee the safe version, [`from_utf8`], for more details.\n\n[`from_utf8`]: String::from_utf8\n\n# Safety\n\nThis function is unsafe because it does not check that the bytes passed\nto it are valid UTF-8. If this constraint is violated, it may cause\nmemory unsafety issues with future users of the `String`, as the rest of\nthe standard library assumes that `String`s are valid UTF-8.\n\n# Examples\n\n```rust\n// some bytes, in a vector\nlet sparkle_heart = vec![240, 159, 146, 150];\n\nlet sparkle_heart = unsafe {\n String::from_utf8_unchecked(sparkle_heart)\n};\n\nassert_eq!(\"💖\", sparkle_heart);\n```" + }, + "sortText": "7ffffff1", + "filterText": "from_utf8_unchecked", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_utf8_unchecked" + } + }, + { + "label": "into_bytes", + "kind": 2, + "detail": "pub const fn into_bytes(self) -> Vec<u8>", + "documentation": { + "kind": "markdown", + "value": "Converts a `String` into a byte vector.\n\nThis consumes the `String`, so we do not need to copy its contents.\n\n# Examples\n\n```rust\nlet s = String::from(\"hello\");\nlet bytes = s.into_bytes();\n\nassert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);\n```" + }, + "sortText": "7fffffff", + "filterText": "into_bytes", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "into_bytes" + } + }, + { + "label": "as_str", + "kind": 2, + "detail": "pub const fn as_str(&self) -> &str", + "documentation": { + "kind": "markdown", + "value": "Extracts a string slice containing the entire `String`.\n\n# Examples\n\n```rust\nlet s = String::from(\"foo\");\n\nassert_eq!(\"foo\", s.as_str());\n```" + }, + "sortText": "7fffffff", + "filterText": "as_str", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "as_str" + } + }, + { + "label": "as_mut_str", + "kind": 2, + "detail": "pub const fn as_mut_str(&mut self) -> &mut str", + "documentation": { + "kind": "markdown", + "value": "Converts a `String` into a mutable string slice.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"foobar\");\nlet s_mut_str = s.as_mut_str();\n\ns_mut_str.make_ascii_uppercase();\n\nassert_eq!(\"FOOBAR\", s_mut_str);\n```" + }, + "sortText": "7fffffff", + "filterText": "as_mut_str", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "as_mut_str" + } + }, + { + "label": "push_str", + "kind": 2, + "detail": "pub fn push_str(&mut self, string: &str)", + "documentation": { + "kind": "markdown", + "value": "Appends a given string slice onto the end of this `String`.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"foo\");\n\ns.push_str(\"bar\");\n\nassert_eq!(\"foobar\", s);\n```" + }, + "sortText": "7fffffff", + "filterText": "push_str", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "push_str" + } + }, + { + "label": "extend_from_within", + "kind": 2, + "detail": "pub fn extend_from_within<R>(&mut self, src: R) where R: RangeBounds<usize>,", + "documentation": { + "kind": "markdown", + "value": "Copies elements from `src` range to the end of the string.\n\n# Panics\n\nPanics if the range has `start_bound > end_bound`, or, if the range is\nbounded on either end and does not lie on a [`char`] boundary.\n\n# Examples\n\n```rust\nlet mut string = String::from(\"abcde\");\n\nstring.extend_from_within(2..);\nassert_eq!(string, \"abcdecde\");\n\nstring.extend_from_within(..2);\nassert_eq!(string, \"abcdecdeab\");\n\nstring.extend_from_within(4..8);\nassert_eq!(string, \"abcdecdeabecde\");\n```" + }, + "sortText": "7fffffff", + "filterText": "extend_from_within", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "extend_from_within" + } + }, + { + "label": "capacity", + "kind": 2, + "detail": "pub const fn capacity(&self) -> usize", + "documentation": { + "kind": "markdown", + "value": "Returns this `String`'s capacity, in bytes.\n\n# Examples\n\n```rust\nlet s = String::with_capacity(10);\n\nassert!(s.capacity() >= 10);\n```" + }, + "sortText": "7fffffff", + "filterText": "capacity", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "capacity" + } + }, + { + "label": "reserve", + "kind": 2, + "detail": "pub fn reserve(&mut self, additional: usize)", + "documentation": { + "kind": "markdown", + "value": "Reserves capacity for at least `additional` bytes more than the\ncurrent length. The allocator may reserve more space to speculatively\navoid frequent allocations. After calling `reserve`,\ncapacity will be greater than or equal to `self.len() + additional`.\nDoes nothing if capacity is already sufficient.\n\n# Panics\n\nPanics if the new capacity overflows [`usize`].\n\n# Examples\n\nBasic usage:\n\n```rust\nlet mut s = String::new();\n\ns.reserve(10);\n\nassert!(s.capacity() >= 10);\n```\n\nThis might not actually increase the capacity:\n\n```rust\nlet mut s = String::with_capacity(10);\ns.push('a');\ns.push('b');\n\n// s now has a length of 2 and a capacity of at least 10\nlet capacity = s.capacity();\nassert_eq!(2, s.len());\nassert!(capacity >= 10);\n\n// Since we already have at least an extra 8 capacity, calling this...\ns.reserve(8);\n\n// ... doesn't actually increase.\nassert_eq!(capacity, s.capacity());\n```" + }, + "sortText": "7fffffff", + "filterText": "reserve", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "reserve" + } + }, + { + "label": "reserve_exact", + "kind": 2, + "detail": "pub fn reserve_exact(&mut self, additional: usize)", + "documentation": { + "kind": "markdown", + "value": "Reserves the minimum capacity for at least `additional` bytes more than\nthe current length. Unlike [`reserve`], this will not\ndeliberately over-allocate to speculatively avoid frequent allocations.\nAfter calling `reserve_exact`, capacity will be greater than or equal to\n`self.len() + additional`. Does nothing if the capacity is already\nsufficient.\n\n[`reserve`]: String::reserve\n\n# Panics\n\nPanics if the new capacity overflows [`usize`].\n\n# Examples\n\nBasic usage:\n\n```rust\nlet mut s = String::new();\n\ns.reserve_exact(10);\n\nassert!(s.capacity() >= 10);\n```\n\nThis might not actually increase the capacity:\n\n```rust\nlet mut s = String::with_capacity(10);\ns.push('a');\ns.push('b');\n\n// s now has a length of 2 and a capacity of at least 10\nlet capacity = s.capacity();\nassert_eq!(2, s.len());\nassert!(capacity >= 10);\n\n// Since we already have at least an extra 8 capacity, calling this...\ns.reserve_exact(8);\n\n// ... doesn't actually increase.\nassert_eq!(capacity, s.capacity());\n```" + }, + "sortText": "7fffffff", + "filterText": "reserve_exact", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "reserve_exact" + } + }, + { + "label": "try_reserve", + "kind": 2, + "detail": "pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>", + "documentation": { + "kind": "markdown", + "value": "Tries to reserve capacity for at least `additional` bytes more than the\ncurrent length. The allocator may reserve more space to speculatively\navoid frequent allocations. After calling `try_reserve`, capacity will be\ngreater than or equal to `self.len() + additional` if it returns\n`Ok(())`. Does nothing if capacity is already sufficient. This method\npreserves the contents even if an error occurs.\n\n# Errors\n\nIf the capacity overflows, or the allocator reports a failure, then an error\nis returned.\n\n# Examples\n\n```rust\nuse std::collections::TryReserveError;\n\nfn process_data(data: &str) -> Result<String, TryReserveError> {\n let mut output = String::new();\n\n // Pre-reserve the memory, exiting if we can't\n output.try_reserve(data.len())?;\n\n // Now we know this can't OOM in the middle of our complex work\n output.push_str(data);\n\n Ok(output)\n}\n```" + }, + "sortText": "7fffffff", + "filterText": "try_reserve", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "try_reserve" + } + }, + { + "label": "try_reserve_exact", + "kind": 2, + "detail": "pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError>", + "documentation": { + "kind": "markdown", + "value": "Tries to reserve the minimum capacity for at least `additional` bytes\nmore than the current length. Unlike [`try_reserve`], this will not\ndeliberately over-allocate to speculatively avoid frequent allocations.\nAfter calling `try_reserve_exact`, capacity will be greater than or\nequal to `self.len() + additional` if it returns `Ok(())`.\nDoes nothing if the capacity is already sufficient.\n\nNote that the allocator may give the collection more space than it\nrequests. Therefore, capacity can not be relied upon to be precisely\nminimal. Prefer [`try_reserve`] if future insertions are expected.\n\n[`try_reserve`]: String::try_reserve\n\n# Errors\n\nIf the capacity overflows, or the allocator reports a failure, then an error\nis returned.\n\n# Examples\n\n```rust\nuse std::collections::TryReserveError;\n\nfn process_data(data: &str) -> Result<String, TryReserveError> {\n let mut output = String::new();\n\n // Pre-reserve the memory, exiting if we can't\n output.try_reserve_exact(data.len())?;\n\n // Now we know this can't OOM in the middle of our complex work\n output.push_str(data);\n\n Ok(output)\n}\n```" + }, + "sortText": "7fffffff", + "filterText": "try_reserve_exact", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "try_reserve_exact" + } + }, + { + "label": "shrink_to_fit", + "kind": 2, + "detail": "pub fn shrink_to_fit(&mut self)", + "documentation": { + "kind": "markdown", + "value": "Shrinks the capacity of this `String` to match its length.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"foo\");\n\ns.reserve(100);\nassert!(s.capacity() >= 100);\n\ns.shrink_to_fit();\nassert_eq!(3, s.capacity());\n```" + }, + "sortText": "7fffffff", + "filterText": "shrink_to_fit", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "shrink_to_fit" + } + }, + { + "label": "shrink_to", + "kind": 2, + "detail": "pub fn shrink_to(&mut self, min_capacity: usize)", + "documentation": { + "kind": "markdown", + "value": "Shrinks the capacity of this `String` with a lower bound.\n\nThe capacity will remain at least as large as both the length\nand the supplied value.\n\nIf the current capacity is less than the lower limit, this is a no-op.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"foo\");\n\ns.reserve(100);\nassert!(s.capacity() >= 100);\n\ns.shrink_to(10);\nassert!(s.capacity() >= 10);\ns.shrink_to(0);\nassert!(s.capacity() >= 3);\n```" + }, + "sortText": "7fffffff", + "filterText": "shrink_to", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "shrink_to" + } + }, + { + "label": "push", + "kind": 2, + "detail": "pub fn push(&mut self, ch: char)", + "documentation": { + "kind": "markdown", + "value": "Appends the given [`char`] to the end of this `String`.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"abc\");\n\ns.push('1');\ns.push('2');\ns.push('3');\n\nassert_eq!(\"abc123\", s);\n```" + }, + "sortText": "7fffffff", + "filterText": "push", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "push" + } + }, + { + "label": "as_bytes", + "kind": 2, + "detail": "pub const fn as_bytes(&self) -> &[u8]", + "documentation": { + "kind": "markdown", + "value": "Returns a byte slice of this `String`'s contents.\n\nThe inverse of this method is [`from_utf8`].\n\n[`from_utf8`]: String::from_utf8\n\n# Examples\n\n```rust\nlet s = String::from(\"hello\");\n\nassert_eq!(&[104, 101, 108, 108, 111], s.as_bytes());\n```" + }, + "sortText": "7fffffff", + "filterText": "as_bytes", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "as_bytes" + } + }, + { + "label": "truncate", + "kind": 2, + "detail": "pub fn truncate(&mut self, new_len: usize)", + "documentation": { + "kind": "markdown", + "value": "Shortens this `String` to the specified length.\n\nIf `new_len` is greater than or equal to the string's current length, this has no\neffect.\n\nNote that this method has no effect on the allocated capacity\nof the string\n\n# Panics\n\nPanics if `new_len` does not lie on a [`char`] boundary.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"hello\");\n\ns.truncate(2);\n\nassert_eq!(\"he\", s);\n```" + }, + "sortText": "7fffffff", + "filterText": "truncate", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "truncate" + } + }, + { + "label": "pop", + "kind": 2, + "detail": "pub fn pop(&mut self) -> Option<char>", + "documentation": { + "kind": "markdown", + "value": "Removes the last character from the string buffer and returns it.\n\nReturns [`None`] if this `String` is empty.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"abč\");\n\nassert_eq!(s.pop(), Some('č'));\nassert_eq!(s.pop(), Some('b'));\nassert_eq!(s.pop(), Some('a'));\n\nassert_eq!(s.pop(), None);\n```" + }, + "sortText": "7fffffff", + "filterText": "pop", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "pop" + } + }, + { + "label": "remove", + "kind": 2, + "detail": "pub fn remove(&mut self, idx: usize) -> char", + "documentation": { + "kind": "markdown", + "value": "Removes a [`char`] from this `String` at byte position `idx` and returns it.\n\nCopies all bytes after the removed char to new positions.\n\nNote that calling this in a loop can result in quadratic behavior.\n\n# Panics\n\nPanics if `idx` is larger than or equal to the `String`'s length,\nor if it does not lie on a [`char`] boundary.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"abç\");\n\nassert_eq!(s.remove(0), 'a');\nassert_eq!(s.remove(1), 'ç');\nassert_eq!(s.remove(0), 'b');\n```" + }, + "sortText": "7fffffff", + "filterText": "remove", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "remove" + } + }, + { + "label": "remove_matches", + "kind": 2, + "detail": "pub fn remove_matches<P>(&mut self, pat: P) where P: Pattern,", + "documentation": { + "kind": "markdown", + "value": "Remove all matches of pattern `pat` in the `String`.\n\n# Examples\n\n```rust\n#![feature(string_remove_matches)]\nlet mut s = String::from(\"Trees are not green, the sky is not blue.\");\ns.remove_matches(\"not \");\nassert_eq!(\"Trees are green, the sky is blue.\", s);\n```\n\nMatches will be detected and removed iteratively, so in cases where\npatterns overlap, only the first pattern will be removed:\n\n```rust\n#![feature(string_remove_matches)]\nlet mut s = String::from(\"banana\");\ns.remove_matches(\"ana\");\nassert_eq!(\"bna\", s);\n```" + }, + "sortText": "7fffffff", + "filterText": "remove_matches", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "remove_matches" + } + }, + { + "label": "retain", + "kind": 2, + "detail": "pub fn retain<F>(&mut self, mut f: F) where F: FnMut(char) -> bool,", + "documentation": { + "kind": "markdown", + "value": "Retains only the characters specified by the predicate.\n\nIn other words, remove all characters `c` such that `f(c)` returns `false`.\nThis method operates in place, visiting each character exactly once in the\noriginal order, and preserves the order of the retained characters.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"f_o_ob_ar\");\n\ns.retain(|c| c != '_');\n\nassert_eq!(s, \"foobar\");\n```\n\nBecause the elements are visited exactly once in the original order,\nexternal state may be used to decide which elements to keep.\n\n```rust\nlet mut s = String::from(\"abcde\");\nlet keep = [false, true, true, false, true];\nlet mut iter = keep.iter();\ns.retain(|_| *iter.next().unwrap());\nassert_eq!(s, \"bce\");\n```" + }, + "sortText": "7fffffff", + "filterText": "retain", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "retain" + } + }, + { + "label": "insert", + "kind": 2, + "detail": "pub fn insert(&mut self, idx: usize, ch: char)", + "documentation": { + "kind": "markdown", + "value": "Inserts a character into this `String` at byte position `idx`.\n\nReallocates if `self.capacity()` is insufficient, which may involve copying all\n`self.capacity()` bytes. Makes space for the insertion by copying all bytes of\n`&self[idx..]` to new positions.\n\nNote that calling this in a loop can result in quadratic behavior.\n\n# Panics\n\nPanics if `idx` is larger than the `String`'s length, or if it does not\nlie on a [`char`] boundary.\n\n# Examples\n\n```rust\nlet mut s = String::with_capacity(3);\n\ns.insert(0, 'f');\ns.insert(1, 'o');\ns.insert(2, 'o');\n\nassert_eq!(\"foo\", s);\n```" + }, + "sortText": "7fffffff", + "filterText": "insert", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "insert" + } + }, + { + "label": "insert_str", + "kind": 2, + "detail": "pub fn insert_str(&mut self, idx: usize, string: &str)", + "documentation": { + "kind": "markdown", + "value": "Inserts a string slice into this `String` at byte position `idx`.\n\nReallocates if `self.capacity()` is insufficient, which may involve copying all\n`self.capacity()` bytes. Makes space for the insertion by copying all bytes of\n`&self[idx..]` to new positions.\n\nNote that calling this in a loop can result in quadratic behavior.\n\n# Panics\n\nPanics if `idx` is larger than the `String`'s length, or if it does not\nlie on a [`char`] boundary.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"bar\");\n\ns.insert_str(0, \"foo\");\n\nassert_eq!(\"foobar\", s);\n```" + }, + "sortText": "7fffffff", + "filterText": "insert_str", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "insert_str" + } + }, + { + "label": "as_mut_vec", + "kind": 2, + "detail": "pub const unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8>", + "documentation": { + "kind": "markdown", + "value": "Returns a mutable reference to the contents of this `String`.\n\n# Safety\n\nThis function is unsafe because the returned `&mut Vec` allows writing\nbytes which are not valid UTF-8. If this constraint is violated, using\nthe original `String` after dropping the `&mut Vec` may violate memory\nsafety, as the rest of the standard library assumes that `String`s are\nvalid UTF-8.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"hello\");\n\nunsafe {\n let vec = s.as_mut_vec();\n assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]);\n\n vec.reverse();\n}\nassert_eq!(s, \"olleh\");\n```" + }, + "sortText": "7fffffff", + "filterText": "as_mut_vec", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "as_mut_vec" + } + }, + { + "label": "len", + "kind": 2, + "detail": "pub const fn len(&self) -> usize", + "documentation": { + "kind": "markdown", + "value": "Returns the length of this `String`, in bytes, not [`char`]s or\ngraphemes. In other words, it might not be what a human considers the\nlength of the string.\n\n# Examples\n\n```rust\nlet a = String::from(\"foo\");\nassert_eq!(a.len(), 3);\n\nlet fancy_f = String::from(\"ƒoo\");\nassert_eq!(fancy_f.len(), 4);\nassert_eq!(fancy_f.chars().count(), 3);\n```" + }, + "sortText": "7fffffff", + "filterText": "len", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "len" + } + }, + { + "label": "is_empty", + "kind": 2, + "detail": "pub const fn is_empty(&self) -> bool", + "documentation": { + "kind": "markdown", + "value": "Returns `true` if this `String` has a length of zero, and `false` otherwise.\n\n# Examples\n\n```rust\nlet mut v = String::new();\nassert!(v.is_empty());\n\nv.push('a');\nassert!(!v.is_empty());\n```" + }, + "sortText": "7fffffff", + "filterText": "is_empty", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "is_empty" + } + }, + { + "label": "split_off", + "kind": 2, + "detail": "pub fn split_off(&mut self, at: usize) -> String", + "documentation": { + "kind": "markdown", + "value": "Splits the string into two at the given byte index.\n\nReturns a newly allocated `String`. `self` contains bytes `[0, at)`, and\nthe returned `String` contains bytes `[at, len)`. `at` must be on the\nboundary of a UTF-8 code point.\n\nNote that the capacity of `self` does not change.\n\n# Panics\n\nPanics if `at` is not on a `UTF-8` code point boundary, or if it is beyond the last\ncode point of the string.\n\n# Examples\n\n```rust\nlet mut hello = String::from(\"Hello, World!\");\nlet world = hello.split_off(7);\nassert_eq!(hello, \"Hello, \");\nassert_eq!(world, \"World!\");\n```" + }, + "sortText": "7ffffff1", + "filterText": "split_off", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "split_off" + } + }, + { + "label": "clear", + "kind": 2, + "detail": "pub fn clear(&mut self)", + "documentation": { + "kind": "markdown", + "value": "Truncates this `String`, removing all contents.\n\nWhile this means the `String` will have a length of zero, it does not\ntouch its capacity.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"foo\");\n\ns.clear();\n\nassert!(s.is_empty());\nassert_eq!(0, s.len());\nassert_eq!(3, s.capacity());\n```" + }, + "sortText": "7fffffff", + "filterText": "clear", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "clear" + } + }, + { + "label": "drain", + "kind": 2, + "detail": "pub fn drain<R>(&mut self, range: R) -> Drain<'_> where R: RangeBounds<usize>,", + "documentation": { + "kind": "markdown", + "value": "Removes the specified range from the string in bulk, returning all\nremoved characters as an iterator.\n\nThe returned iterator keeps a mutable borrow on the string to optimize\nits implementation.\n\n# Panics\n\nPanics if the range has `start_bound > end_bound`, or, if the range is\nbounded on either end and does not lie on a [`char`] boundary.\n\n# Leaking\n\nIf the returned iterator goes out of scope without being dropped (due to\n[`core::mem::forget`], for example), the string may still contain a copy\nof any drained characters, or may have lost characters arbitrarily,\nincluding characters outside the range.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"α is alpha, β is beta\");\nlet beta_offset = s.find('β').unwrap_or(s.len());\n\n// Remove the range up until the β from the string\nlet t: String = s.drain(..beta_offset).collect();\nassert_eq!(t, \"α is alpha, \");\nassert_eq!(s, \"β is beta\");\n\n// A full range clears the string, like `clear()` does\ns.drain(..);\nassert_eq!(s, \"\");\n```" + }, + "sortText": "7fffffff", + "filterText": "drain", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "drain" + } + }, + { + "label": "into_chars", + "kind": 2, + "detail": "pub fn into_chars(self) -> IntoChars", + "documentation": { + "kind": "markdown", + "value": "Converts a `String` into an iterator over the [`char`]s of the string.\n\nAs a string consists of valid UTF-8, we can iterate through a string\nby [`char`]. This method returns such an iterator.\n\nIt's important to remember that [`char`] represents a Unicode Scalar\nValue, and might not match your idea of what a 'character' is. Iteration\nover grapheme clusters may be what you actually want. That functionality\nis not provided by Rust's standard library, check crates.io instead.\n\n# Examples\n\nBasic usage:\n\n```rust\n#![feature(string_into_chars)]\n\nlet word = String::from(\"goodbye\");\n\nlet mut chars = word.into_chars();\n\nassert_eq!(Some('g'), chars.next());\nassert_eq!(Some('o'), chars.next());\nassert_eq!(Some('o'), chars.next());\nassert_eq!(Some('d'), chars.next());\nassert_eq!(Some('b'), chars.next());\nassert_eq!(Some('y'), chars.next());\nassert_eq!(Some('e'), chars.next());\n\nassert_eq!(None, chars.next());\n```\n\nRemember, [`char`]s might not match your intuition about characters:\n\n```rust\n#![feature(string_into_chars)]\n\nlet y = String::from(\"y̆\");\n\nlet mut chars = y.into_chars();\n\nassert_eq!(Some('y'), chars.next()); // not 'y̆'\nassert_eq!(Some('\\u{0306}'), chars.next());\n\nassert_eq!(None, chars.next());\n```\n\n[`char`]: prim@char" + }, + "sortText": "7fffffff", + "filterText": "into_chars", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "into_chars" + } + }, + { + "label": "replace_range", + "kind": 2, + "detail": "pub fn replace_range<R>(&mut self, range: R, replace_with: &str) where R: RangeBounds<usize>,", + "documentation": { + "kind": "markdown", + "value": "Removes the specified range in the string,\nand replaces it with the given string.\nThe given string doesn't need to be the same length as the range.\n\n# Panics\n\nPanics if the range has `start_bound > end_bound`, or, if the range is\nbounded on either end and does not lie on a [`char`] boundary.\n\n# Examples\n\n```rust\nlet mut s = String::from(\"α is alpha, β is beta\");\nlet beta_offset = s.find('β').unwrap_or(s.len());\n\n// Replace the range up until the β from the string\ns.replace_range(..beta_offset, \"Α is capital alpha; \");\nassert_eq!(s, \"Α is capital alpha; β is beta\");\n```" + }, + "sortText": "7fffffff", + "filterText": "replace_range", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "replace_range" + } + }, + { + "label": "into_boxed_str", + "kind": 2, + "detail": "pub fn into_boxed_str(self) -> Box<str>", + "documentation": { + "kind": "markdown", + "value": "Converts this `String` into a <code>[Box]<[str]></code>.\n\nBefore doing the conversion, this method discards excess capacity like [`shrink_to_fit`].\nNote that this call may reallocate and copy the bytes of the string.\n\n[`shrink_to_fit`]: String::shrink_to_fit\n[str]: prim@str \"str\"\n\n# Examples\n\n```rust\nlet s = String::from(\"hello\");\n\nlet b = s.into_boxed_str();\n```" + }, + "sortText": "7fffffff", + "filterText": "into_boxed_str", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "into_boxed_str" + } + }, + { + "label": "leak", + "kind": 2, + "detail": "pub fn leak<'a>(self) -> &'a mut str", + "documentation": { + "kind": "markdown", + "value": "Consumes and leaks the `String`, returning a mutable reference to the contents,\n`&'a mut str`.\n\nThe caller has free choice over the returned lifetime, including `'static`. Indeed,\nthis function is ideally used for data that lives for the remainder of the program's life,\nas dropping the returned reference will cause a memory leak.\n\nIt does not reallocate or shrink the `String`, so the leaked allocation may include unused\ncapacity that is not part of the returned slice. If you want to discard excess capacity,\ncall [`into_boxed_str`], and then [`Box::leak`] instead. However, keep in mind that\ntrimming the capacity may result in a reallocation and copy.\n\n[`into_boxed_str`]: Self::into_boxed_str\n\n# Examples\n\n```rust\nlet x = String::from(\"bucket\");\nlet static_ref: &'static mut str = x.leak();\nassert_eq!(static_ref, \"bucket\");\n```" + }, + "sortText": "7fffffff", + "filterText": "leak", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "leak" + } + }, + { + "label": "to_owned(as ToOwned)", + "kind": 2, + "detail": "pub fn to_owned(&self) -> Self::Owned", + "documentation": { + "kind": "markdown", + "value": "Creates owned data from borrowed data, usually by cloning.\n\n# Examples\n\nBasic usage:\n\n```rust\nlet s: &str = \"a\";\nlet ss: String = s.to_owned();\n\nlet v: &[i32] = &[1, 2];\nlet vv: Vec<i32> = v.to_owned();\n```" + }, + "sortText": "80000004", + "filterText": "to_owned", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "to_owned" + } + }, + { + "label": "clone_into(as ToOwned)", + "kind": 2, + "detail": "pub fn clone_into(&self, target: &mut Self::Owned)", + "documentation": { + "kind": "markdown", + "value": "Uses borrowed data to replace owned data, usually by cloning.\n\nThis is borrow-generalized version of [`Clone::clone_from`].\n\n# Examples\n\nBasic usage:\n\n```rust\nlet mut s: String = String::new();\n\"hello\".clone_into(&mut s);\n\nlet mut v: Vec<i32> = Vec::new();\n[1, 2][..].clone_into(&mut v);\n```" + }, + "sortText": "80000004", + "filterText": "clone_into", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "clone_into" + } + }, + { + "label": "extend(as Extend)", + "kind": 2, + "detail": "pub fn extend<T>(&mut self, iter: T) where T: IntoIterator<Item = A>,", + "documentation": { + "kind": "markdown", + "value": "Extends a collection with the contents of an iterator.\n\nAs this is the only required method for this trait, the [trait-level] docs\ncontain more details.\n\n[trait-level]: Extend\n\n# Examples\n\n```rust\n// You can extend a String with some chars:\nlet mut message = String::from(\"abc\");\n\nmessage.extend(['d', 'e', 'f'].iter());\n\nassert_eq!(\"abcdef\", &message);\n```" + }, + "sortText": "80000004", + "filterText": "extend", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "extend" + } + }, + { + "label": "extend_one(as Extend)", + "kind": 2, + "detail": "pub fn extend_one(&mut self, item: A)", + "documentation": { + "kind": "markdown", + "value": "Extends a collection with exactly one element." + }, + "sortText": "80000004", + "filterText": "extend_one", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "extend_one" + } + }, + { + "label": "extend_reserve(as Extend)", + "kind": 2, + "detail": "pub fn extend_reserve(&mut self, additional: usize)", + "documentation": { + "kind": "markdown", + "value": "Reserves capacity in a collection for the given number of additional elements.\n\nThe default implementation does nothing." + }, + "sortText": "80000004", + "filterText": "extend_reserve", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "extend_reserve" + } + }, + { + "label": "into(as Into)", + "kind": 2, + "detail": "pub fn into(self) -> T", + "documentation": { + "kind": "markdown", + "value": "Converts this type into the (usually inferred) input type." + }, + "sortText": "80000004", + "filterText": "into", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "into" + } + }, + { + "label": "to_string(as ToString)", + "kind": 2, + "detail": "pub fn to_string(&self) -> String", + "documentation": { + "kind": "markdown", + "value": "Converts the given value to a `String`.\n\n# Examples\n\n```rust\nlet i = 5;\nlet five = String::from(\"5\");\n\nassert_eq!(five, i.to_string());\n```" + }, + "sortText": "80000004", + "filterText": "to_string", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "to_string" + } + }, + { + "label": "try_from(as TryFrom)", + "kind": 3, + "detail": "pub fn try_from(value: T) -> Result<Self, Self::Error>", + "documentation": { + "kind": "markdown", + "value": "Performs the conversion." + }, + "sortText": "80000004", + "filterText": "try_from", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "try_from" + } + }, + { + "label": "from_iter(as FromIterator)", + "kind": 3, + "detail": "pub fn from_iter<T>(iter: T) -> Self where T: IntoIterator<Item = A>,", + "documentation": { + "kind": "markdown", + "value": "Creates a value from an iterator.\n\nSee the [module-level documentation] for more.\n\n[module-level documentation]: crate::iter\n\n# Examples\n\n```rust\nlet five_fives = std::iter::repeat(5).take(5);\n\nlet v = Vec::from_iter(five_fives);\n\nassert_eq!(v, vec![5, 5, 5, 5, 5]);\n```" + }, + "sortText": "80000004", + "filterText": "from_iter", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from_iter" + } + }, + { + "label": "as_mut(as AsMut)", + "kind": 2, + "detail": "pub fn as_mut(&mut self) -> &mut T", + "documentation": { + "kind": "markdown", + "value": "Converts this type into a mutable reference of the (usually inferred) input type." + }, + "sortText": "80000004", + "filterText": "as_mut", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "as_mut" + } + }, + { + "label": "try_into(as TryInto)", + "kind": 2, + "detail": "pub fn try_into(self) -> Result<T, Self::Error>", + "documentation": { + "kind": "markdown", + "value": "Performs the conversion." + }, + "sortText": "80000004", + "filterText": "try_into", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "try_into" + } + }, + { + "label": "eq(as PartialEq)", + "kind": 2, + "detail": "pub fn eq(&self, other: &Rhs) -> bool", + "documentation": { + "kind": "markdown", + "value": "Tests for `self` and `other` values to be equal, and is used by `==`." + }, + "sortText": "80000009", + "filterText": "eq", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "eq" + } + }, + { + "label": "ne(as PartialEq)", + "kind": 2, + "detail": "pub fn ne(&self, other: &Rhs) -> bool", + "documentation": { + "kind": "markdown", + "value": "Tests for `!=`. The default implementation is almost always sufficient,\nand should not be overridden without very good reason." + }, + "sortText": "80000009", + "filterText": "ne", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "ne" + } + }, + { + "label": "partial_cmp(as PartialOrd)", + "kind": 2, + "detail": "pub fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>", + "documentation": { + "kind": "markdown", + "value": "This method returns an ordering between `self` and `other` values if one exists.\n\n# Examples\n\n```rust\nuse std::cmp::Ordering;\n\nlet result = 1.0.partial_cmp(&2.0);\nassert_eq!(result, Some(Ordering::Less));\n\nlet result = 1.0.partial_cmp(&1.0);\nassert_eq!(result, Some(Ordering::Equal));\n\nlet result = 2.0.partial_cmp(&1.0);\nassert_eq!(result, Some(Ordering::Greater));\n```\n\nWhen comparison is impossible:\n\n```rust\nlet result = f64::NAN.partial_cmp(&1.0);\nassert_eq!(result, None);\n```" + }, + "sortText": "80000009", + "filterText": "partial_cmp", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "partial_cmp" + } + }, + { + "label": "lt(as PartialOrd)", + "kind": 2, + "detail": "pub fn lt(&self, other: &Rhs) -> bool", + "documentation": { + "kind": "markdown", + "value": "Tests less than (for `self` and `other`) and is used by the `<` operator.\n\n# Examples\n\n```rust\nassert_eq!(1.0 < 1.0, false);\nassert_eq!(1.0 < 2.0, true);\nassert_eq!(2.0 < 1.0, false);\n```" + }, + "sortText": "80000009", + "filterText": "lt", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "lt" + } + }, + { + "label": "le(as PartialOrd)", + "kind": 2, + "detail": "pub fn le(&self, other: &Rhs) -> bool", + "documentation": { + "kind": "markdown", + "value": "Tests less than or equal to (for `self` and `other`) and is used by the\n`<=` operator.\n\n# Examples\n\n```rust\nassert_eq!(1.0 <= 1.0, true);\nassert_eq!(1.0 <= 2.0, true);\nassert_eq!(2.0 <= 1.0, false);\n```" + }, + "sortText": "80000009", + "filterText": "le", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "le" + } + }, + { + "label": "gt(as PartialOrd)", + "kind": 2, + "detail": "pub fn gt(&self, other: &Rhs) -> bool", + "documentation": { + "kind": "markdown", + "value": "Tests greater than (for `self` and `other`) and is used by the `>`\noperator.\n\n# Examples\n\n```rust\nassert_eq!(1.0 > 1.0, false);\nassert_eq!(1.0 > 2.0, false);\nassert_eq!(2.0 > 1.0, true);\n```" + }, + "sortText": "80000009", + "filterText": "gt", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "gt" + } + }, + { + "label": "ge(as PartialOrd)", + "kind": 2, + "detail": "pub fn ge(&self, other: &Rhs) -> bool", + "documentation": { + "kind": "markdown", + "value": "Tests greater than or equal to (for `self` and `other`) and is used by\nthe `>=` operator.\n\n# Examples\n\n```rust\nassert_eq!(1.0 >= 1.0, true);\nassert_eq!(1.0 >= 2.0, false);\nassert_eq!(2.0 >= 1.0, true);\n```" + }, + "sortText": "80000009", + "filterText": "ge", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "ge" + } + }, + { + "label": "as_ref(as AsRef)", + "kind": 2, + "detail": "pub fn as_ref(&self) -> &T", + "documentation": { + "kind": "markdown", + "value": "Converts this type into a shared reference of the (usually inferred) input type." + }, + "sortText": "80000004", + "filterText": "as_ref", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "as_ref" + } + }, + { + "label": "clone(as Clone)", + "kind": 2, + "detail": "pub fn clone(&self) -> Self", + "documentation": { + "kind": "markdown", + "value": "Returns a duplicate of the value.\n\nNote that what \"duplicate\" means varies by type:\n- For most types, this creates a deep, independent copy\n- For reference types like `&T`, this creates another reference to the same value\n- For smart pointers like [`Arc`] or [`Rc`], this increments the reference count\n but still points to the same underlying data\n\n[`Arc`]: ../../std/sync/struct.Arc.html\n[`Rc`]: ../../std/rc/struct.Rc.html\n\n# Examples\n\n```rust\nlet hello = \"Hello\"; // &str implements Clone\n\nassert_eq!(\"Hello\", hello.clone());\n```\n\nExample with a reference-counted type:\n\n```rust\nuse std::sync::{Arc, Mutex};\n\nlet data = Arc::new(Mutex::new(vec![1, 2, 3]));\nlet data_clone = data.clone(); // Creates another Arc pointing to the same Mutex\n\n{\n let mut lock = data.lock().unwrap();\n lock.push(4);\n}\n\n// Changes are visible through the clone because they share the same underlying data\nassert_eq!(*data_clone.lock().unwrap(), vec![1, 2, 3, 4]);\n```" + }, + "sortText": "80000004", + "filterText": "clone", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "clone" + } + }, + { + "label": "clone_from(as Clone)", + "kind": 2, + "detail": "pub fn clone_from(&mut self, source: &Self) where Self: Destruct,", + "documentation": { + "kind": "markdown", + "value": "Performs copy-assignment from `source`.\n\n`a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,\nbut can be overridden to reuse the resources of `a` to avoid unnecessary\nallocations." + }, + "sortText": "80000004", + "filterText": "clone_from", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "clone_from" + } + }, + { + "label": "from(as From)", + "kind": 3, + "detail": "pub fn from(value: T) -> Self", + "documentation": { + "kind": "markdown", + "value": "Converts to this type from the input type." + }, + "sortText": "80000004", + "filterText": "from", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "from" + } + }, + { + "label": "default(as Default)", + "kind": 3, + "detail": "pub fn default() -> Self", + "documentation": { + "kind": "markdown", + "value": "Returns the \"default value\" for a type.\n\nDefault values are often some kind of initial value, identity value, or anything else that\nmay make sense as a default.\n\n# Examples\n\nUsing built-in default values:\n\n```rust\nlet i: i8 = Default::default();\nlet (x, y): (Option<String>, f64) = Default::default();\nlet (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default();\n```\n\nMaking your own:\n\n```rust\nenum Kind {\n A,\n B,\n C,\n}\n\nimpl Default for Kind {\n fn default() -> Self { Kind::A }\n}\n```" + }, + "sortText": "80000004", + "filterText": "default", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "default" + } + }, + { + "label": "cmp(as Ord)", + "kind": 2, + "detail": "pub fn cmp(&self, other: &Self) -> Ordering", + "documentation": { + "kind": "markdown", + "value": "This method returns an [`Ordering`] between `self` and `other`.\n\nBy convention, `self.cmp(&other)` returns the ordering matching the expression\n`self <operator> other` if true.\n\n# Examples\n\n```rust\nuse std::cmp::Ordering;\n\nassert_eq!(5.cmp(&10), Ordering::Less);\nassert_eq!(10.cmp(&5), Ordering::Greater);\nassert_eq!(5.cmp(&5), Ordering::Equal);\n```" + }, + "sortText": "80000004", + "filterText": "cmp", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "cmp" + } + }, + { + "label": "max(as Ord)", + "kind": 2, + "detail": "pub fn max(self, other: Self) -> Self where Self: Sized + Destruct,", + "documentation": { + "kind": "markdown", + "value": "Compares and returns the maximum of two values.\n\nReturns the second argument if the comparison determines them to be equal.\n\n# Examples\n\n```rust\nassert_eq!(1.max(2), 2);\nassert_eq!(2.max(2), 2);\n```\n```rust\nuse std::cmp::Ordering;\n\n#[derive(Eq)]\nstruct Equal(&'static str);\n\nimpl PartialEq for Equal {\n fn eq(&self, other: &Self) -> bool { true }\n}\nimpl PartialOrd for Equal {\n fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(Ordering::Equal) }\n}\nimpl Ord for Equal {\n fn cmp(&self, other: &Self) -> Ordering { Ordering::Equal }\n}\n\nassert_eq!(Equal(\"self\").max(Equal(\"other\")).0, \"other\");\n```" + }, + "sortText": "80000004", + "filterText": "max", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "max" + } + }, + { + "label": "min(as Ord)", + "kind": 2, + "detail": "pub fn min(self, other: Self) -> Self where Self: Sized + Destruct,", + "documentation": { + "kind": "markdown", + "value": "Compares and returns the minimum of two values.\n\nReturns the first argument if the comparison determines them to be equal.\n\n# Examples\n\n```rust\nassert_eq!(1.min(2), 1);\nassert_eq!(2.min(2), 2);\n```\n```rust\nuse std::cmp::Ordering;\n\n#[derive(Eq)]\nstruct Equal(&'static str);\n\nimpl PartialEq for Equal {\n fn eq(&self, other: &Self) -> bool { true }\n}\nimpl PartialOrd for Equal {\n fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(Ordering::Equal) }\n}\nimpl Ord for Equal {\n fn cmp(&self, other: &Self) -> Ordering { Ordering::Equal }\n}\n\nassert_eq!(Equal(\"self\").min(Equal(\"other\")).0, \"self\");\n```" + }, + "sortText": "80000004", + "filterText": "min", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "min" + } + }, + { + "label": "clamp(as Ord)", + "kind": 2, + "detail": "pub fn clamp(self, min: Self, max: Self) -> Self where Self: Sized + Destruct,", + "documentation": { + "kind": "markdown", + "value": "Restrict a value to a certain interval.\n\nReturns `max` if `self` is greater than `max`, and `min` if `self` is\nless than `min`. Otherwise this returns `self`.\n\n# Panics\n\nPanics if `min > max`.\n\n# Examples\n\n```rust\nassert_eq!((-3).clamp(-2, 1), -2);\nassert_eq!(0.clamp(-2, 1), 0);\nassert_eq!(2.clamp(-2, 1), 1);\n```" + }, + "sortText": "80000004", + "filterText": "clamp", + "textEdit": { + "range": { + "start": { + "line": 20, + "character": 8 + }, + "end": { + "line": 20, + "character": 12 + } + }, + "newText": "clamp" + } + } + ] +}
\ No newline at end of file diff --git a/src/com.rs b/src/com.rs new file mode 100644 index 0000000..f2c47ca --- /dev/null +++ b/src/com.rs @@ -0,0 +1,244 @@ +use std::mem::MaybeUninit; +use std::sync::LazyLock; + +use Default::default; +use dsb::cell::Style; +use dsb::{Cell, F}; +use fimg::Image; +use itertools::Itertools; +use lsp_types::*; + +use crate::{Complete, FG}; +const BG: [u8; 3] = crate::text::color(*b"1c212b"); +const T_BG: [u8; 3] = crate::text::color(*b"11141a"); + +pub fn s(x: &Complete, c: usize, filter: &str) -> Vec<Cell> { + let mut out = vec![]; + let x = &x.r; + let y = match x { + CompletionResponse::Array(x) => x, + CompletionResponse::List(x) => &x.items, + }; + static mut MATCHER: LazyLock<nucleo::Matcher> = + LazyLock::new(|| nucleo::Matcher::new(nucleo::Config::DEFAULT)); + let p = nucleo::pattern::Pattern::parse( + filter, + nucleo::pattern::CaseMatching::Ignore, + nucleo::pattern::Normalization::Smart, + ); + + let mut i = y + .iter() + .filter(|y| { + y.filter_text + .as_deref() + .unwrap_or(&y.label) + .starts_with(filter) + }) + .map(|y| { + let mut to = vec![]; + let score = p + .score( + nucleo::Utf32Str::new( + y.filter_text.as_deref().unwrap_or(&y.label), + &mut to, + ), + unsafe { &mut *MATCHER }, + ) + .unwrap_or(0); + (score, y) + }) + .sorted_by_key(|x| x.0) + .take(13); + + // let Some((s, x)) = i.next() else { + // return vec![]; + // }; + + // let mut q = Dq::<_, 13>::new((s, x)); + // for (s, x) in i { + // if q.first().0 <= s { + // q.push_front((s, x)); + // } + // } + + // fuzzy_aho_corasick::FuzzyAhoCorasickBuilder::new() + // .fuzzy( + // FuzzyLimits::new() + // .insertions(20) + // .deletions(2) + // .edits(4) + // .substitutions(5) + // .swaps(3), + // .penalties(FuzzyPenalties { + // ) + // insertion: 0.0, + // deletion: 1.0, + // substitution: 0.5, + // swap: 0.5, + // }) + // .build( + // y.iter().map(|x| x.filter_text.as_deref().unwrap_or(&x.label)), + // ) + // .search(filter, 0.25) + // .into_iter() + // .map(|x| &y[x.pattern_index]) + // // .take(13); + // // for x in y + // // .iter() + // // .filter(|x| { + // // x.filter_text + // // .as_deref() + // // .unwrap_or(&x.label) + // // .starts_with(filter) + // // }) + // .take(13) + i.for_each(|(_, x)| r(x, c, &mut out)); + out +} +fn charc(c: &str) -> usize { + c.chars().count() +} +#[implicit_fn::implicit_fn] +fn r(x: &CompletionItem, c: usize, to: &mut Vec<Cell>) { + let mut b = vec![D; c]; + let ty = match x.kind { + Some(CompletionItemKind::TEXT) => " ", + Some( + CompletionItemKind::METHOD | CompletionItemKind::FUNCTION, + ) => "λ ", + Some(CompletionItemKind::CONSTRUCTOR) => "->", + Some(CompletionItemKind::FIELD) => "x.", + Some(CompletionItemKind::VARIABLE) => "x", + Some(CompletionItemKind::MODULE) => "::", + Some(CompletionItemKind::PROPERTY) => "x.", + Some(CompletionItemKind::VALUE) => "4 ", + Some(CompletionItemKind::ENUM) => "u", + Some(CompletionItemKind::SNIPPET) => "! ", + Some(CompletionItemKind::INTERFACE) => "t ", + Some(CompletionItemKind::REFERENCE) => "& ", + Some(CompletionItemKind::CONSTANT) => "N ", + Some(CompletionItemKind::STRUCT) => "X{", + Some(CompletionItemKind::OPERATOR) => "+ ", + Some(CompletionItemKind::TYPE_PARAMETER) => "T ", + Some(CompletionItemKind::KEYWORD) => " ", + + _ => " ", + }; + b.iter_mut().zip(ty.chars()).for_each(|(x, c)| { + *x = Style { bg: T_BG, color: [154, 155, 154], ..default() } + .basic(c) + }); + let i = &mut b[2..]; + + let left = i.len() as i32 - charc(&x.label) as i32 - 2; + if let Some(details) = &x.detail { + let details = if left < charc(details) as i32 { + details + .chars() + .take(left as _) + .chain(['…']) + .collect::<Vec<_>>() + .into_iter() + .rev() + .collect::<Vec<_>>() + .into_iter() + } else { + details.chars().rev().collect::<Vec<_>>().into_iter() + }; + i.iter_mut() + .rev() + .zip(details.map(|x| { + Style { bg: BG, color: [154, 155, 154], ..default() } + .basic(x) + })) + .for_each(|(a, b)| *a = b); + } + i.iter_mut() + .zip(x.label.chars().map(|x| DS.basic(x))) + .for_each(|(a, b)| *a = b); + to.extend(b); +} +const DS: Style = Style { bg: BG, color: FG, flags: 0 }; +const D: Cell = Cell { letter: None, style: DS }; +#[test] +fn t() { + let ppem = 20.0; + let lh = 10.0; + let (w, h) = (611, 8000); + let (c, r) = dsb::fit(&crate::FONT, ppem, lh, (w, h)); + dbg!(dsb::size(&crate::FONT, ppem, lh, (c, r))); + let y = serde_json::from_str(include_str!("../complete_")).unwrap(); + let cells = + s(&Complete { r: y, start: 0, selection: 0, scroll: 0 }, c, ""); + dbg!(c, r); + dbg!(w, h); + + let mut fonts = dsb::Fonts::new( + F::FontRef(*crate::FONT, &[(2003265652, 550.0)]), + F::instance(*crate::FONT, *crate::BFONT), + F::FontRef(*crate::IFONT, &[(2003265652, 550.0)]), + F::instance(*crate::IFONT, *crate::BIFONT), + ); + + let mut x = Image::build(w as u32, h as u32).fill(crate::hov::BG); + unsafe { + dsb::render( + &cells, + (c, r), + ppem, + &mut fonts, + lh, + true, + x.as_mut(), + (0, 0), + ) + }; + // println!("{:?}", now.elapsed()); + x.as_ref().save("x"); +} + +pub struct Dq<T, const N: usize> { + arr: [MaybeUninit<T>; N], + front: u8, + len: u8, +} + +impl<T: Copy, const N: usize> Dq<T, N> { + pub fn new(first: T) -> Self { + let mut dq = Dq { + arr: [const { MaybeUninit::uninit() }; N], + front: 0, + len: 1, + }; + dq.arr[0].write(first); + dq + } + + pub fn first(&mut self) -> T { + unsafe { + self.arr.get_unchecked(self.front as usize).assume_init() + } + } + + pub fn push_front(&mut self, elem: T) { + // sub 1 + match self.front { + 0 => self.front = N as u8 - 1, + n => self.front = n - 1, + } + self.len += 1; + unsafe { + self.arr.get_unchecked_mut(self.front as usize).write(elem) + }; + } + + pub fn iter(&self) -> impl Iterator<Item = T> + '_ { + self.arr + .iter() + .cycle() + .skip(self.front as _) + .take((self.len as usize).min(N)) + .map(|x| unsafe { x.assume_init() }) + } +} @@ -263,7 +263,7 @@ pub fn markdown2(c: usize, x: &Node) -> Vec<Cell> { } r.to } -pub const BG: [u8; 3] = text::color(b"191E27"); +pub const BG: [u8; 3] = text::color(*b"191E27"); #[test] fn t() { let ppem = 18.0; @@ -1,13 +1,10 @@ use std::collections::HashMap; -use std::io::BufReader; use std::path::Path; -use std::pin::Pin; -use std::process::{Command, Stdio}; use std::sync::atomic::AtomicI32; use std::sync::atomic::Ordering::Relaxed; use std::task::Poll; -use std::thread::{JoinHandle, sleep, spawn}; -use std::time::{Duration, Instant}; +use std::thread::{JoinHandle, spawn}; +use std::time::Instant; use Default::default; use anyhow::Error; @@ -42,7 +39,7 @@ pub struct Client { pub progress: &'static papaya::HashMap<ProgressToken, Option<WorkDoneProgress>>, pub not_rx: Receiver<N>, - pub req_rx: Receiver<Rq>, + // pub req_rx: Receiver<Rq>, pub semantic_tokens: ( &'static ArcSwap<Box<[SemanticToken]>>, Mutex<Option<(tokio::task::JoinHandle<Result<(), Error>>, i32)>>, @@ -136,8 +133,18 @@ impl Client { ) } - pub fn request_complete(&self, f: &Path, (x, y): (usize, usize)) { - let (rx, i) = self + pub fn request_complete( + &self, + f: &Path, + (x, y): (usize, usize), + c: CompletionContext, + ) -> impl Future< + Output = Result< + Option<CompletionResponse>, + oneshot::error::RecvError, + >, + > + use<> { + let (rx, _) = self .request::<Completion>(&CompletionParams { text_document_position: TextDocumentPositionParams { text_document: { @@ -149,16 +156,10 @@ impl Client { }, work_done_progress_params: default(), partial_result_params: default(), - context: None, + context: Some(c), }) .unwrap(); - self.runtime.spawn(async move { - std::fs::write( - "complete_", - format!("{:#?}", rx.await.unwrap()), - ); - // dbg!(rx.recv().unwrap()); - }); + rx } pub fn rq_semantic_tokens(&self, f: &Path) -> anyhow::Result<()> { @@ -217,9 +218,8 @@ pub fn run( let (not_tx, not_rx) = unbounded(); let (_req_tx, _req_rx) = unbounded(); let (ch_tx, ch_rx) = unbounded(); - let mut c = Client { + let mut c: Client = Client { tx, - req_rx: _req_rx, ch_tx: ch_tx.clone(), progress: Box::leak(Box::new(papaya::HashMap::new())), runtime: tokio::runtime::Builder::new_multi_thread() @@ -275,7 +275,34 @@ pub fn run( }), completion_item_kind: Some( CompletionItemKindCapability { - value_set: None, + value_set: Some( +vec![CompletionItemKind::TEXT, +CompletionItemKind::METHOD, // () +CompletionItemKind::FUNCTION, // () +CompletionItemKind::CONSTRUCTOR, // -> +CompletionItemKind::FIELD, // x. +CompletionItemKind::VARIABLE, // x +CompletionItemKind::CLASS, +CompletionItemKind::INTERFACE, +CompletionItemKind::MODULE, // :: +CompletionItemKind::PROPERTY, // x. +CompletionItemKind::UNIT, +CompletionItemKind::VALUE, // 4 +CompletionItemKind::ENUM, // un +CompletionItemKind::KEYWORD, +CompletionItemKind::SNIPPET, // ! +CompletionItemKind::COLOR, +CompletionItemKind::FILE, +CompletionItemKind::REFERENCE, // & +CompletionItemKind::FOLDER, +CompletionItemKind::ENUM_MEMBER, +CompletionItemKind::CONSTANT, // N +CompletionItemKind::STRUCT, // X +CompletionItemKind::EVENT, +CompletionItemKind::OPERATOR, // + +CompletionItemKind::TYPE_PARAMETER] + ), + // value_set: Some(vec![CompletionItemKind::]), }, ), @@ -341,27 +368,41 @@ pub fn run( }), initialization_options: Some(json! {{ "cargo": { - "buildScripts": { - "enable": true, - } + "buildScripts": { "enable": true } }, "procMacro": { "enable": true, + "attributes": { "enable": true } + }, + "inlayHints": { + "closureReturnTypeHints": { "enable": "with_block" }, + "closingBraceHints": { "minLines": 5 }, + "closureStyle": "rust_analyzer", + "genericParameterHints": { + "type": { "enable": true } }, + "rangeExclusiveHints": { "enable": true }, + "closureCaptureHints": { "enable": true }, + "expressionAdjustmentHints": { + "hideOutsideUnsafe": true, + "enable": "never", + "mode": "prefer_prefix" + } + }, + "semanticHighlighting": { + "punctuation": { + "separate": { + "macroBang": true + }, + "specialization": { "enable": true }, + "enable": true + } }, - "procMacro.attributes.enable": true, - "inlayHints.closureReturnTypeHints.enable": "with_block", - "inlayHints.closingBraceHints.minLines": 5, - "inlayHints.closureStyle": "rust_analyzer", "showUnlinkedFileNotification": false, - "inlayHints.genericParameterHints.type.enable": true, - "inlayHints.rangeExclusiveHints.enable": true, - "inlayHints.closureCaptureHints.enable": true, - "inlayHints.expressionAdjustmentHints.hideOutsideUnsafe": true, - "inlayHints.expressionAdjustmentHints.enable": "never", - "inlayHints.expressionAdjustmentHints.mode": "prefer_prefix", - "semanticHighlighting.punctuation.separate.macro.bang": true, - "semanticHighlighting.punctuation.enable": true, - "semanticHighlighting.punctuation.specialization.enable": true, + "completion": { + "fullFunctionSignatures": { "enable": true, }, + "autoIter": { "enable": false, }, + "privateEditable": { "enable": true }, + }, }}), trace: None, workspace_folders: Some(vec![workspace]), @@ -452,85 +493,6 @@ pub fn run( (c, iot, h, ch_rx) } -pub fn x() { - let mut c = Command::new("/home/os/.cargo/bin/rust-analyzer") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::inherit()) - .spawn() - .unwrap(); - - log::info!("helol"); - - let (c, rx, iot, ch) = run( - lsp_server::stdio::stdio_transport( - BufReader::new(c.stdout.take().unwrap()), - c.stdin.take().unwrap(), - ), - WorkspaceFolder { - uri: "file:///home/os/gracilaria".parse().unwrap(), - name: "gracilaria".into(), - }, - ); - let n = c.not_rx.clone(); - let r = c.req_rx.clone(); - let p = c.progress; - - // c.request::<SemanticTokensFullRequest>(&SemanticTokensParams { - // work_done_progress_params: default(), - // partial_result_params: default(), - // text_document: TextDocumentIdentifier::new( - // url::Url::from_file_path(Path::new( - // "/home/os/gracilaria/src/text.rs", - // )) - // .unwrap(), - // ), - // }) - // .unwrap(); - sleep(Duration::from_secs(40)); - c.open( - Path::new("/home/os/gracilaria/src/user.rs"), - "fn main() {}".into(), - ) - .unwrap(); - c.rq_semantic_tokens(Path::new("/home/os/gracilaria/src/user.rs")) - .unwrap(); - - dbg!(rx.writer.join().unwrap()).unwrap(); - - spawn(|| { - for elem in r { - match &*elem.method { - x if x == WorkDoneProgressCreate::METHOD => { - elem.load::<WorkDoneProgressCreate>().unwrap(); - } - _ => {} - } - } - }); - loop {} - drop(c); - - // let wait = c - // .request::<SemanticTokensFullRequest>(&SemanticTokensParams { - // work_done_progress_params: default(), - // partial_result_params: default(), - // text_document: TextDocumentIdentifier { - // uri: "file:///home/os/gracilaria/src/main.rs" - // .parse() - // .unwrap(), - // }, - // }) - // .unwrap(); - // spawn(|| { - // let x = wait.recv_eepy().unwrap(); - // println!( - // "found! {:#?}", - // x.extract::<SemanticTokensResult>().unwrap() - // ); - // }); -} - // trait RecvEepy<T>: Sized { // fn recv_eepy(self) -> Result<T, RecvError> { // self.recv_sleepy(100) diff --git a/src/main.rs b/src/main.rs index 74b066e..89e1d90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ // this looks pretty good though #![feature(tuple_trait, unboxed_closures, fn_traits)] #![feature( + result_option_map_or_default, iter_intersperse, stmt_expr_attributes, new_range_api, @@ -26,6 +27,7 @@ use std::borrow::Cow; use std::io::BufReader; use std::num::NonZeroU32; use std::path::{Path, PathBuf}; +use std::pin::Pin; use std::process::{Command, Stdio}; use std::sync::{Arc, LazyLock, OnceLock}; use std::thread; @@ -34,22 +36,24 @@ use std::time::Instant; use Default::default; use NamedKey::*; use atools::prelude::AASAdd; +use crossbeam::channel::RecvError; use diff_match_patch_rs::PatchInput; use dsb::cell::Style; use dsb::{Cell, F}; use fimg::{Image, OverlayAt}; -use lsp_types::request::HoverRequest; +use lsp_types::request::{Completion, HoverRequest}; use lsp_types::{ - Hover, HoverParams, MarkedString, Position, SemanticTokensOptions, + CompletionContext, CompletionResponse, CompletionTriggerKind, Hover, + HoverParams, MarkedString, Position, SemanticTokensOptions, SemanticTokensServerCapabilities, ServerCapabilities, TextDocumentIdentifier, TextDocumentPositionParams, WorkspaceFolder, }; use parking_lot::Mutex; use regex::Regex; use ropey::Rope; -use rust_fsm::StateMachineImpl; +use rust_fsm::StateMachine; use swash::{FontRef, Instance}; -use tokio::task::spawn_blocking; +use tokio::task::{JoinHandle, spawn_blocking}; use url::Url; use winit::event::{ ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent, @@ -61,8 +65,9 @@ use winit::window::{Icon, Window}; use crate::bar::Bar; use crate::hov::Hovr; -use crate::text::{ Diff, TextArea}; +use crate::text::{Diff, TextArea}; mod bar; +pub mod com; pub mod hov; mod lsp; mod text; @@ -229,7 +234,17 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { }; } let hovering = &*Box::leak(Box::new(Mutex::new(None::<hov::Hovr>))); - + let mut complete = CompletionState::None; + // let mut complete = None::<(CompletionResponse, (usize, usize))>; + // let mut complete_ = None::<( + // JoinHandle< + // Result< + // Option<CompletionResponse>, + // tokio::sync::oneshot::error::RecvError, + // >, + // >, + // (usize, usize), + // )>; // let mut hl_result = None; let mut hist = Hist { @@ -305,6 +320,24 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { state.consume(Action::Changed).unwrap(); window.request_redraw(); } + if let CompletionState::Complete(o, x)= &mut complete && + x.as_ref().is_some_and(|(x, _)|x.is_finished()) && let Some((task, c)) = x.take() && let Some(ref l) = lsp{ + // if text.cursor() ==* c_ { + println!("bl0ck on"); + + *o = l.runtime.block_on(task).ok().and_then(Result::ok).flatten().map(|x| Complete { +r:x,start:0,selection:0,scroll:0, + } ); + if let Some(x) = o { + std::fs::write("complete_", serde_json::to_string_pretty(&x.r).unwrap()).unwrap(); + println!("resolved") + } + // println!("{complete:#?}"); + // } else { + // println!("abort {c_:?}"); + // x.abort(); + // } + } match event { Event::AboutToWait => {} Event::WindowEvent { @@ -436,6 +469,60 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { i.as_mut(),(0,0) ) }; + if let CompletionState::Complete(Some(ref x,),_) = complete { + let c = com::s(x, 40,&if matches!(text.rope.get_char(text.cursor-1), Some('.' | ':')) { + "".to_string() + } else { + text.rope.slice(text.word_left_p()..text.cursor).chars().collect::<String>() + }); + let ppem = 20.0; + + let met = FONT.metrics(&[]); + let fac = ppem / met.units_per_em as f32; + let (_x, _y) = text.cursor(); + let _x = _x + text.line_number_offset()+1; + + // let [(_x, _y), (_x2, _)] = text.position(text.cursor); + // let [_x, _x2] = [_x, _x2].add(text.line_number_offset()+1); + let _y = _y.wrapping_sub(text.vo); + // if !(cursor_position.1 == _y && (_x..=_x2).contains(&cursor_position.0)) { + // return; + // } + let position = ( + ((_x) as f32 * fw).round() as usize, + ((_y as f32 as f32) * (fh + ls * fac)).round() as usize, + ); + + + + let ls = 10.0; + let mut r = c.len()/40; + let (w, h) = dsb::size(&fonts.regular, ppem, ls, (40, r)); + let top = position.1.checked_sub(h).unwrap_or((((_y + 1) as f32) * (fh + ls * fac)).round() as usize,); + let (_, y) = dsb::fit(&fonts.regular, ppem, ls, (window.inner_size().width as _ /* - left */,( window.inner_size().height as usize - top ) )); + r = r.min(y); + + let left = + if position.0 + w as usize > window.inner_size().width as usize { + window.inner_size().width as usize- w as usize + } else { position.0 }; + + let (w, h) = dsb::size(&fonts.regular, ppem, ls, (40, r)); + // let mut i2 = Image::build(w as _, h as _).fill(BG); + unsafe{ dsb::render( + &c, + (40, 0), + ppem, + &mut fonts, + ls, + true, + i.as_mut(), + (left as _, top as _) + )}; + // dbg!(w, h, i2.width(), i2.height(), window.inner_size(), i.width(),i.height()); + // unsafe { i.overlay_at(&i2.as_ref(), left as u32, top as u32) }; + i.r#box((left .saturating_sub(1) as _, top.saturating_sub(1) as _), w as _,h as _, [0;3]); + } hovering.lock().as_ref().map(|x| x.span.clone().map(|sp| { let met = FONT.metrics(&[]); let fac = ppem / met.units_per_em as f32; @@ -636,6 +723,10 @@ RUNNING.remove(&hover,&RUNNING.guard()); if button == MouseButton::Left { unsafe { CLICKING = true }; } + match complete.consume(CompletionAction::Click).unwrap() { + Some(CDo::Abort(x))=>{ x.abort() }, + _ => {}, + } match state.consume(Action::M(button)).unwrap() { Some(Do::MoveCursor) => { text.cursor = text.index_at(cursor_position); @@ -740,12 +831,57 @@ RUNNING.remove(&hover,&RUNNING.guard()); } Some(Do::Edit) => { hist.test_push(&text); - handle2(event.logical_key, &mut text); + let cb4 = text.cursor; + let r = handle2(&event.logical_key, &mut text); text.scroll_to_cursor(); + if hist.record(&text) { change!(); } -lsp!().map(|x|x.0.request_complete(x.1, text.cursor()));; +if let Some(r) = r { + lsp!().map(|(lsp, o)|{ + let window = window.clone(); + let ctx = match complete.consume(CompletionAction::TypeCharacter).unwrap() { + Some(CDo::Request) => { + CompletionContext { + trigger_kind: CompletionTriggerKind::TRIGGER_CHARACTER, trigger_character:Some(r.to_string()) } + + // println!("make rq"); + // let x = lsp.request_complete(o, text.cursor(), ); + // let h = lsp.runtime.spawn(async move { + // let r = x.await; + // window.request_redraw(); + // r + // }); + // complete = CompletionState::Complete(None, Some((h,cb4))); + // dbg!(&complete); + } + Some(CDo::Update) => { + // CompletionContext { + // trigger_kind: CompletionTriggerKind + CompletionContext { + trigger_kind: CompletionTriggerKind::TRIGGER_FOR_INCOMPLETE_COMPLETIONS, trigger_character:None } + // complete = CompletionState::Complete(None, Some(lsp.runtime.spawn(async move { + // let r = x.await; + // window.request_redraw(); + // r + // }))); + } + None => {return}, + _ => panic!(), + }; + println!("make rq"); + let x = lsp.request_complete(o, text.cursor(), ctx); + let h = lsp.runtime.spawn(async move { + let r = x.await; + window.request_redraw(); + r + }); + complete = CompletionState::Complete(None, Some((h,text.cursor))); + dbg!(&complete); + + }); +} } Some(Do::Undo) => { hist.test_push(&text); @@ -895,11 +1031,12 @@ lsp!().map(|x|x.0.request_complete(x.1, text.cursor()));; winit_app::run_app(event_loop, app); } -fn handle2(key: Key, text: &mut TextArea) { +fn handle2<'a>(key: &'a Key, text: &mut TextArea) -> Option<&'a str> { use Key::*; match key { Named(Space) => text.insert(" "), + Named(Backspace) if ctrl() => text.backspace_word(), Named(Backspace) => text.backspace(), Named(Home) if ctrl() => { text.cursor = 0; @@ -927,12 +1064,14 @@ fn handle2(key: Key, text: &mut TextArea) { Named(Enter) => text.enter(), Character(x) => { text.insert(&x); + return Some(x); } _ => {} }; + None } fn handle(key: Key, mut text: TextArea) -> TextArea { - handle2(key, &mut text); + handle2(&key, &mut text); text } pub static FONT: LazyLock<FontRef<'static>> = LazyLock::new(|| { @@ -1040,6 +1179,7 @@ Search((x, y, m)) => { K(_) => Default [Reinsert], } } + #[derive(Copy, Clone, Debug, PartialEq, Eq)] enum InputRequest { SaveFile, @@ -1098,3 +1238,39 @@ impl<T> M<T> for Option<T> { *self = self.take().map(f); } } + +rust_fsm::state_machine! { + #[derive(Debug)] + pub(crate) CompletionState => CompletionAction => CDo + None => Click => None, + None => TypeCharacter => Complete( + (Option<Complete>, Option<(JoinHandle< + Result< + Option<CompletionResponse>, + tokio::sync::oneshot::error::RecvError, + >, + >, usize)>) => (None,None) + ) [Request], + Complete((_x, None)) => Click => None, + Complete((_x, Some((y, _)))) => Click => None [Abort(JoinHandle< + Result< + Option<CompletionResponse>, + tokio::sync::oneshot::error::RecvError, + >, + > => y)], + Complete((_x, _y)) => TypeCharacter => _ [Update], + Complete((Some(x), task)) => Enter => None [Finish(Complete => { + if let Some((task, _)) = task { task.abort() }; x + })] +} +impl Default for CompletionState { + fn default() -> Self { + Self::None + } +} +#[derive(Debug)] struct Complete { + r: CompletionResponse, + start: usize, + selection: usize, + scroll: usize, +} diff --git a/src/text.rs b/src/text.rs index c66d779..55eaf0d 100644 --- a/src/text.rs +++ b/src/text.rs @@ -23,9 +23,9 @@ use winit::keyboard::{NamedKey, SmolStr}; use crate::text::semantic::{MCOLORS, MODIFIED, MSTYLE}; macro_rules! theme { - ($n:literal $($x:literal $color:literal $($style:expr)?),+ $(,)?) => { + ($($x:literal $color:literal $($style:expr)?),+ $(,)?) => { #[rustfmt::skip] - pub const NAMES: [&str; $n] = [$($x),+]; + pub const NAMES: [&str; [$($x),+].len()] = [$($x),+]; #[rustfmt::skip] pub const COLORS: [[u8; 3]; NAMES.len()] = car::map!([$($color),+], |x| color(x.tail())); pub const STYLES: [u8; NAMES.len()] = [$( @@ -33,7 +33,7 @@ macro_rules! theme { ),+]; }; } -theme! { 16 +theme! { "attribute" b"#ffd173", "comment" b"#5c6773" Style::ITALIC, "constant" b"#DFBFFF", @@ -65,7 +65,10 @@ mod semantic { }; } use super::color; - theme! { 19 + theme! { + "constructor" b"#FFAD66", + "field" b"#cccac2", + "comment" b"#5c6773" Style::ITALIC, // "decorator" b"#cccac2", // "enumMember" b"#cccac2", @@ -81,12 +84,13 @@ mod semantic { "string" b"#D5FF80", // "struct" b"#cccac2", // "typeParameter" b"#cccac2", + "class" b"#73b9ff", "enum" b"#73b9ff" Style::ITALIC | Style::BOLD, "builtinType" b"#73d0ff" Style::ITALIC, // "type" b"#73d0ff" Style::ITALIC | Style::BOLD, "typeAlias" b"#69caed" Style::ITALIC | Style::BOLD, "struct" b"#73d0ff" Style::ITALIC | Style::BOLD, - // "variable" b"#cccac2", + "variable" b"#cccac2", // "angle" b"#cccac2", // "arithmetic" b"#cccac2", // "attributeBracket" b"#cccac2", @@ -143,7 +147,7 @@ const fn of(x: &'static str) -> usize { panic!() } -pub const fn color(x: &[u8; 6]) -> [u8; 3] { +pub const fn color(x: [u8; 6]) -> [u8; 3] { car::map!( car::map!(x, |b| (b & 0xF) + 9 * (b >> 6)).chunked::<2>(), |[a, b]| a * 16 + b @@ -292,6 +296,12 @@ impl TextArea { pub fn cursor(&self) -> (usize, usize) { self.xy(self.cursor) } + pub fn x(&self, c: usize) -> usize { + self.xy(c).0 + } + pub fn y(&self, c: usize) -> usize { + self.xy(c).1 + } pub fn xy(&self, c: usize) -> (usize, usize) { let y = self.rope.char_to_line(c); @@ -383,7 +393,7 @@ impl TextArea { self.set_ho(); } - fn at(&self) -> char { + pub fn at(&self) -> char { self.rope.get_char(self.cursor).unwrap_or('\n') } #[implicit_fn] @@ -418,42 +428,51 @@ impl TextArea { self.set_ho(); } // from μ - #[lower::apply(saturating)] pub fn word_left(&mut self) { - self.left(); - while self.at().is_whitespace() { - if self.cursor == 0 { - return; + self.cursor = self.word_left_p(); + self.setc(); + self.set_ho(); + } + #[lower::apply(saturating)] + pub fn word_left_p(&self) -> usize { + let mut c = self.cursor - 1; + if self.x(self.cursor) == 0 { + return c; + } + macro_rules! at { + () => { + self.rope.get_char(c).unwrap_or('\n') + }; + } + while at!().is_whitespace() { + if self.x(c) == 0 { + return c; } - self.left(); + c -= 1 } - if is_word(self.at()).not() - && !self.at().is_whitespace() - && !is_word(self.rope.char(self.cursor - 1)) + if is_word(at!()).not() + && !at!().is_whitespace() + && !is_word(self.rope.char(c - 1)) { - while is_word(self.at()).not() - && self.at().is_whitespace().not() - { - if self.cursor == 0 { - return; + while is_word(at!()).not() && at!().is_whitespace().not() { + if self.x(c) == 0 { + return c; } - self.left(); + c -= 1; } - self.right(); + c += 1; } else { - self.left(); - self.right(); - while is_word(self.at()) { - if self.cursor == 0 { - return; + c -= 1; + while is_word(at!()) { + if self.x(c) == 0 { + return c; } - self.left(); + c -= 1; } + c += 1; } - self.setc(); - self.set_ho(); + c } - pub fn enter(&mut self) { use run::Run; let n = self.indentation(); @@ -512,6 +531,12 @@ impl TextArea { } self.set_ho(); } + pub fn backspace_word(&mut self) { + _ = self.rope.try_remove(self.word_left_p()..self.cursor); + self.cursor = self.word_left_p(); + self.setc(); + self.set_ho(); + } #[lower::apply(saturating)] pub fn backspace(&mut self) { _ = self.rope.try_remove(self.cursor - 1..self.cursor); @@ -1353,12 +1378,12 @@ fn txt() { dbg!(o.as_chunks::<4>().0); } -// pub trait CoerceOption<T> { -// fn coerce(self) -> impl Iterator<Item = T>; -// } -// impl<I: Iterator<Item = T>, T> CoerceOption<T> for Option<I> { -// #[allow(refining_impl_trait)] -// fn coerce(self) -> std::iter::Flatten<std::option::IntoIter<I>> { -// self.into_iter().flatten() -// } -// } +pub trait CoerceOption<T> { + fn coerce(self) -> impl Iterator<Item = T>; +} +impl<I: Iterator<Item = T>, T> CoerceOption<T> for Option<I> { + #[allow(refining_impl_trait)] + fn coerce(self) -> std::iter::Flatten<std::option::IntoIter<I>> { + self.into_iter().flatten() + } +} |