|
| 1 | +:struct IPAddress |
| 2 | + :let _raw_v6_hi U64 |
| 3 | + :let _raw_v6_lo U64 |
| 4 | + |
| 5 | + // This field indicates whether the address is IPv4 or IPv6, and also |
| 6 | + // indicates the number of leading significant bits (i.e. a CIDR mask). |
| 7 | + // |
| 8 | + // For IPv6, this is in the 0 to -128 range, indicating 0 to 128 CIDR bits. |
| 9 | + :let _bits I8 |
| 10 | + |
| 11 | + :fun is_v6: @_bits <= 0 |
| 12 | + :fun is_v4: @_bits > 0 |
| 13 | + |
| 14 | + :fun _v6_cidr_bits U8: if (@_bits == -128) (128 | @_bits.negate.u8) |
| 15 | + :fun _v4_cidr_bits U8: @_bits.u8.bit_shr(8).bit_and(0x3F) |
| 16 | + |
| 17 | + // For IPv4, the raw bytes are kept in the low 32 bits of the IPv6 raw bytes. |
| 18 | + // Here we define a getter and setter function to let us access them easily. |
| 19 | + :fun _raw_v4: @_raw_v6_lo.u32 |
| 20 | + |
| 21 | + :new val new_raw_v4(raw_v4 U32): @_raw_v6_hi = 0, @_raw_v6_lo = raw_v4.u64, @_bits = 96 |
| 22 | + :new val new_raw_v6(@_raw_v6_hi, @_raw_v6_lo): @_bits = -128 |
| 23 | + |
| 24 | + :fun _v4_each_u8 |
| 25 | + raw = @_raw_v4 |
| 26 | + yield raw.bit_shr(24).u8 |
| 27 | + yield raw.bit_shr(16).u8 |
| 28 | + yield raw.bit_shr(8).u8 |
| 29 | + yield raw.u8 |
| 30 | + @ |
| 31 | + |
| 32 | + :fun _v6_each_u16 |
| 33 | + raw_hi = @_raw_v6_hi |
| 34 | + raw_lo = @_raw_v6_lo |
| 35 | + yield raw_hi.bit_shr(48).u16 |
| 36 | + yield raw_hi.bit_shr(32).u16 |
| 37 | + yield raw_hi.bit_shr(16).u16 |
| 38 | + yield raw_hi.u16 |
| 39 | + yield raw_lo.bit_shr(48).u16 |
| 40 | + yield raw_lo.bit_shr(32).u16 |
| 41 | + yield raw_lo.bit_shr(16).u16 |
| 42 | + yield raw_lo.u16 |
| 43 | + @ |
| 44 | + |
| 45 | + :fun format: IPAddress.Format.new(@) |
| 46 | + |
| 47 | + :is IntoString |
| 48 | + :fun into_string(out String'iso): @format.into_string(--out) |
| 49 | + :fun into_string_space: @format.into_string_space |
0 commit comments