///|
fn u8_at(data : Array[Byte], offset : Int) -> Result[Int, FatError] {
if offset < 0 || offset >= data.length() {
Err(Truncated("byte", offset + 1, data.length()))
} else {
Ok(data[offset].to_int())
}
}
///|
fn u16le_at(data : Array[Byte], offset : Int) -> Result[Int, FatError] {
if offset < 0 || offset + 1 >= data.length() {
Err(Truncated("u16", offset + 2, data.length()))
} else {
Ok(data[offset].to_int() | (data[offset + 1].to_int() << 8))
}
}
///|
fn u32le_at(data : Array[Byte], offset : Int) -> Result[Int, FatError] {
if offset < 0 || offset + 3 >= data.length() {
Err(Truncated("u32", offset + 4, data.length()))
} else {
let b0 = data[offset].to_int()
let b1 = data[offset + 1].to_int()
let b2 = data[offset + 2].to_int()
let b3 = data[offset + 3].to_int()
Ok(b0 | (b1 << 8) | (b2 << 16) | (b3 << 24))
}
}
///|
fn put_u8(
data : Array[Byte],
offset : Int,
value : Int,
) -> Result[Unit, FatError] {
if offset < 0 || offset >= data.length() {
Err(Truncated("byte", offset + 1, data.length()))
} else {
data[offset] = (value & 0xFF).to_byte()
Ok(())
}
}
///|
fn put_u16le(
data : Array[Byte],
offset : Int,
value : Int,
) -> Result[Unit, FatError] {
if offset < 0 || offset + 1 >= data.length() {
Err(Truncated("u16", offset + 2, data.length()))
} else {
data[offset] = (value & 0xFF).to_byte()
data[offset + 1] = ((value >> 8) & 0xFF).to_byte()
Ok(())
}
}
///|
fn put_u32le(
data : Array[Byte],
offset : Int,
value : Int,
) -> Result[Unit, FatError] {
if offset < 0 || offset + 3 >= data.length() {
Err(Truncated("u32", offset + 4, data.length()))
} else {
data[offset] = (value & 0xFF).to_byte()
data[offset + 1] = ((value >> 8) & 0xFF).to_byte()
data[offset + 2] = ((value >> 16) & 0xFF).to_byte()
data[offset + 3] = ((value >> 24) & 0xFF).to_byte()
Ok(())
}
}
///|
fn slice_bytes(
data : Array[Byte],
start : Int,
length : Int,
) -> Result[Bytes, FatError] {
if start < 0 || length < 0 || start + length > data.length() {
Err(Truncated("slice", start + length, data.length()))
} else {
Ok(Bytes::makei(length, i => data[start + i]))
}
}
///|
fn blit_bytes(
data : Array[Byte],
start : Int,
source : Bytes,
) -> Result[Unit, FatError] {
if start < 0 || start + source.length() > data.length() {
Err(Truncated("blit", start + source.length(), data.length()))
} else {
for i = 0; i < source.length(); i = i + 1 {
data[start + i] = source[i]
}
Ok(())
}
}
///|
fn fill_bytes(
data : Array[Byte],
start : Int,
length : Int,
value : Byte,
) -> Result[Unit, FatError] {
if start < 0 || length < 0 || start + length > data.length() {
Err(Truncated("fill", start + length, data.length()))
} else {
for i = 0; i < length; i = i + 1 {
data[start + i] = value
}
Ok(())
}
}
///|
fn ascii_pad11(text : String) -> Result[Bytes, FatError] {
let out = Array::make(11, b' ')
let mut i = 0
while i < text.length() && i < 11 {
let code = text[i].to_int()
if code < 32 || code > 126 {
return Err(InvalidName(text))
}
out[i] = code.to_byte()
i = i + 1
}
Ok(Bytes::from_array(out))
}
///|
fn ascii_from_padded(data : Bytes) -> String {
let mut end = data.length()
while end > 0 && data[end - 1] == b' ' {
end = end - 1
}
let mut text = ""
for i = 0; i < end; i = i + 1 {
text = text + data[i].to_int().unsafe_to_char().to_string()
}
text
}
///|
fn hex_digit(value : Int) -> Char {
if value < 10 {
(48 + value).unsafe_to_char()
} else {
(87 + value).unsafe_to_char()
}
}
///|
pub fn hex_encode(data : Bytes) -> String {
let mut text = ""
for i = 0; i < data.length(); i = i + 1 {
let value = data[i].to_int()
text = text + hex_digit((value >> 4) & 0x0F).to_string()
text = text + hex_digit(value & 0x0F).to_string()
}
text
}
///|
fn power_of_two(value : Int) -> Bool {
value > 0 && (value & (value - 1)) == 0
}