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