#uri #wamp

nightly battler-wamprat-uri

Procedural macro for dynamically matching WAMP URIs

8 unstable releases (3 breaking)

Uses new Rust 2024

new 0.4.1 Apr 28, 2025
0.4.0 Apr 28, 2025
0.3.0 Apr 27, 2025
0.2.1 Apr 26, 2025
0.1.1 Jan 19, 2025

#423 in WebSocket

Download history 128/week @ 2025-01-13 118/week @ 2025-01-20 7/week @ 2025-01-27 24/week @ 2025-02-03 1/week @ 2025-02-10 5/week @ 2025-02-17 7/week @ 2025-02-24 10/week @ 2025-03-03 143/week @ 2025-03-17 19/week @ 2025-03-24 5/week @ 2025-03-31 2/week @ 2025-04-07 5/week @ 2025-04-14 207/week @ 2025-04-21

225 downloads per month
Used in 3 crates

MIT license

395KB
9K SLoC

battler-wamprat-uri

battler-wamprat-uri is a utility crate for battler-wamprat. It provides a procedural macro for dynamically matching URIs for WAMP subscriptions and procedure registrations.

Pattern-based subscriptions and procedure registrations can be complex. They provide an additional avenue of input for WAMP messages, outside the arguments and arguments_keyword fields expressed by battler_wamprat_message::WampApplicationMessage types.

For example, a callee can register a procedure on the wildcard URI com.test.add..v2. A caller can then call this procedure using any URI that matches this pattern. One caller may call com.test.add.integers.v2 while another may call com.test.add.strings.v2. The wildcard URI component (in this case, integers or strings) is likely very important to the callee!

This crate provides runtime type checking and pattern matching to incoming and outgoing WAMP URI patterns through the WampUriMatcher derive macro. A URI matcher can be thought of as a glorified regular expression: each wildcard component is a named capture group that can be referenced after matching. The end result is that URIs going out from a peer can be formatted automatically, and URIs coming into a peer can be pattern matched, allowing the extracted URI components to be easily read by application logic.

Basic Usage

A struct using the WampUriMatcher derive macro must have a uri attribute. The URI describes the wildcard pattern, which is used for formatting outgoing URIs and matching incoming URIs.

In the simplest case, a struct with no fields can match a static URI:

use battler_wamprat_uri::WampUriMatcher;

#[derive(WampUriMatcher)]
#[uri("com.test.add")]
struct AddUri {}

For each field you add, that field must be represented in the URI pattern. Otherwise, the struct would be impossible to construct for incoming URIs.

use battler_wamprat_uri::WampUriMatcher;

#[derive(WampUriMatcher)]
#[uri("com.test.add.{name}.v2")]
struct AddUri {
    name: String,
}

Each struct field must be convertible to and from a string, using Display and FromStr respectively.

use battler_wamprat_uri::WampUriMatcher;

#[derive(WampUriMatcher)]
#[uri("com.test.add.{name}.{count}")]
struct AddUri {
    name: String,
    count: u64,
}

Advanced Features

Prefix Matching

In some cases, a URI pattern may need to match in prefix form. Prefix matching is only possible if the last field in the struct is marked with the rest attribute. This attribute requires that an iterator of Strings can be collected into its type.

use battler_wamprat_uri::WampUriMatcher;

#[derive(WampUriMatcher)]
#[uri("com.test.fn.{a}.{rest}")]
struct PrefixUri {
    a: String,
    #[rest]
    rest: Vec<String>,
}

Field Repetition

Fields can be repeated in the URI pattern. The first use of the field will be treated as the source of truth, and all later uses of the field must match this first value.

use battler_wamprat_uri::WampUriMatcher;

#[derive(WampUriMatcher)]
#[uri("com.test.fn.{a}.{b}.{a}")]
struct RepeatedUri {
    a: u64,
    b: u64,
}

Regular Expression Component Matching

In most cases, struct fields should be isolated to their own URI components for simplicity. However, this is not a strict requirement of the URI matcher macro.

Strings and struct fields can be combined into the same URI component. If this is done, the URI pattern matching is less enforceable on the router, but the peer will still validate and match the URI as expected.

use battler_wamprat_uri::WampUriMatcher;

#[derive(WampUriMatcher)]
#[uri("com.test.math.{a}log{b}")]
struct RegExUri {
    a: u64,
    b: u64,
}

Note that in the above case, the URI registered on the router will be the wildcard com.test.math., so the last component can be matched by any string. However, the RegExUri type will enforce the additional restrictions. For instance, the URI com.test.math.abc will be rejected by the peer, while com.test.math.2log12 will be accepted.

Note: URI such as the one above will generate a dependency on the regex crate.

Generators

It can sometimes be useful to generate partial-wildcard URIs based on a URI pattern. For example, one peer may be publishing messages to com.chat.{version}.{channel}.{author}, and another peer may want to subscribe to messages for a specific channel using the com.chat.1.main.{author}. Rather than requiring the subscriber to generate this wildcard URI manually, it can use a derived generator struct from base URI pattern.

A generator struct implements the WampWildcardUriGenerator trait and can be generated automatically with the generator macro attribute. You can generate multiple generators for a single matcher.

use std::marker::PhantomData;

use battler_wamprat_uri::{
    WampUriMatcher,
    Wildcard,
    WampWildcardUriGenerator,
};

#[derive(Clone, WampUriMatcher)]
#[uri("com.chat.{version}.{channel}.{author}")]
#[generator(ChannelMessageUri, fixed(version = 1u64), require(channel), derive(Clone))]
struct MessageUri {
    version: u64,
    channel: String,
    author: String,
}

fn main() {
    assert_matches::assert_matches!(ChannelMessageUri {
        version: PhantomData,
        channel: "main".to_owned(),
        author: Wildcard::Wildcard,
    }.wamp_generate_wildcard_uri(), Ok(uri) => {
        assert_eq!(uri.as_ref(), "com.chat.1.main.");
    });
}

You can also create generators for patterns with unnamed fields, but indices must be prefixed with an underscore (e.g., _0, _1) in the generator attribute.

Note: Generators are limited to simple wildcard URI patterns only. URI patterns with prefix matching and/or regular expression matching cannot use generators.


battler-wamprat-uri

Latest Version

battler-wamprat-uri is a utility crate for battler-wamprat. It provides a procedural macro for dynamically matching URIs for WAMP subscriptions and procedure registrations.

Dependencies

~19–30MB
~552K SLoC