1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
extern crate proc_macro; use proc_macro::TokenStream; mod switch; /// Implements the `Switch` trait based on attributes present on the struct or enum variants. /// /// If deriving an enum, each variant should have a `#[to = ""]` attribute, /// and if deriving a struct, the struct itself should have a `#[to = ""]` attribute. /// /// Inside the `""` you should put your **route matcher string**. /// At its simplest, the route matcher string will create your variant/struct if it exactly matches the browser's route. /// If the route in the url bar is `http://yoursite.com/some/route` and your route matcher string /// for an enum variant is `/some/route`, then that variant will be created when `switch()` is called with the route. /// /// But the route matcher has other capabilities. /// If you want to capture data from the route matcher string, for example, extract an id or user name from the route, /// you can use `{field_name}` to capture data from the route. /// For example, `#[to = "/route/{id}"]` will capture the content after "/route/", /// and if the associated variant is defined as `Route{id: usize}`, then the string that was captured will be /// transformed into a `usize`. /// If the conversion fails, then the match won't succeed and the next variant will be tried instead. /// /// There are also `{*:field_name}` and `{3:field_name}` types of capture sections that will capture /// _everything_, and the next 3 path sections respectively. /// `{1:field_name}` is the same as `{field_name}`. /// /// Tuple-structs and Tuple-enum-variants are also supported. /// If you don't want to specify keys that don't correspond to any specific field, /// `{}`, `{*}`, and `{4}` also denote valid capture sections when used on structs and variants without named fields. /// In datastructures without field names, the captures will be assigned in order - left to right. /// /// # Note /// It should be mentioned that the derived function for matching will try enum variants in order, /// from top to bottom, and that the whole route doesn't need to be matched by the route /// matcher string in order for the match to succeed. /// What is meant by this is that `[to = "/"]` will match "/", but also "/anything/else", /// because as soon as the "/" is satisfied, that is considered a match. /// /// This can be mitigated by specifying a `!` at the end of your route to inform the matcher that if /// any characters are left after matching the route matcher string, the match should fail. /// This means that `[to = "/!"]` will match "/" and _only_ "/". /// /// ----- /// There are other attributes as well. /// `#[rest]`, `#[rest="field_name"]` and `#[end]` attributes exist as well. /// `#[rest]` and `#[rest="field_name"]` are equivalent to `{*}` and `{*:field_name}` respectively. /// `#[end]` is equivalent to `!`. /// The `#[rest]` attributes are good if you just want to delegate the whole matching of a variant to a specific /// wrapped struct or enum that also implements `Switch`. /// /// ------ /// # Example /// ``` /// use yew_router_min::Switch; /// /// #[derive(Switch, Clone)] /// enum AppRoute { /// #[to = "/some/simple/route"] /// SomeSimpleRoute, /// #[to = "/capture/{}"] /// Capture(String), /// #[to = "/named/capture/{name}"] /// NamedCapture { name: String }, /// #[to = "/convert/{id}"] /// Convert { id: usize }, /// #[rest] // shorthand for #[to="{*}"] /// Inner(InnerRoute), /// } /// /// #[derive(Switch, Clone)] /// #[to = "/inner/route/{first}/{second}"] /// struct InnerRoute { /// first: String, /// second: String, /// } /// ``` /// Check out the examples directory in the repository to see some more usages of the routing syntax. #[proc_macro_derive(Switch, attributes(to, rest, end))] pub fn switch(tokens: TokenStream) -> TokenStream { crate::switch::switch_impl(tokens) } #[proc_macro_attribute] pub fn to(_: TokenStream, _: TokenStream) -> TokenStream { TokenStream::new() } #[proc_macro_attribute] pub fn rest(_: TokenStream, _: TokenStream) -> TokenStream { TokenStream::new() } #[proc_macro_attribute] pub fn end(_: TokenStream, _: TokenStream) -> TokenStream { TokenStream::new() }