summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Ziegler <austin@zieglers.ca>2022-01-07 11:48:24 -0500
committerAustin Ziegler <austin@zieglers.ca>2023-02-16 22:06:37 -0500
commitbb89d1304417979e208e5450025c8246429eecbf (patch)
treec6a74ef9bd430a8c584f62c7a9d46cd4082fe85a
parent2b8ae866c21c309805460e90973bf6ce6820a72b (diff)
downloadmime-types-priority-extensions.tar.gz
-rw-r--r--lib/mime/type.rb26
-rw-r--r--lib/mime/type/columnar.rb6
-rw-r--r--lib/mime/types/_columnar.rb7
-rw-r--r--test/test_mime_type.rb53
-rw-r--r--test/test_mime_types_class.rb5
5 files changed, 54 insertions, 43 deletions
diff --git a/lib/mime/type.rb b/lib/mime/type.rb
index b977602..af89667 100644
--- a/lib/mime/type.rb
+++ b/lib/mime/type.rb
@@ -131,7 +131,7 @@ class MIME::Type
@friendly = {}
@obsolete = @registered = @provisional = false
@preferred_extension = @docs = @use_instead = @__sort_priority = nil
- self.__extension_priorities
+ __extension_priorities
self.extensions = []
@@ -176,6 +176,8 @@ class MIME::Type
#
# Note that this implementation of #<=> is deprecated and will be changed
# in the next major version to be the same as #priority_compare.
+ #
+ # Note that MIME::Types no longer compare against nil.
def <=>(other)
return priority_compare(other) if other.is_a?(MIME::Type)
simplified <=> other
@@ -230,7 +232,8 @@ class MIME::Type
# The computed sort priority value. This is _not_ intended to be used by most
# callers.
def __sort_priority # :nodoc:
- @__sort_priority || update_sort_priority
+ update_sort_priority if !instance_variable_defined?(:@__sort_priority) || @__sort_priority.nil?
+ @__sort_priority
end
# Returns the whole MIME content-type string.
@@ -317,7 +320,7 @@ class MIME::Type
if value
add_extensions(value)
set_preferred_extension_priority(value)
- else
+ elsif instance_variable_defined?(:@preferred_extension)
clear_extension_priority(@preferred_extension)
end
@preferred_extension = value
@@ -566,7 +569,7 @@ class MIME::Type
coder["registered"] = registered?
coder["provisional"] = provisional? if provisional?
coder["signature"] = signature? if signature?
- coder["sort-priority"] = __sort_priority
+ coder["sort-priority"] = __sort_priority || 0b11111111
coder["extension-priorities"] = __extension_priorities unless __extension_priorities.empty?
coder
end
@@ -646,12 +649,12 @@ class MIME::Type
end
end
- private
-
- def __extension_priorities
+ def __extension_priorities # :nodoc:
@extension_priorities ||= {}
end
+ private
+
def clear_extension_priority(ext)
__extension_priorities.delete(ext) if ext
end
@@ -686,14 +689,15 @@ class MIME::Type
# 16, to a minimum of 0.
def update_sort_priority
extension_count = @extensions.length
- obsolete = @obsolete ? 1 << 7 : 0
- provisional = @provisional ? 1 << 6 : 0
- registered = @registered ? 0 : 1 << 5
+ obsolete = instance_variable_defined?(:@obsolete) && @obsolete ? 1 << 7 : 0
+ provisional = instance_variable_defined?(:@provisional) && @provisional ? 1 << 6 : 0
+ registered = instance_variable_defined?(:@registered) && @registered ? 0 : 1 << 5
complete = extension_count.nonzero? ? 0 : 1 << 4
extension_count = [0, 16 - extension_count].max
@__sort_priority = obsolete | registered | provisional | complete | extension_count
- @__priority_penalty = (@obsolete ? 3 : 0) + (@registered ? 0 : 2)
+ @__priority_penalty = (instance_variable_defined?(:@obsolete) && @obsolete ? 3 : 0) +
+ (instance_variable_defined?(:@registered) && @registered ? 0 : 2)
end
def __priority_penalty
diff --git a/lib/mime/type/columnar.rb b/lib/mime/type/columnar.rb
index a51f9d9..11719d8 100644
--- a/lib/mime/type/columnar.rb
+++ b/lib/mime/type/columnar.rb
@@ -15,8 +15,10 @@ require "mime/type"
class MIME::Type::Columnar < MIME::Type
def initialize(container, content_type, extensions) # :nodoc:
@container = container
+ @__priority_penalty = nil
self.content_type = content_type
- self.extensions = extensions
+ @extensions = Set[*Array(extensions).flatten.compact].freeze
+ clear_sort_priority
end
def self.column(*methods, file: nil) # :nodoc:
@@ -60,7 +62,7 @@ class MIME::Type::Columnar < MIME::Type
obsolete = (@__sort_priority & (1 << 7)) != 0
registered = (@__sort_priority & (1 << 5)) == 0
- @__priority_penalty = (@obsolete ? 3 : 0) + (@registered ? 0 : 2)
+ @__priority_penalty = (obsolete ? 3 : 0) + (registered ? 0 : 2)
end
end
diff --git a/lib/mime/types/_columnar.rb b/lib/mime/types/_columnar.rb
index c191e39..ab39df1 100644
--- a/lib/mime/types/_columnar.rb
+++ b/lib/mime/types/_columnar.rb
@@ -30,7 +30,6 @@ module MIME::Types::Columnar
line = line.split
content_type = line.shift
extensions = line
- # content_type, *extensions = line.split
type = MIME::Type::Columnar.new(self, content_type, extensions)
@__mime_data__ << type
@@ -162,9 +161,9 @@ module MIME::Types::Columnar
def dict_extension_priority(h, k, v)
return if v.nil?
- v = v.to_i if v.kind_of?(String)
- v = v.trunc if v.kind_of?(Float)
- v = [[-20, v].max, 20].min
+ v = v.to_i if v.is_a?(String)
+ v = v.trunc if v.is_a?(Float)
+ v = [[-20, v].max, 20].min
return if v.zero?
diff --git a/test/test_mime_type.rb b/test/test_mime_type.rb
index 49d8e2c..d366bc6 100644
--- a/test/test_mime_type.rb
+++ b/test/test_mime_type.rb
@@ -175,11 +175,6 @@ describe MIME::Type do
refute_equal text_plain, "text/html"
assert_operator text_plain, :>, "text/html"
end
-
- it "correctly compares against nil" do
- refute_equal text_html, nil
- assert_operator text_plain, :<, nil
- end
end
describe "#ascii?" do
@@ -326,16 +321,20 @@ describe MIME::Type do
end
describe "#priority_compare" do
+ def priority(type)
+ "#{type} (#{("%08b" % type.__sort_priority).split(//).join(" ")})"
+ end
+
def assert_priority_less(left, right)
- assert_equal(-1, left.priority_compare(right))
+ assert_equal -1, left.priority_compare(right), "#{priority(left)} is not less than #{priority(right)}"
end
def assert_priority_same(left, right)
- assert_equal 0, left.priority_compare(right)
+ assert_equal 0, left.priority_compare(right), "#{priority(left)} is not equal to #{priority(right)}"
end
def assert_priority_more(left, right)
- assert_equal 1, left.priority_compare(right)
+ assert_equal 1, left.priority_compare(right), "#{priority(left)} is not more than #{priority(right)}"
end
def assert_priority(left, middle, right)
@@ -348,21 +347,27 @@ describe MIME::Type do
let(:text_1p) { mime_type("content-type" => "text/1") }
let(:text_2) { mime_type("content-type" => "text/2") }
- it "sorts (1) based on the simplified type" do
+ it "sorts based on the simplified type when the sort priorities are the same" do
assert_priority text_1, text_1p, text_2
end
- it "sorts (2) based on extensions" do
- text_1.extensions = ["foo", "bar"]
- text_2.extensions = ["foo"]
+ it "sorts obsolete types higher than non-obsolete types" do
+ text_1.obsolete = text_1p.obsolete = false
+ text_1b = mime_type(text_1) { |t| t.obsolete = true }
+
+ assert_priority_less text_1, text_1b
- assert_priority_same text_1, text_2
+ assert_priority text_1, text_1p, text_1b
+ end
- text_2.registered = true
+ it "sorts provisional types higher than non-provisional types" do
+ text_1.provisional = text_1p.provisional = true
+ text_1b = mime_type(text_1) { |t| t.provisional = false }
- assert_priority_more text_1, text_2
+ assert_priority text_1, text_1p, text_1b
end
+
it "sorts (3) based on the registration state" do
text_1.registered = text_1p.registered = true
text_1b = mime_type(text_1) { |t| t.registered = false }
@@ -377,12 +382,6 @@ describe MIME::Type do
assert_priority text_1, text_1p, text_1b
end
- it "sorts (5) based on obsolete status" do
- text_1.obsolete = text_1p.obsolete = false
- text_1b = mime_type(text_1) { |t| t.obsolete = true }
-
- assert_priority text_1, text_1p, text_1b
- end
it "sorts (5) based on the use-instead value" do
text_1.obsolete = text_1p.obsolete = true
@@ -395,6 +394,14 @@ describe MIME::Type do
assert_priority text_1, text_1p, text_1b
end
+
+ it "sorts based on extensions (more extensions sort lower)" do
+ text_1.extensions = ["foo", "bar"]
+ text_2.extensions = ["foo"]
+
+ assert_priority_less text_1, text_2
+ end
+
end
describe "#raw_media_type" do
@@ -486,10 +493,10 @@ describe MIME::Type do
describe "#to_json" do
let(:expected_1) {
- '{"content-type":"a/b","encoding":"base64","registered":false}'
+ '{"content-type":"a/b","encoding":"base64","registered":false,"sort-priority":48}'
}
let(:expected_2) {
- '{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true}'
+ '{"content-type":"a/b","encoding":"base64","registered":true,"provisional":true,"sort-priority":80}'
}
it "converts to JSON when requested" do
diff --git a/test/test_mime_types_class.rb b/test/test_mime_types_class.rb
index 7b803bd..d59360e 100644
--- a/test/test_mime_types_class.rb
+++ b/test/test_mime_types_class.rb
@@ -47,7 +47,7 @@ describe MIME::Types, "registry" do
}
# This is this way because of a new type ending with gzip that only
# appears in some data files.
- assert_equal %w[application/gzip application/x-gzip multipart/x-gzip], types
+ assert_equal %w[application/gzip multipart/x-gzip application/x-gzip], types
assert_equal 3, types.size
end
@@ -87,8 +87,7 @@ describe MIME::Types, "registry" do
end
it "finds multiple extensions" do
- assert_equal %w[image/jpeg text/plain],
- MIME::Types.type_for(%w[foo.txt foo.jpeg])
+ assert_equal %w[text/plain image/jpeg], MIME::Types.type_for(%w[foo.txt foo.jpeg])
end
it "does not find unknown extensions" do