Login
strenum.cr at tip
Login

File src/remilib/strenum.cr from the latest check-in


     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
#### libremiliacr
#### Copyright(C) 2020-2024 Remilia Scarlet <remilia@posteo.jp>
####
#### This program is free software: you can redistribute it and/or modify
#### it under the terms of the GNU General Public License as published
#### the Free Software Foundation, either version 3 of the License, or
#### (at your option) any later version.
####
#### This program is distributed in the hope that it will be useful,
#### but WITHOUT ANY WARRANTY; without even the implied warranty of
#### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
#### GNU General Public License for more details.
####
#### You should have received a copy of the GNU General Public License
#### along with this program.If not, see<http:####www.gnu.org/licenses/.>

module RemiLib
  # Defines an `Enum` that that allows you to map keys to specific strings.  The
  # enum keys still have numerical values just like any other `Enum`, but these
  # numerical values cannot be specified.
  macro defineStringEnum(name, *values)
    enum {{name.id}}
      {% for val in values %}
        {% if val.is_a?(Assign) %}
           {{val.target.id}}
        {% else %}
          {% raise "Only assignments are supported for string-like Enums" %}
        {% end %}
      {% end %}

      def to_s(io : IO) : Nil
        case self
            {% for val in values %}
              {% if val.is_a?(Assign) %}
              in {{name.id}}::{{val.target.id}} then io << {{val.value}}
              {% end %}
            {% end %}
        end
      end

      def to_s : String
        case self
            {% for val in values %}
              {% if val.is_a?(Assign) %}
              in {{name.id}}::{{val.target.id}} then {{val.value}}
              {% end %}
            {% end %}
        end
      end

      def self.parse?(string : String) : self?
        case string
            {% for val in values %}
              {% if val.is_a?(Assign) %}
              when {{val.value}} then {{name.id}}::{{val.target.id}}
              {% end %}
            {% end %}
        else nil
        end
      end

      def self.parse(string : String) : self
        self.parse?(string) || raise ArgumentError.new("Cannot parse string to a #{ {{@type}} }: #{string}")
      end
    end
  end
end