1:- use_module(library(error)).
2:- use_module(library(dcg/basics)).
3
4:- op(950, xfx, will_be).
5
6%%% Basic definitions
7
8% apply check to value when bound
9will_be(Value, Goal) :-
10 freeze(Value, assertion(call(Goal, Value))).
11
12byte(Value) :- must_be(between(0, 255), Value).
13
14nonnegative_integer(Value) :- must_be(nonneg, Value).
15
16sequence_of_bytes([]).
17sequence_of_bytes([First|Rest]) :-
18 First will_be byte,
19 Rest will_be sequence_of_bytes.
20
21netstring_encoding(PayloadBytes) --> Netstring is a sequence of bytes.
22 netstring_prefix_for_payload(PayloadBytes), It consists of prefix,
23 PayloadBytes, payload,
24 `,`. and terminator. Terminator is single ASCII comma `,`.
25netstring_encoding(netstring(PayloadBytes), Bytes) :-
26 assertion(ground(PayloadBytes); ground(Bytes)),
27 Bytes will_be sequence_of_bytes,
28 phrase(netstring_encoding(PayloadBytes), Bytes).
29
30Netstring prefix is the shortest ASCII decimal representation for length of payload in bytes, followed by ASCII colon `:`. That is number starting with non-zero digit unless payload is empty, in which case it's `0`.
31
32
33
34netstring_prefix_for_payload(PayloadBytes, A, B) :-
35 ( var(PayloadBytes)
36 -> netstring_prefix_codes(Prefix, A, B),
37 number_codes(PayloadLength, Prefix),
38 length(PayloadBytes, PayloadLength)
39 ; length(PayloadBytes, PayloadLength),
40 number_codes(PayloadLength, Prefix),
41 netstring_prefix_codes(Prefix, A, B)
42 ).
43netstring_prefix_codes(`0`) --> `0:`, !.
44netstring_prefix_codes([C|Cs]) -->
45 nonzero_digit(C),
46 !,
47 digits(Cs),
48 `:`.
49
50nonzero_digit(Code) -->
51 [Code],
52 { assertion(ground(Code)) },
53 { member(Code, `123456789`) }.
54
55netstring_of(Goal, Bytes) :-
56 ground(Goal),
57 !,
58 call(Goal, PayloadBytes),
59 netstring_encoding(netstring(PayloadBytes), Bytes).
60
61netstring_of(Goal, Bytes) :-
62 ground(Bytes),
63 !,
64 netstring_encoding(netstring(PayloadBytes), Bytes),
65 call(Goal, PayloadBytes).
66
67
68% :- use_module(library(pldoc/doc_files)).
69% doc_save('spec.pl', [format(html), doc_root(.)]).