A UUID Implementation
I've been toying around with writing a decentralized, P2P application in REBOL 2, and one of the things I need to do is generate a universally unique identifier for users. Questions about how to generate a UUID came up on the old mailing list a few times, but no one ever had a solution. So I thought I'd share my implementation with you guys, in case anyone needs something similar. Feel free to pick it apart too. I'm fairly new to REBOL, and there might be a better approach to what I've done. Cheers! R E B O L [] ; IMPORTANT - random/seed now/precise must be called before running this function ; Also, it must only be called ONCE per application process or duplicates will occur makeUUID: func [ 'Generates a Version 4 UUID that is compliant with RFC 4122' ][ data: copy [] ; generate 16 random integers ; Note: REBOL doesn't support bytes directly ; and so instead we pick numbers within the ; unsigned, 8-bit, byte range (0 - 255) ; Also random normally begins the range at 1, ; not 0, and so -1 allows 0 to be picked loop 16 [append data -1 + random/secure 255] ; get the 'byte' in position 7 pos7: do [pick data 7] ; get the 'byte' in position 9 pos9: do [pick data 9] ; set the first character in the 7th 'byte' to always be 4 poke data 7 do [64 or do [pos7 and 15]] ; set the first character in the 9th 'byte' to always be 8, 9, A or B poke data 9 do [128 or do [pos9 and 63]] ; convert the integers to hexadecimal repeat n 16 [ poke data n do [ ; remove the padded 0s that REBOL adds, i.e. 0000002A = 2A copy/part skip do [to-string to-hex pick data n] 6 2 ] ] uuid: join '' [ join '' do [copy/part skip data 0 4] '-' join '' do [copy/part skip data 4 2] '-' join '' do [copy/part skip data 6 2] '-' join '' do [copy/part skip data 8 2] '-' join '' do [copy/part skip data 10 6] ] ] random/seed now/precise for num 1 30 1 [print makeUUID] halt
posted by: Brian 26-Sep-2016/4:40:08-7:00
It looks like the forum automatically converted all my double quotes to single quotes, after I submitted the post. So just make sure you convert them back before running :)
posted by: Brian 26-Sep-2016/4:50:44-7:00
Here's your same method with a few shortcuts: makeUUID: func [ "Generates a Version 4 UUID that is compliant with RFC 4122" /local data ; so 'data doesn't leak ][ ; COLLECT/KEEP is a handy accumulator data: collect [ loop 16 [keep -1 + random/secure 256] ] ; don't need to wrap each expression with DO ; Rebol infix evaluation is left to right, so don't need to parenthesize data/7: data/7 and 15 or 64 data/9: data/9 and 63 or 128 ; TO BINARY! converts a block of integers to code points ; ENBASE converts the codepoints to hex data: enbase/base to binary! data 16 ; We'll just modify this new string and return the head data: insert skip data 8 "-" data: insert skip data 4 "-" data: insert skip data 4 "-" data: insert skip data 4 "-" head data ] Can I also suggest that you post to Code Review (http://codereview.stackexchange.com/) and tag with 'Rebol'.
posted by: Chris 26-Sep-2016/12:27:43-7:00
This is very cool! Thanks, I'll definitely be putting this to use!
posted by: Edoc 26-Sep-2016/13:33:21-7:00
Oh awesome, thanks for the shortcuts Chris! I will check out Stack Exchange too.
posted by: Brian 26-Sep-2016/13:51:02-7:00
I have updated the code with your changes Chris and submitted it to Stack Exchange. I'll make any further improvements based on the feedback I get there. Thanks again, and thanks for finding that bug with the 255/256 range too :) http://codereview.stackexchange.com/questions/142544/a-version-4-uuid-implementation
posted by: Brian 26-Sep-2016/19:04:45-7:00
|