11from __future__ import annotations
22from struct import pack , unpack_from
3- from typing import cast
43
54try :
65 import numpy as np
1211class Bit :
1312 def __init__ (self , value : bytes | str | list [bool ] | np .ndarray [tuple [int ], np .dtype [np .bool | np .uint8 ]]) -> None :
1413 if isinstance (value , bytes ):
15- length = 8 * len (value )
16- data = value
14+ self . _length = 8 * len (value )
15+ self . _data = value
1716 elif isinstance (value , (list , str )):
1817 if isinstance (value , list ):
1918 def bit_value (v : bool ) -> str :
@@ -30,8 +29,9 @@ def bit_value(v: bool) -> str:
3029 if length % 8 != 0 :
3130 value += '0' * (8 - (length % 8 ))
3231
32+ self ._length = length
3333 try :
34- data = int (value , 2 ).to_bytes (len (value ) // 8 , byteorder = 'big' )
34+ self . _data = int (value , 2 ).to_bytes (len (value ) // 8 , byteorder = 'big' )
3535 except ValueError :
3636 raise ValueError ('expected bit string' )
3737 elif NUMPY_AVAILABLE and isinstance (value , np .ndarray ):
@@ -44,37 +44,31 @@ def bit_value(v: bool) -> str:
4444 if value .ndim != 1 :
4545 raise ValueError ('expected ndim to be 1' )
4646
47- length = len (value )
48- data = np .packbits (value ).tobytes ()
47+ self . _length = len (value )
48+ self . _data = np .packbits (value ).tobytes ()
4949 else :
5050 raise ValueError ('expected bytes, str, list, or ndarray' )
5151
52- self ._value = pack ('>i' , length ) + data
53-
5452 def __repr__ (self ) -> str :
5553 return f'Bit({ self .to_text ()} )'
5654
5755 def __eq__ (self , other : object ) -> bool :
5856 if isinstance (other , self .__class__ ):
59- return self .to_binary () == other .to_binary ()
57+ return self ._length == other ._length and self . _data == other . _data
6058 return False
6159
62- def _length (self ) -> int :
63- length , = cast (tuple [int ], unpack_from ('>i' , self ._value ))
64- return length
65-
6660 def to_list (self ) -> list [bool ]:
6761 # TODO improve
6862 return [v != '0' for v in self .to_text ()]
6963
7064 def to_numpy (self ) -> np .ndarray [tuple [int ], np .dtype [np .bool ]]:
71- return np .unpackbits (np .frombuffer (self ._value [ 4 :] , dtype = np .uint8 ), count = self ._length () ).astype (bool )
65+ return np .unpackbits (np .frombuffer (self ._data , dtype = np .uint8 ), count = self ._length ).astype (bool )
7266
7367 def to_text (self ) -> str :
74- return '' .join (format (v , '08b' ) for v in self ._value [ 4 :] )[:self ._length () ]
68+ return '' .join (format (v , '08b' ) for v in self ._data )[:self ._length ]
7569
7670 def to_binary (self ) -> bytes :
77- return self ._value
71+ return pack ( '>i' , self ._length ) + self . _data
7872
7973 @classmethod
8074 def from_text (cls , value : str ) -> Bit :
@@ -86,10 +80,12 @@ def from_binary(cls, value: bytes) -> Bit:
8680 raise ValueError ('expected bytes' )
8781
8882 length , = unpack_from ('>i' , value )
83+ data = value [4 :]
8984
90- if len (value ) != 4 + (length + 7 ) // 8 :
85+ if len (data ) != (length + 7 ) // 8 :
9186 raise ValueError ('invalid length' )
9287
9388 bit = cls .__new__ (cls )
94- bit ._value = value
89+ bit ._length = length
90+ bit ._data = data
9591 return bit
0 commit comments