Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/netaddr/strategy/__init__.py: 20%
113 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:45 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:45 +0000
1#-----------------------------------------------------------------------------
2# Copyright (c) 2008 by David P. D. Moss. All rights reserved.
3#
4# Released under the BSD license. See the LICENSE file for details.
5#-----------------------------------------------------------------------------
6"""
7Shared logic for various address types.
8"""
9import re as _re
11from netaddr.compat import _range, _is_str
14def bytes_to_bits():
15 """
16 :return: A 256 element list containing 8-bit binary digit strings. The
17 list index value is equivalent to its bit string value.
18 """
19 lookup = []
20 bits_per_byte = _range(7, -1, -1)
21 for num in range(256):
22 bits = 8 * [None]
23 for i in bits_per_byte:
24 bits[i] = '01'[num & 1]
25 num >>= 1
26 lookup.append(''.join(bits))
27 return lookup
29#: A lookup table of 8-bit integer values to their binary digit bit strings.
30BYTES_TO_BITS = bytes_to_bits()
33def valid_words(words, word_size, num_words):
34 """
35 :param words: A sequence of unsigned integer word values.
37 :param word_size: Width (in bits) of each unsigned integer word value.
39 :param num_words: Number of unsigned integer words expected.
41 :return: ``True`` if word sequence is valid for this address type,
42 ``False`` otherwise.
43 """
44 if not hasattr(words, '__iter__'):
45 return False
47 if len(words) != num_words:
48 return False
50 max_word = 2 ** word_size - 1
52 for i in words:
53 if not 0 <= i <= max_word:
54 return False
56 return True
59def int_to_words(int_val, word_size, num_words):
60 """
61 :param int_val: Unsigned integer to be divided into words of equal size.
63 :param word_size: Width (in bits) of each unsigned integer word value.
65 :param num_words: Number of unsigned integer words expected.
67 :return: A tuple contain unsigned integer word values split according
68 to provided arguments.
69 """
70 max_int = 2 ** (num_words * word_size) - 1
72 if not 0 <= int_val <= max_int:
73 raise IndexError('integer out of bounds: %r!' % hex(int_val))
75 max_word = 2 ** word_size - 1
77 words = []
78 for _ in range(num_words):
79 word = int_val & max_word
80 words.append(int(word))
81 int_val >>= word_size
83 return tuple(reversed(words))
86def words_to_int(words, word_size, num_words):
87 """
88 :param words: A sequence of unsigned integer word values.
90 :param word_size: Width (in bits) of each unsigned integer word value.
92 :param num_words: Number of unsigned integer words expected.
94 :return: An unsigned integer that is equivalent to value represented
95 by word sequence.
96 """
97 if not valid_words(words, word_size, num_words):
98 raise ValueError('invalid integer word sequence: %r!' % (words,))
100 int_val = 0
101 for i, num in enumerate(reversed(words)):
102 word = num
103 word = word << word_size * i
104 int_val = int_val | word
106 return int_val
109def valid_bits(bits, width, word_sep=''):
110 """
111 :param bits: A network address in a delimited binary string format.
113 :param width: Maximum width (in bits) of a network address (excluding
114 delimiters).
116 :param word_sep: (optional) character or string used to delimit word
117 groups (default: '', no separator).
119 :return: ``True`` if network address is valid, ``False`` otherwise.
120 """
121 if not _is_str(bits):
122 return False
124 if word_sep != '':
125 bits = bits.replace(word_sep, '')
127 if len(bits) != width:
128 return False
130 max_int = 2 ** width - 1
132 try:
133 if 0 <= int(bits, 2) <= max_int:
134 return True
135 except ValueError:
136 pass
138 return False
141def bits_to_int(bits, width, word_sep=''):
142 """
143 :param bits: A network address in a delimited binary string format.
145 :param width: Maximum width (in bits) of a network address (excluding
146 delimiters).
148 :param word_sep: (optional) character or string used to delimit word
149 groups (default: '', no separator).
151 :return: An unsigned integer that is equivalent to value represented
152 by network address in readable binary form.
153 """
154 if not valid_bits(bits, width, word_sep):
155 raise ValueError('invalid readable binary string: %r!' % (bits,))
157 if word_sep != '':
158 bits = bits.replace(word_sep, '')
160 return int(bits, 2)
163def int_to_bits(int_val, word_size, num_words, word_sep=''):
164 """
165 :param int_val: An unsigned integer.
167 :param word_size: Width (in bits) of each unsigned integer word value.
169 :param num_words: Number of unsigned integer words expected.
171 :param word_sep: (optional) character or string used to delimit word
172 groups (default: '', no separator).
174 :return: A network address in a delimited binary string format that is
175 equivalent in value to unsigned integer.
176 """
177 bit_words = []
179 for word in int_to_words(int_val, word_size, num_words):
180 bits = []
181 while word:
182 bits.append(BYTES_TO_BITS[word & 255])
183 word >>= 8
184 bits.reverse()
185 bit_str = ''.join(bits) or '0' * word_size
186 bits = ('0' * word_size + bit_str)[-word_size:]
187 bit_words.append(bits)
189 if word_sep != '':
190 # Check custom separator.
191 if not _is_str(word_sep):
192 raise ValueError('word separator is not a string: %r!' % (word_sep,))
194 return word_sep.join(bit_words)
197def valid_bin(bin_val, width):
198 """
199 :param bin_val: A network address in Python's binary representation format
200 ('0bxxx').
202 :param width: Maximum width (in bits) of a network address (excluding
203 delimiters).
205 :return: ``True`` if network address is valid, ``False`` otherwise.
206 """
207 if not _is_str(bin_val):
208 return False
210 if not bin_val.startswith('0b'):
211 return False
213 bin_val = bin_val.replace('0b', '')
215 if len(bin_val) > width:
216 return False
218 max_int = 2 ** width - 1
220 try:
221 if 0 <= int(bin_val, 2) <= max_int:
222 return True
223 except ValueError:
224 pass
226 return False
229def int_to_bin(int_val, width):
230 """
231 :param int_val: An unsigned integer.
233 :param width: Maximum allowed width (in bits) of a unsigned integer.
235 :return: Equivalent string value in Python's binary representation format
236 ('0bxxx').
237 """
238 bin_tokens = []
240 try:
241 # Python 2.6.x and upwards.
242 bin_val = bin(int_val)
243 except NameError:
244 # Python 2.4.x and 2.5.x
245 i = int_val
246 while i > 0:
247 word = i & 0xff
248 bin_tokens.append(BYTES_TO_BITS[word])
249 i >>= 8
251 bin_tokens.reverse()
252 bin_val = '0b' + _re.sub(r'^[0]+([01]+)$', r'\1', ''.join(bin_tokens))
254 if len(bin_val[2:]) > width:
255 raise IndexError('binary string out of bounds: %s!' % (bin_val,))
257 return bin_val
260def bin_to_int(bin_val, width):
261 """
262 :param bin_val: A string containing an unsigned integer in Python's binary
263 representation format ('0bxxx').
265 :param width: Maximum allowed width (in bits) of a unsigned integer.
267 :return: An unsigned integer that is equivalent to value represented
268 by Python binary string format.
269 """
270 if not valid_bin(bin_val, width):
271 raise ValueError('not a valid Python binary string: %r!' % (bin_val,))
273 return int(bin_val.replace('0b', ''), 2)