File 8361-ASN.1-JER-Support-decoding-already-decoded-JSON-data.patch of Package erlang

From 618b46b379cf1787df1b2287f0f3de91cb8b9ca1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
Date: Tue, 18 Mar 2025 13:55:37 +0100
Subject: [PATCH] ASN.1 JER: Support decoding already decoded JSON data

---
 lib/asn1/doc/guides/asn1_getting_started.md |  26 +++++
 lib/asn1/src/asn1ct_gen.erl                 | 123 ++++++++++----------
 lib/asn1/test/asn1_test_lib.erl             |  14 ++-
 3 files changed, 96 insertions(+), 67 deletions(-)

diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl
index 213e4f5b82..8926be42ac 100644
--- a/lib/asn1/src/asn1ct_gen.erl
+++ b/lib/asn1/src/asn1ct_gen.erl
@@ -803,6 +803,7 @@ pgen_dispatcher(Gen, Types) ->
         false ->
             ok
     end,
+
     %% DECODER
     ReturnRest = proplists:get_bool(undec_rest, Gen#gen.options),
     Data = case Gen#gen.erule =:= ber andalso ReturnRest of
@@ -811,6 +812,31 @@ pgen_dispatcher(Gen, Types) ->
 	   end,
 
     emit(["decode(Type, ",Data,") ->",nl]),
+    pgen_dispatcher_decode(Gen, ReturnRest, NoOkWrapper),
+
+    case Gen#gen.jer of
+        true ->
+            emit(["jer_decode(Type, ",Data,") ->",nl]),
+            pgen_dispatcher_decode(Gen#gen{erule=jer},
+                                   ReturnRest, NoOkWrapper);
+        false ->
+            ok
+    end,
+
+    %% REST of MODULE
+    gen_decode_partial_incomplete(Gen, NoOkWrapper),
+    gen_partial_inc_dispatcher(Gen),
+
+    case Gen of
+        #gen{erule=jer} ->
+            ok;
+        _ ->
+            gen_dispatcher(Types, "encode_disp", "enc_"),
+            gen_dispatcher(Types, "decode_disp", "dec_")
+    end.
+
+pgen_dispatcher_decode(Gen, ReturnRest, NoOkWrapper) ->
+    CurrMod = lists:concat(["'",get(currmod),"'"]),
 
     case NoOkWrapper of
         false -> emit(["try",nl]);
@@ -818,85 +844,52 @@ pgen_dispatcher(Gen, Types) ->
     end,
 
     DecWrap =
-	case {Gen,ReturnRest} of
-	    {#gen{erule=ber},false} ->
-		asn1ct_func:need({ber,ber_decode_nif,1}),
-		"element(1, ber_decode_nif(Data))";
-	    {#gen{erule=ber},true} ->
-		asn1ct_func:need({ber,ber_decode_nif,1}),
-		emit(["   {Data,Rest} = ber_decode_nif(Data0),",nl]),
-		"Data";
-	    {#gen{erule=jer},false} ->
-		"json:decode(Data)";
-	    {#gen{erule=jer},true} ->
-		exit("JER + return rest not supported");
-	    {_,_} ->
-		"Data"
-	end,
+        case {Gen,ReturnRest} of
+            {#gen{erule=ber},false} ->
+                asn1ct_func:need({ber,ber_decode_nif,1}),
+                "element(1, ber_decode_nif(Data))";
+            {#gen{erule=ber},true} ->
+                asn1ct_func:need({ber,ber_decode_nif,1}),
+                emit(["   {Data,Rest} = ber_decode_nif(Data0),",nl]),
+                "Data";
+            {#gen{erule=jer},false} ->
+                "case Data of\n"
+                "    {json_decoded,Decoded} -> Decoded;\n"
+                "    _ -> json:decode(Data)\n"
+                "end\n";
+            {#gen{erule=jer},true} ->
+                exit("JER + return rest not supported");
+            {_,_} ->
+                "Data"
+        end,
 
     DecodeDisp = ["decode_disp(Type, ",DecWrap,")"],
     case {Gen,ReturnRest} of
-	{#gen{erule=ber},true} ->
-	    emit(["   Result = ",DecodeDisp,",",nl]),
+        {#gen{erule=ber},true} ->
+            emit(["   Result = ",DecodeDisp,",",nl]),
             result_line(NoOkWrapper, ["Result","Rest"]);
-	{#gen{erule=ber},false} ->
-	    emit(["   Result = ",DecodeDisp,",",nl]),
+        {#gen{erule=ber},false} ->
+            emit(["   Result = ",DecodeDisp,",",nl]),
             result_line(NoOkWrapper, ["Result"]);
-	{#gen{erule=jer},false} ->
-	    emit(["   Result = ",{call,jer,decode_jer,[CurrMod,"Type",DecWrap]},",",nl]),
+        {#gen{erule=JER},false} when JER =:= jer ->
+            emit(["   Result = ",{call,jer,decode_jer,[CurrMod,"Type",DecWrap]},",",nl]),
             result_line(NoOkWrapper, ["Result"]);
-
-
-	{#gen{erule=per},true} ->
-	    emit(["   {Result,Rest} = ",DecodeDisp,",",nl]),
+        {#gen{erule=per},true} ->
+            emit(["   {Result,Rest} = ",DecodeDisp,",",nl]),
             result_line(NoOkWrapper, ["Result","Rest"]);
-	{#gen{erule=per},false} ->
-	    emit(["   {Result,_Rest} = ",DecodeDisp,",",nl]),
+        {#gen{erule=per},false} ->
+            emit(["   {Result,_Rest} = ",DecodeDisp,",",nl]),
             result_line(NoOkWrapper, ["Result"])
     end,
 
     case NoOkWrapper of
-	false ->
-	    emit([nl,try_catch(),".",nl,nl]);
-	true ->
-	    emit([".",nl,nl])
-    end,
-
-    case Gen#gen.jer of
-        true ->
-            emit(["jer_decode(Type, ",Data,") ->",nl]),
-            case NoOkWrapper of
-                false -> emit(["try",nl]);
-                true -> ok
-            end,
-            JerDecWrap = "json:decode(Data)",
-	    emit(["   Result = ",
-                  {call,jer,
-                   decode_jer,
-                   [CurrMod,"Type",JerDecWrap]},",",nl]),
-            result_line(false, ["Result"]),
-            case NoOkWrapper of
-                false ->
-                    emit([nl,try_catch(),".",nl,nl]);
-                true ->
-                    emit([".",nl,nl])
-            end;        
         false ->
+            emit([nl,try_catch()]);
+        true ->
             ok
     end,
-    
-
-    %% REST of MODULE
-    gen_decode_partial_incomplete(Gen, NoOkWrapper),
-    gen_partial_inc_dispatcher(Gen),
 
-    case Gen of
-        #gen{erule=jer} ->
-            ok;
-        _ ->
-            gen_dispatcher(Types, "encode_disp", "enc_"),
-            gen_dispatcher(Types, "decode_disp", "dec_")
-    end.
+    emit([".",nl,nl]).
 
 result_line(NoOkWrapper, Items) ->
     S = ["   "|case NoOkWrapper of
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index 7a271cb1d7..a6d0e963a4 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -197,7 +197,7 @@ roundtrip_enc(Mod, Type, Value, ExpectedValue) ->
             ExpectedValue = Mod:decode(Type, Encoded)
     end,
     map_roundtrip(Mod, Type, Encoded),
-    test_ber_indefinite(Mod, Type, Encoded, ExpectedValue),
+    test_special(Mod, Type, Encoded, ExpectedValue),
     Encoded.
 
 map_roundtrip(Mod, Type, Encoded) ->
@@ -248,9 +248,10 @@ match_value_tuple(I, T1, T2) when I =< tuple_size(T1) ->
 match_value_tuple(_, _, _) ->
     ok.
 
-test_ber_indefinite(Mod, Type, Encoded, ExpectedValue) ->
+test_special(Mod, Type, Encoded, ExpectedValue) ->
     case Mod:encoding_rule() of
 	ber ->
+            %% Test indefinite decoding for BER.
 	    Indefinite = iolist_to_binary(ber_indefinite(Encoded)),
             case Mod:decode(Type, Indefinite) of
                 {ok,ExpectedValue} ->
@@ -258,7 +259,14 @@ test_ber_indefinite(Mod, Type, Encoded, ExpectedValue) ->
                 ExpectedValue ->
                     ok
             end;
-	_ ->
+        jer ->
+            %% Test already decoded JSON for JER.
+            JsonDecoded = json:decode(Encoded),
+            case Mod:decode(Type, {json_decoded,JsonDecoded}) of
+                {ok,ExpectedValue} -> ok;
+                ExpectedValue -> ok
+            end;
+        _ ->
 	    ok
     end.
 
-- 
2.43.0

openSUSE Build Service is sponsored by