Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ combined via a separate flag to avoid ambiguity.
- Emit the canonical network string for each IP rather than the original token
- Host bits are cleared: `10.0.0.5/24` → `10.0.0.0/24`
- Bare IPs get explicit prefix lengths: `192.168.1.1` → `192.168.1.1/32`
- IPv6 hex digits are lowercased: `2001:DB8::FfAb` → `2001:db8::ffab/128`
- Does not affect `NonIp` spans, which are always emitted verbatim

### Deduplication: `--unique` / `-u`
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,14 @@ EOF
192.168.1.1/32
```

`--normalize` also lowercases IPv6 hex digits, since it always emits the
canonical network string rather than the original token:

```sh
$ echo "2001:DB8::FfAb" | ipsort --normalize
2001:db8::ffab/128
```

**Extract bare IPs, discarding all decoration and structure:**

```sh
Expand Down
3 changes: 2 additions & 1 deletion ipsort.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ reordered, leaving comments, keys, blank lines, and all other content untouched.
*-n*, *--normalize*
Emit canonical network strings instead of the original token. Host bits are
cleared (_10.0.0.5/24_ becomes _10.0.0.0/24_) and bare IPs gain explicit
prefix lengths (_192.168.1.1_ becomes _192.168.1.1/32_). Surrounding
prefix lengths (_192.168.1.1_ becomes _192.168.1.1/32_). IPv6 hex digits are
also lowercased (_2001:DB8::FfAb_ becomes _2001:db8::ffab/128_). Surrounding
decoration is unaffected.

*--ips-only*
Expand Down
19 changes: 18 additions & 1 deletion src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
//! **`--normalize`**: same as default but `Ip` spans emit the canonical
//! network string (`10.0.0.0/8`) rather than the original token
//! (`10.0.0.5/8`). Bare IPs gain explicit prefix lengths (`192.168.1.1` ->
//! `192.168.1.1/32`).
//! `192.168.1.1/32`). IPv6 hex digits are also lowercased (`2001:DB8::FfAb`
//! -> `2001:db8::ffab/128`).
//!
//! **`--ips-only`** ([`IpsOnlyMode::Flat`]): all `NonIp` spans and all
//! [`ClassifiedLine::NoIp`] lines are discarded. Each `Ip` span becomes one
Expand Down Expand Up @@ -379,6 +380,22 @@ mod tests {
assert_eq!(render_with("2001:db8::1", &opts), vec!["2001:db8::1/128"]);
}

#[test]
fn test_normalize_ipv6_hex_downcased() {
let opts = OutputOptions {
normalize: true,
..Default::default()
};
assert_eq!(
render_with("2001:DB8::FfAb/32", &opts),
vec!["2001:db8::/32"]
);
assert_eq!(
render_with("2001:DB8::FfAb", &opts),
vec!["2001:db8::ffab/128"]
);
}

#[test]
fn test_normalize_decoration_preserved() {
let opts = OutputOptions {
Expand Down
10 changes: 10 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,16 @@ fn test_normalize_bare_ipv6() {
.stdout("2001:db8::1/128\n");
}

#[test]
fn test_normalize_downcases_ipv6_hex() {
ipsort()
.args(["--normalize"])
.write_stdin("2001:DB8::FfAb\n")
.assert()
.success()
.stdout("2001:db8::ffab/128\n");
}

#[test]
fn test_normalize_preserves_decoration() {
ipsort()
Expand Down
Loading