3 unstable releases
Uses new Rust 2024
| 0.2.1 | Dec 14, 2025 |
|---|---|
| 0.2.0 | Dec 14, 2025 |
| 0.1.0 | Sep 7, 2025 |
#1703 in GUI
Used in 3 crates
(via waterui-media)
100KB
2K
SLoC
waterui-url
Fast, zero-allocation URL parsing for WaterUI with compile-time validation and reactive fetching.
Overview
waterui-url provides a unified Url type that handles web URLs, local file paths, data URLs, and blob URLs with a consistent API. The library is designed for performance and safety, offering compile-time URL creation with validation, zero-allocation parsing using byte offsets, and seamless integration with WaterUI's reactive primitives.
Key features:
- Compile-time URL creation: Create and validate URLs at compile time using
const fn - Zero-allocation parsing: Parses URLs once, stores byte offsets to components, no intermediate allocations
- Unified API: Single
Urltype for web URLs, local paths, data URLs, and blob URLs - O(1) component access: Scheme, host, port, path, query, and fragment are extracted during parsing
- no_std compatible: Works without the standard library (with optional
stdfeature forPathsupport) - Reactive integration: Built-in support for reactive URL fetching via
namisignals
Installation
Add this to your Cargo.toml:
[dependencies]
waterui-url = "0.1.0"
For file path support (requires std):
[dependencies]
waterui-url = { version = "0.1.0", features = ["std"] }
Quick Start
use waterui_url::Url;
// Compile-time URL creation with validation
const API_ENDPOINT: Url = Url::new("https://api.example.com/v1/users");
const LOCAL_ASSET: Url = Url::new("/assets/logo.png");
fn main() {
// Runtime parsing
let url: Url = "https://example.com/api?key=value".parse().unwrap();
println!("Host: {:?}", url.host()); // Some("example.com")
println!("Path: {}", url.path()); // "/api"
println!("Query: {:?}", url.query()); // Some("key=value")
}
Core Concepts
Url Type
The Url struct is a unified type that automatically detects and parses different URL kinds:
- Web URLs:
http://,https://,ftp://,ws://,wss://, etc. - Local file paths: Absolute (
/home/user/file.txt) or relative (./images/photo.jpg) - Data URLs:
data:text/plain;base64,SGVsbG8= - Blob URLs:
blob:https://example.com/uuid
The parser runs once during construction and stores component offsets as u16 byte ranges, making subsequent access to URL parts O(1) with no additional parsing.
Compile-Time Validation
URLs created with Url::new() in const contexts are validated at compile time. Malformed URLs cause compilation errors:
// This compiles fine
const VALID: Url = Url::new("https://example.com");
// This fails at compile time: "Web URL must have a host"
const INVALID: Url = Url::new("https://");
Reactive Fetching
The fetch() method returns a reactive signal that can be watched for changes, integrating with WaterUI's reactive update system:
use waterui_url::Url;
let url = Url::parse("https://api.example.com/data.json").unwrap();
let fetched = url.fetch();
// Use with WaterUI's reactive primitives
Examples
Parsing Web URLs
use waterui_url::Url;
let url = Url::parse("https://user:pass@example.com:8080/api/v1?id=123#section").unwrap();
assert_eq!(url.scheme(), Some("https"));
assert_eq!(url.host(), Some("example.com"));
assert_eq!(url.port(), Some(8080));
assert_eq!(url.path(), "/api/v1");
assert_eq!(url.query(), Some("id=123"));
assert_eq!(url.fragment(), Some("section"));
assert_eq!(url.authority(), Some("user:pass@example.com:8080"));
Working with Local Paths
use waterui_url::Url;
let absolute = Url::new("/home/user/documents/file.pdf");
assert!(absolute.is_local());
assert!(absolute.is_absolute());
assert_eq!(absolute.extension(), Some("pdf"));
assert_eq!(absolute.filename(), Some("file.pdf"));
let relative = Url::new("./images/photo.jpg");
assert!(relative.is_relative());
assert_eq!(relative.extension(), Some("jpg"));
Creating Data URLs
use waterui_url::Url;
let data_url = Url::from_data("image/png", b"PNG binary data here...");
assert!(data_url.is_data());
assert_eq!(data_url.scheme(), Some("data"));
// URL is automatically base64-encoded
println!("{}", data_url); // data:image/png;base64,UE5HIGJpbmFyeSBkYXRhIGhlcmUuLi4=
Joining URLs
use waterui_url::Url;
let base = Url::new("https://cdn.example.com/assets/");
let joined = base.join("images/logo.png");
assert_eq!(joined.as_str(), "https://cdn.example.com/assets/images/logo.png");
// Handles file paths too
let base_file = Url::new("https://example.com/path/file.html");
let joined_file = base_file.join("other.html");
assert_eq!(joined_file.as_str(), "https://example.com/path/other.html");
API Overview
Construction
Url::new(url: &'static str) -> Url- Create URL at compile time (const fn)Url::parse(url: impl AsRef<str>) -> Option<Url>- Parse web URL at runtimeUrl::from_file_path(path: impl AsRef<Path>) -> Url- Create from file path (requiresstdfeature)Url::from_file_path_str(path: impl Into<Str>) -> Url- Create from path stringUrl::from_data(mime_type: &str, data: &[u8]) -> Url- Create base64-encoded data URLFromStrtrait - Parse any URL type from string
Type Checking
is_web() -> bool- Check if URL is a web URL (http/https/ftp/ws/wss)is_local() -> bool- Check if URL is a local file pathis_data() -> bool- Check if URL is a data URLis_blob() -> bool- Check if URL is a blob URLis_absolute() -> bool- Check if URL or path is absoluteis_relative() -> bool- Check if URL or path is relative
Component Access
All component accessors are O(1) operations using pre-parsed byte offsets:
scheme() -> Option<&str>- URL scheme (e.g., "https", "file", "data")host() -> Option<&str>- Host portion for web URLsport() -> Option<u16>- Port number for web URLs (parsed as integer)path() -> &str- Path componentquery() -> Option<&str>- Query string without '?'fragment() -> Option<&str>- Fragment without '#'authority() -> Option<&str>- Full authority section (user:pass@host:port)extension() -> Option<&str>- File extension if presentfilename() -> Option<&str>- Filename from path
Manipulation
join(&self, path: &str) -> Url- Join URL with relative pathfetch(&self) -> Fetched- Get reactive signal for URL contentto_file_path(&self) -> Option<PathBuf>- Convert to file path (requiresstdfeature)
Conversion
as_str(&self) -> &str- Get URL as string sliceinto_string(self) -> String- Convert to owned Stringinner(&self) -> Str- Get the underlyingStrvalueAsRef<str>- Automatic conversion to&strDisplay- Format URL as string
Features
The crate supports the following Cargo features:
std(optional): Enablesstd::path::Pathintegration forfrom_file_path()andto_file_path()methods. Without this feature, the crate isno_stdcompatible.
Implementation Details
Zero-Allocation Architecture
The Url type stores the original URL string once and references its components using Span structs containing u16 start/end offsets. This design:
- Parses the URL exactly once during construction
- Stores component offsets, not copies of component strings
- Returns string slices that reference the original URL
- Uses only 2 bytes per component (start + end offset)
- Supports URLs up to 65,535 bytes (reasonable for most use cases)
Const-Compatible Parser
The entire parsing implementation uses const-compatible operations (byte-level comparisons, loops with manual indexing) to enable compile-time URL creation and validation. The parser:
- Validates web URL structure (requires scheme and host)
- Checks port numbers are valid (digits only, max 5 digits)
- Handles IPv6 addresses in brackets
[::1] - Parses data URLs with MIME types and base64 encoding
- Detects Windows vs Unix path conventions
Error Handling
The parse() function returns Result<Url, ParseError> for runtime parsing. The new() const fn panics on invalid URLs, enabling compile-time validation in const contexts.
Platform Support
This crate is no_std compatible by default. Enable the std feature for:
Path/PathBufintegration viafrom_file_path()andto_file_path()std::error::Errortrait implementation forParseError
Windows, macOS, and Linux are all supported. The parser correctly handles platform-specific path conventions (backslashes, drive letters on Windows).