1946055e创建于 2025年8月9日历史提交
/*
Copyright (c) 2025 WuJingrun(吴京润)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
package f_io

import std.binary.*
import std.io.ByteBuffer
import f_base.*

public interface ExtendByteBuffer {
    func readBool(endian!: Endian): ?Bool
    func readUInt8(endian!: Endian): ?UInt8
    func readUInt16(endian!: Endian): ?UInt16
    func readUInt32(endian!: Endian): ?UInt32
    func readUInt64(endian!: Endian): ?UInt64

    func readInt8(endian!: Endian): ?Int8
    func readInt16(endian!: Endian): ?Int16
    func readInt32(endian!: Endian): ?Int32
    func readInt64(endian!: Endian): ?Int64

    func readFloat16(endian!: Endian): ?Float16
    func readFloat32(endian!: Endian): ?Float32
    func readFloat64(endian!: Endian): ?Float64

    func writeBool(value: Bool, endian!: Endian): Unit
    func writeUInt8(value: UInt8, endian!: Endian): Unit
    func writeUInt16(value: UInt16, endian!: Endian): Unit
    func writeUInt32(value: UInt32, endian!: Endian): Unit
    func writeUInt64(value: UInt64, endian!: Endian): Unit

    func writeInt8(value: Int8, endian!: Endian): Unit
    func writeInt16(value: Int16, endian!: Endian): Unit
    func writeInt32(value: Int32, endian!: Endian): Unit
    func writeInt64(value: Int64, endian!: Endian): Unit

    func writeFloat16(value: Float16, endian!: Endian): Unit
    func writeFloat32(value: Float32, endian!: Endian): Unit
    func writeFloat64(value: Float64, endian!: Endian): Unit
}

extend ByteBuffer <: ExtendByteBuffer {
    private func read<T>(len: Int64, endian: Endian): ?T where T <: BigEndianOrder<T> & LittleEndianOrder<T> {
        let bytes = Array<Byte>(len, repeat: 0)
        if (len == 0) {
            None
        } else {
            match (endian) {
                case Big => T.readBigEndian(bytes[0..len])
                case Little => T.readLittleEndian(bytes[0..len])
            }
        }
    }
    public func readBool(endian!: Endian = Endian.Platform): ?Bool {
        if (let Some(x) <- this.readByte()) {
            x != 0
        } else {
            None
        }
    }
    public func readUInt8(endian!: Endian = Endian.Platform): ?UInt8 {
        readByte()
    }
    public func readUInt16(endian!: Endian = Endian.Platform): ?UInt16 {
        read<UInt16>(2, endian)
    }
    public func readUInt32(endian!: Endian = Endian.Platform): ?UInt32 {
        read<UInt32>(4, endian)
    }
    public func readUInt64(endian!: Endian = Endian.Platform): ?UInt64 {
        read<UInt64>(8, endian)
    }
    public func readInt8(endian!: Endian = Endian.Platform): ?Int8 {
        readByte()?.toInt()
    }
    public func readInt16(endian!: Endian = Endian.Platform): ?Int16 {
        read<Int16>(2, endian)
    }
    public func readInt32(endian!: Endian = Endian.Platform): ?Int32 {
        read<Int32>(4, endian)
    }
    public func readInt64(endian!: Endian = Endian.Platform): ?Int64 {
        read<Int64>(8, endian)
    }

    public func readFloat16(endian!: Endian = Endian.Platform): ?Float16 {
        read<Float16>(2, endian)
    }
    public func readFloat32(endian!: Endian = Endian.Platform): ?Float32 {
        read<Float32>(4, endian)
    }
    public func readFloat64(endian!: Endian = Endian.Platform): ?Float64 {
        read<Float64>(8, endian)
    }

    private func write<T>(value: T, len: Int64, endian: Endian): Unit where T <: BigEndianOrder<T> & LittleEndianOrder<T> {
        let bytes = Array<Byte>(len, repeat: 0)
        match (endian) {
            case Big => value.writeBigEndian(bytes)
            case Little => value.writeLittleEndian(bytes)
        }
        write(bytes)
    }
    public func writeBool(value: Bool, endian!: Endian = Endian.Platform): Unit {
        writeUInt8(if (value) {
            1
        } else {
            0
        }, endian: endian)
    }
    public func writeUInt8(value: UInt8, endian!: Endian = Endian.Platform): Unit {
        writeByte(value)
    }
    public func writeUInt16(value: UInt16, endian!: Endian = Endian.Platform): Unit {
        write<UInt16>(value, 2, endian)
    }
    public func writeUInt32(value: UInt32, endian!: Endian = Endian.Platform): Unit {
        write<UInt32>(value, 4, endian)
    }
    public func writeUInt64(value: UInt64, endian!: Endian = Endian.Platform): Unit {
        write<UInt64>(value, 8, endian)
    }

    public func writeInt8(value: Int8, endian!: Endian = Endian.Platform): Unit {
        writeByte(value.toUInt())
    }
    public func writeInt16(value: Int16, endian!: Endian = Endian.Platform): Unit {
        write<Int16>(value, 2, endian)
    }
    public func writeInt32(value: Int32, endian!: Endian = Endian.Platform): Unit {
        write<Int32>(value, 4, endian)
    }
    public func writeInt64(value: Int64, endian!: Endian = Endian.Platform): Unit {
        write<Int64>(value, 8, endian)
    }

    public func writeFloat16(value: Float16, endian!: Endian = Endian.Platform): Unit {
        write<Float16>(value, 2, endian)
    }
    public func writeFloat32(value: Float32, endian!: Endian = Endian.Platform): Unit {
        write<Float32>(value, 4, endian)
    }
    public func writeFloat64(value: Float64, endian!: Endian = Endian.Platform): Unit {
        write<Float64>(value, 8, endian)
    }
}