@@ -167,22 +167,26 @@ function Base.IndexStyle(::Type{S}) where {S<:StructArray}
167167 index_type (S) === Int ? IndexLinear () : IndexCartesian ()
168168end
169169
170- function _undef_array (:: Type{T} , sz; unwrap:: F = alwaysfalse) where {T, F}
170+ function undef_array (:: Type{T} , sz; unwrap:: F = alwaysfalse) where {T, F}
171171 if unwrap (T)
172172 return StructArray {T} (undef, sz; unwrap = unwrap)
173173 else
174174 return Array {T} (undef, sz)
175175 end
176176end
177177
178- function _similar (v:: AbstractArray , :: Type{Z} ; unwrap:: F = alwaysfalse) where {Z, F}
178+ function similar_array (v:: AbstractArray , :: Type{Z} ; unwrap:: F = alwaysfalse) where {Z, F}
179179 if unwrap (Z)
180- return buildfromschema (typ -> _similar (v, typ; unwrap = unwrap), Z)
180+ return buildfromschema (typ -> similar_array (v, typ; unwrap = unwrap), Z)
181181 else
182182 return similar (v, Z)
183183 end
184184end
185185
186+ function similar_structarray (v:: AbstractArray , :: Type{Z} ; unwrap:: F = alwaysfalse) where {Z, F}
187+ buildfromschema (typ -> similar_array (v, typ; unwrap = unwrap), Z)
188+ end
189+
186190"""
187191 StructArray{T}(undef, dims; unwrap=T->false)
188192
@@ -204,14 +208,10 @@ julia> StructArray{ComplexF64}(undef, (2,3))
204208StructArray (:: Base.UndefInitializer , sz:: Dims )
205209
206210function StructArray {T} (:: Base.UndefInitializer , sz:: Dims ; unwrap:: F = alwaysfalse) where {T, F}
207- buildfromschema (typ -> _undef_array (typ, sz; unwrap = unwrap), T)
211+ buildfromschema (typ -> undef_array (typ, sz; unwrap = unwrap), T)
208212end
209213StructArray {T} (u:: Base.UndefInitializer , d:: Integer... ; unwrap:: F = alwaysfalse) where {T, F} = StructArray {T} (u, convert (Dims, d); unwrap = unwrap)
210214
211- function similar_structarray (v:: AbstractArray , :: Type{Z} ; unwrap:: F = alwaysfalse) where {Z, F}
212- buildfromschema (typ -> _similar (v, typ; unwrap = unwrap), Z)
213- end
214-
215215"""
216216 StructArray(A; unwrap = T->false)
217217
@@ -276,14 +276,34 @@ Base.convert(::Type{StructArray}, v::StructArray) = v
276276Base. convert (:: Type{StructVector} , v:: AbstractVector ) = StructVector (v)
277277Base. convert (:: Type{StructVector} , v:: StructVector ) = v
278278
279- function Base. similar (:: Type{<:StructArray{T, <:Any, C}} , sz:: Dims ) where {T, C}
280- buildfromschema (typ -> similar (typ, sz), T, C)
279+ # Mimic OffsetArrays signatures
280+ const OffsetAxisKnownLength = Union{Integer, AbstractUnitRange}
281+ const OffsetAxis = Union{OffsetAxisKnownLength, Colon}
282+
283+ const OffsetShapeKnownLength = Tuple{OffsetAxisKnownLength,Vararg{OffsetAxisKnownLength}}
284+ const OffsetShape = Tuple{OffsetAxis,Vararg{OffsetAxis}}
285+
286+ # Helper function to avoid adding too many dispatches to `Base.similar`
287+ function _similar (s:: StructArray{T} , :: Type{T} , sz) where {T}
288+ return StructArray {T} (map (typ -> similar (typ, sz), components (s)))
281289end
282290
283- Base. similar (s:: StructArray , sz:: Base.DimOrInd... ) = similar (s, Base. to_shape (sz))
284- Base. similar (s:: StructArray ) = similar (s, Base. to_shape (axes (s)))
285- function Base. similar (s:: StructArray{T} , sz:: Tuple ) where {T}
286- StructArray {T} (map (typ -> similar (typ, sz), components (s)))
291+ function _similar (s:: StructArray{T} , S:: Type , sz) where {T}
292+ # If not specified, we don't really know what kind of array to use for each
293+ # interior type, so we just pick the first one arbitrarily. If users need
294+ # something else, they need to be more specific.
295+ c1 = first (components (s))
296+ return isnonemptystructtype (S) ? buildfromschema (typ -> similar (c1, typ, sz), S) : similar (c1, S, sz)
297+ end
298+
299+ for type in (:Dims , :OffsetShapeKnownLength )
300+ @eval function Base. similar (:: Type{<:StructArray{T, N, C}} , sz:: $ (type)) where {T, N, C}
301+ return buildfromschema (typ -> similar (typ, sz), T, C)
302+ end
303+
304+ @eval function Base. similar (s:: StructArray , S:: Type , sz:: $ (type))
305+ return _similar (s, S, sz)
306+ end
287307end
288308
289309@deprecate fieldarrays (x) StructArrays. components (x)
437457
438458Base. copy (s:: StructArray{T} ) where {T} = StructArray {T} (map (copy, components (s)))
439459
440- function Base. reshape (s:: StructArray{T} , d:: Dims ) where {T}
441- StructArray {T} (map (x -> reshape (x, d), components (s)))
460+ for type in (:Dims , :OffsetShape )
461+ @eval function Base. reshape (s:: StructArray{T} , d:: $ (type)) where {T}
462+ StructArray {T} (map (x -> reshape (x, d), components (s)))
463+ end
442464end
443465
444466function showfields (io:: IO , fields:: NTuple{N, Any} ) where N
0 commit comments