aboutsummaryrefslogtreecommitdiff
path: root/doc/bytevector-slices.tm
blob: 3274ece17b3b7c35b8f32dea3f35682af5ae6cf1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
<TeXmacs|2.1>

<project|scheme-gnunet.tm>

<style|tmmanual>

<\body>
  <chapter|Bytevector slices><index|bytevector slices>

  In Scheme, bytes are put in bytevectors. Often, when a procedure needs to
  act on a bytevector, it does not need to act on the whole bytevector, but
  only on a (contiguous) part of the bytevector. This can be accomplished by
  passing the procedure position and length arguments, but this is prone to
  errors such as incorrect bounds calculations.

  To solve this, <dfn|bytevector slices> are implemented in <scm|(gnu gnunet
  utils bv-slice)><index|(gnu gnunet utils bv-slice)>. A bytevector slice is
  a structure referring to a bytevector, with a position inside the
  bytevector and the length (in bytes) of the bytevector. They can be
  accessed with <scm|slice-bv><index|slice-bv>,
  <scm|slice-position><index|slice-position> and
  <scm|slice-length><index|slice-length> respectively.

  <\warning>
    The first two procedures, <scm|slice-bv> and <scm|slice-position>, are
    considered low-level \V it is intended to, at some point in the future,
    replace them with a single pointer. Using them outside low-level code is
    recommended against when alternatives are available.
  </warning>

  Bytevector slices also have a very limited <dfn|capability> system, to
  avoid accidental writes when a slice should only be read and to avoid
  accidental reads when a slice should only be written. However, this is not
  a true capability model, as it can be circumvented by using <scm|slice-bv>
  and <scm|bv-slice/read-write> (i.e., slices are forgable) and because the
  only possible capabilities (read of write or read-write) are very
  coarse-grained; it is impossible to refine it.

  <section|Constructing bytevector slices>

  <\explain>
    <scm|(slice-slice <var|slice>)><index|slice-slice>

    <scm|(slice-slice <var|slice> <var|offset>)>

    <scm|(slice-slice <var|slice> <var|offset> <var|length>)>
  <|explain>
    Select a part of the bytevector slice <var|slice>, preserving
    capabilities. Start at the byte at index <var|offset> in the old slice
    and let the new slice have <var|length> as length.

    If <var|offset> is absent, start at index 0. If <var|length> is absent,
    select the whole remaining part of <var|slice>.

    The new slice must remain within the old slice. If not, an error is
    raised <todo|dedicated exception type>.
  </explain>

  <\explain>
    <scm|slice/read-only><index|slice/read-only>,
    <scm|slice/write-only><index|slice/write-only>,
    <scm|slice/read-write><index|slice/write-only>
  <|explain>
    These procedures function exactly the same as <scm|slice-slice>, except
    that the capabilities are changed to read-only, write-only and read-write
    respectively. The old capabilities must be an upper bound on the new
    capabilities; capabilities cannot be gained with these procedures. If the
    new capabilities exceed the old capabilities, an
    <scm|&missing-capabilities> exception is raised, with the
    \<#2018\>what\<#2019\> field set to the symbol <scm|slice>.
  </explain>

  <\explain>
    <scm|bv-slice/read-only><index|bv-slice/read-only>,
    <scm|bv-slice/write-only><index|bv-slice/write-only>,
    <scm|bv-slice/read-write><index|bv-slice/read-write>
  <|explain>
    These procedures behave like <scm|slice/read-only>,
    <scm|slice/write-only> and <scm|slice/read-write>, except that as first
    argument they accept a bytevector instead of a bytevector slice. They
    also never raise a <scm|&missing-capabilities>.

    <\warning>
      In the future, <scm|bv-slice/write-only> and <scm|bv-slice/read-write>
      could be modified to check if the bytevector is read-only or read-write
      (bytevectors that are part of the program text may not be modified in
      Guile Scheme).
    </warning>
  </explain>

  <\explain>
    <scm|(make-slice/read-write <var|length>)><index|make-slice/read-write>
  </explain|Make a fresh, zero-initialised, read-write slice, of length
  <var|length>.>

  <\explain>
    <scm|(slice-copy/read-write <var|original>)><index|slice-copy/read-write>

    <scm|(slice-copy/read-only <var|original>)><index|slice-copy/read-only>

    <scm|(slice-copy/bytevector <var|original>)><index|slice-copy/bytevector>
  <|explain>
    <scm|slice-copy/read-write> makes a fresh read-write slice with the same
    contents as <var|original>. It requires <var|original> to be readable \U
    if not, a <scm|&missing-capabilities> exception is raised, with the
    \<#2018\>what\<#2019\> field set to the symbol <scm|original>.

    <scm|slice-copy/read-only> behaves the same as
    <scm|slice-copy/read-write>, except for returning a read-only slice
    instead of a read-write slice.

    <scm|slice-copy/bytevector> behave the same as
    <scm|slice-copy/read-write>, except for returning a bytevector instead of
    a read-write slice.
  </explain>

  <section|Predicates>

  <\explain>
    <scm|(slice? <var|object>)>
  <|explain>
    Return <scm|#true> if <var|object> is a slice, <scm|#false> otherwise.
  </explain>

  <\explain>
    <scm|(slice-readable? <var|slice>)>
  </explain|Return <scm|#true> if the slice <var|slice> is readable,
  <scm|#false> otherwise.>

  <\explain>
    <scm|(slice-writable? <var|slice>)>
  </explain|Return <scm|#true> if the slice <var|slice> is writable,
  <scm|#false> otherwise.>

  <\explain>
    <scm|(slice-contents-equal? <var|this>
    <var|that>)><index|slice-contents-equal?>
  <|explain>
    Return <scm|#true> if the two readable bytevector slices <var|this> and
    <var|that> have the same contents, i.e., they have the same length and
    the same octet at each index. If one of the slices is not readable, a
    <scm|&missing-capabilities> exception is raised, with the
    \<#2018\>what\<#2019\> field set to the name of the argument as a symbol.
    If both slices are not readable, it is unspecified whether
    \<#2018\>what\<#2019\> is \<#2018\>this\<#2019\> or
    \<#2018\>that\<#2019\>.
  </explain>

  <section|Reading / modifying bytevector slices>

  To read the value at a (byte) index in the slice, the procedures
  <scm|slice-X-ref><index|slice-X-ref> are used. Likewise, to set the value
  at a certain byte index, the procedures
  <scm|slice-X-set!><index|slice-X-set!> are used. <scm|X> must be one of the
  following:

  <\description>
    <item*|<scm|u8><index|u8>, u16<index|u16>, u32<index|u32>,
    u64<index|u64>>An unsigned 8-bit, 16-bit, 32-bit and 64-bit integer,
    respectively. I.e., an (exact) integer in the (closed) range
    <math|<around*|[|0,2<rsup|N>-1|]>>, where <math|N> is the number of bits.

    <item*|s8<index|s8>, s16<index|s16>, s32<index|s32>, s64<index|s64>>A
    signed 8-bit, 16-bit, 32-bit and 64-bit integer, respectively, encoded in
    the <hlink|two's complement|https://en.wikipedia.org/wiki/Two%27s_complement>
    representation. I.e., an (exact) integer in the (closed) range
    <math|<around*|[|-2<rsup|N-1>,2<rsup|N-1>-1|]>>.

    <item*|<scm|ieee-double><index|ieee-double>>A <hlink|floating-point
    number|https://en.wikipedia.org/wiki/Floating-point>, in
    <hlink|IEEE<index|IEEE> binary64/double<index|binary64><index|double>|https://en.wikipedia.org/wiki/Double-precision_floating-point_format>
    format.
  </description>

  Except for <scm|u8> and <scm|s8>, <scm|slice-X-ref> can be called as
  <scm|(slice-X-ref slice <var|index> <var|endian>)>, where <var|slice> is
  the bytevector slice, <var|index> is the byte index into the slice and
  <var|endian> is the <dfn|endianness> according to which the bytes of the
  type are ordered. Endianness is part of <scm|(rnrs bytevectors>). For
  communication over the network (including communication between clients and
  services), big-endian (i.e., <scm|(endianness big)>) is almost always used
  in GNUnet.

  Except for <scm|u8> and <scm|s8>, <scm|slice-X-set!> can be called as
  <scm|(slice-X-ref slice <var|index> <var|endian> <var|value>)>, where
  <var|slice>, <var|index> and <var|endian> have the same meaning as for
  <scm|slice-X-ref>, and <var|value> is the value to set it to.

  <todo|out-of-bounds, range and capabilities exceptions, can <var|value> be
  a exact for <scm|ieee-double>>

  For <scm|u8> and <scm|s8>, there is only a single byte and hence there is
  no endianness. As such, <scm|slice-u8-ref>, <scm|slice-u8-set!>,
  <scm|slice-s8-ref> and <scm|slice-s8-set!> do not have an endianness
  argument. Aside from that, they behave similarly to the other
  <scm|slice-X-ref> and <scm|slice-X-set!> procedures.

  <scm|slice-X-ref> requires the slice to be readable, if not, an appropriate
  <scm|&missing-capabilities> exception is raised. Likewise,
  <scm|slice-X-set!> requires the slice to be writable. Both require the part
  of the slice that is being read to be in-bounds.

  <section|Quickcheck integration>

  The module <scm|(gnu gnunet utils bv-slice-quickcheck)><index|(gnu gnunet
  utils bv-slice-quickcheck)> defines a few <em|arbitraries> for use with
  Guile-Quickcheck:

  <\explain>
    <scm|($sized-bytevector-slice/read-write
    <var|size>)><index|$sized-bytevector-slice/read-write>
  </explain|Arbitrary generating fresh read-write bytevector slices
  consisting of <var|size> octets.>

  <\explain>
    <scm|($sized-bytevector-slice/read-only
    <var|size>)><index|$sized-bytevector-slice/read-only>
  </explain|Arbitrary generating fresh read-only bytevector slices consisting
  of <var|size> octets.>

  \ <todo|rename>
</body>

<\initial>
  <\collection>
    <associate|page-medium|paper>
    <associate|save-aux|false>
  </collection>
</initial>