Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/netaddr/strategy/eui64.py: 44%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

119 statements  

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""" 

7IEEE 64-bit EUI (Extended Unique Identifier) logic. 

8""" 

9import struct as _struct 

10import re as _re 

11 

12from netaddr.core import AddrFormatError 

13from netaddr.strategy import ( 

14 valid_words as _valid_words, 

15 int_to_words as _int_to_words, 

16 words_to_int as _words_to_int, 

17 valid_bits as _valid_bits, 

18 bits_to_int as _bits_to_int, 

19 int_to_bits as _int_to_bits, 

20 valid_bin as _valid_bin, 

21 int_to_bin as _int_to_bin, 

22 bin_to_int as _bin_to_int, 

23) 

24 

25 

26#: The width (in bits) of this address type. 

27width = 64 

28 

29#: The version of this address type. 

30version = 64 

31 

32#: The maximum integer value that can be represented by this address type. 

33max_int = 2**width - 1 

34 

35# ----------------------------------------------------------------------------- 

36# Dialect classes. 

37# ----------------------------------------------------------------------------- 

38 

39 

40class eui64_base(object): 

41 """A standard IEEE EUI-64 dialect class.""" 

42 

43 #: The individual word size (in bits) of this address type. 

44 word_size = 8 

45 

46 #: The number of words in this address type. 

47 num_words = width // word_size 

48 

49 #: The maximum integer value for an individual word in this address type. 

50 max_word = 2**word_size - 1 

51 

52 #: The separator character used between each word. 

53 word_sep = '-' 

54 

55 #: The format string to be used when converting words to string values. 

56 word_fmt = '%.2X' 

57 

58 #: The number base to be used when interpreting word values as integers. 

59 word_base = 16 

60 

61 

62class eui64_unix(eui64_base): 

63 """A UNIX-style MAC address dialect class.""" 

64 

65 word_size = 8 

66 num_words = width // word_size 

67 word_sep = ':' 

68 word_fmt = '%x' 

69 word_base = 16 

70 

71 

72class eui64_unix_expanded(eui64_unix): 

73 """A UNIX-style MAC address dialect class with leading zeroes.""" 

74 

75 word_fmt = '%.2x' 

76 

77 

78class eui64_cisco(eui64_base): 

79 """A Cisco 'triple hextet' MAC address dialect class.""" 

80 

81 word_size = 16 

82 num_words = width // word_size 

83 word_sep = '.' 

84 word_fmt = '%.4x' 

85 word_base = 16 

86 

87 

88class eui64_bare(eui64_base): 

89 """A bare (no delimiters) MAC address dialect class.""" 

90 

91 word_size = 64 

92 num_words = width // word_size 

93 word_sep = '' 

94 word_fmt = '%.16X' 

95 word_base = 16 

96 

97 

98#: The default dialect to be used when not specified by the user. 

99 

100DEFAULT_EUI64_DIALECT = eui64_base 

101 

102# ----------------------------------------------------------------------------- 

103#: Regular expressions to match all supported MAC address formats. 

104#: For efficiency, each string regexp converted in place to its compiled 

105#: counterpart. 

106RE_EUI64_FORMATS = [ 

107 _re.compile(_, _re.IGNORECASE) 

108 for _ in ( 

109 # 2 bytes x 8 (UNIX, Windows, EUI-64) 

110 '^' + ':'.join(['([0-9A-F]{1,2})'] * 8) + '$', 

111 '^' + '-'.join(['([0-9A-F]{1,2})'] * 8) + '$', 

112 # 4 bytes x 4 (Cisco like) 

113 '^' + ':'.join(['([0-9A-F]{1,4})'] * 4) + '$', 

114 '^' + '-'.join(['([0-9A-F]{1,4})'] * 4) + '$', 

115 '^' + r'\.'.join(['([0-9A-F]{1,4})'] * 4) + '$', 

116 # 16 bytes (bare, no delimiters) 

117 '^(' + ''.join(['[0-9A-F]'] * 16) + ')$', 

118 ) 

119] 

120 

121 

122def _get_match_result(address, formats): 

123 for regexp in formats: 

124 match = regexp.findall(address) 

125 if match: 

126 return match[0] 

127 

128 

129def valid_str(addr): 

130 """ 

131 :param addr: An IEEE EUI-64 identifier in string form. 

132 

133 :return: ``True`` if EUI-64 identifier is valid, ``False`` otherwise. 

134 """ 

135 try: 

136 if _get_match_result(addr, RE_EUI64_FORMATS): 

137 return True 

138 except TypeError: 

139 pass 

140 

