File: parser.rb

package info (click to toggle)
ruby-device-detector 1.0.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster, forky, sid, trixie
  • size: 3,104 kB
  • sloc: ruby: 1,224; makefile: 5
file content (82 lines) | stat: -rw-r--r-- 1,990 bytes parent folder | download
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
class DeviceDetector
  class Parser < Struct.new(:user_agent)

    ROOT = File.expand_path('../../..', __FILE__)

    def name
      from_cache(['name', self.class.name, user_agent]) do
        NameExtractor.new(user_agent, regex_meta).call
      end
    end

    def full_version
      from_cache(['full_version', self.class.name, user_agent]) do
        VersionExtractor.new(user_agent, regex_meta).call
      end
    end

    private

    def regex_meta
      @regex_meta ||= matching_regex || {}
    end

    def matching_regex
      from_cache([self.class.name, user_agent]) do
        regexes.find { |r| user_agent =~ r[:regex] }
      end
    end

    def regexes
      @regexes ||= regexes_for(filepaths)
    end

    def filenames
      fail NotImplementedError
    end

    def filepaths
      filenames.map do |filename|
        [ filename.to_sym, File.join(ROOT, 'regexes', filename) ]
      end
    end

    def regexes_for(file_paths)
      from_cache(['regexes', self.class]) do
        load_regexes(file_paths).flat_map { |path, regex| parse_regexes(path, regex) }
      end
    end

    def load_regexes(file_paths)
      file_paths.map { |path, full_path| [path, symbolize_keys!(YAML.load_file(full_path))] }
    end

    def symbolize_keys!(object)
      case object
      when Array
        object.map!{ |v| symbolize_keys!(v) }
      when Hash
        object.keys.each{ |k| object[k.to_sym] = symbolize_keys!(object.delete(k)) if k.is_a?(String) }
      end
      object
    end

    def parse_regexes(path, raw_regexes)
      raw_regexes.map do |meta|
        fail "invalid device spec: #{meta.inspect}" unless meta[:regex].is_a? String
        meta[:regex] = build_regex(meta[:regex])
        meta[:path] = path
        meta
      end
    end

    def build_regex(src)
      Regexp.new('(?:^|[^A-Z0-9\-_]|[^A-Z0-9\-]_|sprd-)(?:' + src + ')', Regexp::IGNORECASE)
    end

    def from_cache(key)
      DeviceDetector.cache.get_or_set(key) { yield }
    end

  end
end