@@ -122,40 +122,89 @@ class FillValueCoder:
122122 """
123123
124124 @classmethod
125- def encode (cls , value : int | float | str | bytes , dtype : np .dtype [Any ]) -> Any :
125+ def encode (
126+ cls , value : int | float | complex | str | bytes , dtype : np .dtype [Any ]
127+ ) -> Any :
126128 if dtype .kind == "S" :
127129 # byte string, this implies that 'value' must also be `bytes` dtype.
128- assert isinstance (value , bytes )
130+ if not isinstance (value , bytes ):
131+ raise TypeError (
132+ f"Failed to encode fill_value: expected bytes for dtype { dtype } , got { type (value ).__name__ } "
133+ )
129134 return base64 .standard_b64encode (value ).decode ()
130135 elif dtype .kind == "b" :
131136 # boolean
132137 return bool (value )
133138 elif dtype .kind in "iu" :
134- # todo: do we want to check for decimals?
139+ if not isinstance (value , int | float | np .integer | np .floating ):
140+ raise TypeError (
141+ f"Failed to encode fill_value: expected int or float for dtype { dtype } , got { type (value ).__name__ } "
142+ )
135143 return int (value )
136144 elif dtype .kind == "f" :
145+ if not isinstance (value , int | float | np .integer | np .floating ):
146+ raise TypeError (
147+ f"Failed to encode fill_value: expected int or float for dtype { dtype } , got { type (value ).__name__ } "
148+ )
137149 return base64 .standard_b64encode (struct .pack ("<d" , float (value ))).decode ()
150+ elif dtype .kind == "c" :
151+ # complex - encode each component as base64, matching float encoding
152+ if not isinstance (value , complex ) and not np .issubdtype (
153+ type (value ), np .complexfloating
154+ ):
155+ raise TypeError (
156+ f"Failed to encode fill_value: expected complex for dtype { dtype } , got { type (value ).__name__ } "
157+ )
158+ return [
159+ base64 .standard_b64encode (
160+ struct .pack ("<d" , float (value .real )) # type: ignore[union-attr]
161+ ).decode (),
162+ base64 .standard_b64encode (
163+ struct .pack ("<d" , float (value .imag )) # type: ignore[union-attr]
164+ ).decode (),
165+ ]
138166 elif dtype .kind == "U" :
139167 return str (value )
140168 else :
141169 raise ValueError (f"Failed to encode fill_value. Unsupported dtype { dtype } " )
142170
143171 @classmethod
144- def decode (cls , value : int | float | str | bytes , dtype : str | np .dtype [Any ]):
172+ def decode (
173+ cls , value : int | float | str | bytes | list , dtype : str | np .dtype [Any ]
174+ ):
145175 if dtype == "string" :
146176 # zarr V3 string type
147177 return str (value )
148178 elif dtype == "bytes" :
149179 # zarr V3 bytes type
150- assert isinstance (value , str | bytes )
180+ if not isinstance (value , str | bytes ):
181+ raise TypeError (
182+ f"Failed to decode fill_value: expected str or bytes for dtype { dtype } , got { type (value ).__name__ } "
183+ )
151184 return base64 .standard_b64decode (value )
152185 np_dtype = np .dtype (dtype )
153186 if np_dtype .kind == "f" :
154- assert isinstance (value , str | bytes )
187+ if not isinstance (value , str | bytes ):
188+ raise TypeError (
189+ f"Failed to decode fill_value: expected str or bytes for dtype { np_dtype } , got { type (value ).__name__ } "
190+ )
155191 return struct .unpack ("<d" , base64 .standard_b64decode (value ))[0 ]
192+ elif np_dtype .kind == "c" :
193+ # complex - decode each component from base64, matching float decoding
194+ if not (isinstance (value , list | tuple ) and len (value ) == 2 ):
195+ raise TypeError (
196+ f"Failed to decode fill_value: expected a 2-element list for dtype { np_dtype } , got { type (value ).__name__ } "
197+ )
198+ real = struct .unpack ("<d" , base64 .standard_b64decode (value [0 ]))[0 ]
199+ imag = struct .unpack ("<d" , base64 .standard_b64decode (value [1 ]))[0 ]
200+ return complex (real , imag )
156201 elif np_dtype .kind == "b" :
157202 return bool (value )
158203 elif np_dtype .kind in "iu" :
204+ if not isinstance (value , int | float | np .integer | np .floating ):
205+ raise TypeError (
206+ f"Failed to decode fill_value: expected int or float for dtype { np_dtype } , got { type (value ).__name__ } "
207+ )
159208 return int (value )
160209 else :
161210 raise ValueError (f"Failed to decode fill_value. Unsupported dtype { dtype } " )
0 commit comments