+ # Returns a copy of `self`
+ fun clone: Bytes do
+ var b = new Bytes.with_capacity(length)
+ b.append(self)
+ return b
+ end
+
+ # Trims off the whitespaces at the beginning and the end of `self`
+ #
+ # var b = "102041426E6F1020" .hexdigest_to_bytes
+ # assert b.trim.hexdigest == "41426E6F"
+ #
+ # NOTE: A whitespace is defined here as a byte whose value is <= 0x20
+ fun trim: Bytes do
+ var st = 0
+ while st < length do
+ if self[st] > 0x20u8 then break
+ st += 1
+ end
+ if st >= length then return new Bytes.empty
+ var ed = length - 1
+ while ed > 0 do
+ if self[ed] > 0x20u8 then break
+ ed -= 1
+ end
+ return slice(st, ed - st + 1)
+ end
+
+ # Returns a subset of the content of `self` starting at `from` and of length `count`
+ #
+ # var b = "abcd".to_bytes
+ # assert b.slice(1, 2).hexdigest == "6263"
+ # assert b.slice(-1, 2).hexdigest == "61"
+ # assert b.slice(1, 0).hexdigest == ""
+ # assert b.slice(2, 5).hexdigest == "6364"
+ fun slice(from, count: Int): Bytes do
+ if count <= 0 then return new Bytes.empty
+
+ if from < 0 then
+ count += from
+ if count < 0 then count = 0
+ from = 0
+ end
+
+ if (count + from) > length then count = length - from
+ if count <= 0 then return new Bytes.empty
+
+ var ret = new Bytes.with_capacity(count)
+
+ ret.append_ns(items.fast_cstring(from), count)
+ return ret
+ end
+
+ # Returns a copy of `self` starting at `from`
+ #
+ # var b = "abcd".to_bytes
+ # assert b.slice_from(1).hexdigest == "626364"
+ # assert b.slice_from(-1).hexdigest == "61626364"
+ # assert b.slice_from(2).hexdigest == "6364"
+ fun slice_from(from: Int): Bytes do
+ if from >= length then return new Bytes.empty
+ if from < 0 then from = 0
+ return slice(from, length)
+ end
+
+ # Returns self as an hexadecimal digest.
+ #
+ # Also known as plain hexdump or postscript hexdump.
+ #
+ # ~~~
+ # var b = "abcd".to_bytes
+ # assert b.hexdigest == "61626364"
+ # assert b.hexdigest.hexdigest_to_bytes == b
+ # ~~~
+ fun hexdigest: String do
+ var elen = length * 2
+ var ns = new CString(elen)
+ var i = 0
+ var oi = 0
+ while i < length do
+ self[i].add_digest_at(ns, oi)
+ i += 1
+ oi += 2
+ end
+ return new FlatString.full(ns, elen, 0, elen)
+ end
+
+ # Return self as a C hexadecimal digest where bytes are prefixed by `\x`
+ #
+ # The output is compatible with literal stream of bytes for most languages
+ # including C and Nit.
+ #
+ # ~~~
+ # var b = "abcd".to_bytes
+ # assert b.chexdigest == "\\x61\\x62\\x63\\x64"
+ # assert b.chexdigest.unescape_to_bytes == b
+ # ~~~
+ fun chexdigest: String do
+ var elen = length * 4
+ var ns = new CString(elen)
+ var i = 0
+ var oi = 0
+ while i < length do
+ ns[oi] = 0x5Cu8 # b'\\'
+ ns[oi+1] = 0x78u8 # b'x'
+ self[i].add_digest_at(ns, oi+2)
+ i += 1
+ oi += 4
+ end
+ return new FlatString.full(ns, elen, 0, elen)
+ end
+
+
+ # Returns self as a stream of bits (0 and 1)
+ #
+ # ~~~
+ # var b = "abcd".to_bytes
+ # assert b.binarydigest == "01100001011000100110001101100100"
+ # assert b.binarydigest.binarydigest_to_bytes == b
+ # ~~~
+ fun binarydigest: String do
+ var elen = length * 8
+ var ns = new CString(elen)
+ var i = 0
+ var oi = 0
+ while i < length do
+ var c = self[i]
+ var b = 128u8
+ while b > 0u8 do
+ if c & b == 0u8 then
+ ns[oi] = 0x30u8 # b'0'
+ else
+ ns[oi] = 0x31u8 # b'1'
+ end
+ oi += 1
+ b = b >> 1
+ end
+ i += 1
+ end
+ return new FlatString.full(ns, elen, 0, elen)
+ end
+
+ # Interprets `self` as a big-endian positive integer.
+ #
+ # ~~~
+ # var b = "0102".hexdigest_to_bytes
+ # assert b.to_i == 258
+ # ~~~
+ #
+ # Nul bytes on the left are trimmed.
+ # 0 is returned for an empty Bytes object.
+ #
+ # ~~~
+ # assert "01".hexdigest_to_bytes.to_i == 1
+ # assert "0001".hexdigest_to_bytes.to_i == 1
+ #
+ # assert "0000".hexdigest_to_bytes.to_i == 0
+ # assert "00".hexdigest_to_bytes.to_i == 0
+ # assert "".hexdigest_to_bytes.to_i == 0
+ # ~~~
+ #
+ # `Int::to_bytes` is a loosely reverse method.
+ #
+ # ~~~
+ # assert b.to_i.to_bytes == b
+ # assert (b.to_i + 1).to_bytes.hexdigest == "0103"
+ # assert "0001".hexdigest_to_bytes.to_i.to_bytes.hexdigest == "01"
+ # ~~~
+ #
+ # Warning: `Int` might overflow for bytes with more than 60 bits.
+ fun to_i: Int do
+ var res = 0
+ var i = 0
+ while i < length do
+ res *= 256
+ res += self[i].to_i
+ i += 1
+ end
+ return res
+ end
+