Reputation: 2021
C# contains method to generate Guid from bytes:
byte[] bytes = {107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223};
Guid guid = new Guid(bytes); // => {f29b616b-3424-57b6-43df-a3a607af7bdf}
How to write ruby code which will generate the same uuid as C#? The uuid defined in Ruby:SecureRandom doesn't accept any parameters.
Upvotes: 0
Views: 1221
Reputation: 239240
This can be done in a really straightforward way by converting the bytes to an array of hex strings, inserting -
's in the right locations, and then joining the array.
def to_uuid(bytes)
hex = bytes.map { |b| b.to_s(16).rjust(2, '0') }
[4, 7, 10, 13].inject(hex) { |hex, n| hex.insert(n, '-') }.join
end
to_uuid([107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223])
# => "6b619bf2-2434-b657-43df-a3a607af7bdf"
Given a byte array...
bytes = [107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223];
You can convert the bytes to hexadecimal and then pad the resulting strings with leading 0
s...
hex = bytes.map { |b| b.to_s(16).rjust(2, '0') }
# => ["6b", "61", "9b", "f2", "24", "34", "b6", "57", "43", "df", "a3", "a6", "07", "af", "7b", "df"]
Then insert hyphens at the right places...
[4, 7, 10, 13].inject(hex) { |hex, n| hex.insert(n, '-') }
# => ["6b", "61", "9b", "f2", "-", "24", "34", "-", "b6", "57", "-", "43", "df", "-", "a3", "a6", "07", "af", "7b", "df"]
Then join the array:
hex.join
# => "6b619bf2-2434-b657-43df-a3a607af7bdf"
Upvotes: 0
Reputation: 4538
Another way to skin a cat, simple and easy to understand:
a = [107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223]
def _guid(ints, reverse=false)
hexes = ints.map { |b| b.to_s(16).rjust(2, '0') }
return hexes.reverse.join if reverse
hexes.join
end
def guid(ints)
'%s-%s-%s-%s-%s' % [
_guid(ints[0...4], true),
_guid(ints[4...6], true),
_guid(ints[6...8], true),
_guid(ints[8...10]),
_guid(ints[10..-1]),
]
end
puts guid a # => f29b616b-3424-57b6-43df-a3a607af7bdf
Upvotes: 1
Reputation: 106027
Here's one way, using nothing but sprintf
. I'm not sure if I love it or hate it.
arr = [107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223]
fmt = "%4$02x%3$02x%2$02x%1$02x-" \
"%6$02x%5$02x-%8$02x%7$02x-%9$02x%10$02x-" \
"%11$02x%12$02x%13$02x%14$x%15$x%16$x"
str = sprintf(fmt, *arr)
# => "f29b616b-3424-57b6-43df-a3a607af7bdf"
This uses sprintf
's $
flag to explicitly specify the order for the hex digits, e.g. %4$02x
means "print the fourth octet in the arguments as two hex digits."
We could, of course, generate the format string:
positions = [[4, 3, 2, 1], [6, 5], [8, 7], [9, 10], 11..16]
fmt = positions.map {|a| a.map {|d| "%#{d}$02x" }.join }.join("-")
# => "%4$02x%3$02x%2$02x%1$02x-%6$02x%5$02x-%8$02x%7$02x-%9$02x%10$02x-%11$02x%12$02x%13$02x%14$02x%15$02x%16$02x"
str = sprintf(fmt, *arr)
# => "f29b616b-3424-57b6-43df-a3a607af7bdf"
...but at that point you might as well just do this:
positions = [ [ 3, 2, 1, 0 ], [ 5, 4 ], [ 7, 6 ], [ 8, 9 ], 10..15 ]
str = positions.map {|a| a.map {|n| "%02x" % arr[n] }.join }.join("-")
# => f29b616b-3424-57b6-43df-a3a607af7bdf
You can see all of these in action on repl.it: https://repl.it/@jrunning/FamousRewardingApplescript
Upvotes: 2
Reputation: 11638
First approximation answer:
a = [107, 97, 155, 242, 36, 52, 182, 87, 67, 223, 163, 166, 7, 175, 123, 223]
ah = a.map{ |i| i.to_s(16) }
puts [4,2,2,2,6].inject([]) { |result, idx| result << ah.slice!(0, idx).reverse.join }.join("-")
f29b616b-3424-57b6-df43-df7baf7a6a3
=> nil
There is almost certainly a cleaner way to do it, but this gives you something to work with. It uses inject to accumulate the generated uuid string sections into an array, then joins those into the guid.
Each block of the guid is a subarray of the byte array, seemingly ordered lsb to msb.
Upvotes: -1
Reputation: 121000
Sometimes development process involves writing code, not only calling existing libraries:
bytes.each_with_object([]) do |b, acc|
acc << [] if acc.size == 0 ||
acc.size == 1 && acc.last.size == 4 ||
acc.size > 1 && acc.size < 5 && acc.last.size == 2
acc.last << b.to_s(16).rjust(2, '0')
end.map.with_index do |e, idx|
idx < 3 ? e.reverse : e
end.map(&:join).join('-')
#⇒ "f29b616b-3424-57b6-43df-a3a607af7bdf"
Upvotes: 4