CIDR provides value-semantic Swift types for classless Internet Protocol
addressing and related routing identifiers: addresses, prefix lengths, networks,
exact address ranges and coverage sets, endpoints, and Autonomous System numbers
that need stable modeling across routing, addressing, policy, validation,
configuration, server, and POSIX boundaries.
Although an Autonomous System number is not a CIDR prefix, it is a foundational
Internet routing identifier. Inter-domain routing operates between autonomous
systems, and AS numbers are used alongside IP prefixes throughout BGP, RPKI ROAs,
RPSL, IRR queries, route-origin validation, and routing policy—not BGP alone.
swift-cidr therefore owns the protocol-neutral numeric AutonomousSystemNumber
value, while higher-level packages own contextual syntax and behavior. For
example, swift-rpsl owns AS-prefixed forms, AS expressions, sets, references,
and policy semantics.
Progressive disclosure. Many apps only need IPv4Address / IPv6Address.
Infrastructure work adds PrefixLength, IPNetwork, blocks, selectors, ASN, and
mixed-family types. You do not need the full surface on day one—see
DESIGN.md.
The core models are currency types: public value types intended to be stored, passed, and composed throughout network infrastructure software.
Swift for Network Infrastructure. swift-cidr is a foundation for Swift
applications that model, validate, configure, and operate on IP networks. Built
from the network model outward, it provides type-safe foundations for IP
infrastructure software: routing, addressing, policy, validation,
configuration, and control-plane data.
swift-cidr brings native CIDR currency types to Swift on Server, apps,
services, tooling, and network control-plane systems. It is not "Swift
networking" in the URLSession or socket-adapter sense, and it is not just
another IP address parser: it is a typed, pure Swift foundation for carrying
addresses, prefixes, networks, and endpoint values through network
infrastructure software without falling back to loosely typed strings or
POSIX-shaped state.
That scope includes routing protocols, RPKI validation, access-list builders, IPAM systems, NETCONF/SSH configuration tooling, ping and diagnostic utilities, and other systems that process high-volume IP data or control-plane state.
- Family-safe APIs expose familiar IPv4 and IPv6 names like
IPv4Address,IPv6Address,IPv4Network, andIPv6Network, while keeping address-family boundaries explicit in the type system. AddressFamilymodels selected IANA address-family values as compile-time traits instead of runtime tags, carrying storage width, parser, formatter, and IANA family metadata in the type system.AutonomousSystemNumber, also available asASN, is the canonical numeric AS-number value, whileAF.ASNremains its IANA address-family marker.IPNetworkis first-class, so CIDR prefixes can participate directly in containment checks, subnet traversal, summarization, and mixed-family API boundaries. In this package,CIDRis a protocol shared by several forms— not a single hybridstruct CIDRwrapper around a host address (see DESIGN.md).IPAddressRangerepresents one exact inclusive address interval independently of CIDR prefix structure, whileIPAddressCoveragenormalizes an exact union of ranges for deterministic containment and summarization.- RPSL-style prefix-range operators model route-policy prefix selection with
^+,^-,^n, and^n-mforms. - Multicast group addresses and group-address ranges are modeled explicitly, so multicast CIDR notation does not inherit unicast subnet, host, or broadcast semantics.
- The core
CIDRmodule stays pure Swift and dependency-free. POSIX and SwiftNIO support live at adapter boundaries instead of shaping the core type system. IPv4AddressandIPv6Addressexpose fixed-size, network-byte-orderInlineArrayprojections on supported toolchains and platforms while keeping integer storage as the canonical representation for CIDR math.- The API is designed for network infrastructure software: routing, addressing,
policy, validation, configuration, and control-plane data pipelines that need
small value types, explicit family metadata, predictable formatting/parsing,
and optional
CIDRNIOinteroperability for SwiftNIO users. - Performance work is measured with benchmark coverage against Swift public APIs
and system baselines, including IPv4/IPv6
inet_ptonparser baselines and IPv4/IPv6inet_ntopformatter baselines.
The package is organized around a family-bound core:
AddressFamilyis the compile-time trait that binds storage width, parsing, formatting, and IANA family metadata to selected registry families.IPAddressFamilynarrows that surface to IP address families, withAF.V4andAF.V6as the concrete IPv4 and IPv6 marker types.IPAddress<Family>stores an IP address together with its prefix context.IPNetwork<Family>stores a canonical network boundary.IPAddressRange<Family>stores one inclusive address interval using strictlower...uppertext, andIPAddressCoverage<Family>stores a normalized exact union of those intervals.PrefixLength<Family>validates CIDR prefix lengths per family.IPMulticastGroup<Family>andIPMulticastGroupRange<Family>model multicast destination identifiers and group-address ranges, with aliases such asIPv4MulticastGroupandIPv6MulticastGroup.AnyIPAddress,AnyIPNetwork,AnyIPAddressRange, andAnyPrefixLengthprovide mixed-family wrappers for boundary APIs.AutonomousSystemNumberstores a four-octet AS number and parses its canonical bareasplaindecimal representation.Portstores numeric transport-layer port values and round-trips their canonical decimal text, whileIPEndpointcombines an IP address with a port. Design intent treats endpoint, port, and future scoped IPv6 (addr%zone) as a host/context layer above pure prefix math (see DESIGN.md and issue #10).
swift-cidr is built around established Internet standards and registry
terminology rather than package-specific interpretations.
Type ↔ standards map, form comparison, and layering: Documentation/DESIGN.md.
Dogfooding / usage examples: Documentation/Examples.md.
Internals for contributors and prior-art explorers: Documentation/INTERNALS.md.
Flagship references (full map in DESIGN.md):
- The IANA Address Family Numbers registry
grounds
AddressFamily.ianaValueand the selected registry families modeled byAF, including IPv4, IPv6, AS Number, 48-bit MAC, and 64-bit MAC. - RFC 791 grounds IPv4 as a 32-bit Internet address family.
- RFC 4291 grounds IPv6 as a 128-bit address family and defines conventional IPv6 text forms.
- RFC 4632 is Classless Inter-domain Routing: The Internet Address Assignment and Aggregation Plan—not merely slash-text parsing. The package’s abbreviated Classless / Inter-domain / Routing reading is in DESIGN.md §2.
- RFC 7020 describes the
Internet Numbers Registry System for globally unique IP address space and AS
numbers; that registry and delegation context is why
CIDRBlockexists as a neutral address-space block separate from host addresses and configured network prefixes. - RFC 5952 guides compressed IPv6 text formatting.
- RFC 2622 defines
the RPSL address-prefix-range operators modeled by
NetworkPrefixRange. - RFC 6308 informs the multicast address allocation and assignment model used by multicast types.
- RFC 1930 defines the
Autonomous System concept modeled by
AutonomousSystemNumberand identified by theAF.ASNfamily marker. ASNs appear with BGP, RPKI ROAs, IRR, and policy—not only BGP. - RFC 5396 defines bare decimal
asplainas the canonical textual representation of an AS number. - RFC 6793 defines four-octet
AS numbers, matching
AutonomousSystemNumber'sAF.ASN.Storagebacking.
The package includes short learning guides for developers who know Swift but may not have deep network-architecture background:
These guides explain why swift-cidr separates host addresses, network
prefixes, Regional Internet Registry-style delegated CIDR blocks, and multicast
group ranges into distinct types while leaving operational context to higher
layers. For a single map of types to standards and the math vs host/context
split, start with DESIGN.md.
CIDR: Core address, network, prefix, mixed-family, and endpoint types.CIDRArgumentParser: Opt-in Swift Argument Parser conformances forPort,AutonomousSystemNumber, family-bound address, endpoint, network, and prefix-length values, plus theAnyIPAddressandAnyIPNetworkmixed-family boundary types. See CIDRArgumentParser.md.CIDRPOSIX: POSIX interoperability helpers for address families andsockaddrconversion.CIDRNIO: SwiftNIO adapters forByteBufferandSocketAddress. ImportingCIDRNIOis explicit, and the coreCIDRtarget does not importNIOCore.
IANA registry datasets are intentionally outside the core CIDR package,
keeping this package focused on value types, parsing, formatting, and CIDR math.
Beginning with swift-cidr 0.7.0, CLI targets can opt into direct
@Option / @Argument parsing by depending on CIDR, CIDRArgumentParser,
and Swift Argument Parser, then importing all three modules explicitly:
import ArgumentParser
import CIDR
import CIDRArgumentParser
struct PeerOptions: ParsableArguments {
@Option var peer: IPv4Address
@Option var port: Port = Port(179)
@Option(name: .customLong("local-as"))
var localAS: AutonomousSystemNumber = AutonomousSystemNumber(65001)
@Option(name: .customLong("local-address"))
var localAddress: IPv4Address?
@Option(name: .customLong("allowed-prefix"))
var allowedPrefix: IPv4Network?
@Option(name: .customLong("listen-endpoint"))
var listenEndpoint: IPEndpoint<V6>?
@Option(name: .customLong("maximum-prefix-length"))
var maximumPrefixLength: IPv4PrefixLength?
@Option(name: .customLong("next-hop"))
var nextHop: AnyIPAddress?
@Option(name: .customLong("route"))
var route: AnyIPNetwork?
}The adapter accepts numeric ports, bare asplain ASNs, and literal IPv4 or IPv6
addresses. Bare addresses receive /32 or /128 context, and an explicit valid
prefix is preserved. It also parses family-bound endpoints, networks, and
standalone prefix lengths: endpoints require a numeric port (and brackets around
IPv6), networks require an explicit prefix and clear host bits to the canonical
network boundary, and prefix lengths must fit their address family.
AnyIPAddress and AnyIPNetwork provide the same address and network behavior
when the family is selected from each literal at runtime, which is useful for
dual-stack CLI boundaries. DNS names, service-name ports, AS-prefixed/asdot
ASNs, and an explicit empty option value are rejected. Omit an optional option
to get nil.
The CIDR, CIDRPOSIX, and CIDRNIO targets do not depend on or link Swift
Argument Parser. SwiftPM does resolve swift-argument-parser as part of the
overall swift-cidr package graph because it is declared in the package
manifest; only targets that opt into CIDRArgumentParser link the adapter and
Argument Parser. No modules are underscored re-exports.
- Swift 6.2 or later
- Swift 6.2 or later Command Line Tools for command-line and editor-based workflows
- Minimum Apple deployment targets:
- macOS 15
- iOS 18
The Apple platform minimums come from this toolchain's built-in UInt128
availability. The InlineArray octet adapters require macOS 26, iOS 26,
tvOS 26, watchOS 26, or visionOS 26; existing APIs retain the package's lower
deployment targets. Linux validation is handled in CI, including the Swift 6.2
minimum toolchain.
On macOS with standalone Command Line Tools, use the repository test wrapper:
./scripts/test.shThe wrapper still runs SwiftPM tests. It only adds the Swift Testing framework
and runtime paths needed by standalone Command Line Tools installations where
plain swift test cannot locate Testing.framework.
For local Linux validation with Docker Desktop, use the Linux wrapper:
./scripts/linux-test.shThe wrapper uses the official swift:6.3 image and defaults to linux/amd64 to
match GitHub Actions. On Apple Silicon, a faster architecture-native smoke test
is available with:
CIDR_LINUX_PLATFORM=linux/arm64 ./scripts/linux-test.shUse the interactive Linux shell when diagnosing platform-specific failures:
./scripts/linux-test.sh shellimport CIDR
if let host = IPv4Address("192.0.2.1/24"),
let port = Port("53") {
let endpoint = IPEndpoint(address: host, port: port)
print(host.description)
// 192.0.2.1/24
print(port.description)
// 53
print(host.network.description)
// 192.0.2.0/24
print(endpoint.description)
// 192.0.2.1/24:53
}On Swift 6.2 or later, IPv4Address and IPv6Address can exchange address bits
with packet, protocol, and FFI boundaries through fixed-size InlineArray
values. On Apple platforms these APIs require macOS 26, iOS 26, tvOS 26,
watchOS 26, or visionOS 26.
import CIDR
let wireOctets: InlineArray<4, UInt8> = [192, 0, 2, 129]
let address = IPv4Address(octets: wireOctets)
print(address.description)
// 192.0.2.129/32
let projected = address.octets
print(projected[0], projected[1], projected[2], projected[3])
// 192 0 2 129Octets use network byte order, with the most-significant octet first. They are
an owned projection of address bits only: they do not carry prefix length,
network canonicalization, or IPv6 scope. The integer-backed address remains the
math representation. This adapter is an exact, allocation-free, text-free
interoperability boundary; it does not replace integer storage or model a
borrowed View.
Four locked currency benchmarks cover IPv4 and IPv6 octet projection and reconstruction. Their configured p50, p75, and p90 gates require zero mallocs, object allocations, retains, and releases; see the benchmark methodology.
This standard-library octet boundary coexists with the richer CIDRPOSIX and
CIDRNIO adapters. On Linux and Apple OS 26 or later, the CIDRNIO
SocketAddress bridge consumes this same octet projection when copying address
bytes to and from POSIX socket fields. Supported pre-26 Apple deployments retain
a private, behavior-equivalent integer network-byte-order fallback because
InlineArray is not back-deployed. The ByteBuffer bridge remains integer
network-byte-order I/O.
The InlineArray used by CIDRNIO is a transient, owned transfer value. It is
not the literal storage of SocketAddress, a zero-copy representation, or a
borrowed View. The allocation-free evidence above applies to the octet
projection itself; it is not a claim that constructing a SwiftNIO
SocketAddress performs no allocations. Integer-backed address identity and
CIDR math remain canonical in every case.
import CIDR
if let network = IPv4Network("192.0.2.0/24"),
let start = IPv4Address("192.0.2.0"),
let end = IPv4Address("192.0.2.255") {
let subnets = Array(network.subnets(prefixLength: 26)).map(\.description)
let summary = IPv4Network.summarize(from: start, to: end).map(\.description)
print(subnets)
// ["192.0.2.0/26", "192.0.2.64/26", "192.0.2.128/26", "192.0.2.192/26"]
print(summary)
// ["192.0.2.0/24"]
}import CIDR
if let v4 = AnyIPAddress("192.0.2.1/24"),
let v6 = AnyIPAddress("2001:db8::1/64") {
let addresses = [v4, v6]
for address in addresses {
print(address.familyName, address.network.description)
}
}IPAddressRange text is a strict, library-defined lower...upper form. It
models inclusive address coverage rather than preserving the CIDR prefixes that
may have produced that coverage. Adjacent and overlapping ranges can be
normalized into an IPAddressCoverage, whose containment lookup uses its
sorted range index.
import CIDR
if let lower = IPv4AddressRange("192.0.2.0...192.0.2.63"),
let upper = IPv4AddressRange("192.0.2.64...192.0.2.127") {
let coverage = IPAddressCoverage([upper, lower])
print(coverage.ranges.map(\.description))
// ["192.0.2.0...192.0.2.127"]
print(coverage.summarizedNetworks().map(\.description))
// ["192.0.2.0/25"]
}summarizedNetworks() preserves the exact address union, but it does not retain
the original prefix lengths used to construct a range or coverage set.
import CIDR
if let asn = AutonomousSystemNumber("64496") {
print(asn.rawValue)
// 64496
print(asn.description)
// 64496
}The numeric value intentionally does not accept the RPSL form AS64496 or
legacy asdot text. Those lexical and policy concerns belong in higher-level
packages.
Common local commands:
swift build --target CIDR
swift build --target CIDRArgumentParser
swift build --target CIDRPOSIX
swift build --target CIDRNIO
./scripts/test.sh
./scripts/linux-test.sh
./scripts/benchmarks.sh build
./scripts/benchmarks.sh checkBuild, test, and run the primary public/API-facing benchmarks from the repository root:
./scripts/test.sh
./scripts/benchmarks.sh run --no-progress --scale --time-units nanoseconds
./scripts/benchmarks.sh check./scripts/benchmarks.sh run defaults to CIDRBenchmarkTarget, which exercises
the normal public APIs such as IPv4Address, IPv6Address, IPNetwork, and
formatting paths. Deeper benchmark targets for parser experiments, fixed-loop CPU
research, and SwiftNIO adapters are documented below.
Benchmark tooling lives in the separate Benchmarks/ package rather than the
root library package, so contributors may not see it when opening only the root
Package.swift in Xcode.
From the repository root:
./scripts/benchmarks.sh build
./scripts/benchmarks.sh run
./scripts/benchmarks.sh check
./scripts/benchmarks.sh update
./scripts/benchmarks.sh graphThe wrapper defaults to CIDRBenchmarkTarget, the public/API-facing benchmark
target.
For fixed-loop research benchmarks that report only user CPU time, select
CIDRCPUBenchmarkTarget:
CIDR_BENCHMARK_TARGET=CIDRCPUBenchmarkTarget ./scripts/benchmarks.sh runFor opt-in SwiftNIO adapter benchmarks, select CIDRNIOBenchmarkTarget:
CIDR_BENCHMARK_TARGET=CIDRNIOBenchmarkTarget ./scripts/benchmarks.sh runOpen Benchmarks/Package.swift separately in Xcode if you want the benchmark
package to appear in Xcode's package navigator.
Benchmark details live in Benchmarks/README.md, and the
root wrapper script lives at scripts/benchmarks.sh.
Benchmark tooling is intentionally isolated in the nested Benchmarks package
so normal library builds, tests, and non-macOS Apple destinations do not pull
in Benchmark.
Linux remains part of normal build/test CI, and the opt-in Linux benchmark job
checks benchmark target compilation. Benchmark-threshold validation remains a
local/macOS workflow unless it is explicitly run on Linux.
CIDR is licensed under Apache-2.0. See LICENSE.