@@ -34,6 +34,7 @@ import Dates
3434import Dates: DateTime, Second, Millisecond
3535import PooledArrays: PooledArray, RefArray
3636using Tables: Tables
37+ import OrderedCollections: OrderedDict
3738
3839export MatlabStructArray, StructArrayField, convert_struct_array
3940export MatlabClassObject
@@ -68,7 +69,7 @@ using MAT
6869s_arr = MatlabStructArray(["a", "b"], [[1, 2],["foo", 5]])
6970
7071# write-read
71- matwrite("matfile.mat", Dict("struct_array" => s_arr))
72+ matwrite("matfile.mat", Dict{String,Any} ("struct_array" => s_arr))
7273read_s_arr = matread("matfile.mat")["struct_array"]
7374
7475# convert to Dict Array
@@ -144,6 +145,8 @@ Base.haskey(arr::MatlabStructArray, k::AbstractString) = k in keys(arr)
144145function Base. copy (arr:: MatlabStructArray{N} ) where {N}
145146 return MatlabStructArray {N} (copy (arr. names), copy (arr. values))
146147end
148+ class (arr:: MatlabStructArray ) = arr. class
149+ class (d:: AbstractDict ) = " "
147150
148151function Base. iterate (arr:: T , i= next_state (arr)) where {T<: MatlabStructArray }
149152 if i == 0
@@ -255,6 +258,16 @@ function Base.Array{D,N}(arr::MatlabStructArray{N}) where {D<:AbstractDict,N}
255258 return result
256259end
257260
261+ function Base. getindex (arr:: MatlabStructArray , s:: Integer )
262+ row_values = [getindex (v, s) for v in arr. values]
263+ if isempty (arr. class)
264+ D = Dict{String,Any}
265+ else
266+ D = OrderedDict{String,Any}
267+ end
268+ return create_struct (D, arr. names, row_values, arr. class)
269+ end
270+
258271function create_struct (:: Type{D} , keys, values, class:: String ) where {T,D<: AbstractDict{T} }
259272 return D (T .(keys) .=> values)
260273end
@@ -284,7 +297,7 @@ Internal Marker for Empty Structs with dimensions like 1x0 or 0x0
284297struct EmptyStruct
285298 dims:: Vector{UInt64}
286299end
287-
300+ class (m :: EmptyStruct ) = " "
288301
289302"""
290303 MatlabClassObject(
@@ -296,11 +309,13 @@ Type to store old class objects. Inside MATLAB a class named \"TestClassOld\" wo
296309
297310If you want to write these objects you have to make sure the keys in the Dict match the class defined properties/fields.
298311"""
299- struct MatlabClassObject <: AbstractDict{String,Any}
300- d:: Dict{String,Any}
312+ struct MatlabClassObject{D <: AbstractDict{String,Any} } <: AbstractDict{String,Any}
313+ d:: D
301314 class:: String
302315end
303316
317+ class (m:: MatlabClassObject ) = m. class
318+
304319Base. eltype (:: Type{MatlabClassObject} ) = Pair{String,Any}
305320Base. length (m:: MatlabClassObject ) = length (m. d)
306321Base. keys (m:: MatlabClassObject ) = keys (m. d)
@@ -320,7 +335,7 @@ function Base.isapprox(m1::MatlabClassObject, m2::MatlabClassObject; kwargs...)
320335 return m1. class == m2. class && dict_isapprox (m1. d, m2. d; kwargs... )
321336end
322337
323- function MatlabStructArray (arr:: AbstractArray{MatlabClassObject} )
338+ function MatlabStructArray (arr:: AbstractArray{<: MatlabClassObject} )
324339 first_obj, remaining_obj = Iterators. peel (arr)
325340 class = first_obj. class
326341 if ! all (x -> isequal (class, x. class), remaining_obj)
@@ -331,7 +346,7 @@ function MatlabStructArray(arr::AbstractArray{MatlabClassObject})
331346 return MatlabStructArray (arr, class)
332347end
333348
334- function convert_struct_array (d:: Dict {String,Any} , class:: String = " " )
349+ function convert_struct_array (d:: AbstractDict {String,Any} , class:: String = " " )
335350 # there is no possibility of having cell arrays mixed with struct arrays (afaik)
336351 field_values = first (values (d))
337352 if field_values isa StructArrayField
@@ -351,13 +366,15 @@ function Base.Array(arr::MatlabStructArray{N}) where {N}
351366 if isempty (arr. class)
352367 return Array {Dict{String,Any},N} (arr)
353368 else
354- return Array {MatlabClassObject,N} (arr)
369+ # ordered dict by default, to preserve field order
370+ D = OrderedDict{String,Any}
371+ return Array {MatlabClassObject{D},N} (arr)
355372 end
356373end
357374
358- function create_struct (:: Type{D} , keys, values, class:: String ) where {D<: MatlabClassObject }
359- d = Dict {String,Any} (string .(keys) .=> values)
360- return MatlabClassObject (d, class)
375+ function create_struct (:: Type{MatlabClassObject{D}} , keys, values, class:: String ) where {D<: AbstractDict }
376+ d = D (string .(keys) .=> values)
377+ return MatlabClassObject {D} (d, class)
361378end
362379
363380"""
@@ -370,10 +387,11 @@ Type to store opaque class objects.
370387These are the 'modern' Matlab classes, different from the old `MatlabClassObject` types.
371388
372389"""
373- struct MatlabOpaque <: AbstractDict{String,Any}
374- d:: Dict{String,Any}
390+ struct MatlabOpaque{D <: AbstractDict{String,Any} } <: AbstractDict{String,Any}
391+ d:: D
375392 class:: String
376393end
394+ class (m:: MatlabOpaque ) = m. class
377395
378396Base. eltype (:: Type{MatlabOpaque} ) = Pair{String,Any}
379397Base. length (m:: MatlabOpaque ) = length (m. d)
492510
493511function MatlabOpaque (d:: ScalarOrArray{DateTime} )
494512 return MatlabOpaque (
495- Dict (
513+ Dict {String,Any} (
496514 " tz" => " " ,
497515 " data" => map_or_not (to_matlab_data, d),
498516 " fmt" => " " ,
@@ -514,7 +532,7 @@ to_matlab_millis(d::Millisecond) = Float64(Dates.value(d))
514532
515533function MatlabOpaque (d:: ScalarOrArray{Millisecond} )
516534 return MatlabOpaque (
517- Dict (
535+ Dict {String,Any} (
518536 " millis" => map_or_not (to_matlab_millis, d),
519537 ),
520538 " duration"
0 commit comments