{"id":21815345,"url":"https://github.com/yescallop/fluent-uri-rs","last_synced_at":"2025-05-16T06:04:32.971Z","repository":{"id":44873387,"uuid":"420412399","full_name":"yescallop/fluent-uri-rs","owner":"yescallop","description":"A generic URI/IRI handling library compliant with RFC 3986/3987.","archived":false,"fork":false,"pushed_at":"2025-02-24T10:04:13.000Z","size":565,"stargazers_count":90,"open_issues_count":9,"forks_count":7,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-16T06:04:11.966Z","etag":null,"topics":["builder","iri","parser","rfc3986","rfc3987","rust","uri"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yescallop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-10-23T12:55:32.000Z","updated_at":"2025-05-06T12:24:29.000Z","dependencies_parsed_at":"2024-01-18T17:00:57.880Z","dependency_job_id":"5e15c2a4-c339-42bb-9cc0-5ed2843585f0","html_url":"https://github.com/yescallop/fluent-uri-rs","commit_stats":{"total_commits":121,"total_committers":2,"mean_commits":60.5,"dds":0.06611570247933884,"last_synced_commit":"2bbcc73a085c11a4a3fbaa7194dbd06575fe7cc7"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yescallop%2Ffluent-uri-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yescallop%2Ffluent-uri-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yescallop%2Ffluent-uri-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yescallop%2Ffluent-uri-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yescallop","download_url":"https://codeload.github.com/yescallop/fluent-uri-rs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254478186,"owners_count":22077675,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["builder","iri","parser","rfc3986","rfc3987","rust","uri"],"created_at":"2024-11-27T15:17:59.738Z","updated_at":"2025-05-16T06:04:32.912Z","avatar_url":"https://github.com/yescallop.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fluent-uri\n\nA generic URI/IRI handling library compliant with [RFC 3986] and [RFC 3987]. It is:\n\n- **Fast:** Zero-copy parsing. Benchmarked to be highly performant.[^bench-res]\n- **Easy:** Carefully designed and documented APIs. Handy percent-encoding utilities.\n- **Correct:** Forbids unsafe code. Extensively fuzz-tested against other implementations.\n\n[![crates.io](https://img.shields.io/crates/v/fluent-uri.svg)](https://crates.io/crates/fluent-uri)\n[![build](https://img.shields.io/github/actions/workflow/status/yescallop/fluent-uri-rs/ci.yml\n)](https://github.com/yescallop/fluent-uri-rs/actions/workflows/ci.yml)\n[![license](https://img.shields.io/crates/l/fluent-uri.svg)](/LICENSE)\n\n[Documentation](https://docs.rs/fluent-uri) | [Discussions](https://github.com/yescallop/fluent-uri-rs/discussions)\n\n[RFC 3986]: https://datatracker.ietf.org/doc/html/rfc3986\n[RFC 3987]: https://datatracker.ietf.org/doc/html/rfc3987\n[^bench-res]: In [a benchmark](https://github.com/yescallop/fluent-uri-rs/blob/main/bench/benches/bench.rs)\n    on an Intel Core i5-11300H processor, `fluent-uri` parsed a 61-byte IRI\n    in ~85ns compared to ~125ns for `iref`, `iri-string`, and `oxiri`.\n\n## Terminology\n\nA *[URI reference]* is either a *[URI]* or a *[relative reference]*. If it starts with a *[scheme]*\n(like `http`, `ftp`, `mailto`, etc.) followed by a colon (`:`), it is a URI. For example,\n`http://example.com/` and `mailto:user@example.com` are URIs. Otherwise, it is\na relative reference. For example, `//example.org/`, `/index.html`, `../`, `foo`,\n`?bar`, and `#baz` are relative references.\n\nAn *[IRI]* (reference) is an internationalized version of URI (reference)\nwhich may contain non-ASCII characters.\n\n[URI reference]: https://datatracker.ietf.org/doc/html/rfc3986#section-4.1\n[URI]: https://datatracker.ietf.org/doc/html/rfc3986#section-3\n[IRI]: https://datatracker.ietf.org/doc/html/rfc3987#section-2\n[relative reference]: https://datatracker.ietf.org/doc/html/rfc3986#section-4.2\n[scheme]: https://datatracker.ietf.org/doc/html/rfc3986#section-3.1\n\n## Examples\n\n- Parse and extract components from a URI:\n\n    ```rust\n    const SCHEME_FOO: \u0026Scheme = Scheme::new_or_panic(\"foo\");\n\n    let s = \"foo://user@example.com:8042/over/there?name=ferret#nose\";\n    let uri = Uri::parse(s)?;\n\n    assert_eq!(uri.scheme(), SCHEME_FOO);\n\n    let auth = uri.authority().unwrap();\n    assert_eq!(auth.as_str(), \"user@example.com:8042\");\n    assert_eq!(auth.userinfo().unwrap(), \"user\");\n    assert_eq!(auth.host(), \"example.com\");\n    assert!(matches!(auth.host_parsed(), Host::RegName(name) if name == \"example.com\"));\n    assert_eq!(auth.port().unwrap(), \"8042\");\n    assert_eq!(auth.port_to_u16(), Ok(Some(8042)));\n\n    assert_eq!(uri.path(), \"/over/there\");\n    assert_eq!(uri.query().unwrap(), \"name=ferret\");\n    assert_eq!(uri.fragment().unwrap(), \"nose\");\n    ```\n\n- Build a URI using the builder pattern:\n\n    ```rust\n    const SCHEME_FOO: \u0026Scheme = Scheme::new_or_panic(\"foo\");\n\n    let uri = Uri::builder()\n        .scheme(SCHEME_FOO)\n        .authority_with(|b| {\n            b.userinfo(EStr::new_or_panic(\"user\"))\n                .host(EStr::new_or_panic(\"example.com\"))\n                .port(8042)\n        })\n        .path(EStr::new_or_panic(\"/over/there\"))\n        .query(EStr::new_or_panic(\"name=ferret\"))\n        .fragment(EStr::new_or_panic(\"nose\"))\n        .build()\n        .unwrap();\n\n    assert_eq!(\n        uri.as_str(),\n        \"foo://user@example.com:8042/over/there?name=ferret#nose\"\n    );\n    ```\n\n- Resolve a URI reference against a base URI:\n\n    ```rust\n    let base = Uri::parse(\"http://example.com/foo/bar\")?;\n\n    let uri_ref = UriRef::parse(\"baz\")?;\n    assert_eq!(uri_ref.resolve_against(\u0026base).unwrap(), \"http://example.com/foo/baz\");\n\n    let uri_ref = UriRef::parse(\"../baz\")?;\n    assert_eq!(uri_ref.resolve_against(\u0026base).unwrap(), \"http://example.com/baz\");\n\n    let uri_ref = UriRef::parse(\"?baz\")?;\n    assert_eq!(uri_ref.resolve_against(\u0026base).unwrap(), \"http://example.com/foo/bar?baz\");\n    ```\n\n- Normalize a URI:\n\n    ```rust\n    let uri = Uri::parse(\"eXAMPLE://a/./b/../b/%63/%7bfoo%7d\")?;\n    assert_eq!(uri.normalize(), \"example://a/b/c/%7Bfoo%7D\");\n    ```\n\n- `EStr` (Percent-encoded string slices):\n\n    All components in a URI that may be percent-encoded are parsed as `EStr`s,\n    which allows easy splitting and decoding:\n\n    ```rust\n    let s = \"?name=%E5%BC%A0%E4%B8%89\u0026speech=%C2%A1Ol%C3%A9%21\";\n    let query = UriRef::parse(s).unwrap().query().unwrap();\n    let map: HashMap\u003c_, _\u003e = query\n        .split('\u0026')\n        .map(|s| s.split_once('=').unwrap_or((s, EStr::EMPTY)))\n        .map(|(k, v)| (k.decode().into_string_lossy(), v.decode().into_string_lossy()))\n        .collect();\n    assert_eq!(map[\"name\"], \"张三\");\n    assert_eq!(map[\"speech\"], \"¡Olé!\");\n    ```\n\n- `EString` (A percent-encoded, growable string):\n\n    You can encode key-value pairs to a query string and use it to build a URI reference:\n\n    ```rust\n    let pairs = [(\"name\", \"张三\"), (\"speech\", \"¡Olé!\")];\n    let mut buf = EString::\u003cQuery\u003e::new();\n    for (k, v) in pairs {\n        if !buf.is_empty() {\n            buf.push_byte(b'\u0026');\n        }\n        buf.encode::\u003cData\u003e(k);\n        buf.push_byte(b'=');\n        buf.encode::\u003cData\u003e(v);\n    }\n\n    assert_eq!(buf, \"name=%E5%BC%A0%E4%B8%89\u0026speech=%C2%A1Ol%C3%A9%21\");\n\n    let uri_ref = UriRef::builder()\n        .path(EStr::EMPTY)\n        .query(\u0026buf)\n        .build()\n        .unwrap();\n    assert_eq!(uri_ref.as_str(), \"?name=%E5%BC%A0%E4%B8%89\u0026speech=%C2%A1Ol%C3%A9%21\");\n    ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyescallop%2Ffluent-uri-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyescallop%2Ffluent-uri-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyescallop%2Ffluent-uri-rs/lists"}