From 50e63b7ef0d24a46fdd346afa359e57dfc3747b0 Mon Sep 17 00:00:00 2001 From: Austin Ziegler Date: Sat, 21 Nov 2020 16:22:24 -0500 Subject: [PATCH] Add a stable sort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - This probably has a negative performance impact, so I’m not sure I’m going to merge this. --- lib/mime/types.rb | 19 ++++++++++++------- mime-types.gemspec | 12 ++++++------ test/test_mime_types.rb | 13 +++++++++---- test/test_mime_types_class.rb | 4 ++++ 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/lib/mime/types.rb b/lib/mime/types.rb index 26ff937..75f26fb 100644 --- a/lib/mime/types.rb +++ b/lib/mime/types.rb @@ -131,9 +131,7 @@ def [](type_id, complete: false, registered: false) @type_variants[MIME::Type.simplified(type_id)] end - prune_matches(matches, complete, registered).sort { |a, b| - a.priority_compare(b) - } + stable_sort(prune_matches(matches, complete, registered)) end # Return the list of MIME::Types which belongs to the file based on its @@ -149,11 +147,12 @@ def [](type_id, complete: false, registered: false) # puts MIME::Types.type_for(%w(citydesk.xml citydesk.gif)) # => [application/xml, image/gif, text/xml] def type_for(filename) - Array(filename).flat_map { |fn| + results = + Array(filename).flat_map { |fn| @extension_index[fn.chomp.downcase[/\.?([^.]*?)$/, 1]] - }.compact.inject(Set.new, :+).sort { |a, b| - a.priority_compare(b) - } + }.compact.inject(Set.new, :+) + + stable_sort(results) end alias of type_for @@ -221,6 +220,12 @@ def match(pattern) k =~ pattern }.values.inject(Set.new, :+) end + + def stable_sort(list) + list.lazy.each_with_index.sort { |(a, ai), (b, bi)| + a.priority_compare(b).nonzero? || ai <=> bi + }.map(&:first) + end end require 'mime/types/cache' diff --git a/mime-types.gemspec b/mime-types.gemspec index 3a2a61f..a5be6f3 100644 --- a/mime-types.gemspec +++ b/mime-types.gemspec @@ -26,7 +26,7 @@ Gem::Specification.new do |s| if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q.freeze, ["~> 3.2015"]) - s.add_development_dependency(%q.freeze, ["~> 5.13"]) + s.add_development_dependency(%q.freeze, ["~> 5.14"]) s.add_development_dependency(%q.freeze, ["~> 1.0"]) s.add_development_dependency(%q.freeze, ["~> 1.1"]) s.add_development_dependency(%q.freeze, ["~> 1.6"]) @@ -38,10 +38,10 @@ Gem::Specification.new do |s| s.add_development_dependency(%q.freeze, [">= 10.0", "< 14.0"]) s.add_development_dependency(%q.freeze, ["~> 0.7"]) s.add_development_dependency(%q.freeze, [">= 4.0", "< 7"]) - s.add_development_dependency(%q.freeze, ["~> 3.20"]) + s.add_development_dependency(%q.freeze, ["~> 3.22"]) else s.add_dependency(%q.freeze, ["~> 3.2015"]) - s.add_dependency(%q.freeze, ["~> 5.13"]) + s.add_dependency(%q.freeze, ["~> 5.14"]) s.add_dependency(%q.freeze, ["~> 1.0"]) s.add_dependency(%q.freeze, ["~> 1.1"]) s.add_dependency(%q.freeze, ["~> 1.6"]) @@ -53,11 +53,11 @@ Gem::Specification.new do |s| s.add_dependency(%q.freeze, [">= 10.0", "< 14.0"]) s.add_dependency(%q.freeze, ["~> 0.7"]) s.add_dependency(%q.freeze, [">= 4.0", "< 7"]) - s.add_dependency(%q.freeze, ["~> 3.20"]) + s.add_dependency(%q.freeze, ["~> 3.22"]) end else s.add_dependency(%q.freeze, ["~> 3.2015"]) - s.add_dependency(%q.freeze, ["~> 5.13"]) + s.add_dependency(%q.freeze, ["~> 5.14"]) s.add_dependency(%q.freeze, ["~> 1.0"]) s.add_dependency(%q.freeze, ["~> 1.1"]) s.add_dependency(%q.freeze, ["~> 1.6"]) @@ -69,6 +69,6 @@ Gem::Specification.new do |s| s.add_dependency(%q.freeze, [">= 10.0", "< 14.0"]) s.add_dependency(%q.freeze, ["~> 0.7"]) s.add_dependency(%q.freeze, [">= 4.0", "< 7"]) - s.add_dependency(%q.freeze, ["~> 3.20"]) + s.add_dependency(%q.freeze, ["~> 3.22"]) end end diff --git a/test/test_mime_types.rb b/test/test_mime_types.rb index 6a9689f..a99cbb7 100644 --- a/test/test_mime_types.rb +++ b/test/test_mime_types.rb @@ -18,7 +18,8 @@ def mime_types 'content-type' => 'application/gzip', 'extensions' => 'gz', 'registered' => true - ) + ), + *MIME::Types.type_for('foo.webm') } end @@ -38,8 +39,8 @@ def mime_types end it 'is countable with an enumerator' do - assert_equal 6, mime_types.each.count - assert_equal 6, mime_types.lazy.count + assert_equal 8, mime_types.each.count + assert_equal 8, mime_types.lazy.count end end @@ -159,11 +160,15 @@ def mime_types plain_text.add_extensions('xtxt') assert_includes mime_types.type_for('xtxt'), 'text/plain' end + + it 'returns a stable order for types with equal priority' do + assert_equal %w(audio/webm video/webm), mime_types.type_for('foo.webm') + end end describe '#count' do it 'can count the number of types inside' do - assert_equal 6, mime_types.count + assert_equal 8, mime_types.count end end end diff --git a/test/test_mime_types_class.rb b/test/test_mime_types_class.rb index a9f4468..7793d05 100644 --- a/test/test_mime_types_class.rb +++ b/test/test_mime_types_class.rb @@ -100,6 +100,10 @@ def setup plain_text.add_extensions('xtxt') assert_includes MIME::Types.type_for('xtxt'), 'text/plain' end + + it 'returns a stable order for types with equal priority' do + assert_equal %w(audio/webm video/webm), MIME::Types.type_for('foo.webm') + end end describe '.count' do