uri

moon add tonyfettes/uri@0.1.0
Download zip
Version
0.1.0
License
Apache-2.0
Last updated
last year
Downloads
35
README

#URI Parser for MoonBit

A comprehensive URI parser implementation in MoonBit following RFC 3986.

#Features

This implementation provides full RFC 3986 compliant URI parsing with the following features:

#Core Components

  • Scheme parsing: Validates and normalizes URI schemes
  • Authority parsing: Handles userinfo, host, and port components
  • Path parsing: Supports all path types (absolute, relative, empty)
  • Query parsing: Handles query string parameters
  • Fragment parsing: Supports fragment identifiers

#Advanced Features

  • IPv6 support: Properly handles IPv6 literal addresses in brackets
  • Percent encoding/decoding: Full implementation of percent-encoding rules
  • URI normalization: Lowercases schemes and hosts, removes default ports
  • Relative URI references: Supports parsing of relative URIs
  • URI reconstruction: Convert parsed URIs back to string representation

#Data Structures

#Uri

struct Uri {
scheme : String? // URI scheme (http, https, etc.)
authority : Authority?// Authority component
path : String // Path component
query : String? // Query component
fragment : String? // Fragment component
}

#Authority

struct Authority {
userinfo : String? // User information (user:pass)
host : String // Host name or IP address
port : Int? // Port number
}

#Public API

#Core Functions

  • parse_uri(uri_str: String) -> Uri - Parse a complete URI
  • parse_uri_reference(uri_str: String) -> Uri - Parse URI or relative reference
  • Uri::to_string(self: Uri) -> String - Convert URI back to string
  • normalize_uri(uri: Uri) -> Uri - Normalize URI according to RFC 3986

#Utility Functions

  • percent_encode(s: String, valid_chars: (Char) -> Bool) -> String - Encode string with percent encoding
  • percent_decode(s: String) -> String - Decode percent-encoded string

#Usage Examples

#Basic URI Parsing

let uri = parse_uri("http://www.example.com/path?query=value#fragment")
println("Scheme: \{uri.scheme.unwrap()}") // "http"
println("Host: \{uri.authority.unwrap().host}") // "www.example.com"
println("Path: \{uri.path}") // "/path"
println("Query: \{uri.query.unwrap()}") // "query=value"
println("Fragment: \{uri.fragment.unwrap()}") // "fragment"

#URI with Authentication

let uri = parse_uri("https://user:pass@example.com:8080/secure/path")
let auth = uri.authority.unwrap()
println("Userinfo: \{auth.userinfo.unwrap()}") // "user:pass"
println("Host: \{auth.host}") // "example.com"
println("Port: \{auth.port.unwrap()}") // 8080

#IPv6 Support

let uri = parse_uri("http://[2001:db8::1]:8080/path")
let auth = uri.authority.unwrap()
println("Host: \{auth.host}") // "[2001:db8::1]"
println("Port: \{auth.port.unwrap()}") // 8080

#URI Normalization

let uri = parse_uri("HTTP://EXAMPLE.COM:80/path")
let normalized = normalize_uri(uri)
println("Normalized: \{normalized.to_string()}") // "http://example.com/path"

#Percent Encoding

let encoded = percent_encode("hello world!", is_unreserved)
println("Encoded: \{encoded}") // "hello%20world%21"

let decoded = percent_decode("hello%20world%21")
println("Decoded: \{decoded}") // "hello world!"

#Relative URI References

let relative = parse_uri_reference("/path/to/resource?query=val")
println("Scheme: None (relative reference)")
println("Path: \{relative.path}") // "/path/to/resource"
println("Query: \{relative.query.unwrap()}") // "query=val"

#RFC 3986 Compliance

This implementation follows RFC 3986 specifications including:

  • Complete URI syntax: scheme ":" hier-part [ "?" query ] [ "#" fragment ]
  • Authority parsing: [ userinfo "@" ] host [ ":" port ]
  • All character classification rules (unreserved, reserved, pchar, etc.)
  • Proper percent-encoding validation and handling
  • IPv6 literal address support
  • Case normalization for schemes and hosts
  • Default port removal during normalization

#Character Sets

The implementation includes proper validation for all RFC 3986 character sets:

  • Unreserved: ALPHA / DIGIT / "-" / "." / "_" / "~"
  • Reserved: gen-delims / sub-delims
  • Gen-delims: ":" / "/" / "?" / "#" / "[" / "]" / "@"
  • Sub-delims: "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
  • Pchar: unreserved / pct-encoded / sub-delims / ":" / "@"

#Testing

Run the comprehensive test suite:

moon run src

The test suite includes:
  • Basic URI parsing tests
  • Authority component parsing
  • IPv6 address parsing
  • Percent encoding/decoding
  • URI normalization
  • Relative reference parsing
  • Round-trip parsing and reconstruction

#Implementation Details

  • Character handling: Proper Unicode character support using MoonBit's Char type
  • Memory efficient: Uses string operations without unnecessary allocations
  • Error handling: Uses abort() for invalid input (can be extended with proper error types)
  • Modular design: Clear separation between parsing, validation, and utility functions

#License

This implementation is provided as an example of RFC 3986 compliant URI parsing in MoonBit.

#
ParseError

pub suberror ParseError {
InvalidScheme(
View
)
InvalidHeirPart(
View
)
InvalidPercentEncoding(
View
)
MissingColon
MissingScheme
InvalidSegment(
View
)
InvalidSchemeOrSegment(
View
)
Invalid(
View
)
}

#
Authority

pub struct Authority {
userinfo :
View
?
host : Host
port : Int?
}

impl Eq for Authority
impl Show for Authority

#
Host

impl Eq for Host
impl Show for Host

#
Uri

impl Eq for Uri
impl Show for Uri

#
Uri::parse

fn Uri::parse(source :
View
) -> Uri raise ParseError

Source Files

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io