(** ** Properties of [loadbytes]. *)
(** [loadbytes] succeeds if and only if we have read permissions on the accessed memory area. *)

(* Specifications: *)
Axiom range_perm_loadbytes:
forall m b ofs len,
range_perm m b ofs (ofs + len) Cur Readable ->
exists bytes, loadbytes m b ofs len = Some bytes.
Axiom loadbytes_range_perm:
forall m b ofs len bytes,
loadbytes m b ofs len = Some bytes ->
range_perm m b ofs (ofs + len) Cur Readable.
(** If [loadbytes] succeeds, the corresponding [load] succeeds and returns a value that is determined by the bytes read by [loadbytes]. *)
Axiom loadbytes_load:
forall chunk m b ofs bytes,
loadbytes m b ofs (size_chunk chunk) = Some bytes ->
(align_chunk chunk | ofs) ->
load chunk m b ofs = Some(decode_val chunk bytes).
(** Conversely, if [load] returns a value, the corresponding [loadbytes] succeeds and returns a list of bytes which decodes into the result of [load]. *)
Axiom load_loadbytes:
forall chunk m b ofs v,
load chunk m b ofs = Some v ->
exists bytes, loadbytes m b ofs (size_chunk chunk) = Some bytes
/\ v = decode_val chunk bytes.
(** [loadbytes] returns a list of length [n] (the number of bytes read). *)
Axiom loadbytes_length:
forall m b ofs n bytes,
loadbytes m b ofs n = Some bytes ->
length bytes = nat_of_Z n.
Axiom loadbytes_empty:
forall m b ofs n,
n <= 0 -> loadbytes m b ofs n = Some nil.
(** Composing or decomposing [loadbytes] operations at adjacent addresses. *)
Axiom loadbytes_concat:
forall m b ofs n1 n2 bytes1 bytes2,
loadbytes m b ofs n1 = Some bytes1 ->
loadbytes m b (ofs + n1) n2 = Some bytes2 ->
n1 >= 0 -> n2 >= 0 ->
loadbytes m b ofs (n1 + n2) = Some(bytes1 ++ bytes2).
Axiom loadbytes_split:
forall m b ofs n1 n2 bytes,
loadbytes m b ofs (n1 + n2) = Some bytes ->
n1 >= 0 -> n2 >= 0 ->
exists bytes1, exists bytes2,
loadbytes m b ofs n1 = Some bytes1
/\ loadbytes m b (ofs + n1) n2 = Some bytes2
/\ bytes = bytes1 ++ bytes2.