diff --git a/Makefile b/Makefile
index e3488b0..121abf7 100644
--- a/Makefile
+++ b/Makefile
@@ -15,8 +15,8 @@ serve: clean doc
build:
v -path "$$(realpath $$PWD/../)|@vlib|@vmodules" \
- -prod -skip-unused -parallel-cc -cflags -static -cflags -s -d no_segfault_handler \
- cmd/dataunit.v -o dataunit
+ -prod -parallel-cc -cflags -static -cflags -s -d no_segfault_handler \
+ cmd/dataunit -o dataunit
clean:
rm -r $(DOC_DIR) || true
diff --git a/README.md b/README.md
index 7eae74b..5c8dec6 100644
--- a/README.md
+++ b/README.md
@@ -12,13 +12,16 @@ Example:
import dataunits
fn main() {
+ // convert via convert fn
kilobytes := dataunits.convert(500, dataunits.mbit, dataunits.kb)
println(kilobytes) // 62500.0
+ // convert via DataSize method (the arguments order matters)
mebibytes := (dataunits.gib * 15).mib()
println(mebibytes) // 15360.0
- bytes := dataunits.DataSize(2000 * dataunits.gib).bytes()
+ // convert via DataSize method with explicit type cast
+ bytes := dataunits.DataSize(2000 * dataunits.gib).byte()
println(bytes) // 2.147483648e+12 == 2147483648000
}
```
diff --git a/cmd/dataunit.v b/cmd/dataunit.v
deleted file mode 100644
index f9103e1..0000000
--- a/cmd/dataunit.v
+++ /dev/null
@@ -1,88 +0,0 @@
-// This is free and unencumbered software released into the public domain.
-
-// Anyone is free to copy, modify, publish, use, compile, sell, or
-// distribute this software, either in source code form or as a compiled
-// binary, for any purpose, commercial or non-commercial, and by any
-// means.
-
-// In jurisdictions that recognize copyright laws, the author or authors
-// of this software dedicate any and all copyright interest in the
-// software to the public domain. We make this dedication for the benefit
-// of the public at large and to the detriment of our heirs and
-// successors. We intend this dedication to be an overt act of
-// relinquishment in perpetuity of all present and future rights to this
-// software under copyright law.
-
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
-// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-// OTHER DEALINGS IN THE SOFTWARE.
-
-// For more information, please refer to
-
-/*
- dataunit - a simple CLI tool for data units convertion.
-*/
-
-module main
-
-import os
-import flag
-import dataunits
-
-@[name: 'dataunit']
-struct FlagConfig {
- help bool
- from string @[short: f]
- to string @[short: t]
-mut:
- value f64 @[ignore]
-}
-
-fn main() {
- mut flags, no_matches := flag.to_struct[FlagConfig](os.args, skip: 1, style: .v) or {
- eprintln('cmdline parsing error, see -help for info')
- exit(2)
- }
- if no_matches.len > 1 {
- eprintln('unrecognized arguments: ${no_matches[1..]}')
- exit(2)
- } else if no_matches.len == 1 {
- flags.value = no_matches[0].f64()
- }
- if flags.help {
- println('convert the value between data size units.')
- println('usage: dataunit -f -t ')
- println('options:')
- println(' -help print this help message and exit')
- println(' -f, -from source data unit')
- println(' -t, -to destination data unit')
- exit(0)
- }
- if flags.from == '' || flags.to == '' {
- eprintln('no -from or -to flag set, see -help for info')
- exit(2)
- }
- if flags.value == 0 {
- eprintln('no value passed, see -help for info')
- exit(2)
- }
- src := dataunits.from_string(flags.from, ci: true) or {
- eprintln('invalid source unit: ${err}')
- exit(1)
- }
- dst := dataunits.from_string(flags.to, ci: true) or {
- eprintln('invalid destination unit: ${err}')
- exit(1)
- }
- result := '${dataunits.convert(flags.value, src, dst):.20f}'
- splitted := result.split('.')
- if splitted[1].contains_only('0') {
- println(splitted[0])
- } else {
- println(result.trim_right('0'))
- }
-}
diff --git a/src/dataunits.v b/src/dataunits.v
index ec7c804..2d25b7b 100644
--- a/src/dataunits.v
+++ b/src/dataunits.v
@@ -37,8 +37,8 @@ pub fn (d DataSize) nibble() f64 {
return f64(d / nibble)
}
-pub fn (d DataSize) bytes() f64 {
- return f64(d / bytes)
+pub fn (d DataSize) byte() f64 {
+ return f64(d / byte)
}
pub fn (d DataSize) kb() f64 {
@@ -171,9 +171,9 @@ pub fn (d DataSize) yibit() f64 {
pub const bit = DataSize(1)
pub const nibble = bit * 4
-pub const bytes = bit * 8
+pub const byte = bit * 8
-pub const kb = bytes * 1000
+pub const kb = byte * 1000
pub const mb = kb * 1000
pub const gb = mb * 1000
pub const tb = gb * 1000
@@ -182,7 +182,7 @@ pub const eb = pb * 1000
pub const zb = eb * 1000
pub const yb = zb * 1000
-pub const kib = bytes * 1024
+pub const kib = byte * 1024
pub const mib = kib * 1024
pub const gib = mib * 1024
pub const tib = gib * 1024
@@ -212,7 +212,7 @@ pub const yibit = zibit * 1024
const units = {
'bit': bit
'nibble': nibble
- 'bytes': bytes
+ 'byte': byte
'kB': kb
'MB': mb
'GB': gb
@@ -282,22 +282,22 @@ pub fn convert(value f64, from DataSize, to DataSize) f64 {
// 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.
+// ambiguous. Use `bit` suffix for values in bits. 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
+// assert dataunits.from_string('M')! == dataunits.mb
+// assert dataunits.from_string('M', in_bits: true)! == dataunits.mbit
+// assert dataunits.from_string('ZeTtAbYtEs', case_insensitive: 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 {
+ if params.case_insensitive {
for key, value in units {
- if key.to_lower_ascii() == unit {
+ if key.to_lower_ascii() == unit.to_lower_ascii() {
return value
}
}
@@ -309,45 +309,52 @@ fn parse_unit_str(input string, params ParseParams) string {
mut unit := ''
match true {
input.to_lower_ascii() in ['byte', 'bytes'] {
- return 'bytes'
+ return 'byte'
}
input.to_lower_ascii() in ['bit', 'bits'] {
return 'bit'
}
input.len == 1 {
- if params.metric {
- unit = input
- } else {
+ if params.binary_size {
unit = input.to_upper_ascii() + 'i'
+ } else {
+ unit = input
}
- if params.bits {
+ if params.in_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'
+ input.len == 2 && input[1] == u8(`i`) {
+ if params.in_bits {
+ return input + 'bit'
}
- return input[..1].to_upper_ascii() + 'bit'
+ return input + 'B'
+ }
+ input.len == 3 && input.ends_with('ib') && params.case_insensitive == false {
+ // Mib -> Mibit
+ return input[..2] + 'bit'
+ }
+ input.len == 2 && input[1] == u8(`b`) && params.case_insensitive == false {
+ // Mb -> Mbit
+ return input[..1] + 'bit'
}
else {
unit = input
}
}
- if params.ci {
+ if params.case_insensitive {
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,
- ]))
+ // transform full names to short ones: megabits --> mbit, etc.
+ prefixes_array := maps.flat_map[string, string, string](prefixes, |k, v| [k, v])
+ unit = unit.replace_each(prefixes_array)
unit = unit.replace_each(['bytes', 'B', 'byte', 'B']).replace_once('bits', 'bit')
return unit
}
@@ -355,9 +362,12 @@ fn parse_unit_str(input string, params ParseParams) string {
@[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
+ // if true parse string in case insensitive mode
+ case_insensitive bool
+ // if true accept input such 'M', 'Gi' as bits, otherwise as bytes
+ in_bits bool
+ // if true accept single letter prefix as binary (power of two), otherwise as metric prefix
+ binary_size bool
}
// to_string returns a string representation of data size unit in short form
diff --git a/tests/dataunits_test.v b/tests/dataunits_test.v
index 8d18710..3fe0fef 100644
--- a/tests/dataunits_test.v
+++ b/tests/dataunits_test.v
@@ -1,31 +1,39 @@
import dataunits
fn test_convert() {
- assert (dataunits.nibble * 4).bytes() == 2
+ assert (dataunits.nibble * 4).byte() == 2
assert (dataunits.bit * 8).bit() == 8
- assert (dataunits.bit * 8).bytes() == 1
+ assert (dataunits.bit * 8).byte() == 1
assert (dataunits.gib * 10).mib() == 10240
- assert (dataunits.gib * 5000).bytes() == i64(5368709120000)
+ assert (dataunits.gib * 5000).byte() == 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)
+ assert dataunits.DataSize(4000 * dataunits.gib).byte() == 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('M')! == dataunits.mb
+ assert dataunits.from_string('m', case_insensitive: true)! == dataunits.mb
+ assert dataunits.from_string('M', binary_size: true)! == dataunits.mib
+ assert dataunits.from_string('M', in_bits: true)! == dataunits.mbit
+ assert dataunits.from_string('ZeTtAbYtEs', case_insensitive: true)! == dataunits.zb
+ assert dataunits.from_string('bytes')! == dataunits.byte
+ assert dataunits.from_string('byte')! == dataunits.byte
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('Mb', case_insensitive: 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
+ assert dataunits.from_string('gibit', case_insensitive: true)! == dataunits.gibit
+ assert dataunits.from_string('gIBiT', case_insensitive: true)! == dataunits.gibit
+ assert dataunits.from_string('Gib', case_insensitive: true)! == dataunits.gib
+ assert dataunits.from_string('Gib')! == dataunits.gibit
+ assert dataunits.from_string('k')! == dataunits.kb
+ assert dataunits.from_string('kB')! == dataunits.kb
+ assert dataunits.from_string('kb')! == dataunits.kbit
+ assert dataunits.from_string('Ki')! == dataunits.kib
+ assert dataunits.from_string('Gi')! == dataunits.gib
}