pub struct Path<'a>(/* private fields */);Expand description
A broadcast path that provides safe prefix matching operations.
This type wraps a string but provides path-aware operations that respect delimiter boundaries, preventing issues like “foo” matching “foobar”.
Paths are automatically trimmed of leading and trailing slashes on creation,
making all slashes implicit at boundaries. A path names a point in the origin’s
tree from its root; a leading slash never escapes that root. The same type names
an exact broadcast and the prefix a route or announcement covers, so a broadcast’s
own path is the prefix it announces. See Relative for ..-style references.
Owned paths (PathOwned) share one reference-counted allocation: cloning, converting
a shared path with Path::to_owned, and suffix operations like Path::strip_prefix
do not copy the underlying bytes.
§Examples
use moq_net::{Path};
// Creation automatically trims slashes
let path1 = Path::new("/foo/bar/");
let path2 = Path::new("foo/bar");
assert_eq!(path1, path2);
// Methods accept both &str and Path
let base = Path::new("api/v1");
assert!(base.has_prefix("api"));
assert!(base.has_prefix(&Path::new("api/v1")));
let joined = base.join("users");
assert_eq!(joined.as_str(), "api/v1/users");Implementations§
Source§impl<'a> Path<'a>
impl<'a> Path<'a>
Sourcepub const MAX_PARTS: usize = 32
pub const MAX_PARTS: usize = 32
Maximum number of slash-separated parts in a path.
Matches the IETF moq-transport limit of 32 fields in a namespace tuple. moq-lite enforces the same bound: encoding or decoding a deeper path fails, and publishing one to an origin is rejected.
Sourcepub fn new(s: &'a str) -> Self
pub fn new(s: &'a str) -> Self
Create a new Path from a string slice.
Leading and trailing slashes are automatically trimmed. Multiple consecutive internal slashes are collapsed to single slashes.
Sourcepub fn has_prefix(&self, prefix: impl AsPath) -> bool
pub fn has_prefix(&self, prefix: impl AsPath) -> bool
Check if this path has the given prefix, respecting path boundaries.
Unlike String::starts_with, this ensures that “foo” does not match “foobar”. The prefix must either:
- Be exactly equal to this path
- Be followed by a ‘/’ delimiter in the original path
- Be empty (matches everything)
§Examples
use moq_net::Path;
let path = Path::new("foo/bar");
assert!(path.has_prefix("foo"));
assert!(path.has_prefix(&Path::new("foo")));
assert!(path.has_prefix("foo/"));
assert!(!path.has_prefix("fo"));
let path = Path::new("foobar");
assert!(!path.has_prefix("foo"));Sourcepub fn strip_prefix(&'a self, prefix: impl AsPath) -> Option<Path<'a>>
pub fn strip_prefix(&'a self, prefix: impl AsPath) -> Option<Path<'a>>
The remainder after removing prefix, or None if it isn’t a prefix.
Only whole segments match: a/bc is not prefixed by a/b. An empty prefix
returns the whole path.
Sourcepub fn parts(&self) -> impl Iterator<Item = &str>
pub fn parts(&self) -> impl Iterator<Item = &str>
Iterate over the slash-separated parts of the path.
The empty path has no parts.
§Examples
use moq_net::Path;
let path = Path::new("foo/bar/baz");
assert_eq!(path.parts().collect::<Vec<_>>(), ["foo", "bar", "baz"]);
assert_eq!(Path::empty().parts().count(), 0);Sourcepub fn next_part(&'a self) -> Option<(&'a str, Path<'a>)>
pub fn next_part(&'a self) -> Option<(&'a str, Path<'a>)>
Strip the directory component of the path, if any, and return the rest of the path.
Sourcepub fn as_str(&self) -> &str
pub fn as_str(&self) -> &str
The normalized path as a string, with no leading or trailing slash.
Sourcepub fn to_owned(&self) -> PathOwned
pub fn to_owned(&self) -> PathOwned
Clone into a 'static path, sharing the existing buffer when there is one.
Sourcepub fn into_owned(self) -> PathOwned
pub fn into_owned(self) -> PathOwned
Consume into a 'static path, reusing the existing buffer when there is one.
Sourcepub fn borrow(&'a self) -> Path<'a>
pub fn borrow(&'a self) -> Path<'a>
A copy of this path bound to self’s lifetime, without copying the underlying bytes.
Sourcepub fn join(&self, other: impl AsPath) -> PathOwned
pub fn join(&self, other: impl AsPath) -> PathOwned
Join this path with another path component.
§Examples
use moq_net::Path;
let base = Path::new("foo");
let joined = base.join("bar");
assert_eq!(joined.as_str(), "foo/bar");
let joined = base.join(&Path::new("bar"));
assert_eq!(joined.as_str(), "foo/bar");Sourcepub fn resolve(&self, rel: &Relative<'_>) -> PathOwned
pub fn resolve(&self, rel: &Relative<'_>) -> PathOwned
Resolve a Relative against this path.
A non-empty reference replaces the last segment of the base, matching relative URL
resolution. .. segments then pop another segment; other segments are appended.
Excess .. is a no-op once the base is empty (subsequent named segments still append).
An empty rel returns this path as an owned copy.
Relative::new strips empty and redundant . segments, but preserves a lone .
so it can reference the base’s parent.
§Examples
use moq_net::{Path, path::Relative};
let base = Path::new("a/b/c");
assert_eq!(base.resolve(&Relative::new("./d")).as_str(), "a/b/d");
assert_eq!(base.resolve(&Relative::new(".")).as_str(), "a/b");
assert_eq!(base.resolve(&Relative::new("../d")).as_str(), "a/d");Sourcepub fn try_resolve(&self, rel: &Relative<'_>) -> Option<PathOwned>
pub fn try_resolve(&self, rel: &Relative<'_>) -> Option<PathOwned>
Resolve a Relative, returning None if it escapes above the root.
Unlike Path::resolve, this distinguishes a valid reference to the empty root
path from excess .. segments. Use it when an untrusted relative reference must
not be clamped to the root.
Sourcepub fn relative(&self, base: impl AsPath) -> Option<RelativeOwned>
pub fn relative(&self, base: impl AsPath) -> Option<RelativeOwned>
Express this path relative to base: the inverse of Path::resolve.
The result round-trips (base.resolve(&rel) == self) and never walks above the
root, so Path::try_resolve accepts it too.
A relative reference replaces the last segment of the base, matching relative URL resolution, so a target nested under the base repeats the base’s own last segment.
The empty reference names the base itself, so that is what a self-reference returns.
Returns None for a target no reference can name: a path segment may literally be
. or .., which resolution reads as navigation instead of as a name. Only the
segments past the shared prefix matter, since the rest are never emitted.
§Examples
use moq_net::Path;
// The base names a broadcast, so its last segment is replaced, not descended into.
let base = Path::new("a/b");
assert_eq!(Path::new("a/b/c").relative(&base).unwrap().as_str(), "b/c");
assert_eq!(Path::new("a/c").relative(&base).unwrap().as_str(), "c");
assert_eq!(Path::new("c").relative(&base).unwrap().as_str(), "../c");
// The lone `.` names the base's parent, which the empty reference cannot.
assert_eq!(Path::new("a").relative(&base).unwrap().as_str(), ".");
// The base itself.
assert_eq!(Path::new("a/b").relative(&base).unwrap().as_str(), "");
// A segment named `..` is a legal path component but an unnameable target.
assert!(Path::new("a/..").relative(&base).is_none());