11from fakeredis import _msgs as msgs
22from fakeredis ._commands import (command , Key , Int , BitOffset , BitValue , fix_range_string )
3- from fakeredis ._helpers import SimpleError
3+ from fakeredis ._helpers import SimpleError , casematch
44
55
66class BitmapCommandsMixin :
@@ -11,15 +11,28 @@ class BitmapCommandsMixin:
1111 def bitcount (self , key , * args ):
1212 # Redis checks the argument count before decoding integers. That's why
1313 # we can't declare them as Int.
14- if args :
15- if len (args ) != 2 :
16- raise SimpleError (msgs .SYNTAX_ERROR_MSG )
17- start = Int .decode (args [0 ])
18- end = Int .decode (args [1 ])
19- start , end = fix_range_string (start , end , len (key .value ))
20- value = key .value [start :end ]
21- else :
14+ if len (args ) == 0 :
2215 value = key .value
16+ return bin (int .from_bytes (value , 'little' )).count ('1' )
17+
18+ if not 2 <= len (args ) <= 3 :
19+ raise SimpleError (msgs .SYNTAX_ERROR_MSG )
20+ start = Int .decode (args [0 ])
21+ end = Int .decode (args [1 ])
22+ bit_mode = False
23+ if len (args ) == 3 :
24+ bit_mode = casematch (args [2 ], b'bit' )
25+ if not bit_mode and not casematch (args [2 ], b'byte' ):
26+ raise SimpleError (msgs .SYNTAX_ERROR_MSG )
27+
28+ if bit_mode :
29+ value = key .value .decode () if key .value else ''
30+ value = list (map (int , '' .join ([bin (ord (i )).lstrip ('0b' ).rjust (8 , '0' ) for i in value ])))
31+ start , end = fix_range_string (start , end , len (value ))
32+ return value [start :end ].count (1 )
33+ start , end = fix_range_string (start , end , len (key .value ))
34+ value = key .value [start :end ]
35+
2336 return bin (int .from_bytes (value , 'little' )).count ('1' )
2437
2538 @command ((Key (bytes ), BitOffset ))
0 commit comments