1BytesLabels(3) OCaml library BytesLabels(3)
2
3
4
6 BytesLabels - Byte sequence operations.
7
9 Module BytesLabels
10
12 Module BytesLabels
13 : sig end
14
15
16 Byte sequence operations.
17
18 A byte sequence is a mutable data structure that contains a
19 fixed-length sequence of bytes. Each byte can be indexed in constant
20 time for reading or writing.
21
22 Given a byte sequence s of length l , we can access each of the l bytes
23 of s via its index in the sequence. Indexes start at 0 , and we will
24 call an index valid in s if it falls within the range [0...l-1] (inclu‐
25 sive). A position is the point between two bytes or at the beginning or
26 end of the sequence. We call a position valid in s if it falls within
27 the range [0...l] (inclusive). Note that the byte at index n is between
28 positions n and n+1 .
29
30 Two parameters start and len are said to designate a valid range of s
31 if len >= 0 and start and start+len are valid positions in s .
32
33 Byte sequences can be modified in place, for instance via the set and
34 blit functions described below. See also strings (module String ),
35 which are almost the same data structure, but cannot be modified in
36 place.
37
38 Bytes are represented by the OCaml type char .
39
40 The labeled version of this module can be used as described in the Std‐
41 Labels module.
42
43
44 Since 4.02.0
45
46
47
48
49
50
51 val length : bytes -> int
52
53 Return the length (number of bytes) of the argument.
54
55
56
57 val get : bytes -> int -> char
58
59
60 get s n returns the byte at index n in argument s .
61
62
63 Raises Invalid_argument if n is not a valid index in s .
64
65
66
67 val set : bytes -> int -> char -> unit
68
69
70 set s n c modifies s in place, replacing the byte at index n with c .
71
72
73 Raises Invalid_argument if n is not a valid index in s .
74
75
76
77 val create : int -> bytes
78
79
80 create n returns a new byte sequence of length n . The sequence is
81 uninitialized and contains arbitrary bytes.
82
83
84 Raises Invalid_argument if n < 0 or n > Sys.max_string_length .
85
86
87
88 val make : int -> char -> bytes
89
90
91 make n c returns a new byte sequence of length n , filled with the byte
92 c .
93
94
95 Raises Invalid_argument if n < 0 or n > Sys.max_string_length .
96
97
98
99 val init : int -> f:(int -> char) -> bytes
100
101
102 init n f returns a fresh byte sequence of length n , with character i
103 initialized to the result of f i (in increasing index order).
104
105
106 Raises Invalid_argument if n < 0 or n > Sys.max_string_length .
107
108
109
110 val empty : bytes
111
112 A byte sequence of size 0.
113
114
115
116 val copy : bytes -> bytes
117
118 Return a new byte sequence that contains the same bytes as the argu‐
119 ment.
120
121
122
123 val of_string : string -> bytes
124
125 Return a new byte sequence that contains the same bytes as the given
126 string.
127
128
129
130 val to_string : bytes -> string
131
132 Return a new string that contains the same bytes as the given byte se‐
133 quence.
134
135
136
137 val sub : bytes -> pos:int -> len:int -> bytes
138
139
140 sub s ~pos ~len returns a new byte sequence of length len , containing
141 the subsequence of s that starts at position pos and has length len .
142
143
144 Raises Invalid_argument if pos and len do not designate a valid range
145 of s .
146
147
148
149 val sub_string : bytes -> pos:int -> len:int -> string
150
151 Same as BytesLabels.sub but return a string instead of a byte sequence.
152
153
154
155 val extend : bytes -> left:int -> right:int -> bytes
156
157
158 extend s ~left ~right returns a new byte sequence that contains the
159 bytes of s , with left uninitialized bytes prepended and right unini‐
160 tialized bytes appended to it. If left or right is negative, then bytes
161 are removed (instead of appended) from the corresponding side of s .
162
163
164 Since 4.05.0 in BytesLabels
165
166
167 Raises Invalid_argument if the result length is negative or longer than
168 Sys.max_string_length bytes.
169
170
171
172 val fill : bytes -> pos:int -> len:int -> char -> unit
173
174
175 fill s ~pos ~len c modifies s in place, replacing len characters with c
176 , starting at pos .
177
178
179 Raises Invalid_argument if pos and len do not designate a valid range
180 of s .
181
182
183
184 val blit : src:bytes -> src_pos:int -> dst:bytes -> dst_pos:int ->
185 len:int -> unit
186
187
188 blit ~src ~src_pos ~dst ~dst_pos ~len copies len bytes from sequence
189 src , starting at index src_pos , to sequence dst , starting at index
190 dst_pos . It works correctly even if src and dst are the same byte se‐
191 quence, and the source and destination intervals overlap.
192
193
194 Raises Invalid_argument if src_pos and len do not designate a valid
195 range of src , or if dst_pos and len do not designate a valid range of
196 dst .
197
198
199
200 val blit_string : src:string -> src_pos:int -> dst:bytes -> dst_pos:int
201 -> len:int -> unit
202
203
204 blit ~src ~src_pos ~dst ~dst_pos ~len copies len bytes from string src
205 , starting at index src_pos , to byte sequence dst , starting at index
206 dst_pos .
207
208
209 Since 4.05.0 in BytesLabels
210
211
212 Raises Invalid_argument if src_pos and len do not designate a valid
213 range of src , or if dst_pos and len do not designate a valid range of
214 dst .
215
216
217
218 val concat : sep:bytes -> bytes list -> bytes
219
220
221 concat ~sep sl concatenates the list of byte sequences sl , inserting
222 the separator byte sequence sep between each, and returns the result as
223 a new byte sequence.
224
225
226 Raises Invalid_argument if the result is longer than
227 Sys.max_string_length bytes.
228
229
230
231 val cat : bytes -> bytes -> bytes
232
233
234 cat s1 s2 concatenates s1 and s2 and returns the result as a new byte
235 sequence.
236
237
238 Since 4.05.0 in BytesLabels
239
240
241 Raises Invalid_argument if the result is longer than
242 Sys.max_string_length bytes.
243
244
245
246 val iter : f:(char -> unit) -> bytes -> unit
247
248
249 iter ~f s applies function f in turn to all the bytes of s . It is
250 equivalent to f (get s 0); f (get s 1); ...; f (get s
251 (length s - 1)); () .
252
253
254
255 val iteri : f:(int -> char -> unit) -> bytes -> unit
256
257 Same as BytesLabels.iter , but the function is applied to the index of
258 the byte as first argument and the byte itself as second argument.
259
260
261
262 val map : f:(char -> char) -> bytes -> bytes
263
264
265 map ~f s applies function f in turn to all the bytes of s (in increas‐
266 ing index order) and stores the resulting bytes in a new sequence that
267 is returned as the result.
268
269
270
271 val mapi : f:(int -> char -> char) -> bytes -> bytes
272
273
274 mapi ~f s calls f with each character of s and its index (in increasing
275 index order) and stores the resulting bytes in a new sequence that is
276 returned as the result.
277
278
279
280 val fold_left : f:('a -> char -> 'a) -> init:'a -> bytes -> 'a
281
282
283 fold_left f x s computes f (... (f (f x (get s 0)) (get s 1)) ...) (get
284 s (n-1)) , where n is the length of s .
285
286
287 Since 4.13.0
288
289
290
291 val fold_right : f:(char -> 'a -> 'a) -> bytes -> init:'a -> 'a
292
293
294 fold_right f s x computes f (get s 0) (f (get s 1) ( ... (f (get s
295 (n-1)) x) ...)) , where n is the length of s .
296
297
298 Since 4.13.0
299
300
301
302 val for_all : f:(char -> bool) -> bytes -> bool
303
304
305 for_all p s checks if all characters in s satisfy the predicate p .
306
307
308 Since 4.13.0
309
310
311
312 val exists : f:(char -> bool) -> bytes -> bool
313
314
315 exists p s checks if at least one character of s satisfies the predi‐
316 cate p .
317
318
319 Since 4.13.0
320
321
322
323 val trim : bytes -> bytes
324
325 Return a copy of the argument, without leading and trailing whitespace.
326 The bytes regarded as whitespace are the ASCII characters ' ' , '\012'
327 , '\n' , '\r' , and '\t' .
328
329
330
331 val escaped : bytes -> bytes
332
333 Return a copy of the argument, with special characters represented by
334 escape sequences, following the lexical conventions of OCaml. All
335 characters outside the ASCII printable range (32..126) are escaped, as
336 well as backslash and double-quote.
337
338
339 Raises Invalid_argument if the result is longer than
340 Sys.max_string_length bytes.
341
342
343
344 val index : bytes -> char -> int
345
346
347 index s c returns the index of the first occurrence of byte c in s .
348
349
350 Raises Not_found if c does not occur in s .
351
352
353
354 val index_opt : bytes -> char -> int option
355
356
357 index_opt s c returns the index of the first occurrence of byte c in s
358 or None if c does not occur in s .
359
360
361 Since 4.05
362
363
364
365 val rindex : bytes -> char -> int
366
367
368 rindex s c returns the index of the last occurrence of byte c in s .
369
370
371 Raises Not_found if c does not occur in s .
372
373
374
375 val rindex_opt : bytes -> char -> int option
376
377
378 rindex_opt s c returns the index of the last occurrence of byte c in s
379 or None if c does not occur in s .
380
381
382 Since 4.05
383
384
385
386 val index_from : bytes -> int -> char -> int
387
388
389 index_from s i c returns the index of the first occurrence of byte c in
390 s after position i . index s c is equivalent to index_from s 0 c .
391
392
393 Raises Invalid_argument if i is not a valid position in s .
394
395
396 Raises Not_found if c does not occur in s after position i .
397
398
399
400 val index_from_opt : bytes -> int -> char -> int option
401
402
403 index_from_opt s i c returns the index of the first occurrence of byte
404 c in s after position i or None if c does not occur in s after position
405 i . index_opt s c is equivalent to index_from_opt s 0 c .
406
407
408 Since 4.05
409
410
411 Raises Invalid_argument if i is not a valid position in s .
412
413
414
415 val rindex_from : bytes -> int -> char -> int
416
417
418 rindex_from s i c returns the index of the last occurrence of byte c in
419 s before position i+1 . rindex s c is equivalent to rindex_from s
420 (length s - 1) c .
421
422
423 Raises Invalid_argument if i+1 is not a valid position in s .
424
425
426 Raises Not_found if c does not occur in s before position i+1 .
427
428
429
430 val rindex_from_opt : bytes -> int -> char -> int option
431
432
433 rindex_from_opt s i c returns the index of the last occurrence of byte
434 c in s before position i+1 or None if c does not occur in s before po‐
435 sition i+1 . rindex_opt s c is equivalent to rindex_from s (length s -
436 1) c .
437
438
439 Since 4.05
440
441
442 Raises Invalid_argument if i+1 is not a valid position in s .
443
444
445
446 val contains : bytes -> char -> bool
447
448
449 contains s c tests if byte c appears in s .
450
451
452
453 val contains_from : bytes -> int -> char -> bool
454
455
456 contains_from s start c tests if byte c appears in s after position
457 start . contains s c is equivalent to contains_from
458 s 0 c .
459
460
461 Raises Invalid_argument if start is not a valid position in s .
462
463
464
465 val rcontains_from : bytes -> int -> char -> bool
466
467
468 rcontains_from s stop c tests if byte c appears in s before position
469 stop+1 .
470
471
472 Raises Invalid_argument if stop < 0 or stop+1 is not a valid position
473 in s .
474
475
476
477 val uppercase_ascii : bytes -> bytes
478
479 Return a copy of the argument, with all lowercase letters translated to
480 uppercase, using the US-ASCII character set.
481
482
483 Since 4.05.0
484
485
486
487 val lowercase_ascii : bytes -> bytes
488
489 Return a copy of the argument, with all uppercase letters translated to
490 lowercase, using the US-ASCII character set.
491
492
493 Since 4.05.0
494
495
496
497 val capitalize_ascii : bytes -> bytes
498
499 Return a copy of the argument, with the first character set to upper‐
500 case, using the US-ASCII character set.
501
502
503 Since 4.05.0
504
505
506
507 val uncapitalize_ascii : bytes -> bytes
508
509 Return a copy of the argument, with the first character set to lower‐
510 case, using the US-ASCII character set.
511
512
513 Since 4.05.0
514
515
516 type t = bytes
517
518
519 An alias for the type of byte sequences.
520
521
522
523 val compare : t -> t -> int
524
525 The comparison function for byte sequences, with the same specification
526 as compare . Along with the type t , this function compare allows the
527 module Bytes to be passed as argument to the functors Set.Make and
528 Map.Make .
529
530
531
532 val equal : t -> t -> bool
533
534 The equality function for byte sequences.
535
536
537 Since 4.05.0
538
539
540
541 val starts_with : prefix:bytes -> bytes -> bool
542
543
544 starts_with ~prefix s is true if and only if s starts with prefix .
545
546
547 Since 4.13.0
548
549
550
551 val ends_with : suffix:bytes -> bytes -> bool
552
553
554 ends_with ~suffix s is true if and only if s ends with suffix .
555
556
557 Since 4.13.0
558
559
560
561
562 Unsafe conversions (for advanced users)
563 This section describes unsafe, low-level conversion functions between
564 bytes and string . They do not copy the internal data; used improperly,
565 they can break the immutability invariant on strings provided by the
566 -safe-string option. They are available for expert library authors, but
567 for most purposes you should use the always-correct BytesLa‐
568 bels.to_string and BytesLabels.of_string instead.
569
570 val unsafe_to_string : bytes -> string
571
572 Unsafely convert a byte sequence into a string.
573
574 To reason about the use of unsafe_to_string , it is convenient to con‐
575 sider an "ownership" discipline. A piece of code that manipulates some
576 data "owns" it; there are several disjoint ownership modes, including:
577
578 -Unique ownership: the data may be accessed and mutated
579
580 -Shared ownership: the data has several owners, that may only access
581 it, not mutate it.
582
583 Unique ownership is linear: passing the data to another piece of code
584 means giving up ownership (we cannot write the data again). A unique
585 owner may decide to make the data shared (giving up mutation rights on
586 it), but shared data may not become uniquely-owned again.
587
588
589 unsafe_to_string s can only be used when the caller owns the byte se‐
590 quence s -- either uniquely or as shared immutable data. The caller
591 gives up ownership of s , and gains ownership of the returned string.
592
593 There are two valid use-cases that respect this ownership discipline:
594
595 1. Creating a string by initializing and mutating a byte sequence that
596 is never changed after initialization is performed.
597
598
599 let string_init len f : string =
600 let s = Bytes.create len in
601 for i = 0 to len - 1 do Bytes.set s i (f i) done;
602 Bytes.unsafe_to_string s
603
604
605 This function is safe because the byte sequence s will never be ac‐
606 cessed or mutated after unsafe_to_string is called. The string_init
607 code gives up ownership of s , and returns the ownership of the result‐
608 ing string to its caller.
609
610 Note that it would be unsafe if s was passed as an additional parameter
611 to the function f as it could escape this way and be mutated in the fu‐
612 ture -- string_init would give up ownership of s to pass it to f , and
613 could not call unsafe_to_string safely.
614
615 We have provided the String.init , String.map and String.mapi functions
616 to cover most cases of building new strings. You should prefer those
617 over to_string or unsafe_to_string whenever applicable.
618
619 2. Temporarily giving ownership of a byte sequence to a function that
620 expects a uniquely owned string and returns ownership back, so that we
621 can mutate the sequence again after the call ended.
622
623
624 let bytes_length (s : bytes) =
625 String.length (Bytes.unsafe_to_string s)
626
627
628 In this use-case, we do not promise that s will never be mutated after
629 the call to bytes_length s . The String.length function temporarily
630 borrows unique ownership of the byte sequence (and sees it as a string
631 ), but returns this ownership back to the caller, which may assume that
632 s is still a valid byte sequence after the call. Note that this is only
633 correct because we know that String.length does not capture its argu‐
634 ment -- it could escape by a side-channel such as a memoization combi‐
635 nator.
636
637 The caller may not mutate s while the string is borrowed (it has tempo‐
638 rarily given up ownership). This affects concurrent programs, but also
639 higher-order functions: if String.length returned a closure to be
640 called later, s should not be mutated until this closure is fully ap‐
641 plied and returns ownership.
642
643
644
645 val unsafe_of_string : string -> bytes
646
647 Unsafely convert a shared string to a byte sequence that should not be
648 mutated.
649
650 The same ownership discipline that makes unsafe_to_string correct ap‐
651 plies to unsafe_of_string : you may use it if you were the owner of the
652 string value, and you will own the return bytes in the same mode.
653
654 In practice, unique ownership of string values is extremely difficult
655 to reason about correctly. You should always assume strings are shared,
656 never uniquely owned.
657
658 For example, string literals are implicitly shared by the compiler, so
659 you never uniquely own them.
660
661
662 let incorrect = Bytes.unsafe_of_string "hello"
663 let s = Bytes.of_string "hello"
664
665
666 The first declaration is incorrect, because the string literal "hello"
667 could be shared by the compiler with other parts of the program, and
668 mutating incorrect is a bug. You must always use the second version,
669 which performs a copy and is thus correct.
670
671 Assuming unique ownership of strings that are not string literals, but
672 are (partly) built from string literals, is also incorrect. For exam‐
673 ple, mutating unsafe_of_string ("foo" ^ s) could mutate the shared
674 string "foo" -- assuming a rope-like representation of strings. More
675 generally, functions operating on strings will assume shared ownership,
676 they do not preserve unique ownership. It is thus incorrect to assume
677 unique ownership of the result of unsafe_of_string .
678
679 The only case we have reasonable confidence is safe is if the produced
680 bytes is shared -- used as an immutable byte sequence. This is possibly
681 useful for incremental migration of low-level programs that manipulate
682 immutable sequences of bytes (for example Marshal.from_bytes ) and pre‐
683 viously used the string type for this purpose.
684
685
686
687 val split_on_char : sep:char -> bytes -> bytes list
688
689
690 split_on_char sep s returns the list of all (possibly empty) subse‐
691 quences of s that are delimited by the sep character.
692
693 The function's output is specified by the following invariants:
694
695
696 -The list is not empty.
697
698 -Concatenating its elements using sep as a separator returns a byte se‐
699 quence equal to the input ( Bytes.concat (Bytes.make 1 sep)
700 (Bytes.split_on_char sep s) = s ).
701
702 -No byte sequence in the result contains the sep character.
703
704
705
706 Since 4.13.0
707
708
709
710
711 Iterators
712 val to_seq : t -> char Seq.t
713
714 Iterate on the string, in increasing index order. Modifications of the
715 string during iteration will be reflected in the sequence.
716
717
718 Since 4.07
719
720
721
722 val to_seqi : t -> (int * char) Seq.t
723
724 Iterate on the string, in increasing order, yielding indices along
725 chars
726
727
728 Since 4.07
729
730
731
732 val of_seq : char Seq.t -> t
733
734 Create a string from the generator
735
736
737 Since 4.07
738
739
740
741
742 UTF codecs and validations
743 UTF-8
744 val get_utf_8_uchar : t -> int -> Uchar.utf_decode
745
746
747 get_utf_8_uchar b i decodes an UTF-8 character at index i in b .
748
749
750
751 val set_utf_8_uchar : t -> int -> Uchar.t -> int
752
753
754 set_utf_8_uchar b i u UTF-8 encodes u at index i in b and returns the
755 number of bytes n that were written starting at i . If n is 0 there was
756 not enough space to encode u at i and b was left untouched. Otherwise a
757 new character can be encoded at i + n .
758
759
760
761 val is_valid_utf_8 : t -> bool
762
763
764 is_valid_utf_8 b is true if and only if b contains valid UTF-8 data.
765
766
767
768
769 UTF-16BE
770 val get_utf_16be_uchar : t -> int -> Uchar.utf_decode
771
772
773 get_utf_16be_uchar b i decodes an UTF-16BE character at index i in b .
774
775
776
777 val set_utf_16be_uchar : t -> int -> Uchar.t -> int
778
779
780 set_utf_16be_uchar b i u UTF-16BE encodes u at index i in b and returns
781 the number of bytes n that were written starting at i . If n is 0 there
782 was not enough space to encode u at i and b was left untouched. Other‐
783 wise a new character can be encoded at i + n .
784
785
786
787 val is_valid_utf_16be : t -> bool
788
789
790 is_valid_utf_16be b is true if and only if b contains valid UTF-16BE
791 data.
792
793
794
795
796 UTF-16LE
797 val get_utf_16le_uchar : t -> int -> Uchar.utf_decode
798
799
800 get_utf_16le_uchar b i decodes an UTF-16LE character at index i in b .
801
802
803
804 val set_utf_16le_uchar : t -> int -> Uchar.t -> int
805
806
807 set_utf_16le_uchar b i u UTF-16LE encodes u at index i in b and returns
808 the number of bytes n that were written starting at i . If n is 0 there
809 was not enough space to encode u at i and b was left untouched. Other‐
810 wise a new character can be encoded at i + n .
811
812
813
814 val is_valid_utf_16le : t -> bool
815
816
817 is_valid_utf_16le b is true if and only if b contains valid UTF-16LE
818 data.
819
820
821
822
823 Binary encoding/decoding of integers
824 The functions in this section binary encode and decode integers to and
825 from byte sequences.
826
827 All following functions raise Invalid_argument if the space needed at
828 index i to decode or encode the integer is not available.
829
830 Little-endian (resp. big-endian) encoding means that least (resp. most)
831 significant bytes are stored first. Big-endian is also known as net‐
832 work byte order. Native-endian encoding is either little-endian or
833 big-endian depending on Sys.big_endian .
834
835 32-bit and 64-bit integers are represented by the int32 and int64
836 types, which can be interpreted either as signed or unsigned numbers.
837
838 8-bit and 16-bit integers are represented by the int type, which has
839 more bits than the binary encoding. These extra bits are handled as
840 follows:
841
842 -Functions that decode signed (resp. unsigned) 8-bit or 16-bit integers
843 represented by int values sign-extend (resp. zero-extend) their result.
844
845 -Functions that encode 8-bit or 16-bit integers represented by int val‐
846 ues truncate their input to their least significant bytes.
847
848
849 val get_uint8 : bytes -> int -> int
850
851
852 get_uint8 b i is b 's unsigned 8-bit integer starting at byte index i .
853
854
855 Since 4.08
856
857
858
859 val get_int8 : bytes -> int -> int
860
861
862 get_int8 b i is b 's signed 8-bit integer starting at byte index i .
863
864
865 Since 4.08
866
867
868
869 val get_uint16_ne : bytes -> int -> int
870
871
872 get_uint16_ne b i is b 's native-endian unsigned 16-bit integer start‐
873 ing at byte index i .
874
875
876 Since 4.08
877
878
879
880 val get_uint16_be : bytes -> int -> int
881
882
883 get_uint16_be b i is b 's big-endian unsigned 16-bit integer starting
884 at byte index i .
885
886
887 Since 4.08
888
889
890
891 val get_uint16_le : bytes -> int -> int
892
893
894 get_uint16_le b i is b 's little-endian unsigned 16-bit integer start‐
895 ing at byte index i .
896
897
898 Since 4.08
899
900
901
902 val get_int16_ne : bytes -> int -> int
903
904
905 get_int16_ne b i is b 's native-endian signed 16-bit integer starting
906 at byte index i .
907
908
909 Since 4.08
910
911
912
913 val get_int16_be : bytes -> int -> int
914
915
916 get_int16_be b i is b 's big-endian signed 16-bit integer starting at
917 byte index i .
918
919
920 Since 4.08
921
922
923
924 val get_int16_le : bytes -> int -> int
925
926
927 get_int16_le b i is b 's little-endian signed 16-bit integer starting
928 at byte index i .
929
930
931 Since 4.08
932
933
934
935 val get_int32_ne : bytes -> int -> int32
936
937
938 get_int32_ne b i is b 's native-endian 32-bit integer starting at byte
939 index i .
940
941
942 Since 4.08
943
944
945
946 val get_int32_be : bytes -> int -> int32
947
948
949 get_int32_be b i is b 's big-endian 32-bit integer starting at byte in‐
950 dex i .
951
952
953 Since 4.08
954
955
956
957 val get_int32_le : bytes -> int -> int32
958
959
960 get_int32_le b i is b 's little-endian 32-bit integer starting at byte
961 index i .
962
963
964 Since 4.08
965
966
967
968 val get_int64_ne : bytes -> int -> int64
969
970
971 get_int64_ne b i is b 's native-endian 64-bit integer starting at byte
972 index i .
973
974
975 Since 4.08
976
977
978
979 val get_int64_be : bytes -> int -> int64
980
981
982 get_int64_be b i is b 's big-endian 64-bit integer starting at byte in‐
983 dex i .
984
985
986 Since 4.08
987
988
989
990 val get_int64_le : bytes -> int -> int64
991
992
993 get_int64_le b i is b 's little-endian 64-bit integer starting at byte
994 index i .
995
996
997 Since 4.08
998
999
1000
1001 val set_uint8 : bytes -> int -> int -> unit
1002
1003
1004 set_uint8 b i v sets b 's unsigned 8-bit integer starting at byte index
1005 i to v .
1006
1007
1008 Since 4.08
1009
1010
1011
1012 val set_int8 : bytes -> int -> int -> unit
1013
1014
1015 set_int8 b i v sets b 's signed 8-bit integer starting at byte index i
1016 to v .
1017
1018
1019 Since 4.08
1020
1021
1022
1023 val set_uint16_ne : bytes -> int -> int -> unit
1024
1025
1026 set_uint16_ne b i v sets b 's native-endian unsigned 16-bit integer
1027 starting at byte index i to v .
1028
1029
1030 Since 4.08
1031
1032
1033
1034 val set_uint16_be : bytes -> int -> int -> unit
1035
1036
1037 set_uint16_be b i v sets b 's big-endian unsigned 16-bit integer start‐
1038 ing at byte index i to v .
1039
1040
1041 Since 4.08
1042
1043
1044
1045 val set_uint16_le : bytes -> int -> int -> unit
1046
1047
1048 set_uint16_le b i v sets b 's little-endian unsigned 16-bit integer
1049 starting at byte index i to v .
1050
1051
1052 Since 4.08
1053
1054
1055
1056 val set_int16_ne : bytes -> int -> int -> unit
1057
1058
1059 set_int16_ne b i v sets b 's native-endian signed 16-bit integer start‐
1060 ing at byte index i to v .
1061
1062
1063 Since 4.08
1064
1065
1066
1067 val set_int16_be : bytes -> int -> int -> unit
1068
1069
1070 set_int16_be b i v sets b 's big-endian signed 16-bit integer starting
1071 at byte index i to v .
1072
1073
1074 Since 4.08
1075
1076
1077
1078 val set_int16_le : bytes -> int -> int -> unit
1079
1080
1081 set_int16_le b i v sets b 's little-endian signed 16-bit integer start‐
1082 ing at byte index i to v .
1083
1084
1085 Since 4.08
1086
1087
1088
1089 val set_int32_ne : bytes -> int -> int32 -> unit
1090
1091
1092 set_int32_ne b i v sets b 's native-endian 32-bit integer starting at
1093 byte index i to v .
1094
1095
1096 Since 4.08
1097
1098
1099
1100 val set_int32_be : bytes -> int -> int32 -> unit
1101
1102
1103 set_int32_be b i v sets b 's big-endian 32-bit integer starting at byte
1104 index i to v .
1105
1106
1107 Since 4.08
1108
1109
1110
1111 val set_int32_le : bytes -> int -> int32 -> unit
1112
1113
1114 set_int32_le b i v sets b 's little-endian 32-bit integer starting at
1115 byte index i to v .
1116
1117
1118 Since 4.08
1119
1120
1121
1122 val set_int64_ne : bytes -> int -> int64 -> unit
1123
1124
1125 set_int64_ne b i v sets b 's native-endian 64-bit integer starting at
1126 byte index i to v .
1127
1128
1129 Since 4.08
1130
1131
1132
1133 val set_int64_be : bytes -> int -> int64 -> unit
1134
1135
1136 set_int64_be b i v sets b 's big-endian 64-bit integer starting at byte
1137 index i to v .
1138
1139
1140 Since 4.08
1141
1142
1143
1144 val set_int64_le : bytes -> int -> int64 -> unit
1145
1146
1147 set_int64_le b i v sets b 's little-endian 64-bit integer starting at
1148 byte index i to v .
1149
1150
1151 Since 4.08
1152
1153
1154
1155
1156 Byte sequences and concurrency safety
1157 Care must be taken when concurrently accessing byte sequences from mul‐
1158 tiple domains: accessing a byte sequence will never crash a program,
1159 but unsynchronized accesses might yield surprising (non-sequen‐
1160 tially-consistent) results.
1161
1162
1163 Atomicity
1164 Every byte sequence operation that accesses more than one byte is not
1165 atomic. This includes iteration and scanning.
1166
1167 For example, consider the following program:
1168 let size = 100_000_000
1169 let b = Bytes.make size ' '
1170 let update b f () =
1171 Bytes.iteri (fun i x -> Bytes.set b i (Char.chr (f (Char.code x)))) b
1172 let d1 = Domain.spawn (update b (fun x -> x + 1))
1173 let d2 = Domain.spawn (update b (fun x -> 2 * x + 1))
1174 let () = Domain.join d1; Domain.join d2
1175
1176 the bytes sequence b may contain a non-deterministic mixture of '!' ,
1177 'A' , 'B' , and 'C' values.
1178
1179 After executing this code, each byte of the sequence b is either '!' ,
1180 'A' , 'B' , or 'C' . If atomicity is required, then the user must im‐
1181 plement their own synchronization (for example, using Mutex.t ).
1182
1183
1184 Data races
1185 If two domains only access disjoint parts of a byte sequence, then the
1186 observed behaviour is the equivalent to some sequential interleaving of
1187 the operations from the two domains.
1188
1189 A data race is said to occur when two domains access the same byte
1190 without synchronization and at least one of the accesses is a write.
1191 In the absence of data races, the observed behaviour is equivalent to
1192 some sequential interleaving of the operations from different domains.
1193
1194 Whenever possible, data races should be avoided by using synchroniza‐
1195 tion to mediate the accesses to the elements of the sequence.
1196
1197 Indeed, in the presence of data races, programs will not crash but the
1198 observed behaviour may not be equivalent to any sequential interleaving
1199 of operations from different domains. Nevertheless, even in the pres‐
1200 ence of data races, a read operation will return the value of some
1201 prior write to that location.
1202
1203
1204 Mixed-size accesses
1205 Another subtle point is that if a data race involves mixed-size writes
1206 and reads to the same location, the order in which those writes and
1207 reads are observed by domains is not specified. For instance, the fol‐
1208 lowing code write sequentially a 32-bit integer and a char to the same
1209 index
1210 let b = Bytes.make 10 '\000'
1211 let d1 = Domain.spawn (fun () -> Bytes.set_int32_ne b 0 100; b.[0] <- 'd' )
1212
1213
1214 In this situation, a domain that observes the write of 'd' to b. 0 is
1215 not guaranteed to also observe the write to indices 1 , 2 , or 3 .
1216
1217OCamldoc 2023-07-20 BytesLabels(3)