Add missing exa-prefixed units, from_string(), to_string(), update example
This commit is contained in:
parent
080e37a7c2
commit
7d81684acb
@ -1,4 +1,4 @@
|
|||||||
## Data units converter
|
## The data size units converter
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
@ -33,48 +33,6 @@ import os
|
|||||||
import flag
|
import flag
|
||||||
import dataunits
|
import dataunits
|
||||||
|
|
||||||
const units = {
|
|
||||||
'bit': dataunits.bit
|
|
||||||
'nibble': dataunits.nibble
|
|
||||||
'bytes': dataunits.bytes
|
|
||||||
'kb': dataunits.kb
|
|
||||||
'mb': dataunits.mb
|
|
||||||
'gb': dataunits.gb
|
|
||||||
'tb': dataunits.tb
|
|
||||||
'pb': dataunits.pb
|
|
||||||
'zb': dataunits.zb
|
|
||||||
'yb': dataunits.yb
|
|
||||||
'kib': dataunits.kib
|
|
||||||
'mib': dataunits.mib
|
|
||||||
'gib': dataunits.gib
|
|
||||||
'tib': dataunits.tib
|
|
||||||
'pib': dataunits.pib
|
|
||||||
'zib': dataunits.zib
|
|
||||||
'yib': dataunits.yib
|
|
||||||
'kbit': dataunits.kbit
|
|
||||||
'mbit': dataunits.mbit
|
|
||||||
'gbit': dataunits.gbit
|
|
||||||
'tbit': dataunits.tbit
|
|
||||||
'pbit': dataunits.pbit
|
|
||||||
'zbit': dataunits.zbit
|
|
||||||
'ybit': dataunits.ybit
|
|
||||||
'kibit': dataunits.kibit
|
|
||||||
'mibit': dataunits.mibit
|
|
||||||
'gibit': dataunits.gibit
|
|
||||||
'tibit': dataunits.tibit
|
|
||||||
'pibit': dataunits.pibit
|
|
||||||
'zibit': dataunits.zibit
|
|
||||||
'yibit': dataunits.yibit
|
|
||||||
}
|
|
||||||
|
|
||||||
fn units_str() string {
|
|
||||||
mut str := []string{}
|
|
||||||
for key, _ in units {
|
|
||||||
str << key
|
|
||||||
}
|
|
||||||
return str.join(', ')
|
|
||||||
}
|
|
||||||
|
|
||||||
@[name: 'dataunit']
|
@[name: 'dataunit']
|
||||||
struct FlagConfig {
|
struct FlagConfig {
|
||||||
help bool
|
help bool
|
||||||
@ -96,7 +54,7 @@ fn main() {
|
|||||||
flags.value = no_matches[0].f64()
|
flags.value = no_matches[0].f64()
|
||||||
}
|
}
|
||||||
if flags.help {
|
if flags.help {
|
||||||
println('convert the value between *from* and *to* units.')
|
println('convert the value between data size units.')
|
||||||
println('usage: dataunit -f <unit> -t <unit> <value>')
|
println('usage: dataunit -f <unit> -t <unit> <value>')
|
||||||
println('options:')
|
println('options:')
|
||||||
println(' -help print this help message and exit')
|
println(' -help print this help message and exit')
|
||||||
@ -112,15 +70,15 @@ fn main() {
|
|||||||
eprintln('no value passed, see -help for info')
|
eprintln('no value passed, see -help for info')
|
||||||
exit(2)
|
exit(2)
|
||||||
}
|
}
|
||||||
unit_from := units[flags.from.to_lower()] or {
|
src := dataunits.from_string(flags.from) or {
|
||||||
eprintln('invalid unit ${flags.from}, valid ones: ${units_str()}')
|
eprintln('invalid source unit: ${err}')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
unit_to := units[flags.to.to_lower()] or {
|
dst := dataunits.from_string(flags.to) or {
|
||||||
eprintln('invalid unit ${flags.to}, valid ones: ${units_str()}')
|
eprintln('invalid destination unit: ${err}')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
result := '${dataunits.convert(flags.value, unit_from, unit_to):.20f}'
|
result := '${dataunits.convert(flags.value, src, dst):.20f}'
|
||||||
splitted := result.split('.')
|
splitted := result.split('.')
|
||||||
if splitted[1].contains_only('0') {
|
if splitted[1].contains_only('0') {
|
||||||
println(splitted[0])
|
println(splitted[0])
|
||||||
|
182
src/dataunits.v
182
src/dataunits.v
@ -25,9 +25,11 @@
|
|||||||
|
|
||||||
module dataunits
|
module dataunits
|
||||||
|
|
||||||
|
import maps
|
||||||
|
|
||||||
pub type DataSize = f64
|
pub type DataSize = f64
|
||||||
|
|
||||||
pub fn (d DataSize) bits() f64 {
|
pub fn (d DataSize) bit() f64 {
|
||||||
return f64(d)
|
return f64(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +61,10 @@ pub fn (d DataSize) pb() f64 {
|
|||||||
return f64(d / pb)
|
return f64(d / pb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (d DataSize) eb() f64 {
|
||||||
|
return f64(d / eb)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (d DataSize) zb() f64 {
|
pub fn (d DataSize) zb() f64 {
|
||||||
return f64(d / zb)
|
return f64(d / zb)
|
||||||
}
|
}
|
||||||
@ -87,6 +93,10 @@ pub fn (d DataSize) pib() f64 {
|
|||||||
return f64(d / pib)
|
return f64(d / pib)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (d DataSize) eib() f64 {
|
||||||
|
return f64(d / eib)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (d DataSize) zib() f64 {
|
pub fn (d DataSize) zib() f64 {
|
||||||
return f64(d / zib)
|
return f64(d / zib)
|
||||||
}
|
}
|
||||||
@ -115,6 +125,10 @@ pub fn (d DataSize) pbit() f64 {
|
|||||||
return f64(d / pbit)
|
return f64(d / pbit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (d DataSize) ebit() f64 {
|
||||||
|
return f64(d / ebit)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (d DataSize) zbit() f64 {
|
pub fn (d DataSize) zbit() f64 {
|
||||||
return f64(d / zbit)
|
return f64(d / zbit)
|
||||||
}
|
}
|
||||||
@ -143,6 +157,10 @@ pub fn (d DataSize) pibit() f64 {
|
|||||||
return f64(d / pibit)
|
return f64(d / pibit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (d DataSize) eibit() f64 {
|
||||||
|
return f64(d / eibit)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (d DataSize) zibit() f64 {
|
pub fn (d DataSize) zibit() f64 {
|
||||||
return f64(d / zibit)
|
return f64(d / zibit)
|
||||||
}
|
}
|
||||||
@ -160,7 +178,8 @@ pub const mb = kb * 1000
|
|||||||
pub const gb = mb * 1000
|
pub const gb = mb * 1000
|
||||||
pub const tb = gb * 1000
|
pub const tb = gb * 1000
|
||||||
pub const pb = tb * 1000
|
pub const pb = tb * 1000
|
||||||
pub const zb = tb * 1000
|
pub const eb = pb * 1000
|
||||||
|
pub const zb = eb * 1000
|
||||||
pub const yb = zb * 1000
|
pub const yb = zb * 1000
|
||||||
|
|
||||||
pub const kib = bytes * 1024
|
pub const kib = bytes * 1024
|
||||||
@ -168,7 +187,8 @@ pub const mib = kib * 1024
|
|||||||
pub const gib = mib * 1024
|
pub const gib = mib * 1024
|
||||||
pub const tib = gib * 1024
|
pub const tib = gib * 1024
|
||||||
pub const pib = tib * 1024
|
pub const pib = tib * 1024
|
||||||
pub const zib = tib * 1024
|
pub const eib = pib * 1024
|
||||||
|
pub const zib = eib * 1024
|
||||||
pub const yib = zib * 1024
|
pub const yib = zib * 1024
|
||||||
|
|
||||||
pub const kbit = bit * 1000
|
pub const kbit = bit * 1000
|
||||||
@ -176,7 +196,8 @@ pub const mbit = kbit * 1000
|
|||||||
pub const gbit = mbit * 1000
|
pub const gbit = mbit * 1000
|
||||||
pub const tbit = gbit * 1000
|
pub const tbit = gbit * 1000
|
||||||
pub const pbit = tbit * 1000
|
pub const pbit = tbit * 1000
|
||||||
pub const zbit = pbit * 1000
|
pub const ebit = pbit * 1000
|
||||||
|
pub const zbit = ebit * 1000
|
||||||
pub const ybit = zbit * 1000
|
pub const ybit = zbit * 1000
|
||||||
|
|
||||||
pub const kibit = bit * 1024
|
pub const kibit = bit * 1024
|
||||||
@ -184,9 +205,69 @@ pub const mibit = kibit * 1024
|
|||||||
pub const gibit = mibit * 1024
|
pub const gibit = mibit * 1024
|
||||||
pub const tibit = gibit * 1024
|
pub const tibit = gibit * 1024
|
||||||
pub const pibit = tibit * 1024
|
pub const pibit = tibit * 1024
|
||||||
pub const zibit = tibit * 1024
|
pub const eibit = pibit * 1024
|
||||||
|
pub const zibit = eibit * 1024
|
||||||
pub const yibit = zibit * 1024
|
pub const yibit = zibit * 1024
|
||||||
|
|
||||||
|
const units = {
|
||||||
|
'bit': bit
|
||||||
|
'nibble': nibble
|
||||||
|
'bytes': bytes
|
||||||
|
'kB': kb
|
||||||
|
'MB': mb
|
||||||
|
'GB': gb
|
||||||
|
'TB': tb
|
||||||
|
'PB': pb
|
||||||
|
'EB': eb
|
||||||
|
'ZB': zb
|
||||||
|
'YB': yb
|
||||||
|
'KiB': kib
|
||||||
|
'MiB': mib
|
||||||
|
'GiB': gib
|
||||||
|
'TiB': tib
|
||||||
|
'PiB': pib
|
||||||
|
'EiB': eib
|
||||||
|
'ZiB': zib
|
||||||
|
'YiB': yib
|
||||||
|
'kbit': kbit
|
||||||
|
'Mbit': mbit
|
||||||
|
'Gbit': gbit
|
||||||
|
'Tbit': tbit
|
||||||
|
'Pbit': pbit
|
||||||
|
'Ebit': ebit
|
||||||
|
'Zbit': zbit
|
||||||
|
'Ybit': ybit
|
||||||
|
'Kibit': kibit
|
||||||
|
'Mibit': mibit
|
||||||
|
'Gibit': gibit
|
||||||
|
'Tibit': tibit
|
||||||
|
'Pibit': pibit
|
||||||
|
'Eibit': eibit
|
||||||
|
'Zibit': zibit
|
||||||
|
'Yibit': yibit
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const prefixes = {
|
||||||
|
// Metric size (1000^N)
|
||||||
|
'kilo': 'k'
|
||||||
|
'mega': 'M'
|
||||||
|
'giga': 'G'
|
||||||
|
'tera': 'T'
|
||||||
|
'peta': 'P'
|
||||||
|
'exa': 'E'
|
||||||
|
'zetta': 'Z'
|
||||||
|
'yotta': 'Y'
|
||||||
|
// Binary size (1024^N)
|
||||||
|
'kibi': 'Ki'
|
||||||
|
'mebi': 'Mi'
|
||||||
|
'gibi': 'Gi'
|
||||||
|
'tebi': 'Ti'
|
||||||
|
'pebi': 'Pi'
|
||||||
|
'exbi': 'Ei'
|
||||||
|
'zebi': 'Zi'
|
||||||
|
'yobi': 'Yi'
|
||||||
|
}
|
||||||
|
|
||||||
// convert returns the value converted between the *from* and *to* units.
|
// convert returns the value converted between the *from* and *to* units.
|
||||||
// Example:
|
// Example:
|
||||||
// ```
|
// ```
|
||||||
@ -198,3 +279,94 @@ pub fn convert(value f64, from DataSize, to DataSize) f64 {
|
|||||||
}
|
}
|
||||||
return f64(value * from / to)
|
return f64(value * from / to)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from_string parses input and returns the actual DataSize.
|
||||||
|
// Note: Case insensitivity makes unit abbreviations such as `Mb` (megabit) and `MB` (megabyte)
|
||||||
|
// ambiguous. Use `bit` suffix for bit units. The `b` suffix will be accepted as byte unit.
|
||||||
|
// Example:
|
||||||
|
// ```
|
||||||
|
// assert dataunits.from_string('GiB')! == dataunits.gib
|
||||||
|
// assert dataunits.from_string('M')! == dataunits.mib
|
||||||
|
// assert dataunits.from_string('M', bits: true, metric: true)! == dataunits.mbit
|
||||||
|
// assert dataunits.from_string('ZeTtAbYtEs', ci: true)! == dataunits.zb
|
||||||
|
// ```
|
||||||
|
pub fn from_string(input string, params ParseParams) !DataSize {
|
||||||
|
if !input.is_pure_ascii() {
|
||||||
|
return error('${input} non-ASCII characters is not allowed in data size unit')
|
||||||
|
}
|
||||||
|
unit := parse_unit_str(input, params)
|
||||||
|
if params.ci {
|
||||||
|
for key, value in units {
|
||||||
|
if key.to_lower_ascii() == unit {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return units[unit] or { error('${input} is not a valid data size unit') }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_unit_str(input string, params ParseParams) string {
|
||||||
|
mut unit := ''
|
||||||
|
match true {
|
||||||
|
input.to_lower_ascii() in ['byte', 'bytes'] {
|
||||||
|
return 'bytes'
|
||||||
|
}
|
||||||
|
input.to_lower_ascii() in ['bit', 'bits'] {
|
||||||
|
return 'bit'
|
||||||
|
}
|
||||||
|
input.len == 1 {
|
||||||
|
if params.metric {
|
||||||
|
unit = input
|
||||||
|
} else {
|
||||||
|
unit = input.to_upper_ascii() + 'i'
|
||||||
|
}
|
||||||
|
if params.bits {
|
||||||
|
unit += 'bit'
|
||||||
|
} else {
|
||||||
|
unit += 'B'
|
||||||
|
}
|
||||||
|
return unit
|
||||||
|
}
|
||||||
|
input.len == 2 && input[1] == u8(`b`) && params.ci == false {
|
||||||
|
if input[0] != u8(`k`) {
|
||||||
|
return input[..1] + 'bit'
|
||||||
|
}
|
||||||
|
return input[..1].to_upper_ascii() + 'bit'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unit = input
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if params.ci {
|
||||||
|
unit = unit.to_lower_ascii()
|
||||||
|
}
|
||||||
|
if unit.len == 5 && unit.ends_with('ibit') {
|
||||||
|
// prevent Gibit --> Git transform
|
||||||
|
return unit
|
||||||
|
}
|
||||||
|
unit = unit.replace_each(maps.flat_map[string, string, string](prefixes, |k, v| [
|
||||||
|
k,
|
||||||
|
v,
|
||||||
|
]))
|
||||||
|
unit = unit.replace_each(['bytes', 'B', 'byte', 'B']).replace_once('bits', 'bit')
|
||||||
|
return unit
|
||||||
|
}
|
||||||
|
|
||||||
|
@[params]
|
||||||
|
pub struct ParseParams {
|
||||||
|
pub:
|
||||||
|
ci bool // if true parse string in case insensitive mode
|
||||||
|
bits bool // if true interpret single letter abbreviations as bit, otherwise as byte
|
||||||
|
metric bool // if ture apply single letter as metric prefix (power of ten), otherwise as binary
|
||||||
|
}
|
||||||
|
|
||||||
|
// to_string returns a string representation of data size unit in short form
|
||||||
|
// e.g. kB, Mbit, GiB, etc.
|
||||||
|
pub fn to_string(input DataSize) !string {
|
||||||
|
for key, value in units {
|
||||||
|
if value == input {
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error('invalid input data size unit')
|
||||||
|
}
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import dataunits
|
|
||||||
|
|
||||||
fn test_convert() {
|
|
||||||
assert (dataunits.nibble * 4).bytes() == 2
|
|
||||||
assert (dataunits.bit * 8).bits() == 8
|
|
||||||
assert (dataunits.bit * 8).bytes() == 1
|
|
||||||
assert (dataunits.gib * 10).mib() == 10240
|
|
||||||
assert (dataunits.gib * 5000).bytes() == i64(5368709120000)
|
|
||||||
assert (dataunits.mbit * 500).kb() == 62500
|
|
||||||
assert dataunits.convert(500, dataunits.mbit, dataunits.kb) == 62500
|
|
||||||
assert dataunits.DataSize(4000 * dataunits.gib).bytes() == f64(4294967296000)
|
|
||||||
}
|
|
31
tests/dataunits_test.v
Normal file
31
tests/dataunits_test.v
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import dataunits
|
||||||
|
|
||||||
|
fn test_convert() {
|
||||||
|
assert (dataunits.nibble * 4).bytes() == 2
|
||||||
|
assert (dataunits.bit * 8).bit() == 8
|
||||||
|
assert (dataunits.bit * 8).bytes() == 1
|
||||||
|
assert (dataunits.gib * 10).mib() == 10240
|
||||||
|
assert (dataunits.gib * 5000).bytes() == i64(5368709120000)
|
||||||
|
assert (dataunits.mbit * 500).kb() == 62500
|
||||||
|
assert dataunits.convert(500, dataunits.mbit, dataunits.kb) == 62500
|
||||||
|
assert dataunits.DataSize(4000 * dataunits.gib).bytes() == f64(4294967296000)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_from_string() {
|
||||||
|
assert dataunits.from_string('GiB')! == dataunits.gib
|
||||||
|
assert dataunits.from_string('M')! == dataunits.mib
|
||||||
|
assert dataunits.from_string('m', ci: true)! == dataunits.mib
|
||||||
|
assert dataunits.from_string('M', bits: true, metric: true)! == dataunits.mbit
|
||||||
|
assert dataunits.from_string('ZeTtAbYtEs', ci: true)! == dataunits.zb
|
||||||
|
assert dataunits.from_string('bytes')! == dataunits.bytes
|
||||||
|
assert dataunits.from_string('byte')! == dataunits.bytes
|
||||||
|
assert dataunits.from_string('megabytes')! == dataunits.mb
|
||||||
|
assert dataunits.from_string('megabyte')! == dataunits.mb
|
||||||
|
assert dataunits.from_string('exbibit')! == dataunits.eibit
|
||||||
|
assert dataunits.from_string('Mb')! == dataunits.mbit
|
||||||
|
assert dataunits.from_string('MB')! == dataunits.mb
|
||||||
|
assert dataunits.from_string('Mb', ci: true)! == dataunits.mb
|
||||||
|
assert dataunits.from_string('Gibit')! == dataunits.gibit
|
||||||
|
assert dataunits.from_string('gibit', ci: true)! == dataunits.gibit
|
||||||
|
assert dataunits.from_string('Gib', ci: true)! == dataunits.gib
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user