processone / xmpp

Erlang/Elixir XMPP parsing and serialization library on top of Fast XML
http://process-one.net
Apache License 2.0
137 stars 88 forks source link

How to decode with var #7

Closed grizzly-monkey closed 7 years ago

grizzly-monkey commented 7 years ago

Hello i want to write a custom spec in xmpp_codec.spec which will decode json cdata

_-xml(sync,

elem{name = <<"sync">>,

 xmlns =  <<"mycustom:xmlsns:sync">>,
 cdata =  #cdata{label = '$json',
              dec = {jsonutil,dec_json, []},  ### how to pass the attribute variable here 
              enc = {jsonutil,enc_json, []}},  ### how to pass the attribute variable here 
 result = {sync, '$c','$json', '$_els'},
 attrs = [ #attr{name = <<"c">>,
                 default = 0}
         ]})._

in dec = dec_json , [] i want to pass the label '$c' so that my decode will be based on '$c'

how can i achieve this right now it just accepts the atom or constants is it possible to pass a attribute var ? any other method i can achieve this?

Merci

zinid commented 7 years ago

Conditional decoding is unsupported. I was thinking about it, but it's not that simple and may introduce infinite loops.

zinid commented 7 years ago

Also, 'default = 0' is incorrect, you need to add dec/enc functions in this case.

zinid commented 7 years ago

It seems like you need something like this:

-xml(sync,
     #elem{name = <<"sync">>,
           xmlns = <<"mycustom:xmlsns:sync">>,
           result = {sync, '$c','$json', '$_els'},
           cdata = #cdata{label = '$json'},
           attrs = [#attr{name = <<"c">>,
                          enc = {enc_int, []},
                          dec = {dec_int, [0, unlimited]},
                          default = 0}]}).

Then in ejabberd's code you should add json decoding/encoding of #sync.json based on #sync.c value.

grizzly-monkey commented 7 years ago

yes zinid you are correct i need enc = {enc_int, []}, dec = {dec_int, [0, unlimited]},

however my json decoding should happen based on my attribute <<"c">> is there any other way you could point me to and i can try it

zinid commented 7 years ago

No, you should make decoding manually in the code, as I said above. E.g.

foo(#sync{c = C, json = Data}) when C == 0 ->
    try jiffy:decode(Data) of
       JSON -> do_something(JSON)
    catch _:_ ->
          process_invalid_json()
    end;
...
zinid commented 7 years ago

I actually need this conditional decoding myself in some places (like privacy lists decoding), but implementing this is tough.

grizzly-monkey commented 7 years ago

Cool thanks hope we can get this conditional decoding ... :) thanks for your help 👍