class Range

Represents a range request header.

Nested Classes and Modules

class ByteRange

Represents one byte-range-spec or suffix-byte-range-spec.

Definitions

def self.parse(value)

Parse a raw range header value.

Signature

parameter value String

The raw header value.

returns Range

The parsed range header.

Implementation

def self.parse(value)
	unless match = HEADER.match(value)
		raise ParseError, "Invalid range header: #{value.inspect}"
	end
	
	unit = match[:unit].downcase
	ranges = match[:ranges].split(SEPARATOR, -1)
	
	if ranges.empty? || ranges.any?(&:empty?)
		raise ParseError, "Invalid range set: #{match[:ranges].inspect}"
	end
	
	if unit == "bytes"
		ranges.map!{|range| ByteRange.parse(range)}
	elsif ranges.any?{|range| !OTHER_RANGE.match?(range)}
		raise ParseError, "Invalid range set: #{match[:ranges].inspect}"
	end
	
	return self.new(unit, ranges)
end

def self.coerce(value)

Coerce a value into a range header.

Signature

parameter value Object

The value to coerce.

returns Range

The parsed range header.

Implementation

def self.coerce(value)
	self.parse(value.to_s)
end

def initialize(unit, ranges)

Initialize a range header.

Signature

parameter unit String

The range unit.

parameter ranges Array

The range specifiers.

Implementation

def initialize(unit, ranges)
	@unit = unit
	@ranges = ranges
end

attr :unit

Signature

attribute String

The range unit.

attr :ranges

Signature

attribute Array

The range specifiers.

def bytes?

Whether this header contains byte ranges.

Signature

returns Boolean

Whether the range unit is bytes.

Implementation

def bytes?
	@unit == "bytes"
end

def resolve(size)

Resolve all byte ranges against the selected representation size.

Signature

parameter size Integer

The size of the selected representation.

returns Array(::Range)

The satisfiable byte ranges.

Implementation

def resolve(size)
	unless bytes?
		raise ArgumentError, "Cannot resolve #{@unit.inspect} ranges as byte ranges!"
	end
	
	size = Integer(size)
	raise ArgumentError, "Size must not be negative!" if size < 0
	
	@ranges.filter_map{|range| range.resolve(size)}
end

def <<(value)

Combine another raw range header value with this one.

Signature

parameter value String

The raw range header value.

Implementation

def <<(value)
	other = self.class.parse(value)
	
	unless other.unit == @unit
		raise ParseError, "Cannot combine range units: #{@unit.inspect} and #{other.unit.inspect}"
	end
	
	@ranges.concat(other.ranges)
	
	return self
end

def to_s

Convert this header to its wire representation.

Signature

returns String

The serialized range header.

Implementation

def to_s
	"#{@unit}=#{@ranges.join(",")}"
end

def self.trailer?

Whether this header is acceptable in HTTP trailers.

Signature

returns Boolean

false, as range headers apply to a selected representation.

Implementation

def self.trailer?
	false
end