Crate hostaddr

Crate hostaddr 

Source
Expand description

hostaddr

Extended types (Domain, Host, HostAddr) for working with net in Rust.

github LoC Build codecov

docs.rs crates.io crates.io license

English | 简体中文

§Features

  • no_std and no-alloc compatible: Use the Buffer type for stack-allocated domains
  • Generic storage: Works with String, Arc<str>, Box<str>, Vec<u8>, and many more
  • IDNA/Punycode support: Automatic conversion of international domain names (requires alloc or std)
  • Type-safe parsing: Compile-time guarantees for valid domains and hosts
  • Percent-encoding: Automatic decoding of percent-encoded domains

§Installation

[dependencies]
hostaddr = "0.2"

§Cargo Features

  • std (default): Enables standard library support
  • alloc: Enables allocation support without std
  • serde: Serialize/deserialize support
  • arbitrary: Support for fuzzing with arbitrary
  • cheap-clone: Implement CheapClone for smart pointer types
  • String types: smol_str, triomphe, bytes, tinyvec, smallvec

§API Overview

This library provides three main types:

  • Domain<S>: A validated DNS domain name (e.g., example.com, 測試.中國)
  • Host<S>: Either a domain name or an IP address
  • HostAddr<S>: A host with an optional port number

§Examples

§Basic Usage

use hostaddr::HostAddr;

// Parse domain with String storage
let addr: HostAddr<String> = "example.com".parse().unwrap();
assert!(addr.is_domain());
assert_eq!(addr.to_string(), "example.com");

// Parse domain with port
let addr: HostAddr<String> = "example.com:8080".parse().unwrap();
assert_eq!(addr.port(), Some(8080));

// Parse IP address with port
let addr: HostAddr<String> = "127.0.0.1:8080".parse().unwrap();
assert!(addr.is_ip());
assert_eq!(addr.port(), Some(8080));

// Parse IPv6 address with port
let addr: HostAddr<String> = "[::1]:8080".parse().unwrap();
assert!(addr.is_ipv6());

§Using Different Storage Types

use hostaddr::HostAddr;
use std::sync::Arc;

// Using Arc<str> for shared ownership
let addr: HostAddr<Arc<str>> = "example.com:8080".parse().unwrap();

// Using Box<str> for heap allocation
let addr: HostAddr<Box<str>> = "example.com:8080".parse().unwrap();

// Using Vec<u8> for byte storage
let addr: HostAddr<Vec<u8>> = "example.com".parse().unwrap();

§Using Buffer for no_std/no-alloc

use hostaddr::{HostAddr, Buffer, Domain};

// Stack-allocated domain (no heap allocation)
let domain: Domain<Buffer> = Domain::try_from("example.com").unwrap();

// Works in no_std environments
let addr: HostAddr<Buffer> = HostAddr::try_from("example.com:443").unwrap();

§Working with Domains

use hostaddr::Domain;

// International domain names are automatically converted to punycode
let domain: Domain<String> = "測試.中國".parse().unwrap();
assert_eq!(domain.as_inner().as_str(), "xn--g6w251d.xn--fiqz9s");

// Parse ASCII-only domains without punycode conversion
let domain = Domain::try_from_ascii_str("example.com").unwrap();
assert_eq!(domain.as_ref().into_inner(), "example.com");

// Fully-qualified domain names (FQDN) are supported
let domain: Domain<String> = "example.com.".parse().unwrap();
assert_eq!(domain.as_inner().as_str(), "example.com.");

§Working with Hosts

use hostaddr::Host;
use std::net::IpAddr;

// Parse a host (domain or IP)
let host: Host<String> = "example.com".parse().unwrap();
assert!(host.is_domain());

let host: Host<String> = "127.0.0.1".parse().unwrap();
assert!(host.is_ip());

// Convert between types
let ip: IpAddr = "127.0.0.1".parse().unwrap();
let host: Host<String> = Host::from(ip);

§Manipulating HostAddr

use hostaddr::HostAddr;

// Create and modify
let mut addr: HostAddr<String> = "example.com".parse().unwrap();
addr.set_port(8080);
assert_eq!(addr.port(), Some(8080));

// Builder-style API
let addr = HostAddr::<String>::from_domain("api.example.com".parse().unwrap())
    .with_port(443);
assert_eq!(addr.to_string(), "api.example.com:443");

// Check host type
if addr.is_domain() {
    assert_eq!(addr.port(), Some(443));
}

§Percent Encoding

use hostaddr::Domain;

// Percent-encoded domains are automatically decoded
let domain: Domain<String> = "example%2Ecom".parse().unwrap();
assert_eq!(domain.as_inner().as_str(), "example.com");

// Works with international domains too
let domain: Domain<String> = "測試%2E中國".parse().unwrap();
assert_eq!(domain.as_inner().as_str(), "xn--g6w251d.xn--fiqz9s");

§Verification Functions

use hostaddr::{verify_domain, verify_ascii_domain};

// Verify any domain (including international)
assert!(verify_domain(b"example.com").is_ok());
assert!(verify_domain("測試.中國".as_bytes()).is_ok());

// Verify ASCII-only domains
assert!(verify_ascii_domain(b"example.com").is_ok());
assert!(verify_ascii_domain("測試.中國".as_bytes()).is_err());
§License

hostaddr is under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE, LICENSE-MIT for details.

Copyright (c) 2025 Al Liu.

Structs§

Buffer
An immutable buffer which contains a valid domain.
Domain
A DNS domain name, as . dot-separated labels. Non-ASCII labels are encoded in punycode per IDNA if this is the host of a special URL, or percent encoded for non-special URLs.
HostAddr
A host address, which consists of a Host and an optional port number.
ParseAsciiDomainError
The provided input could not be parsed because it is not an ASCII syntactically-valid DNS Domain.
ParseAsciiHostError
An error which can be returned when parsing an ASCII Host.
ParseDomainError
The provided input could not be parsed because it is not a syntactically-valid DNS Domain.
ParseHostError
An error which can be returned when parsing a Host.
TryUnwrapError
Error returned by the derived TryUnwrap implementation.

Enums§

Host
The host name
ParseAsciiHostAddrError
An error which can be returned when parsing a HostAddr.
ParseHostAddrError
An error which can be returned when parsing a HostAddr.

Functions§

verify_ascii_domain
Verifies that the input is a valid ASCII domain name.
verify_ascii_domain_allow_percent_encoding
Verifies that the input is a valid ASCII domain name. The input can be a percent-encoded domain name.
verify_domainalloc or std
Verifies that the input is a valid domain name.