///|
/// バイナリデータリーダー
/// カーソル位置を追跡しながらリトルエンディアンで読み込む
pub struct Reader {
data : Array[Byte]
mut pos : Int
}
///|
/// 新しいリーダーを作成
pub fn Reader::new(data~ : Bytes) -> Reader {
{ data: data.to_array(), pos: 0 }
}
///|
/// 現在の位置を取得
pub fn Reader::position(self : Reader) -> Int {
self.pos
}
///|
/// データの長さを取得
pub fn Reader::length(self : Reader) -> Int {
self.data.length()
}
///|
/// まだデータが残っているか
pub fn Reader::has_remaining(self : Reader) -> Bool {
self.pos < self.data.length()
}
///|
/// 残りのバイト数を取得
pub fn Reader::remaining(self : Reader) -> Int {
self.data.length() - self.pos
}
///|
/// 1バイト読み込んで位置を進める
pub fn Reader::read_byte(self : Reader) -> Byte {
let b = self.data[self.pos]
self.pos = self.pos + 1
b
}
///|
/// 2バイト読み込む(リトルエンディアン、UInt16)
pub fn Reader::read_word(self : Reader) -> UInt16 {
let b0 = self.read_byte().to_uint16()
let b1 = self.read_byte().to_uint16()
b0 | (b1 << 8)
}
///|
/// 4バイト読み込む(リトルエンディアン、UInt32)
pub fn Reader::read_dword(self : Reader) -> UInt {
let b0 = self.read_byte().to_uint()
let b1 = self.read_byte().to_uint()
let b2 = self.read_byte().to_uint()
let b3 = self.read_byte().to_uint()
b0 | (b1 << 8) | (b2 << 16) | (b3 << 24)
}
///|
/// 8バイト読み込んでUInt64として解釈
pub fn Reader::read_uint64(self : Reader) -> UInt64 {
let b0 = self.read_byte().to_uint64()
let b1 = self.read_byte().to_uint64()
let b2 = self.read_byte().to_uint64()
let b3 = self.read_byte().to_uint64()
let b4 = self.read_byte().to_uint64()
let b5 = self.read_byte().to_uint64()
let b6 = self.read_byte().to_uint64()
let b7 = self.read_byte().to_uint64()
b0 |
(b1 << 8) |
(b2 << 16) |
(b3 << 24) |
(b4 << 32) |
(b5 << 40) |
(b6 << 48) |
(b7 << 56)
}
///|
/// IEEE 754 double (8バイト) を読み込む
pub fn Reader::read_double(self : Reader) -> Double {
let bits = self.read_uint64()
UInt64::reinterpret_as_double(bits)
}
///|
/// nバイトスキップする
pub fn Reader::skip(self : Reader, n~ : Int) -> Unit {
self.pos = self.pos + n
}
///|
/// nバイト読み込む
/// データが不足している場合は空のBytesを返す
pub fn Reader::read_bytes(self : Reader, n~ : Int) -> Bytes {
if self.remaining() < n {
return Bytes::from_array([])
}
let start = self.pos
let end = self.pos + n
self.pos = end
Bytes::from_array(self.data[start:end])
}