{"id":15713772,"url":"https://github.com/watzon/subnet","last_synced_at":"2026-02-27T10:36:13.644Z","repository":{"id":91428271,"uuid":"194377145","full_name":"watzon/subnet","owner":"watzon","description":"Crystal library for working with IPv4 and IPv6 addresses","archived":false,"fork":false,"pushed_at":"2019-08-08T23:27:14.000Z","size":346,"stargazers_count":14,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-12T23:34:51.056Z","etag":null,"topics":["crystal","crystal-language","ip","ipv4","ipv6","subnet","subnetting"],"latest_commit_sha":null,"homepage":"https://watzon.github.io/subnet/","language":"Crystal","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/watzon.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}},"created_at":"2019-06-29T07:23:24.000Z","updated_at":"2024-03-09T22:08:01.000Z","dependencies_parsed_at":"2024-02-06T16:16:13.560Z","dependency_job_id":null,"html_url":"https://github.com/watzon/subnet","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/watzon/subnet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fsubnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fsubnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fsubnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fsubnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/watzon","download_url":"https://codeload.github.com/watzon/subnet/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/watzon%2Fsubnet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29891767,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-27T09:48:51.284Z","status":"ssl_error","status_checked_at":"2026-02-27T09:48:43.992Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["crystal","crystal-language","ip","ipv4","ipv6","subnet","subnetting"],"created_at":"2024-10-03T21:33:24.344Z","updated_at":"2026-02-27T10:36:13.636Z","avatar_url":"https://github.com/watzon.png","language":"Crystal","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Subnet\n\n[![Crystal Version](https://img.shields.io/badge/crystal-%3E%3D1.0.0-black)](https://crystal-lang.org)\n[![GitHub release](https://img.shields.io/github/v/release/watzon/subnet)](https://github.com/watzon/subnet/releases)\n[![License](https://img.shields.io/github/license/watzon/subnet)](LICENSE)\n\nA Crystal library for working with IPv4 and IPv6 addresses.\n\nSubnet provides a complete set of methods to handle IP addresses for any need, from simple scripting to full network design. It features a clean OO interface, comprehensive IPv4/IPv6 support, and efficient native `UInt128` operations for IPv6.\n\nBased on the Ruby [IPAddress](https://github.com/ipaddress-gem/ipaddress) gem.\n\n## Table of Contents\n\n- [Install](#install)\n- [Usage](#usage)\n  - [IPv4](#ipv4)\n  - [IPv6](#ipv6)\n  - [Network Operations](#network-operations)\n- [API](#api)\n- [Maintainers](#maintainers)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Install\n\nAdd the dependency to your `shard.yml`:\n\n```yaml\ndependencies:\n  subnet:\n    github: watzon/subnet\n    version: ~\u003e 0.2.0\n```\n\nRun `shards install`.\n\n## Usage\n\n```crystal\nrequire \"subnet\"\n```\n\n### IPv4\n\nCreate and manipulate IPv4 addresses:\n\n```crystal\n# Create an IPv4 address\nip = Subnet::IPv4.new(\"172.16.10.1/24\")\n\n# Or use the universal parser\nip = Subnet.parse(\"172.16.10.1/24\")\n\n# Access properties\nip.address    # =\u003e \"172.16.10.1\"\nip.prefix     # =\u003e 24\nip.netmask    # =\u003e \"255.255.255.0\"\nip.octets     # =\u003e [172, 16, 10, 1]\nip.to_u32     # =\u003e 2886732289\n\n# Network calculations\nip.network.to_string    # =\u003e \"172.16.10.0/24\"\nip.broadcast.to_string  # =\u003e \"172.16.10.255/24\"\nip.first.to_s           # =\u003e \"172.16.10.1\"\nip.last.to_s            # =\u003e \"172.16.10.254\"\n\n# Check address types\nip.private?     # =\u003e true\nip.loopback?    # =\u003e false\nip.network?     # =\u003e false\n\n# Iterate over addresses\nip.each_host { |host| puts host }\n```\n\n### IPv6\n\nFull IPv6 support with native `UInt128` operations:\n\n```crystal\nip6 = Subnet::IPv6.new(\"2001:db8::8:800:200c:417a/64\")\n\nip6.address     # =\u003e \"2001:0db8:0000:0000:0008:0800:200c:417a\"\nip6.compressed  # =\u003e \"2001:db8::8:800:200c:417a\"\nip6.to_u128     # =\u003e 42540766411282592856906245548098208122 (UInt128)\n\n# Special addresses\nloopback = Subnet::IPv6::Loopback.new\nloopback.to_string  # =\u003e \"::1/128\"\n\n# IPv4-mapped addresses\nmapped = Subnet::IPv6::Mapped.new(\"::ffff:172.16.10.1/128\")\nmapped.ipv4.address  # =\u003e \"172.16.10.1\"\n```\n\n### Network Operations\n\nSubnet provides powerful network manipulation:\n\n```crystal\n# Subnetting - divide a network\nnetwork = Subnet::IPv4.new(\"172.16.10.0/24\")\nsubnets = network.split(4)\nsubnets.map(\u0026.to_string)\n# =\u003e [\"172.16.10.0/26\", \"172.16.10.64/26\", \n#     \"172.16.10.128/26\", \"172.16.10.192/26\"]\n\n# Supernetting - combine networks\nnetwork.supernet(23).to_string  # =\u003e \"172.16.10.0/23\"\n\n# Summarization - find optimal supernet\nip1 = Subnet::IPv4.new(\"172.16.10.0/24\")\nip2 = Subnet::IPv4.new(\"172.16.11.0/24\")\nSubnet::IPv4.summarize(ip1, ip2).map(\u0026.to_string)\n# =\u003e [\"172.16.10.0/23\"]\n\n# Check inclusion\nnetwork.includes?(Subnet::IPv4.new(\"172.16.10.50/32\"))  # =\u003e true\n\n# Allocate addresses sequentially\nip = Subnet::IPv4.new(\"10.0.0.0/24\")\nip.allocate  # =\u003e \"10.0.0.1/24\"\nip.allocate  # =\u003e \"10.0.0.2/24\"\n```\n\n## API\n\n### Subnet Module\n\n- `Subnet.parse(address)` - Parse IPv4, IPv6, or mapped addresses\n- `Subnet.valid?(address)` - Check if address is valid\n- `Subnet.valid_ipv4?(address)` - Check IPv4 validity\n- `Subnet.valid_ipv6?(address)` - Check IPv6 validity\n\n### Subnet::IPv4\n\n**Creation:**\n- `.new(address)` - Create from string (e.g., \"192.168.1.1/24\")\n- `.parse_u32(int, prefix)` - Create from 32-bit integer\n- `.parse_data(bytes, prefix)` - Create from byte array\n- `.parse_classful(address)` - Create with classful prefix\n- `.extract(string)` - Extract IPv4 from string\n\n**Properties:**\n- `#address` - Address string\n- `#prefix` - Prefix object\n- `#netmask` - Netmask string\n- `#octets` - Array of octets\n- `#to_u32` / `#to_i` - 32-bit integer\n- `#bits` - Binary string\n- `#hexstring` - Hex string\n\n**Network:**\n- `#network` - Network address\n- `#broadcast` - Broadcast address\n- `#first` / `#last` - First/last host\n- `#size` - Number of addresses\n- `#hosts` - Array of host addresses\n- `#includes?(other)` - Check if includes address\n- `#each` / `#each_host` - Iterate addresses\n\n**Operations:**\n- `#subnet(prefix)` - Subnet to new prefix\n- `#split(count)` - Split into N subnets\n- `#supernet(prefix)` - Create supernet\n- `#allocate(skip)` - Allocate next address\n- `.summarize(*addresses)` - Summarize addresses\n\n**Checks:**\n- `#private?` / `#loopback?` / `#multicast?` / `#link_local?`\n- `#network?` - Is network address\n- `#a?` / `#b?` / `#c?` - Classful checks\n\n### Subnet::IPv6\n\nSimilar interface to IPv4, with additions:\n\n- `#to_u128` - 128-bit integer (UInt128)\n- `#compressed` - Compressed string\n- `#groups` / `#hex_groups` - 16-bit groups\n- `#unspecified?` / `#loopback?` / `#mapped?`\n- `#link_local?` / `#unique_local?`\n- `.expand(address)` / `.compress(address)` - String utilities\n- `.parse_u128(int, prefix)` - Create from UInt128\n- `.parse_hex(hex, prefix)` - Create from hex string\n\n**Subclasses:**\n- `Subnet::IPv6::Loopback` - Loopback address (::1)\n- `Subnet::IPv6::Unspecified` - Unspecified address (::)\n- `Subnet::IPv6::Mapped` - IPv4-mapped address (::ffff:x.x.x.x)\n\n## Maintainers\n\n- [Chris Watson](https://github.com/watzon)\n\n## Contributing\n\n1. Fork it ([https://github.com/watzon/subnet/fork](https://github.com/watzon/subnet/fork))\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\nBug reports and pull requests are welcome on GitHub.\n\n## License\n\n[MIT](LICENSE) - Chris Watson\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwatzon%2Fsubnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwatzon%2Fsubnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwatzon%2Fsubnet/lists"}