Строковая версия term_to_binary - PullRequest
2 голосов
/ 21 октября 2010

Я пытаюсь написать простой сервер, который общается с клиентами через tcp. У меня он отлично посылает сообщения, но теперь я хочу, чтобы он интерпретировал сообщения как типы данных Erlang. Например, представьте, что он похож на HTTP (это не так) и что я хочу отправить от клиента {get, "/foo.html"}, и пусть сервер интерпретирует это как кортеж, содержащий атом и список, а не просто большой список или двоичный файл.

Я, вероятно, в конечном итоге буду использовать term_to_binary и binary_to_term, но отладка текстовых протоколов настолько проста, что я надеялся найти более удобную для списка версию. Там кто-то прячется?

1 Ответ

4 голосов
/ 21 октября 2010

Вы можете проанализировать строку как выражение (аналогично file:consult) с помощью:

% InputString = "...",
{ok, Scanned, _} = erl_scan:string(InputString),
{ok, Exprs} = erl_parse:parse_exprs(Scanned),
{value, ParsedValue, _} = erl_eval:exprs(Exprs, [])

(см. http://www.trapexit.org/String_Eval)

Вы должны иметь возможность использовать io_lib:format для преобразования выражения в строку, используя коды формата ~w или ~p, например io_lib:format("~w", [{get, "/foo.html"}]).

Я не думаю, что это будет очень быстро, поэтому, если производительность является проблемой, вы, вероятно, не должны использовать такие строки.

Также обратите внимание, что это потенциально небезопасно, поскольку вы оцениваете произвольные выражения - если вы идете по этому пути, вам, вероятно, следует выполнить некоторые проверки промежуточного вывода. Я бы посоветовал посмотреть на результат erl_parse:parse_exprs, чтобы убедиться, что он содержит интересующие вас форматы (т. Е. Это всегда кортеж {atom (), list ()}) без вызовов встроенных функций. Вы должны быть в состоянии сделать это с помощью сопоставления с образцом.

...