Class: Protocol::Media::Range

Inherits:
Object
  • Object
show all
Defined in:
lib/protocol/media/range.rb

Overview

A media range and its parameters.

Direct Known Subclasses

Type

Constant Summary collapse

TOKEN =
/[!#$%&'*+\-.^_`|~0-9A-Z]+/i
QUOTED_STRING =
/"(?:.(?!(?<!\\)"))*.?"/
MEDIA_TYPE =
/(?<type>#{TOKEN})\/(?<subtype>#{TOKEN})/
PARAMETER =
/\s*;\s*(?<key>#{TOKEN})=((?<value>#{TOKEN})|(?<quoted_value>#{QUOTED_STRING}))/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, subtype = "*", parameters = {}) ⇒ Range

Returns a new instance of Range.



107
108
109
110
111
# File 'lib/protocol/media/range.rb', line 107

def initialize(type, subtype = "*", parameters = {})
	@type = type
	@subtype = subtype
	@parameters = parameters
end

Instance Attribute Details

#parametersObject (readonly)

Returns the value of attribute parameters.



102
103
104
# File 'lib/protocol/media/range.rb', line 102

def parameters
  @parameters
end

#subtypeObject (readonly)

Returns the value of attribute subtype.



99
100
101
# File 'lib/protocol/media/range.rb', line 99

def subtype
  @subtype
end

#The subtype, e.g. `plain` or `*`.(subtype, e.g.`plain`) ⇒ Object (readonly)



99
# File 'lib/protocol/media/range.rb', line 99

attr_reader :subtype

#The top-level type, e.g. `text` or `*`.(top-leveltype, e.g.`text`) ⇒ Object (readonly)



96
# File 'lib/protocol/media/range.rb', line 96

attr_reader :type

#typeObject (readonly)

Returns the value of attribute type.



96
97
98
# File 'lib/protocol/media/range.rb', line 96

def type
  @type
end

Class Method Details

.build(type, subtype = "*", parameters = {}) ⇒ Object

Build a normalized media range.



25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/protocol/media/range.rb', line 25

def self.build(type, subtype = "*", parameters = {})
	type = type.downcase
	subtype = subtype.downcase
	
	# A wildcard type requires a wildcard subtype:
	if type == "*"
		if subtype != "*"
			raise ArgumentError, "Invalid wildcards in media range: #{type}/#{subtype}"
		end
	end
	
	return new(type, subtype, parameters)
end

.for(value) ⇒ Object

Parse strings into media ranges while preserving compatible objects.



43
44
45
46
47
48
49
# File 'lib/protocol/media/range.rb', line 43

def self.for(value)
	if value.is_a?(String)
		parse(value)
	else
		value
	end
end

.parse(text, normalize_whitespace = true) ⇒ Object

Parse a media range.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/protocol/media/range.rb', line 56

def self.parse(text, normalize_whitespace = true)
	scanner = StringScanner.new(text)
	
	unless scanner.scan(MEDIA_TYPE)
		raise ArgumentError, "Invalid media range: #{text.inspect}"
	end
	
	type = scanner[:type]
	subtype = scanner[:subtype]
	parameters = parse_parameters(scanner, normalize_whitespace)
	
	unless scanner.eos?
		raise ArgumentError, "Invalid media range: #{text.inspect}"
	end
	
	return build(type, subtype, parameters)
end

.parse_parameters(scanner, normalize_whitespace = true) ⇒ Object

Parse media type parameters from the scanner.



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/protocol/media/range.rb', line 79

def self.parse_parameters(scanner, normalize_whitespace = true)
	parameters = {}
	
	while scanner.scan(PARAMETER)
		key = scanner[:key]
		
		if value = scanner[:value]
			parameters[key] = value
		elsif quoted_value = scanner[:quoted_value]
			parameters[key] = unquote(quoted_value, normalize_whitespace)
		end
	end
	
	parameters
end

.unquote(value, normalize_whitespace) ⇒ Object



197
198
199
200
201
202
# File 'lib/protocol/media/range.rb', line 197

def self.unquote(value, normalize_whitespace)
	value = value[1...-1]
	value.gsub!(/\\(.)/, '\\1')
	value.gsub!(/[\r\n]+\s+/, " ") if normalize_whitespace
	value
end

Instance Method Details

#eql?(other) ⇒ Boolean Also known as: ==

Compare this media range with another media range.

Returns:

  • (Boolean)


169
170
171
# File 'lib/protocol/media/range.rb', line 169

def eql?(other)
	other.instance_of?(self.class) && @type.eql?(other.type) && @subtype.eql?(other.subtype) && @parameters.eql?(other.parameters)
end

#freezeObject

Freeze the media range and its direct values.



135
136
137
138
139
140
141
142
143
# File 'lib/protocol/media/range.rb', line 135

def freeze
	return self if frozen?
	
	@type.freeze
	@subtype.freeze
	@parameters.freeze
	
	return super
end

#hashObject

Generate a hash key consistent with #eql?.



178
179
180
# File 'lib/protocol/media/range.rb', line 178

def hash
	[self.class, @type, @subtype, @parameters].hash
end

#match?(media_range) ⇒ Boolean Also known as: ===

Whether this range matches the given media type or range.

Returns:

  • (Boolean)


149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/protocol/media/range.rb', line 149

def match?(media_range)
	# Both type components must be compatible:
	unless component_match?(@type, media_range.type)
		return false
	end
	
	# Both subtype components must be compatible:
	unless component_match?(@subtype, media_range.subtype)
		return false
	end
	
	return true
end

#nameObject Also known as: mime_type

The complete media range name.



116
117
118
# File 'lib/protocol/media/range.rb', line 116

def name
	"#{@type}/#{@subtype}"
end

#The media range parameters.=(mediarangeparameters. = (value)) ⇒ Object



102
# File 'lib/protocol/media/range.rb', line 102

attr_reader :parameters

#to_sObject Also known as: to_str

Convert the media range and parameters to a string.



125
126
127
128
129
# File 'lib/protocol/media/range.rb', line 125

def to_s
	name + @parameters.collect do |key, value|
		"; #{key}=#{quote(value.to_s)}"
	end.join
end