@@ -51,6 +51,25 @@ module Encode =
5151 | Some pair -> acc @ [ pair]
5252 | None -> acc
5353
54+ // ------------------------------
55+ // Helper for recursive array shorthand detection
56+ // ------------------------------
57+ let rec tryGetArrayShorthand ( cwlType : CWLType ) : string option =
58+ match cwlType with
59+ | File _ -> Some " File"
60+ | Directory _ -> Some " Directory"
61+ | Dirent _ -> Some " Dirent"
62+ | String -> Some " string"
63+ | Int -> Some " int"
64+ | Long -> Some " long"
65+ | Float -> Some " float"
66+ | Double -> Some " double"
67+ | Boolean -> Some " boolean"
68+ | Array innerSchema ->
69+ // Recursively get shorthand for inner type and append []
70+ tryGetArrayShorthand innerSchema.Items |> Option.map ( fun s -> s + " []" )
71+ | _ -> None
72+
5473 // ------------------------------
5574 // CWLType encoder
5675 // ------------------------------
@@ -87,17 +106,10 @@ module Encode =
87106 | Double -> Encode.string " double?"
88107 | Boolean -> Encode.string " boolean?"
89108 | Array arraySchema ->
90- // Optional array - check if items are simple
91- match arraySchema.Items with
92- | File _ -> Encode.string " File[]?"
93- | Directory _ -> Encode.string " Directory[]?"
94- | String -> Encode.string " string[]?"
95- | Int -> Encode.string " int[]?"
96- | Long -> Encode.string " long[]?"
97- | Float -> Encode.string " float[]?"
98- | Double -> Encode.string " double[]?"
99- | Boolean -> Encode.string " boolean[]?"
100- | _ ->
109+ // Optional array - use recursive shorthand detection
110+ match tryGetArrayShorthand arraySchema.Items with
111+ | Some shorthand -> Encode.string ( shorthand + " []?" )
112+ | None ->
101113 // Complex optional array - use full form
102114 YAMLElement.Sequence [ Encode.string " null" ; encodeInputArraySchema arraySchema ]
103115 | _ ->
@@ -107,21 +119,9 @@ module Encode =
107119 // General union - use array form
108120 typesList |> List.map encodeCWLType |> YAMLElement.Sequence
109121 | Array arraySchema ->
110- // Try to use short form for simple arrays
111- let shortForm =
112- match arraySchema.Items with
113- | File _ -> Some " File[]"
114- | Directory _ -> Some " Directory[]"
115- | Dirent _ -> Some " Dirent[]"
116- | String -> Some " string[]"
117- | Int -> Some " int[]"
118- | Long -> Some " long[]"
119- | Float -> Some " float[]"
120- | Double -> Some " double[]"
121- | Boolean -> Some " boolean[]"
122- | _ -> None
123- match shortForm with
124- | Some s -> Encode.string s
122+ // Try to use short form for arrays (handles arbitrary nesting depth recursively)
123+ match tryGetArrayShorthand arraySchema.Items with
124+ | Some shorthand -> Encode.string ( shorthand + " []" )
125125 | None -> encodeInputArraySchema arraySchema
126126 | Record recordSchema -> encodeInputRecordSchema recordSchema
127127 | Enum enumSchema -> encodeInputEnumSchema enumSchema
@@ -504,4 +504,55 @@ module Encode =
504504 let encodeProcessingUnit ( pu : CWLProcessingUnit ) : string =
505505 match pu with
506506 | CommandLineTool td -> encodeToolDescription td
507- | Workflow wd -> encodeWorkflowDescription wd
507+ | Workflow wd -> encodeWorkflowDescription wd
508+
509+ /// Escape a string for JSON
510+ let private jsonEscapeString ( s : string ) =
511+ s.Replace( " \\ " , " \\\\ " )
512+ .Replace( " \" " , " \\\" " )
513+ .Replace( " \n " , " \\ n" )
514+ .Replace( " \r " , " \\ r" )
515+ .Replace( " \t " , " \\ t" )
516+
517+ /// Encode a CWLType to a JSON string
518+ /// Note: This is only called for complex types without shorthand notation
519+ let rec encodeCWLTypeJson ( t : CWLType ) : string =
520+ match t with
521+ | Union types ->
522+ // Union of complex types - use array form
523+ let encodedTypes = types |> Seq.toList |> List.map encodeCWLTypeJson
524+ " [" + String.concat " ," encodedTypes + " ]"
525+ | Array arraySchema ->
526+ // Array of complex type
527+ encodeInputArraySchemaJson arraySchema
528+ | Record recordSchema -> encodeInputRecordSchemaJson recordSchema
529+ | Enum enumSchema -> encodeInputEnumSchemaJson enumSchema
530+ | _ ->
531+ // Fallback for any simple type (shouldn't be reached, but include for safety)
532+ failwith " encodeCWLTypeJson should only be called for complex types"
533+
534+ and encodeInputRecordFieldJson ( field : InputRecordField ) : string =
535+ sprintf " \" %s \" :{\" type\" :%s }" ( jsonEscapeString field.Name) ( encodeCWLTypeJson field.Type)
536+
537+ and encodeInputRecordSchemaJson ( schema : InputRecordSchema ) : string =
538+ let fieldsJson =
539+ match schema.Fields with
540+ | Some fs ->
541+ fs |> Seq.map encodeInputRecordFieldJson |> String.concat " ,"
542+ | None -> " "
543+
544+ sprintf " {\" type\" :\" record\" ,\" fields\" :{%s }}" fieldsJson
545+
546+ and encodeInputEnumSchemaJson ( schema : InputEnumSchema ) : string =
547+ let symbolsJson =
548+ schema.Symbols
549+ |> Seq.map ( fun s -> sprintf " \" %s \" " ( jsonEscapeString s))
550+ |> String.concat " ,"
551+ sprintf " {\" type\" :\" enum\" ,\" symbols\" :[%s ]}" symbolsJson
552+
553+ and encodeInputArraySchemaJson ( schema : InputArraySchema ) : string =
554+ sprintf " {\" type\" :\" array\" ,\" items\" :%s }" ( encodeCWLTypeJson schema.Items)
555+
556+ /// Convert a CWLType to a compact JSON string for use in JSON serialization
557+ let cwlTypeToJsonString ( t : CWLType ) : string =
558+ encodeCWLTypeJson t
0 commit comments