/*
* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* This source file is part of the Cangjie project, licensed under Apache-2.0
* with Runtime Library Exception.
*
* See https://cangjie-lang.cn/pages/LICENSE for license information.
*/
// The Cangjie API is in Beta. For details on its capabilities and limitations, please refer to the README file.
package std.net
import std.binary.*
import std.convert.*
import std.overflow.*
@C
struct UInt128 {
static prop Max: UInt128 {
get() {
UInt128(0xFFFF_FFFF_FFFF_FFFFu64, 0xFFFF_FFFF_FFFF_FFFFu64)
}
}
static prop Min: UInt128 {
get() {
UInt128(0u64, 0u64)
}
}
private let _hi: UInt64
private let _lo: UInt64
public const init(hi: UInt64, lo: UInt64) {
this._hi = hi
this._lo = lo
}
public func checkedShl(shiftcount: UInt64): ?UInt128 {
if (shiftcount >= 128 || shiftcount < 0) {
return None
}
if (shiftcount < 64) {
let hi = _hi.wrappingShl(shiftcount) | _lo.wrappingShr(64 - shiftcount)
let lo = _lo.wrappingShl(shiftcount)
return UInt128(hi, lo)
} else {
let hi = _lo.wrappingShl(shiftcount - 64)
return UInt128(hi, 0)
}
}
public func checkedShr(shiftcount: UInt64): ?UInt128 {
if (shiftcount >= 128 || shiftcount < 0) {
return None
}
if (shiftcount < 64) {
let lo = _lo.wrappingShr(shiftcount) | _hi.wrappingShl(64 - shiftcount)
let hi = _hi.wrappingShr(shiftcount)
return UInt128(hi, lo)
} else {
let lo = _hi.wrappingShr(shiftcount - 64)
return UInt128(0, lo)
}
}
public operator func &(rhs: UInt128): UInt128 {
return UInt128(this._hi & rhs._hi, this._lo & rhs._lo)
}
public operator func ^(rhs: UInt128): UInt128 {
return UInt128(this._hi ^ rhs._hi, this._lo ^ rhs._lo)
}
public operator func |(rhs: UInt128): UInt128 {
return UInt128(this._hi | rhs._hi, this._lo | rhs._lo)
}
public operator func !(): UInt128 {
return UInt128(!this._hi, !this._lo)
}
public func toU16(): Array<UInt16> {
let src = toBigEndian()
let dst = Array<UInt16>(src.size / 2, repeat: 0)
for (i in 0..dst.size) {
dst[i] = UInt16.readBigEndian(src[i * 2..])
}
return dst
}
public static func fromU16(src: Array<UInt16>): UInt128 {
let dst = Array<UInt8>(src.size * 2, repeat: 0)
for (i in 0..src.size) {
src[i].writeBigEndian(dst[i * 2..])
}
return UInt128.readBigEndian(dst)
}
public static func readBigEndian(buf: Array<UInt8>): UInt128 {
return UInt128(UInt64.readBigEndian(buf), UInt64.readBigEndian(buf[8..]))
}
public func writeBigEndian(buf: Array<UInt8>): Int64 {
_hi.writeBigEndian(buf)
_lo.writeBigEndian(buf[8..])
return 16
}
public static func readLittleEndian(buf: Array<UInt8>): UInt128 {
return UInt128(UInt64.readLittleEndian(buf[8..]), UInt64.readLittleEndian(buf[..8]))
}
public func writeLittleEndian(buf: Array<UInt8>): Int64 {
_lo.writeLittleEndian(buf)
_hi.writeLittleEndian(buf[8..])
return 16
}
public func toBigEndian(): Array<UInt8> {
let buf = Array<Byte>(16, repeat: 0)
writeBigEndian(buf)
return buf
}
public func toLittleEndian(): Array<UInt8> {
let buf = Array<Byte>(16, repeat: 0)
writeLittleEndian(buf)
return buf
}
public func swapBytes(): UInt128 {
UInt128(this._lo.swapBytes(), this._hi.swapBytes())
}
public operator func ==(rhs: UInt128): Bool {
return this._hi == rhs._hi && this._lo == rhs._lo
}
public operator func !=(rhs: UInt128): Bool {
return !(this == rhs)
}
public func toString(): String {
let octets = toLittleEndian()
let sb = StringBuilder()
for (i in octets) {
sb.append(i.format("#x"))
sb.append(" ")
}
return sb.toString()
}
}