changeset 38:bae384998d85

JSON: Improve empty field detector
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 25 Mar 2023 21:19:46 +0100
parents 37a528750178
children 8a21e7a32029
files julia/parallel/ParallelProcessing/src/ParallelProcessing.jl julia/parallel/ParallelProcessing/src/metaparser.jl
diffstat 2 files changed, 47 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/julia/parallel/ParallelProcessing/src/ParallelProcessing.jl	Fri Mar 24 22:07:52 2023 +0100
+++ b/julia/parallel/ParallelProcessing/src/ParallelProcessing.jl	Sat Mar 25 21:19:46 2023 +0100
@@ -1,7 +1,8 @@
 module ParallelProcessing
 
-include("json.jl")
 
 include("jsonparser.jl")
 include("metaparser.jl")
+include("json.jl")
+
 end # module ParallelProcessing
--- a/julia/parallel/ParallelProcessing/src/metaparser.jl	Fri Mar 24 22:07:52 2023 +0100
+++ b/julia/parallel/ParallelProcessing/src/metaparser.jl	Sat Mar 25 21:19:46 2023 +0100
@@ -16,11 +16,15 @@
             "Field $f in $typedef must be type! (we don't support constructors etc. - struct must be plain)",
         )
         name, typ = f.args
-        typeof(typ) == Symbol ||
+
+        is_type = (typeof(typ) == Symbol || (typeof(typ) == Expr && typ.head == :curly))
+        is_type ||
             error("Type of $f should be symbol (simple type) but is $(typeof(typ)): $typ")
+
         typ = eval(typ)
         isconcretetype(typ) ||
             error("Type of field $name must be concrete, but is not (is $typ)!")
+
         push!(fields_exprs, name => eval(typ))
     end
 
@@ -38,22 +42,53 @@
     end
 end
 
+function map_type_to_parse_method(::Type{<:Number})::Symbol
+    :take_num!
+end
+function map_type_to_parse_method(::Type{<:AbstractString})::Symbol
+    :take_str!
+end
+function map_type_to_parse_method(::Type{Bool})::Symbol
+    :take_bool!
+end
+function map_type_to_parse_method(::Type{<:AbstractDict})::Symbol
+    :take_object!
+end
+function map_type_to_parse_method(::Type{<:AbstractVector})::Symbol
+    :take_list!
+end
+function map_type_to_parse_method(::Type{T})::Symbol where {T}
+    error("unexpected type")
+    if isstructtype(T)
+        :take_struct!
+    else
+        error("Unknown type $T for JSON parsing!")
+    end
+end
+
+function check_variables_filled_expr(varnames::AbstractVector{Symbol})::Vector{Expr}
+    check_var_cond(sym) = begin
+        syms = string(sym)
+        quote
+            syms = $syms
+            if isnothing($sym)
+                error("Field $syms not given in JSON object!")
+            end
+        end
+    end
+    [check_var_cond(s) for s in varnames]
+end
+
 function json_parseable(strct)
     typs::Vector{Pair{Symbol,Type}} = parse_struct(strct)
     typ = get_type_of_struct(strct)
 
     fieldvars = [:($(name)::Union{$typ,Nothing} = nothing) for (name, typ) in typs]
     fieldnames = [name for (name, _) in typs]
+    fields_filled_cond = check_variables_filled_expr(fieldnames)
     Mod = :ParallelProcessing
 
-    method_map = Dict(
-        Int64 => :take_num!,
-        Float64 => :take_num!,
-        String => :take_str!,
-        Dict => :take_object!,
-        Bool => :take_bool!,
-    )
-    methods = [(name, method_map[typ]) for (name, typ) in typs]
+    methods = [(name, map_type_to_parse_method(typ)) for (name, typ) in typs]
     field_dispatch = [
         quote
             if !matched && key == $(string(name))
@@ -96,9 +131,7 @@
                 end
             end
 
-            #if $(fields_filled_cond...)
-            #    error("Elements missing from object")
-            #end
+            $(fields_filled_cond...)
 
             $Mod.expect!(jp, '}') || error("unclosed object")