-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add Enum.parse(Bytes) and Enum.parse?(Bytes)
#17175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -492,6 +492,10 @@ abstract struct Enum | |
| parse?(string) || raise ArgumentError.new("Unknown enum #{self} value: #{string}") | ||
| end | ||
|
|
||
| def self.parse(slice : Bytes) : self | ||
| parse?(slice) || raise ArgumentError.new("Unknown enum #{self} value: #{slice}") | ||
| end | ||
|
|
||
| # Returns the enum member that has the given name, or | ||
| # `nil` if no such member exists. The comparison is made by using | ||
| # `String#camelcase` and `String#downcase` between *string* and | ||
|
|
@@ -508,6 +512,10 @@ abstract struct Enum | |
| # | ||
| # If multiple members match the same normalized string, the first one is returned. | ||
| def self.parse?(string : String) : self? | ||
| parse? string.to_slice | ||
| end | ||
|
|
||
| def self.parse?(slice : Bytes) : self? | ||
| {% begin %} | ||
| # FIXME: There is no `StringLiteral#bytesize` or any other adequate means | ||
| # to figure out how much space we actually need. Maybe some regex could | ||
|
|
@@ -520,14 +528,14 @@ abstract struct Enum | |
| {% max_size = @type.constants.map(&.size).sort.last %} | ||
| buffer = uninitialized UInt8[{{ max_size * 4 + 1 }}] | ||
| appender = buffer.to_unsafe.appender | ||
| char_counter = 0 | ||
| string.each_char do |char| | ||
| next if char == '-' || char == '_' | ||
| char_counter += 1 | ||
| return nil if char_counter > {{max_size}} | ||
| char.downcase &.each_byte do |byte| | ||
| appender << byte | ||
| end | ||
| byte_counter = 0 | ||
| slice.each do |byte| | ||
| next if byte == '-'.ord || byte == '_'.ord | ||
| byte_counter += 1 | ||
| return nil if byte_counter > {{max_size}} | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue: We cannot compare a byte index with a char size.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. I didn't think about enum members with non-ASCII names. There weren't any tests for them, so I added some, including a couple with case-folding, in e3a80b8. A discussion for another time is whether we should add support for
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I must've gotten it confused with something else. We can disregard that part, then. |
||
| # Setting the 6th bit on an alphabetical ASCII byte is effectively a | ||
| # downcase. | ||
| appender << ('A'.ord <= byte <= 'Z'.ord ? byte | 0x20_u8 : byte) | ||
| end | ||
| # Temporarily map all constants to their normalized value in order to | ||
| # avoid duplicates in the `case` conditions. | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.