From 331d918190cc1b722e1469dd29bb94142bc4e14b Mon Sep 17 00:00:00 2001 From: Karchnu Date: Mon, 30 Nov 2020 04:55:15 +0100 Subject: [PATCH] string-keys-to-int: converting string keys into integers. --- README.md | 10 +++++ shard.yml | 2 + src/string-keys-to-int.cr | 89 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 src/string-keys-to-int.cr diff --git a/README.md b/README.md index 76f221d..3029f65 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,13 @@ json-to-cbor < file.json > file.cbor hs < file.cbor ``` +# string-keys-to-int usage + +JSON format has a limitation on the type of hash keys: it has to be a string. +CBOR doesn't come with such limitation. +`string-keys-to-int` automatically converts string keys into integers, whenever all the keys in a hash can be converted. + +```sh +string-keys-to-int < file.cbor +``` + diff --git a/shard.yml b/shard.yml index fe1de54..8293371 100644 --- a/shard.yml +++ b/shard.yml @@ -14,6 +14,8 @@ targets: main: src/json-to-cbor.cr hs: main: src/hs.cr + string-keys-to-int: + main: src/string-keys-to-int.cr bm-json-vs-cbor: main: tests/json-vs-cbor.cr diff --git a/src/string-keys-to-int.cr b/src/string-keys-to-int.cr new file mode 100644 index 0000000..8dddadb --- /dev/null +++ b/src/string-keys-to-int.cr @@ -0,0 +1,89 @@ +require "cbor" +require "option_parser" + +class Context + class_property debug = false +end + +OptionParser.parse do |parser| + parser.banner = "usage: string-keys-to-int < file.cbor" + + parser.on "-d", "--debug", + "Debug: print keys to convert, input and output data." do + Context.debug = true + end + + parser.on "-h", "--help", "Displays this help and exits." do + puts parser + exit 0 + end +end + +def are_hash_keys_all_int?(data) + case d = data + when Hash + keys = d.keys + if keys.all? {|v| v.is_a?(String) } + keys.all? {|v| v.as(String).to_i64 rescue false } + else + false + end + else + false + end +end + +def change(data) + # 1. change keys + if are_hash_keys_all_int? data + if Context.debug + puts "keys to convert: #{data.as(Hash).keys}" + end + + # Do something + case d = data + when Hash + keys = d.keys + keys.each do |k| + d[k.as(String).to_i32] = d[k] + d.delete k + end + end + end + + # 2. dig + case d = data + when Hash + keys = d.keys + keys.each do |k| + change d[k] + end + end +rescue e + STDERR.puts "something went wrong: #{e}" +end + +buffer = Bytes.new 1_000_000 # 1 MB + +until STDIN.read(buffer) == 0 + decoder = CBOR::Decoder.new(buffer) + while data = decoder.read_value + break if data == 0 + + if Context.debug + puts "input data:" + pp data + end + + change data + + if Context.debug + puts "output data:" + pp data + else + STDOUT.write data.to_cbor + STDOUT.flush + end + end + buffer = Bytes.new 1_000_000 # 1 MB +end