Login
resolverset.cr at tip
Login

File src/remilib/config/resolverset.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
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
   100
   101
   102
   103
   104
   105
   106
   107
   108
   109
   110
   111
   112
   113
   114
   115
   116
   117
   118
   119
   120
   121
   122
   123
   124
   125
   126
   127
   128
   129
   130
   131
   132
   133
   134
   135
   136
   137
   138
#### 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/.>
require "./resolver"

module RemiLib::Config
  # The `ResolverSet` allows a collection of `Resolver` instances to be used in
  # a prioritized way.
  class ResolverSet
    @resolvers : Array(Resolver)

    # Creates a new `ResolverSet` instance.
    def initialize(*res : Resolver)
      @resolvers = res.to_a
    end

    # Returns the `Resolver` at the given index.
    def [](idx : Int)
      @resolvers[idx]
    end

    # Appends a `Resolver` to the end of this set.
    def <<(res : Resolver)
      @resolvers << res
    end

    # Inserts the given `Resolver` at the given index.
    def insert(idx : Int, res : Resolver)
      @resolvers.insert(idx, res)
    end

    # Deletes the given `Resolver` from the given index.
    def delete_at(idx : Int)
      @resolvers.delete_at(idx)
    end

    # If the given `Resolver` exists in this set, it is removed from this set
    # and returned.  Otherwise, this returns `nil`.
    def delete(res : Resolver) : Resolver?
      @resolvers.delete(res)
    end

    # Loops over all of the `Resolver` instances in this set, yielding each one
    # sequentially.
    def each(&)
      @resolvers.each do |res|
        yield res
      end
    end

    # Associates a data file named `filename` with a symbolic name for every one
    # of the associated `Resolver` instances.  The symbolic name must be unique
    # for every `Resolver`.
    def defineDataFile(symname : Symbol, filename : String|Path)
      @resolvers.each &.defineDataFile(symname, filename)
    end

    # Associates a data file named `filename` with a symbolic name for every one
    # of the associated `Resolver` instances.
    #
    # If the symbol is not unique to any of the `Resolver`s in this set, then
    # the old path is forgotten for that `Resolver` and the symbol becomes
    # associated with the new path.
    def defineDataFile!(symname : Symbol, filename : String|Path)
      @resolvers.each &.defineDataFile!(symname, filename)
    end

    protected def getDataFilePath(symname : Symbol) : Path?
      @resolvers.find do |res|
        if res.dataFiles.has_key?(symname)
          return res.getDataFilePath(symname)
        end
      end

      nil
    end

    # Given a symbolic name for a data file, this looks at each `Resolver` in
    # the order it appears in this set.  The first `Resolver` that knows about
    # the data file will return the `Path` associated with it.
    #
    # If the symbol is not registered with any `Resolver`s in this set, then
    # this raises an `UnknownDataFileError`.
    def dataFile(symname : Symbol) : Path
      getDataFilePath(symname) ||
        raise UnknownDataFileError.new("Data file is not registered in any Resolvers: #{symname}")
    end

    # Given a symbolic name for a data file, this looks at each `Resolver` in
    # the order it appears in this set.  The first `Resolver` that knows about
    # the data file will return the `Path` associated with it.
    #
    # If the symbol is not registered with any `Resolver`s in this set, then
    # this returns `nil`.
    def dataFile?(symname : Symbol) : Path?
      getDataFilePath(symname)
    end

    # Given a symbolic name for a data file, this looks at each `Resolver` in
    # the order it appears in the set.  The first `Resolver` that knows about
    # the data file will then open a new `File` stream and yield it.  If the
    # symbol is not registered with any `Resolver`, then this raises an
    # `UnknownDataFileError`.
    def dataFile(symname : Symbol, &) : Nil
      File.open(datafile(symname)) do |file|
        yield file
      end
    end

    # Given a symbolic name for a data file, this looks at each `Resolver` in
    # the order it appears in the set.  The first `Resolver` that knows about
    # the data file will then open a new `File` stream and yield it, then return
    # `true`.  If the symbol is not registered with any `Resolver`, then this
    # returns `false`.
    def dataFile?(symname : Symbol, &) : Bool
      if filename = dataFile?(symname)
        File.open(filename) do |file|
          yield file
        end
        true
      else
        false
      end
    end
  end
end