// This file is part of netaddr. // // netaddr is free software: you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License as published by the // Free Software Foundation, either version 3 of the License, or (at your // option) any later version. // // netaddr is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public // License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with netaddr. If not, see . /* This file contains functions for operating with big endian ordered byte arrays. Using big.Integer is significantly slower than doing math strictly on 128-bit numbers. At a minimum, you have to do expensive instantiation of big.Integer. The functions below do not require copying arrays and allocate less memory. Functions missing: fn add_128(a [16]u8, b [16]u8) [16]u8 fn diff_128(a [16]u8, b [16]u8) [16]u8 */ module netaddr import math.bits const max_128 = [16]u8{init: 0xff} @[direct_array_access; inline] fn bit_len_128(a [16]u8) int { if a == [16]u8{} { return 0 } mut len := 128 mut zeros := 0 for i in 0 .. 16 { zeros = bits.leading_zeros_8(a[i]) if zeros == 0 { break } len -= zeros } return len } @[direct_array_access; inline] fn left_shift_128(a [16]u8, shift int) [16]u8 { mut res := [16]u8{} shift_mod := shift % 8 mask := u8((1 << shift_mod) - 1) offset := shift / 8 for i := 0; i < 16; i++ { src_idx := i + offset if src_idx >= 16 { res[i] = 0 } else { mut dst := u8(a[i] << shift_mod) if src_idx + 1 < 16 { dst |= a[src_idx + 1] >> ((8 - shift_mod) & mask) } res[i] = dst } } return res } @[direct_array_access; inline] fn right_shift_128(a [16]u8, shift int) [16]u8 { mut res := [16]u8{} shift_mod := shift % 8 mask := u8(0xff) << (8 - shift_mod) offset := shift / 8 for i := 15; i >= 0; i-- { src_idx := i - offset if src_idx < 0 { res[i] = 0 } else { mut dst := (u8(0xff) & a[i]) >> shift_mod if src_idx - 1 >= 0 { dst |= a[src_idx - 1] << ((8 - shift_mod) & mask) } res[i] = dst } } return res } @[direct_array_access; inline] fn bitwise_and_128(a [16]u8, b [16]u8) [16]u8 { mut res := [16]u8{} for i := 0; i < 16; i++ { res[i] = a[i] & b[i] } return res } @[direct_array_access; inline] fn bitwise_or_128(a [16]u8, b [16]u8) [16]u8 { mut res := [16]u8{} for i := 0; i < 16; i++ { res[i] = a[i] | b[i] } return res } @[direct_array_access; inline] fn bitwise_xor_128(a [16]u8, b [16]u8) [16]u8 { mut res := [16]u8{} for i := 0; i < 16; i++ { res[i] = a[i] ^ b[i] } return res } // compare_128 returns: // // * -1 if a < b // * 0 if a == b // * +1 if a > b @[direct_array_access; inline] fn compare_128(a [16]u8, b [16]u8) int { for i in 0 .. 16 { if a[i] != b[i] { return if a[i] < b[i] { -1 } else { 1 } } } return 0 }