File: uri.rb

package info (click to toggle)
mikutter 3.8.6%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 10,544 kB
  • sloc: ruby: 20,548; sh: 99; makefile: 19
file content (141 lines) | stat: -rw-r--r-- 3,270 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
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
139
140
141
# -*- coding: utf-8 -*-

=begin rdoc
=Model用のURIクラス

mikutterでは、 URI や Addressable::URI の代わりに、このクラスを使用します。
URI や Addressable::URI に比べて、次のような特徴があります。

* コンストラクタに文字列を渡している場合、 _to_s_ がその文字列を返す。
  * 正規化しないかわりに高速に動作します。
* Retriever::URI のインスタンスは URI と同じように使える
* unicode文字などが入っていて URI では表現できない場合、 Addressable::URI を使う
  * Addressable::URIでないと表現できないURIであればそちらを使うという判断を自動で行う

== 使い方
Retriever::URI() メソッドの引数にString, URI, Addressable::URI, Hash, Retriever::URIのいずれかを与えます。

[String] uriの文字列(ex: "http://mikutter.hachune.net/")
[URI] URI のインスタンス
[Addressable::URI] Addressable::URI のインスタンス
[Hash] これを引数にURI::Generic.build に渡すのと同じ形式の Hash
[Retriever::URI] 即座にこれ自身を返す

== 例

    Retriever::URI("http://mikutter.hachune.net/")
    Retriever::URI(URI::Generic.build(scheme: 'http', host: 'mikutter.hachune.net'))
=end

require 'uri'
require 'addressable/uri'

class Retriever::URI
  def initialize(uri)
    case uri.freeze
    when URI, Addressable::URI
      @uri = uri
    when String
      @uri_string = uri
    when Hash
      @uri_hash = uri
    end
  end

  def ==(other)
    case other
    when URI, Addressable::URI
      other == to_uri
    when Retriever::URI
      if has_string? or other.has_string?
        to_s == other.to_s
      else
        other.to_uri == to_uri
      end
    end
  end

  def hash
    to_s.hash ^ self.class.hash
  end

  def has_string?
    !!@uri_string
  end

  def has_uri?
    !!@uri
  end

  def to_s
    @uri_string ||= to_uri.to_s.freeze
  end

  def to_uri
    @uri ||= generate_uri.freeze
  end

  def scheme
    if has_string? and !has_uri?
      match = @uri_string.match(%r<\A(\w+)://>)
      if match
        match[1]
      else
        to_uri.scheme
      end
    else
      to_uri.scheme
    end
  end

  def freeze
    unless frozen?
      to_uri
      to_s
    end
    super
  end

  def respond_to?(method)
    super or to_uri.respond_to?(method)
  end

  def method_missing(method, *rest, &block)
    to_uri.__send__(method, *rest, &block)
  end

  private

  def generate_uri
    if @uri
      @uri
    elsif @uri_string
      @uri = generate_uri_by_string
    elsif @uri_hash
      @uri = generate_uri_by_hash
    end
    @uri
  end

  def generate_uri_by_string
    if @uri_string.match(%r<\A\w+://>)
      uri = Addressable::URI.parse(@uri_string)
    else
      uri, = Plugin.filtering(:uri_filter, @uri_string)
    end
    case uri
    when URI, Addressable::URI
      uri
    when String
      raise Retriever::InvalidURIError, 'The string is not URI.'
    else
      raise Retriever::InvalidURIError, "Filter `uri_filter' returns instance of `#{uri.class}', but expect URI or Addressable::URI."
    end
  end

  def generate_uri_by_hash
    URI::Generic.build(@uri_hash)
  rescue URI::InvalidComponentError
    Addressable::URI.new(@uri_hash)
  end
end