diff --git a/src/geef_pkt.erl b/src/geef_pkt.erl index 025df6a..c01b038 100644 --- a/src/geef_pkt.erl +++ b/src/geef_pkt.erl @@ -1,6 +1,10 @@ -module(geef_pkt). --export([line/1]). +-export([line/1, parse/1]). + +-include("geef_records.hrl"). + +-define(SHA_LEN, 40). -spec line(iolist()) -> iolist(). line(Text) -> @@ -8,3 +12,29 @@ line(Text) -> Len = 4 + iolist_size(Text) + 1, Prefix = io_lib:format("~4.16.0b", [Len]), [Prefix, Text, "\n"]. + +-spec parse(iolist()) -> {{want | have, geef_oid()}, binary()}. +parse(In0) -> + In = iolist_to_binary(In0), + <> = In, + Len = binary_to_integer(BLen, 16), + case Len of + 0 -> + flush; + _ -> + parse_pkt(Rest, Len - 4) + end. + +parse_pkt(In, Len) when size(In) < Len -> + {error, ebufs}; +parse_pkt(In, Len0) -> + Len1 = Len0 - 5, % "want " | "have " + case In of + <<"want ", Sha:?SHA_LEN/binary, Rest0/binary>> -> + Pkt = {want, geef_oid:parse(Sha)}; + <<"have ", Sha:?SHA_LEN/binary, Rest0/binary>> -> + Pkt = {have, geef_oid:parse(Sha)} + end, + Len2 = Len1 - ?SHA_LEN, % get rid of the LF if we have it + <<_:Len2/binary, Rest/binary>> = Rest0, + {Pkt, Rest}. diff --git a/test/pkt_test.erl b/test/pkt_test.erl new file mode 100644 index 0000000..5c3c9e2 --- /dev/null +++ b/test/pkt_test.erl @@ -0,0 +1,12 @@ +-module(pkt_test). +-compile([export_all]). +-include_lib("eunit/include/eunit.hrl"). +-include("src/geef_records.hrl"). + +flush_test() -> + geef_pkt:parse("0000"). + +have_test() -> + Expected = {{want, geef_oid:parse("e17ca7f2d877acbf8b9a9a1cb4c243ca72e86463")}, <<>>}, + Actual = geef_pkt:parse("0032want e17ca7f2d877acbf8b9a9a1cb4c243ca72e86463\n"), + ?assertEqual(Expected, Actual).