141 return False 

142 

143 

144def str_to_int(addr): 

145 """ 

146 :param addr: An IEEE EUI-64 identifier in string form. 

147 

148 :return: An unsigned integer that is equivalent to value represented 

149 by EUI-64 string address formatted according to the dialect 

150 """ 

151 words = [] 

152 

153 try: 

154 words = _get_match_result(addr, RE_EUI64_FORMATS) 

155 if not words: 

156 raise TypeError 

157 except TypeError: 

158 raise AddrFormatError('invalid IEEE EUI-64 identifier: %r!' % (addr,)) 

159 

160 if isinstance(words, tuple): 

161 pass 

162 else: 

163 words = (words,) 

164 

165 if len(words) == 8: 

166 # 2 bytes x 8 (UNIX, Windows, EUI-48) 

167 int_val = int(''.join(['%.2x' % int(w, 16) for w in words]), 16) 

168 elif len(words) == 4: 

169 # 4 bytes x 4 (Cisco like) 

170 int_val = int(''.join(['%.4x' % int(w, 16) for w in words]), 16) 

171 elif len(words) == 1: 

172 # 16 bytes (bare, no delimiters) 

173 int_val = int('%016x' % int(words[0], 16), 16) 

174 else: 

175 raise AddrFormatError('bad word count for EUI-64 identifier: %r!' % addr) 

176 

177 return int_val 

178 

179 

180def int_to_str(int_val, dialect=None): 

181 """ 

182 :param int_val: An unsigned integer. 

183 

184 :param dialect: (optional) a Python class defining formatting options 

185 

186 :return: An IEEE EUI-64 identifier that is equivalent to unsigned integer. 

187 """ 

188 if dialect is None: 

189 dialect = eui64_base 

190 words = int_to_words(int_val, dialect) 

191 tokens = [dialect.word_fmt % i for i in words] 

192 addr = dialect.word_sep.join(tokens) 

193 return addr 

194 

195 

196def int_to_packed(int_val): 

197 """ 

198 :param int_val: the integer to be packed. 

199 

200 :return: a packed string that is equivalent to value represented by an 

201 unsigned integer. 

202 """ 

203 words = int_to_words(int_val) 

204 return _struct.pack('>8B', *words) 

205 

206 

207def packed_to_int(packed_int): 

208 """ 

209 :param packed_int: a packed string containing an unsigned integer. 

210 It is assumed that string is packed in network byte order. 

211 

212 :return: An unsigned integer equivalent to value of network address 

213 represented by packed binary string. 

214 """ 

215 words = list(_struct.unpack('>8B', packed_int)) 

216 

217 int_val = 0 

218 for i, num in enumerate(reversed(words)): 

219 word = num 

220 word = word << 8 * i 

221 int_val = int_val | word 

222 

223 return int_val 

224 

225 

226def valid_words(words, dialect=None): 

227 if dialect is None: 

228 dialect = DEFAULT_EUI64_DIALECT 

229 return _valid_words(words, dialect.word_size, dialect.num_words) 

230 

231 

232def int_to_words(int_val, dialect=None): 

233 if dialect is None: 

234 dialect = DEFAULT_EUI64_DIALECT 

235 return _int_to_words(int_val, dialect.word_size, dialect.num_words) 

236 

237 

238def words_to_int(words, dialect=None): 

239 if dialect is None: 

240 dialect = DEFAULT_EUI64_DIALECT 

241 return _words_to_int(words, dialect.word_size, dialect.num_words) 

242 

243 

244def valid_bits(bits, dialect=None): 

245 if dialect is None: 

246 dialect = DEFAULT_EUI64_DIALECT 

247 return _valid_bits(bits, width, dialect.word_sep) 

248 

249 

250def bits_to_int(bits, dialect=None): 

251 if dialect is None: 

252 dialect = DEFAULT_EUI64_DIALECT 

253 return _bits_to_int(bits, width, dialect.word_sep) 

254 

255 

256def int_to_bits(int_val, dialect=None): 

257 if dialect is None: 

258 dialect = DEFAULT_EUI64_DIALECT 

259 return _int_to_bits(int_val, dialect.word_size, dialect.num_words, dialect.word_sep) 

260 

261 

262def valid_bin(bin_val, dialect=None): 

263 if dialect is None: 

264 dialect = DEFAULT_EUI64_DIALECT 

265 return _valid_bin(bin_val, width) 

266 

267 

268def int_to_bin(int_val): 

269 return _int_to_bin(int_val, width) 

270 

271 

272def bin_to_int(bin_val): 

273 return _bin_to_int(bin_val, width)