Skip to main content

Crate hostaddr

Crate hostaddr 

Source
Expand description

hostaddr

Type-safe, validated DNS domain names, hosts, and host addresses for Rust.

github LoC Build codecov

docs.rs crates.io crates.io license

English | 简体中文

§Overview

hostaddr provides type-safe, validated types for working with network host identifiers:

  • Domain<S> – A validated DNS domain name, with IDNA/punycode and percent-encoding support
  • Host<S> – Either a domain name or an IP address (v4/v6)
  • HostAddr<S> – A host with an optional port number (e.g. example.com:8080, [::1]:443)

All types are generic over their storage backend S, allowing you to choose the representation that best fits your use case – from zero-alloc stack buffers (Buffer) to shared smart pointers (Arc<str>).

§Features

  • no_std and no-alloc compatible: Use the Buffer type for stack-allocated domains without any heap allocation
  • Generic storage: Works with String, Arc<str>, Box<str>, Vec<u8>, SmolStr, Bytes, and more
  • IDNA/Punycode support: Automatic conversion of international domain names (e.g. 测试.中国 to punycode)
  • Type-safe validation: Domain names are validated at construction time per RFC 1035 rules
  • Percent-encoding: Transparent decoding of percent-encoded domains
  • IPv4/IPv6: Full support for IP addresses, including proper [::1]:port bracket syntax
  • Serde: Optional serialization/deserialization support
  • Fuzzing: Built-in arbitrary and quickcheck generators for property-based testing

§Installation

[dependencies]
hostaddr = "0.2"

§Feature Flags

FeatureDescription
std (default)Standard library support, enables IDNA and percent-decoding
allocAllocation support without std
serdeSerialize/deserialize support
arbitraryFuzzing with arbitrary crate
cheap-cloneCheapClone trait for smart pointer types
smol_strSmolStr storage support
bytesBytes storage support
triomphetriomphe::Arc storage support
tinyvecTinyVec storage support
smallvecSmallVec storage support

§Quick Start

use hostaddr::HostAddr;

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

// IPv4 with port
let addr: HostAddr<String> = "127.0.0.1:3000".parse().unwrap();
assert!(addr.is_ipv4());

// IPv6 with port (bracket syntax)
let addr: HostAddr<String> = "[::1]:443".parse().unwrap();
assert!(addr.is_ipv6());
assert_eq!(addr.to_string(), "[::1]:443");

// International domain names (auto punycode)
let addr: HostAddr<String> = "测试.中国:80".parse().unwrap();

§Examples

§Working with Domains

use hostaddr::Domain;

// Validated at construction -- invalid names are rejected
assert!(Domain::<String>::try_from("example.com").is_ok());
assert!(Domain::<String>::try_from("-invalid.com").is_err());

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

// FQDN support
let domain: Domain<String> = "example.com.".parse().unwrap();
assert!(domain.is_fqdn());

// ASCII-only fast path (no punycode or percent-decoding)
let domain = Domain::try_from_ascii_str("example.com").unwrap();

§Choosing a Storage Type

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

// Heap-allocated String
let addr: HostAddr<String> = "example.com:8080".parse().unwrap();

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

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

§Stack-Allocated Domains (no_std / no-alloc)

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

// No heap allocation -- 255-byte stack buffer
let domain: Domain<Buffer> = Domain::try_from("example.com").unwrap();
let addr: HostAddr<Buffer> = HostAddr::try_from("example.com:443").unwrap();

§Manipulating Addresses

use hostaddr::HostAddr;

let mut addr: HostAddr<String> = "example.com".parse().unwrap();
addr.set_port(8080);
assert_eq!(addr.to_string(), "example.com:8080");

// Builder-style with default port
let addr = "example.com".parse::<HostAddr<String>>().unwrap()
    .with_default_port(443);
assert_eq!(addr.port(), Some(443));

§Verification Functions

use hostaddr::{verify_domain, verify_ascii_domain};

assert!(verify_domain(b"example.com").is_ok());
assert!(verify_domain("测试.中国".as_bytes()).is_ok());

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.