vlib.crypto+other: fix mut args
parent
818c4a14e5
commit
511a3d3901
|
@ -747,7 +747,7 @@ fn (v mut V) cc() {
|
||||||
}
|
}
|
||||||
$if windows {
|
$if windows {
|
||||||
if v.os == .msvc {
|
if v.os == .msvc {
|
||||||
cc_msvc(v)
|
cc_msvc(mut v)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,8 @@ pub fn new_cbc(b AesCipher, iv []byte) AesCbc {
|
||||||
|
|
||||||
pub fn (x &AesCbc) block_size() int { return x.block_size }
|
pub fn (x &AesCbc) block_size() int { return x.block_size }
|
||||||
|
|
||||||
pub fn (x &AesCbc) encrypt_blocks(dst, src []byte) {
|
pub fn (x mut AesCbc) encrypt_blocks(dst mut []byte, src_ []byte) {
|
||||||
|
mut src := src_
|
||||||
if src.len%x.block_size != 0 {
|
if src.len%x.block_size != 0 {
|
||||||
panic('crypto.cipher: input not full blocks')
|
panic('crypto.cipher: input not full blocks')
|
||||||
}
|
}
|
||||||
|
@ -72,14 +73,14 @@ pub fn (x &AesCbc) encrypt_blocks(dst, src []byte) {
|
||||||
} else {
|
} else {
|
||||||
src = src.right(x.block_size)
|
src = src.right(x.block_size)
|
||||||
}
|
}
|
||||||
dst = dst.right(x.block_size)
|
*dst = dst.right(x.block_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the iv for the next crypt_blocks call.
|
// Save the iv for the next crypt_blocks call.
|
||||||
copy(x.iv, iv)
|
copy(x.iv, iv)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (x &AesCbc) decrypt_blocks(dst mut []byte, src []byte) {
|
pub fn (x mut AesCbc) decrypt_blocks(dst mut []byte, src []byte) {
|
||||||
if src.len%x.block_size != 0 {
|
if src.len%x.block_size != 0 {
|
||||||
panic('crypto.cipher: input not full blocks')
|
panic('crypto.cipher: input not full blocks')
|
||||||
}
|
}
|
||||||
|
@ -105,7 +106,7 @@ pub fn (x &AesCbc) decrypt_blocks(dst mut []byte, src []byte) {
|
||||||
// Loop over all but the first block.
|
// Loop over all but the first block.
|
||||||
for start > 0 {
|
for start > 0 {
|
||||||
x.b.decrypt(dst.slice(start, end), src.slice(start, end))
|
x.b.decrypt(dst.slice(start, end), src.slice(start, end))
|
||||||
cipher.xor_bytes(dst.slice(start, end), dst.slice(start, end), src.slice(prev, start))
|
cipher.xor_bytes(mut dst.slice(start, end), dst.slice(start, end), src.slice(prev, start))
|
||||||
|
|
||||||
end = start
|
end = start
|
||||||
start = prev
|
start = prev
|
||||||
|
@ -122,7 +123,7 @@ pub fn (x &AesCbc) decrypt_blocks(dst mut []byte, src []byte) {
|
||||||
x.tmp = x.iv
|
x.tmp = x.iv
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (x &AesCbc) set_iv(iv []byte) {
|
fn (x mut AesCbc) set_iv(iv []byte) {
|
||||||
if iv.len != x.iv.len {
|
if iv.len != x.iv.len {
|
||||||
panic('cipher: incorrect length IV')
|
panic('cipher: incorrect length IV')
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ fn test_crypto_aes() {
|
||||||
panic('ciphertext is not a multiple of the block size')
|
panic('ciphertext is not a multiple of the block size')
|
||||||
}
|
}
|
||||||
mode := aes.new_cbc(block, iv)
|
mode := aes.new_cbc(block, iv)
|
||||||
mode.encrypt_blocks(ciphertext, ciphertext)
|
mode.encrypt_blocks(mut ciphertext, ciphertext)
|
||||||
|
|
||||||
assert ciphertext.hex() == 'c210459b514668ddc44674885e4979215265a6c44431a248421254ef357a8c2a308a8bddf5623af9df91737562041cf1'
|
assert ciphertext.hex() == 'c210459b514668ddc44674885e4979215265a6c44431a248421254ef357a8c2a308a8bddf5623af9df91737562041cf1'
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,7 +160,7 @@ fn rotw(w u32) u32 { return u32(w<<u32(8)) | u32(w>>u32(24)) }
|
||||||
|
|
||||||
// Key expansion algorithm. See FIPS-197, Figure 11.
|
// Key expansion algorithm. See FIPS-197, Figure 11.
|
||||||
// Their rcon[i] is our powx[i-1] << 24.
|
// Their rcon[i] is our powx[i-1] << 24.
|
||||||
fn expand_key_generic(key []byte, enc, dec []u32) {
|
fn expand_key_generic(key []byte, enc mut []u32, dec mut []u32) {
|
||||||
// Encryption key setup.
|
// Encryption key setup.
|
||||||
mut i := 0
|
mut i := 0
|
||||||
nk := key.len / 4
|
nk := key.len / 4
|
||||||
|
|
|
@ -13,10 +13,10 @@ import (
|
||||||
// this is the generiv v version, no arch optimisations
|
// this is the generiv v version, no arch optimisations
|
||||||
fn new_cipher_generic(key []byte) AesCipher {
|
fn new_cipher_generic(key []byte) AesCipher {
|
||||||
n := key.len + 28
|
n := key.len + 28
|
||||||
c := AesCipher{
|
mut c := AesCipher{
|
||||||
enc: [u32(0); n]
|
enc: [u32(0); n]
|
||||||
dec: [u32(0); n]
|
dec: [u32(0); n]
|
||||||
}
|
}
|
||||||
expand_key_generic(key, c.enc, c.dec)
|
expand_key_generic(key, mut c.enc, mut c.dec)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,6 @@ pub fn safe_xor_bytes(dst mut []byte, a, b []byte, n int) {
|
||||||
|
|
||||||
// fast_xor_words XORs multiples of 4 or 8 bytes (depending on architecture.)
|
// fast_xor_words XORs multiples of 4 or 8 bytes (depending on architecture.)
|
||||||
// The slice arguments a and b are assumed to be of equal length.
|
// The slice arguments a and b are assumed to be of equal length.
|
||||||
pub fn xor_words(dst, a, b []byte) {
|
pub fn xor_words(dst mut []byte, a, b []byte) {
|
||||||
safe_xor_bytes(mut dst, a, b, b.len)
|
safe_xor_bytes(mut dst, a, b, b.len)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,14 +55,15 @@ pub fn new() *Digest {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d mut Digest) write(p mut []byte) ?int {
|
pub fn (d mut Digest) write(p_ []byte) ?int {
|
||||||
|
mut p := p_
|
||||||
nn := p.len
|
nn := p.len
|
||||||
d.len += u64(nn)
|
d.len += u64(nn)
|
||||||
if d.nx > 0 {
|
if d.nx > 0 {
|
||||||
n := copy(d.x.right(d.nx), p)
|
n := copy(d.x.right(d.nx), p)
|
||||||
d.nx += n
|
d.nx += n
|
||||||
if d.nx == BlockSize {
|
if d.nx == BlockSize {
|
||||||
block(d, d.x)
|
block(mut d, d.x)
|
||||||
d.nx = 0
|
d.nx = 0
|
||||||
}
|
}
|
||||||
if n >= p.len {
|
if n >= p.len {
|
||||||
|
@ -73,7 +74,7 @@ pub fn (d mut Digest) write(p mut []byte) ?int {
|
||||||
}
|
}
|
||||||
if p.len >= BlockSize {
|
if p.len >= BlockSize {
|
||||||
n := p.len &~ (BlockSize - 1)
|
n := p.len &~ (BlockSize - 1)
|
||||||
block(d, p.left(n))
|
block(mut d, p.left(n))
|
||||||
if n >= p.len {
|
if n >= p.len {
|
||||||
p = []byte
|
p = []byte
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,7 +108,7 @@ pub fn (d mut Digest) checksum() []byte {
|
||||||
tmp[0] = 0x80
|
tmp[0] = 0x80
|
||||||
pad := (55 - int(d.len)) % 64 // calculate number of padding bytes
|
pad := (55 - int(d.len)) % 64 // calculate number of padding bytes
|
||||||
binary.little_endian_put_u64(mut tmp.right(1+pad), u64(d.len<<u64(3))) // append length in bits
|
binary.little_endian_put_u64(mut tmp.right(1+pad), u64(d.len<<u64(3))) // append length in bits
|
||||||
d.write(mut tmp.left(1+pad+8))
|
d.write(tmp.left(1+pad+8))
|
||||||
|
|
||||||
// The previous write ensures that a whole number of
|
// The previous write ensures that a whole number of
|
||||||
// blocks (i.e. a multiple of 64 bytes) have been hashed.
|
// blocks (i.e. a multiple of 64 bytes) have been hashed.
|
||||||
|
@ -127,7 +128,7 @@ pub fn (d mut Digest) checksum() []byte {
|
||||||
// sum returns the MD5 checksum of the data.
|
// sum returns the MD5 checksum of the data.
|
||||||
pub fn sum(data []byte) []byte {
|
pub fn sum(data []byte) []byte {
|
||||||
mut d := new()
|
mut d := new()
|
||||||
d.write(mut data)
|
d.write(data)
|
||||||
return d.checksum()
|
return d.checksum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub fn new_cipher(key []byte) ?Cipher {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset zeros the key data and makes the Cipher unusable.
|
// reset zeros the key data and makes the Cipher unusable.good to com
|
||||||
//
|
//
|
||||||
// Deprecated: Reset can't guarantee that the key will be entirely removed from
|
// Deprecated: Reset can't guarantee that the key will be entirely removed from
|
||||||
// the process's memory.
|
// the process's memory.
|
||||||
|
@ -69,7 +69,7 @@ pub fn (c mut Cipher) xor_key_stream(dst mut []byte, src []byte) {
|
||||||
mut i := c.i
|
mut i := c.i
|
||||||
mut j := c.j
|
mut j := c.j
|
||||||
_ := dst[src.len-1]
|
_ := dst[src.len-1]
|
||||||
dst = dst.left(src.len) // eliminate bounds check from loop
|
*dst = dst.left(src.len) // eliminate bounds check from loop
|
||||||
for k, v in src {
|
for k, v in src {
|
||||||
i += u8(1)
|
i += u8(1)
|
||||||
x := c.s[i]
|
x := c.s[i]
|
||||||
|
|
|
@ -7,7 +7,7 @@ import crypto.rc4
|
||||||
fn test_crypto_rc4() {
|
fn test_crypto_rc4() {
|
||||||
key := 'tthisisourrc4key'.bytes()
|
key := 'tthisisourrc4key'.bytes()
|
||||||
|
|
||||||
c := rc4.new_cipher(key) or {
|
mut c := rc4.new_cipher(key) or {
|
||||||
println(err)
|
println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,8 @@ pub fn new() &Digest {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d mut Digest) write(p mut []byte) ?int {
|
pub fn (d mut Digest) write(p_ []byte) ?int {
|
||||||
|
mut p := p_
|
||||||
nn := p.len
|
nn := p.len
|
||||||
d.len += u64(nn)
|
d.len += u64(nn)
|
||||||
|
|
||||||
|
@ -108,15 +109,15 @@ fn (d mut Digest) checksum() []byte {
|
||||||
tmp[0] = 0x80
|
tmp[0] = 0x80
|
||||||
|
|
||||||
if int(len)%64 < 56 {
|
if int(len)%64 < 56 {
|
||||||
d.write(mut tmp.left(56-int(len)%64))
|
d.write(tmp.left(56-int(len)%64))
|
||||||
} else {
|
} else {
|
||||||
d.write(mut tmp.left(64+56-int(len)%64))
|
d.write(tmp.left(64+56-int(len)%64))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length in bits.
|
// Length in bits.
|
||||||
len <<= u64(3)
|
len <<= u64(3)
|
||||||
binary.big_endian_put_u64(mut tmp, len)
|
binary.big_endian_put_u64(mut tmp, len)
|
||||||
d.write(mut tmp.left(8))
|
d.write(tmp.left(8))
|
||||||
|
|
||||||
mut digest := [byte(0); Size]
|
mut digest := [byte(0); Size]
|
||||||
|
|
||||||
|
@ -132,14 +133,14 @@ fn (d mut Digest) checksum() []byte {
|
||||||
// Sum returns the SHA-1 checksum of the data.
|
// Sum returns the SHA-1 checksum of the data.
|
||||||
pub fn sum(data []byte) []byte {
|
pub fn sum(data []byte) []byte {
|
||||||
mut d := new()
|
mut d := new()
|
||||||
d.write(mut data)
|
d.write(data)
|
||||||
return d.checksum()
|
return d.checksum()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block(dig &Digest, p []byte) {
|
fn block(dig &Digest, p []byte) {
|
||||||
// For now just use block_generic until we have specific
|
// For now just use block_generic until we have specific
|
||||||
// architecture optimized versions
|
// architecture optimized versions
|
||||||
block_generic(dig, p)
|
block_generic(mut dig, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d &Digest) size() int { return Size }
|
pub fn (d &Digest) size() int { return Size }
|
||||||
|
|
|
@ -17,7 +17,8 @@ const (
|
||||||
_K3 = 0xCA62C1D6
|
_K3 = 0xCA62C1D6
|
||||||
)
|
)
|
||||||
|
|
||||||
fn block_generic(dig mut Digest, p []byte) {
|
fn block_generic(dig mut Digest, p_ []byte) {
|
||||||
|
mut p := p_
|
||||||
mut w := [u32(0); 16]
|
mut w := [u32(0); 16]
|
||||||
mut h0 := dig.h[0]
|
mut h0 := dig.h[0]
|
||||||
mut h1 := dig.h[1]
|
mut h1 := dig.h[1]
|
||||||
|
|
|
@ -92,7 +92,8 @@ pub fn new224() *Digest {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (d mut Digest) write(p mut []byte) ?int {
|
fn (d mut Digest) write(p_ []byte) ?int {
|
||||||
|
mut p := p_
|
||||||
nn := p.len
|
nn := p.len
|
||||||
d.len += u64(nn)
|
d.len += u64(nn)
|
||||||
if d.nx > 0 {
|
if d.nx > 0 {
|
||||||
|
@ -145,15 +146,15 @@ fn (d mut Digest) checksum() []byte {
|
||||||
mut tmp := [byte(0); 64]
|
mut tmp := [byte(0); 64]
|
||||||
tmp[0] = 0x80
|
tmp[0] = 0x80
|
||||||
if int(len)%64 < 56 {
|
if int(len)%64 < 56 {
|
||||||
d.write(mut tmp.left(56-int(len)%64))
|
d.write(tmp.left(56-int(len)%64))
|
||||||
} else {
|
} else {
|
||||||
d.write(mut tmp.left(64+56-int(len)%64))
|
d.write(tmp.left(64+56-int(len)%64))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length in bits.
|
// Length in bits.
|
||||||
len <<= u64(3)
|
len <<= u64(3)
|
||||||
binary.big_endian_put_u64(mut tmp, len)
|
binary.big_endian_put_u64(mut tmp, len)
|
||||||
d.write(mut tmp.left(8))
|
d.write(tmp.left(8))
|
||||||
|
|
||||||
if d.nx != 0 {
|
if d.nx != 0 {
|
||||||
panic('d.nx != 0')
|
panic('d.nx != 0')
|
||||||
|
@ -183,14 +184,14 @@ pub fn sum(data []byte) []byte {
|
||||||
// sum256 returns the SHA256 checksum of the data.
|
// sum256 returns the SHA256 checksum of the data.
|
||||||
pub fn sum256(data []byte) []byte {
|
pub fn sum256(data []byte) []byte {
|
||||||
mut d := new()
|
mut d := new()
|
||||||
d.write(mut data)
|
d.write(data)
|
||||||
return d.checksum()
|
return d.checksum()
|
||||||
}
|
}
|
||||||
|
|
||||||
// sum224 returns the SHA224 checksum of the data.
|
// sum224 returns the SHA224 checksum of the data.
|
||||||
pub fn sum224(data []byte) []byte {
|
pub fn sum224(data []byte) []byte {
|
||||||
mut d := new224()
|
mut d := new224()
|
||||||
d.write(mut data)
|
d.write(data)
|
||||||
sum := d.checksum()
|
sum := d.checksum()
|
||||||
mut sum224 := [byte(0); Size224]
|
mut sum224 := [byte(0); Size224]
|
||||||
copy(sum224, sum.left(Size224))
|
copy(sum224, sum.left(Size224))
|
||||||
|
|
|
@ -80,7 +80,9 @@ const (
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
fn block_generic(dig mut Digest, p []byte) {
|
fn block_generic(dig mut Digest, p_ []byte) {
|
||||||
|
mut p := p_
|
||||||
|
|
||||||
mut w := [u32(0); 64]
|
mut w := [u32(0); 64]
|
||||||
|
|
||||||
mut h0 := dig.h[0]
|
mut h0 := dig.h[0]
|
||||||
|
|
|
@ -146,7 +146,8 @@ fn new384() *Digest {
|
||||||
return _new(crypto.Hash.SHA384)
|
return _new(crypto.Hash.SHA384)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (d mut Digest) write(p mut []byte) ?int {
|
fn (d mut Digest) write(p_ []byte) ?int {
|
||||||
|
mut p := p_
|
||||||
nn := p.len
|
nn := p.len
|
||||||
d.len += u64(nn)
|
d.len += u64(nn)
|
||||||
if d.nx > 0 {
|
if d.nx > 0 {
|
||||||
|
@ -209,9 +210,9 @@ fn (d mut Digest) checksum() []byte {
|
||||||
tmp[0] = 0x80
|
tmp[0] = 0x80
|
||||||
|
|
||||||
if int(len)%128 < 112 {
|
if int(len)%128 < 112 {
|
||||||
d.write(mut tmp.left(112-int(len)%128))
|
d.write(tmp.left(112-int(len)%128))
|
||||||
} else {
|
} else {
|
||||||
d.write(mut tmp.left(128+112-int(len)%128))
|
d.write(tmp.left(128+112-int(len)%128))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length in bits.
|
// Length in bits.
|
||||||
|
@ -219,7 +220,7 @@ fn (d mut Digest) checksum() []byte {
|
||||||
|
|
||||||
binary.big_endian_put_u64(mut tmp, u64(0)) // upper 64 bits are always zero, because len variable has type u64
|
binary.big_endian_put_u64(mut tmp, u64(0)) // upper 64 bits are always zero, because len variable has type u64
|
||||||
binary.big_endian_put_u64(mut tmp.right(8), len)
|
binary.big_endian_put_u64(mut tmp.right(8), len)
|
||||||
d.write(mut tmp.left(16))
|
d.write(tmp.left(16))
|
||||||
|
|
||||||
if d.nx != 0 {
|
if d.nx != 0 {
|
||||||
panic('d.nx != 0')
|
panic('d.nx != 0')
|
||||||
|
@ -244,14 +245,14 @@ fn (d mut Digest) checksum() []byte {
|
||||||
// sum512 returns the SHA512 checksum of the data.
|
// sum512 returns the SHA512 checksum of the data.
|
||||||
pub fn sum512(data []byte) []byte {
|
pub fn sum512(data []byte) []byte {
|
||||||
mut d := _new(crypto.Hash.SHA512)
|
mut d := _new(crypto.Hash.SHA512)
|
||||||
d.write(mut data)
|
d.write(data)
|
||||||
return d.checksum()
|
return d.checksum()
|
||||||
}
|
}
|
||||||
|
|
||||||
// sum384 returns the SHA384 checksum of the data.
|
// sum384 returns the SHA384 checksum of the data.
|
||||||
pub fn sum384(data []byte) []byte {
|
pub fn sum384(data []byte) []byte {
|
||||||
mut d := _new(crypto.Hash.SHA384)
|
mut d := _new(crypto.Hash.SHA384)
|
||||||
d.write(mut data)
|
d.write(data)
|
||||||
sum := d.checksum()
|
sum := d.checksum()
|
||||||
mut sum384 := [byte(0); Size384]
|
mut sum384 := [byte(0); Size384]
|
||||||
copy(sum384, sum.left(Size384))
|
copy(sum384, sum.left(Size384))
|
||||||
|
@ -261,7 +262,7 @@ pub fn sum384(data []byte) []byte {
|
||||||
// sum512_224 returns the Sum512/224 checksum of the data.
|
// sum512_224 returns the Sum512/224 checksum of the data.
|
||||||
pub fn sum512_224(data []byte) []byte {
|
pub fn sum512_224(data []byte) []byte {
|
||||||
mut d := _new(crypto.Hash.SHA512_224)
|
mut d := _new(crypto.Hash.SHA512_224)
|
||||||
d.write(mut data)
|
d.write(data)
|
||||||
sum := d.checksum()
|
sum := d.checksum()
|
||||||
mut sum224 := [byte(0); Size224]
|
mut sum224 := [byte(0); Size224]
|
||||||
copy(sum224, sum.left(Size224))
|
copy(sum224, sum.left(Size224))
|
||||||
|
@ -271,7 +272,7 @@ pub fn sum512_224(data []byte) []byte {
|
||||||
// Sum512_256 returns the Sum512/256 checksum of the data.
|
// Sum512_256 returns the Sum512/256 checksum of the data.
|
||||||
pub fn sum512_256(data []byte) []byte {
|
pub fn sum512_256(data []byte) []byte {
|
||||||
mut d := _new(crypto.Hash.SHA512_256)
|
mut d := _new(crypto.Hash.SHA512_256)
|
||||||
d.write(mut data)
|
d.write(data)
|
||||||
sum := d.checksum()
|
sum := d.checksum()
|
||||||
mut sum256 := [byte(0); Size256]
|
mut sum256 := [byte(0); Size256]
|
||||||
copy(sum256, sum.left(Size256))
|
copy(sum256, sum.left(Size256))
|
||||||
|
@ -281,7 +282,7 @@ pub fn sum512_256(data []byte) []byte {
|
||||||
fn block(dig mut Digest, p []byte) {
|
fn block(dig mut Digest, p []byte) {
|
||||||
// For now just use block_generic until we have specific
|
// For now just use block_generic until we have specific
|
||||||
// architecture optimized versions
|
// architecture optimized versions
|
||||||
block_generic(mut dig, mut p)
|
block_generic(mut dig, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (d &Digest) size() int {
|
pub fn (d &Digest) size() int {
|
||||||
|
|
|
@ -94,7 +94,9 @@ const(
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
fn block_generic(dig mut Digest, p mut []byte) {
|
fn block_generic(dig mut Digest, p_ []byte) {
|
||||||
|
mut p := p_
|
||||||
|
|
||||||
mut w := [u64(0); 80]
|
mut w := [u64(0); 80]
|
||||||
|
|
||||||
mut h0 := dig.h[0]
|
mut h0 := dig.h[0]
|
||||||
|
|
Loading…
Reference in New Issue