feat: extended jxl support

This commit is contained in:
Louie Torres
2023-01-12 00:25:34 +08:00
committed by Alex Kontos
parent 75887a0792
commit f6af2f42ad
26 changed files with 2982 additions and 2686 deletions

4
Cargo.lock generated
View File

@@ -4082,9 +4082,9 @@ dependencies = [
[[package]]
name = "mime_guess"
version = "2.0.4"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
dependencies = [
"mime",
"unicase",

View File

@@ -1288,6 +1288,7 @@ function maybeRecordToHandleTelemetry(uri, isLaunch) {
".xhtml",
".svg",
".webp",
".jxl",
]);
if (registeredExtensions.has(extension)) {
counter[extension].add(1);

View File

@@ -67,6 +67,7 @@
<uap:FileType>.xhtml</uap:FileType>
<uap:FileType>.svg</uap:FileType>
<uap:FileType>.webp</uap:FileType>
<uap:FileType>.jxl</uap:FileType>
</uap:SupportedFileTypes>
<uap:Logo>Assets\Document44x44.png</uap:Logo>
<uap2:SupportedVerbs>

View File

@@ -513,6 +513,7 @@ ${RemoveDefaultBrowserAgentShortcut}
${AddAssociationIfNoneExist} ".svg" "WaterfoxHTML$5"
${AddAssociationIfNoneExist} ".webp" "WaterfoxHTML$5"
${AddAssociationIfNoneExist} ".avif" "WaterfoxHTML$5"
${AddAssociationIfNoneExist} ".jxl" "WaterfoxHTML$5"
${AddAssociationIfNoneExist} ".pdf" "WaterfoxPDF$5"

View File

@@ -505,7 +505,9 @@ Section "Uninstall"
${un.RegCleanFileHandler} ".ogv" "WaterfoxHTML-$AppUserModelID"
${un.RegCleanFileHandler} ".webm" "WaterfoxHTML-$AppUserModelID"
${un.RegCleanFileHandler} ".svg" "WaterfoxHTML-$AppUserModelID"
${un.RegCleanFileHandler} ".webp" "WaterfoxHTML-$AppUserModelID"
${un.RegCleanFileHandler} ".avif" "WaterfoxHTML-$AppUserModelID"
${un.RegCleanFileHandler} ".jxl" "WaterfoxHTML-$AppUserModelID"
${un.RegCleanFileHandler} ".pdf" "WaterfoxPDF-$AppUserModelID"

View File

@@ -249,7 +249,8 @@ nsresult DecoderFactory::CreateAnimationDecoder(
}
MOZ_ASSERT(aType == DecoderType::GIF || aType == DecoderType::PNG ||
aType == DecoderType::WEBP || aType == DecoderType::AVIF,
aType == DecoderType::WEBP || aType == DecoderType::AVIF ||
aType == DecoderType::JXL,
"Calling CreateAnimationDecoder for non-animating DecoderType");
// Create an anonymous decoder. Interaction with the SurfaceCache and the
@@ -304,7 +305,8 @@ already_AddRefed<Decoder> DecoderFactory::CloneAnimationDecoder(
// rediscover it is animated).
DecoderType type = aDecoder->GetType();
MOZ_ASSERT(type == DecoderType::GIF || type == DecoderType::PNG ||
type == DecoderType::WEBP || type == DecoderType::AVIF,
type == DecoderType::WEBP || type == DecoderType::AVIF ||
type == DecoderType::JXL,
"Calling CloneAnimationDecoder for non-animating DecoderType");
RefPtr<Decoder> decoder = GetDecoder(type, nullptr, /* aIsRedecode = */ true);

View File

@@ -45,9 +45,20 @@ nsJXLDecoder::nsJXLDecoder(RasterImage* aImage)
Transition::TerminateSuccess()),
mDecoder(JxlDecoderMake(nullptr)),
mParallelRunner(
JxlThreadParallelRunnerMake(nullptr, PreferredThreadCount())) {
JxlDecoderSubscribeEvents(mDecoder.get(),
JXL_DEC_BASIC_INFO | JXL_DEC_FULL_IMAGE);
JxlThreadParallelRunnerMake(nullptr, PreferredThreadCount())),
mUsePipeTransform(true),
mCMSLine(nullptr),
mNumFrames(0),
mTimeout(FrameTimeout::Forever()),
mSurfaceFormat(SurfaceFormat::OS_RGBX),
mContinue(false) {
int events = JXL_DEC_BASIC_INFO | JXL_DEC_FRAME | JXL_DEC_FULL_IMAGE;
if (mCMSMode != CMSMode::Off) {
events |= JXL_DEC_COLOR_ENCODING;
}
JxlDecoderSubscribeEvents(mDecoder.get(), events);
JxlDecoderSetParallelRunner(mDecoder.get(), JxlThreadParallelRunner,
mParallelRunner.get());
@@ -58,6 +69,10 @@ nsJXLDecoder::nsJXLDecoder(RasterImage* aImage)
nsJXLDecoder::~nsJXLDecoder() {
MOZ_LOG(sJXLLog, LogLevel::Debug,
("[this=%p] nsJXLDecoder::~nsJXLDecoder", this));
if (mCMSLine) {
free(mCMSLine);
}
}
size_t nsJXLDecoder::PreferredThreadCount() {
@@ -86,14 +101,20 @@ LexerResult nsJXLDecoder::DoDecode(SourceBufferIterator& aIterator,
LexerTransition<nsJXLDecoder::State> nsJXLDecoder::ReadJXLData(
const char* aData, size_t aLength) {
const uint8_t* input = (const uint8_t*)aData;
size_t length = aLength;
if (mBuffer.length() != 0) {
JXL_TRY_BOOL(mBuffer.append(aData, aLength));
input = mBuffer.begin();
length = mBuffer.length();
// Ignore data we have already read.
// This will only occur as a result of a yield for animation.
if (!mContinue) {
const uint8_t* input = (const uint8_t*)aData;
size_t length = aLength;
if (mBuffer.length() != 0) {
JXL_TRY_BOOL(mBuffer.append(aData, aLength));
input = mBuffer.begin();
length = mBuffer.length();
}
JXL_TRY(JxlDecoderSetInput(mDecoder.get(), input, length));
}
JXL_TRY(JxlDecoderSetInput(mDecoder.get(), input, length));
mContinue = false;
while (true) {
JxlDecoderStatus status = JxlDecoderProcessInput(mDecoder.get());
@@ -106,6 +127,34 @@ LexerTransition<nsJXLDecoder::State> nsJXLDecoder::ReadJXLData(
size_t remaining = JxlDecoderReleaseInput(mDecoder.get());
mBuffer.clear();
JXL_TRY_BOOL(mBuffer.append(aData + aLength - remaining, remaining));
if (mNumFrames == 0 && InFrame()) {
// If an image was flushed by JxlDecoderFlushImage, then we know that
// JXL_DEC_FRAME has already been run and there is a pipe.
if (JxlDecoderFlushImage(mDecoder.get()) == JXL_DEC_SUCCESS) {
// A full frame partial image is written to the buffer.
mPipe.ResetToFirstRow();
for (uint8_t* rowPtr = mOutBuffer.begin();
rowPtr < mOutBuffer.end(); rowPtr += mInfo.xsize * mChannels) {
uint8_t* rowToWrite = rowPtr;
if (!mUsePipeTransform && mTransform) {
qcms_transform_data(mTransform, rowToWrite, mCMSLine,
mInfo.xsize);
rowToWrite = mCMSLine;
}
mPipe.WriteBuffer(reinterpret_cast<uint32_t*>(rowToWrite));
}
if (Maybe<SurfaceInvalidRect> invalidRect =
mPipe.TakeInvalidRect()) {
PostInvalidation(invalidRect->mInputSpaceRect,
Some(invalidRect->mOutputSpaceRect));
}
}
}
return Transition::ContinueUnbuffered(State::JXL_DATA);
}
@@ -116,42 +165,199 @@ LexerTransition<nsJXLDecoder::State> nsJXLDecoder::ReadJXLData(
PostFrameCount(/* aFrameCount */ 1);
}
if (mInfo.alpha_bits > 0) {
mSurfaceFormat = SurfaceFormat::OS_RGBA;
PostHasTransparency();
}
if (!mInfo.have_animation && IsMetadataDecode()) {
return Transition::TerminateSuccess();
}
// If CMS is off or the image is RGB, always output in RGBA.
// If the image is grayscale, then the pipe transform can't be used.
if (mCMSMode != CMSMode::Off) {
mChannels = mInfo.num_color_channels == 1
? 1 + (mInfo.alpha_bits > 0 ? 1 : 0)
: 4;
} else {
mChannels = 4;
}
mFormat = {mChannels, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0};
break;
}
case JXL_DEC_COLOR_ENCODING: {
size_t size = 0;
JXL_TRY(JxlDecoderGetICCProfileSize(
mDecoder.get(), JXL_COLOR_PROFILE_TARGET_DATA, &size))
std::vector<uint8_t> icc_profile(size);
JXL_TRY(JxlDecoderGetColorAsICCProfile(mDecoder.get(),
JXL_COLOR_PROFILE_TARGET_DATA,
icc_profile.data(), size))
mInProfile = qcms_profile_from_memory((char*)icc_profile.data(), size);
uint32_t profileSpace = qcms_profile_get_color_space(mInProfile);
// Skip color management if color profile is not compatible with number
// of channels.
if (profileSpace != icSigRgbData &&
(mInfo.num_color_channels == 3 || profileSpace != icSigGrayData)) {
break;
}
mUsePipeTransform =
profileSpace == icSigRgbData && mInfo.num_color_channels == 3;
qcms_data_type inType;
if (mInfo.num_color_channels == 3) {
inType = QCMS_DATA_RGBA_8;
} else if (mInfo.alpha_bits > 0) {
inType = QCMS_DATA_GRAYA_8;
} else {
inType = QCMS_DATA_GRAY_8;
}
if (!mUsePipeTransform) {
mCMSLine =
static_cast<uint8_t*>(malloc(sizeof(uint32_t) * mInfo.xsize));
}
int intent = gfxPlatform::GetRenderingIntent();
if (intent == -1) {
intent = qcms_profile_get_rendering_intent(mInProfile);
}
mTransform =
qcms_transform_create(mInProfile, inType, GetCMSOutputProfile(),
QCMS_DATA_RGBA_8, (qcms_intent)intent);
break;
}
case JXL_DEC_FRAME: {
if (mInfo.have_animation) {
JXL_TRY(JxlDecoderGetFrameHeader(mDecoder.get(), &mFrameHeader));
int32_t duration = (int32_t)(1000.0 * mFrameHeader.duration *
mInfo.animation.tps_denominator /
mInfo.animation.tps_numerator);
mTimeout = FrameTimeout::FromRawMilliseconds(duration);
if (!HasAnimation()) {
PostIsAnimated(mTimeout);
}
}
bool is_last = mInfo.have_animation ? mFrameHeader.is_last : true;
MOZ_LOG(sJXLLog, LogLevel::Debug,
("[this=%p] nsJXLDecoder::ReadJXLData - frame %d, is_last %d, "
"metadata decode %d, first frame decode %d\n",
this, mNumFrames, is_last, IsMetadataDecode(),
IsFirstFrameDecode()));
if (IsMetadataDecode()) {
return Transition::TerminateSuccess();
}
OrientedIntSize size(mInfo.xsize, mInfo.ysize);
Maybe<AnimationParams> animParams;
if (!IsFirstFrameDecode()) {
animParams.emplace(FullFrame().ToUnknownRect(), mTimeout, mNumFrames,
BlendMethod::SOURCE, DisposalMethod::CLEAR);
}
SurfacePipeFlags pipeFlags = SurfacePipeFlags();
if (mNumFrames == 0) {
// The first frame may be displayed progressively.
pipeFlags |= SurfacePipeFlags::PROGRESSIVE_DISPLAY;
}
if (mSurfaceFormat == SurfaceFormat::OS_RGBA &&
!(GetSurfaceFlags() & SurfaceFlags::NO_PREMULTIPLY_ALPHA)) {
pipeFlags |= SurfacePipeFlags::PREMULTIPLY_ALPHA;
}
qcms_transform* pipeTransform =
mUsePipeTransform ? mTransform : nullptr;
Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
this, size, OutputSize(), FullFrame(), SurfaceFormat::R8G8B8A8,
mSurfaceFormat, animParams, pipeTransform, pipeFlags);
if (!pipe) {
MOZ_LOG(sJXLLog, LogLevel::Debug,
("[this=%p] nsJXLDecoder::ReadJXLData - no pipe\n", this));
return Transition::TerminateFailure();
}
mPipe = std::move(*pipe);
break;
}
case JXL_DEC_NEED_IMAGE_OUT_BUFFER: {
size_t size = 0;
JxlPixelFormat format{4, JXL_TYPE_UINT8, JXL_LITTLE_ENDIAN, 0};
JXL_TRY(JxlDecoderImageOutBufferSize(mDecoder.get(), &format, &size));
JXL_TRY(JxlDecoderImageOutBufferSize(mDecoder.get(), &mFormat, &size));
mOutBuffer.clear();
JXL_TRY_BOOL(mOutBuffer.growBy(size));
JXL_TRY(JxlDecoderSetImageOutBuffer(mDecoder.get(), &format,
JXL_TRY(JxlDecoderSetImageOutBuffer(mDecoder.get(), &mFormat,
mOutBuffer.begin(), size));
break;
}
case JXL_DEC_FULL_IMAGE: {
OrientedIntSize size(mInfo.xsize, mInfo.ysize);
Maybe<SurfacePipe> pipe = SurfacePipeFactory::CreateSurfacePipe(
this, size, OutputSize(), FullFrame(), SurfaceFormat::R8G8B8A8,
SurfaceFormat::OS_RGBA, Nothing(), nullptr, SurfacePipeFlags());
mPipe.ResetToFirstRow();
for (uint8_t* rowPtr = mOutBuffer.begin(); rowPtr < mOutBuffer.end();
rowPtr += mInfo.xsize * 4) {
pipe->WriteBuffer(reinterpret_cast<uint32_t*>(rowPtr));
rowPtr += mInfo.xsize * mChannels) {
uint8_t* rowToWrite = rowPtr;
if (!mUsePipeTransform && mTransform) {
qcms_transform_data(mTransform, rowToWrite, mCMSLine, mInfo.xsize);
rowToWrite = mCMSLine;
}
mPipe.WriteBuffer(reinterpret_cast<uint32_t*>(rowToWrite));
}
if (Maybe<SurfaceInvalidRect> invalidRect = pipe->TakeInvalidRect()) {
if (Maybe<SurfaceInvalidRect> invalidRect = mPipe.TakeInvalidRect()) {
PostInvalidation(invalidRect->mInputSpaceRect,
Some(invalidRect->mOutputSpaceRect));
}
PostFrameStop();
PostDecodeDone();
Opacity opacity = mSurfaceFormat == SurfaceFormat::OS_RGBA
? Opacity::SOME_TRANSPARENCY
: Opacity::FULLY_OPAQUE;
PostFrameStop(opacity);
if (!IsFirstFrameDecode() && mInfo.have_animation &&
!mFrameHeader.is_last) {
mNumFrames++;
mContinue = true;
// Notify for a new frame but there may be data in the current buffer
// that can immediately be processed.
return Transition::ToAfterYield(State::JXL_DATA);
}
[[fallthrough]]; // We are done.
}
case JXL_DEC_SUCCESS: {
int32_t loopArg;
if (HasAnimation()) {
// JXL num_loops: 0 means infinite. (num_loops - 1) becomes -1.
// JXL num_loops: 1 means play once. (num_loops - 1) becomes 0 (0 repeats).
// JXL num_loops: N means play N times. (num_loops - 1) becomes N-1 (N-1 repeats).
loopArg = static_cast<int32_t>(mInfo.animation.num_loops) - 1;
} else {
loopArg = 0; // For non-animated images, repeat count is 0.
}
PostLoopCount(loopArg); // Pass the loop count to PostLoopCount
PostDecodeDone(); // Call PostDecodeDone without arguments
return Transition::TerminateSuccess();
}
}

View File

@@ -45,7 +45,19 @@ class nsJXLDecoder final : public Decoder {
JxlThreadParallelRunnerPtr mParallelRunner;
Vector<uint8_t> mBuffer;
Vector<uint8_t> mOutBuffer;
JxlBasicInfo mInfo{};
JxlBasicInfo mInfo;
JxlPixelFormat mFormat;
JxlFrameHeader mFrameHeader;
bool mUsePipeTransform;
uint8_t mChannels;
uint8_t* mCMSLine;
uint32_t mNumFrames;
FrameTimeout mTimeout;
gfx::SurfaceFormat mSurfaceFormat;
SurfacePipe mPipe;
bool mContinue;
};
} // namespace mozilla::image

View File

@@ -2347,6 +2347,12 @@ version = "1.4.0"
notes = "I have read over the macros, and audited the unsafe code."
aggregated-from = "https://raw.githubusercontent.com/mozilla/cargo-vet/main/supply-chain/audits.toml"
[[audits.mozilla.audits.mime_guess]]
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
criteria = "safe-to-deploy"
delta = "2.0.4 -> 2.0.5"
aggregated-from = "https://raw.githubusercontent.com/mozilla/glean/main/supply-chain/audits.toml"
[[audits.mozilla.audits.rkv]]
who = "Kagami Sascha Rosylight <krosylight@mozilla.com>"
criteria = "safe-to-deploy"

View File

@@ -1 +1 @@
{"files":{"Cargo.lock":"1be3b2e0b56466b1a4ab94c35176df5a41846677caa7bd2d5603cfdb19d9eef3","Cargo.toml":"c367dbd734e16d3dc6333fc072021372baee73170ec1c9b19606bb52f1772d9a","LICENSE":"6919f1acec82afc721be2d9907b993267f433a44d25d8aedf1003b5f59ebfd46","README.md":"417338ebb9da8e8bdfad3c3da81248ab5f023652f3468ec5dcb2fdf43ea40b32","benches/benchmark.rs":"2287c7233cf78a9af98b2b53cd20e221e4a785209bd70a87030f1ade34a02507","build.rs":"8e47254c0a927eeb243058cfc0da413f34a958226707c941e8634e4514562f04","examples/rev_map.rs":"0bab6cc20b9eace741c6cc4a8c67ebfa124df1bf213038c5e34976081ffd2ebc","src/impl_bin_search.rs":"32a89409690d57f074f11eb93a9d6e422f73788af63fc29f980e13d1c2d2fa6f","src/impl_phf.rs":"321028cc657364c6f7c5b5f538b0033bcfd6f3b5ef711304d806c0644466a964","src/lib.rs":"bb190bcbbf4139c410af20564f0376a99a83474ca12b7e8c6860228e0caff7da","src/mime_types.rs":"57ee8db84eb0fc4f06a3eac0da8c730a334cb99a7e81e60413f5febd886d91f4"},"package":"4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"}
{"files":{"Cargo.lock":"2b59f34ab30d336b54edb66ea861174599310a5a87d597f45ca518cf55a186dc","Cargo.toml":"aca17af6f0fd2497700e94f764a25862ea41a35629fe4ba6603596213b8e1d88","LICENSE":"816000f9c28f7005d931c77636eb79fa7020071eb0f6e6a995515dfccd3559cb","README.md":"32663b3f4530e71cfec689576cca62911c83e504232963c65da82ebed26e2aa7","benches/benchmark.rs":"021dde9d834a3e4fab08d41f6e23d4f083f18c5f382b59866c2e07dc0ed9747a","build.rs":"bc413487e376b343b65089a9a897f4bb3c9d5fbaa5a6833e87db1d3c18c462d8","examples/rev_map.rs":"13a79d0b9eba6bfb49f99102917d1dada89c37ffcfab492759af997539b616ba","src/impl_bin_search.rs":"dd5817c9bc817c36274361c4cd0612ed303347c38bdbf8dff84cf57cd2918808","src/impl_phf.rs":"a9d956119304926c1f37754102ff74fbfe36004e24e326329e67e7c51fff381b","src/lib.rs":"7ea3571f3b7a231e4bf0003d66056becddeedb3084ee7af7fa9826f0602613f4","src/mime_types.rs":"1e89c58024547606d78e71488f0e027b740613fc22ac5877e24e3851e0f0628b"},"package":"f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"}

View File

@@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "atty"
version = "0.2.14"
@@ -15,42 +24,27 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.0.1"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "bitflags"
version = "1.2.1"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bstr"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
dependencies = [
"lazy_static",
"memchr",
"regex-automata",
"serde",
]
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bumpalo"
version = "3.7.0"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "cast"
version = "0.2.7"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
dependencies = [
"rustc_version",
]
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cfg-if"
@@ -60,9 +54,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"bitflags",
"textwrap",
@@ -71,9 +65,9 @@ dependencies = [
[[package]]
name = "criterion"
version = "0.3.5"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
dependencies = [
"atty",
"cast",
@@ -97,65 +91,45 @@ dependencies = [
[[package]]
name = "criterion-plot"
version = "0.4.4"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57"
checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.5"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"cfg-if",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "csv"
version = "1.1.6"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe"
dependencies = [
"bstr",
"csv-core",
"itoa",
"ryu",
@@ -164,24 +138,24 @@ dependencies = [
[[package]]
name = "csv-core"
version = "0.1.10"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70"
dependencies = [
"memchr",
]
[[package]]
name = "either"
version = "1.6.1"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "half"
version = "1.7.1"
version = "1.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
[[package]]
name = "hermit-abi"
@@ -194,73 +168,61 @@ dependencies = [
[[package]]
name = "itertools"
version = "0.10.1"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.7"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "js-sys"
version = "0.3.52"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce791b7ca6638aae45be056e068fc756d871eb3b3b10b8efa62d1c9cec616752"
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.98"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "log"
version = "0.4.14"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memchr"
version = "2.4.0"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
[[package]]
name = "memoffset"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [
"autocfg",
]
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "mime"
version = "0.3.16"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.4"
version = "2.0.5"
dependencies = [
"criterion",
"mime",
@@ -269,22 +231,18 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.14"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "oorandom"
@@ -294,9 +252,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "plotters"
version = "0.3.1"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3"
dependencies = [
"num-traits",
"plotters-backend",
@@ -307,97 +265,91 @@ dependencies = [
[[package]]
name = "plotters-backend"
version = "0.3.2"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c"
checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7"
[[package]]
name = "plotters-svg"
version = "0.3.1"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9"
checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705"
dependencies = [
"plotters-backend",
]
[[package]]
name = "proc-macro2"
version = "1.0.28"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-xid",
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.9"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.5.1"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.1"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "regex"
version = "1.5.4"
version = "1.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
dependencies = [
"semver",
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "ryu"
version = "1.0.5"
name = "regex-syntax"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
@@ -408,29 +360,20 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
[[package]]
name = "serde"
version = "1.0.127"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_cbor"
version = "0.11.1"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half",
"serde",
@@ -438,9 +381,9 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.127"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
@@ -449,9 +392,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.66"
version = "1.0.118"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
dependencies = [
"itoa",
"ryu",
@@ -460,13 +403,13 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.74"
version = "2.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"unicode-ident",
]
[[package]]
@@ -490,47 +433,46 @@ dependencies = [
[[package]]
name = "unicase"
version = "2.6.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-width"
version = "0.1.8"
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-xid"
version = "0.2.2"
name = "unicode-width"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
[[package]]
name = "version_check"
version = "0.9.3"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.3.2"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.75"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586"
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -538,13 +480,13 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.75"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f"
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
@@ -553,9 +495,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.75"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c"
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -563,9 +505,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.75"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f"
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [
"proc-macro2",
"quote",
@@ -576,15 +518,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.75"
version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2"
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]]
name = "web-sys"
version = "0.3.52"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01c70a82d842c9979078c772d4a1344685045f1a5628f677c2b2eab4dd7d2696"
checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -608,11 +550,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
dependencies = [
"winapi",
"windows-sys",
]
[[package]]
@@ -620,3 +562,76 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"

View File

@@ -11,12 +11,16 @@
[package]
name = "mime_guess"
version = "2.0.4"
version = "2.0.5"
authors = ["Austin Bonander <austin.bonander@gmail.com>"]
description = "A simple crate for detection of a file's MIME type by its extension."
documentation = "https://docs.rs/mime_guess/"
readme = "README.md"
keywords = ["mime", "filesystem", "extension"]
keywords = [
"mime",
"filesystem",
"extension",
]
license = "MIT"
repository = "https://github.com/abonander/mime_guess"
@@ -27,13 +31,16 @@ required-features = ["rev-mappings"]
[[bench]]
name = "benchmark"
harness = false
[dependencies.mime]
version = "0.3"
[dependencies.unicase]
version = "2.4.0"
[dev-dependencies.criterion]
version = "0.3"
[build-dependencies.unicase]
version = "2.4.0"

View File

@@ -1,22 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Austin Bonander
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The MIT License (MIT)
Copyright (c) 2015 Austin Bonander
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,86 +1,86 @@
# mime_guess ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/abonander/mime_guess/Rust) [![Crates.io](https://img.shields.io/crates/v/mime_guess.svg)](https://crates.io/crates/mime_guess)
MIME/MediaType guessing by file extension.
Uses a static map of known file extension -> MIME type mappings.
**Returning Contributors: New Requirements for Submissions Below**
##### Required Rust Version: 1.33
#### [Documentation](https://docs.rs/mime_guess/)
### Versioning
Due to a mistaken premature release, `mime_guess` currently publicly depends on a pre-1.0 `mime`,
which means `mime` upgrades are breaking changes and necessitate a major version bump.
Refer to the following table to find a version of `mime_guess` which matches your version of `mime`:
| `mime` version | `mime_guess` version |
|----------------|----------------------|
| `0.1.x, 0.2.x` | `1.x.y` |
| `0.3.x` | `2.x.y` |
#### Note: MIME Types Returned Are Not Stable/Guaranteed
The media types returned for a given extension are not considered to be part of the crate's
stable API and are often updated in patch (`x.y.z + 1`) releases to be as correct as possible. MIME
changes are backported to previous major releases on a best-effort basis.
Note that only the extensions of paths/filenames are inspected in order to guess the MIME type. The
file that may or may not reside at that path may or may not be a valid file of the returned MIME type.
Be wary of unsafe or un-validated assumptions about file structure or length.
An extension may also have multiple applicable MIME types. When more than one is returned, the first
is considered to be the most "correct"--see below for elaboration.
Contributing
-----------
#### Adding or correcting MIME types for extensions
Is the MIME type for a file extension wrong or missing? Great!
Well, not great for us, but great for you if you'd like to open a pull request!
The file extension -> MIME type mappings are listed in `src/mime_types.rs`.
**The list is sorted lexicographically by file extension, and all extensions are lowercase (where applicable).**
The former is necessary to support fallback to binary search when the
`phf-map` feature is turned off, and for the maintainers' sanity.
The latter is only for consistency's sake; the search is case-insensitive.
Simply add or update the appropriate string pair(s) to make the correction(s) needed.
Run `cargo test` to make sure the library continues to work correctly.
#### Important! Citing the corrected MIME type
When opening a pull request, please include a link to an official document or RFC noting
the correct MIME type for the file type in question **in the commit message** so
that the commit history can be used as an audit trail.
Though we're only guessing here, we like to be as correct as we can.
It makes it much easier to vet your contribution if we don't have to search for corroborating material.
#### Multiple MIME types per extension
As of `2.0.0`, multiple MIME types per extension are supported. The first MIME type in the list for
a given extension should be the most "correct" so users who only care about getting a single MIME
type can use the `first*()` methods.
The definition of "correct" is open to debate, however. In the author's opinion this should be
whatever is defined by the latest IETF RFC for the given file format, or otherwise explicitly
supercedes all others.
If an official IANA registration replaces an older "experimental" style media type, please
place the new type before the old type in the list, but keep the old type for reference:
```
- ("md", &["text/x-markdown"]),
+ ("md", &["text/markdown", "text/x-markdown"]),
```
#### Changes to the API or operation of the crate
We're open to changes to the crate's API or its inner workings, breaking or not, if it improves the overall operation, efficiency, or ergonomics of the crate. However, it would be a good idea to open an issue on the repository so we can discuss your proposed changes and decide how best to approach them.
License
-------
MIT (See the `LICENSE` file in this repository for more information.)
# mime_guess ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/abonander/mime_guess/rust.yml?branch=master) [![Crates.io](https://img.shields.io/crates/v/mime_guess.svg)](https://crates.io/crates/mime_guess)
MIME/MediaType guessing by file extension.
Uses a static map of known file extension -> MIME type mappings.
**Returning Contributors: New Requirements for Submissions Below**
##### Required Rust Version: 1.33
#### [Documentation](https://docs.rs/mime_guess/)
### Versioning
Due to a mistaken premature release, `mime_guess` currently publicly depends on a pre-1.0 `mime`,
which means `mime` upgrades are breaking changes and necessitate a major version bump.
Refer to the following table to find a version of `mime_guess` which matches your version of `mime`:
| `mime` version | `mime_guess` version |
|----------------|----------------------|
| `0.1.x, 0.2.x` | `1.x.y` |
| `0.3.x` | `2.x.y` |
#### Note: MIME Types Returned Are Not Stable/Guaranteed
The media types returned for a given extension are not considered to be part of the crate's
stable API and are often updated in patch (`x.y.z + 1`) releases to be as correct as possible. MIME
changes are backported to previous major releases on a best-effort basis.
Note that only the extensions of paths/filenames are inspected in order to guess the MIME type. The
file that may or may not reside at that path may or may not be a valid file of the returned MIME type.
Be wary of unsafe or un-validated assumptions about file structure or length.
An extension may also have multiple applicable MIME types. When more than one is returned, the first
is considered to be the most "correct"--see below for elaboration.
Contributing
-----------
#### Adding or correcting MIME types for extensions
Is the MIME type for a file extension wrong or missing? Great!
Well, not great for us, but great for you if you'd like to open a pull request!
The file extension -> MIME type mappings are listed in `src/mime_types.rs`.
**The list is sorted lexicographically by file extension, and all extensions are lowercase (where applicable).**
The former is necessary to support fallback to binary search when the
`phf-map` feature is turned off, and for the maintainers' sanity.
The latter is only for consistency's sake; the search is case-insensitive.
Simply add or update the appropriate string pair(s) to make the correction(s) needed.
Run `cargo test` to make sure the library continues to work correctly.
#### Important! Citing the corrected MIME type
When opening a pull request, please include a link to an official document or RFC noting
the correct MIME type for the file type in question **in the commit message** so
that the commit history can be used as an audit trail.
Though we're only guessing here, we like to be as correct as we can.
It makes it much easier to vet your contribution if we don't have to search for corroborating material.
#### Multiple MIME types per extension
As of `2.0.0`, multiple MIME types per extension are supported. The first MIME type in the list for
a given extension should be the most "correct" so users who only care about getting a single MIME
type can use the `first*()` methods.
The definition of "correct" is open to debate, however. In the author's opinion this should be
whatever is defined by the latest IETF RFC for the given file format, or otherwise explicitly
supercedes all others.
If an official IANA registration replaces an older "experimental" style media type, please
place the new type before the old type in the list, but keep the old type for reference:
```
- ("md", &["text/x-markdown"]),
+ ("md", &["text/markdown", "text/x-markdown"]),
```
#### Changes to the API or operation of the crate
We're open to changes to the crate's API or its inner workings, breaking or not, if it improves the overall operation, efficiency, or ergonomics of the crate. However, it would be a good idea to open an issue on the repository so we can discuss your proposed changes and decide how best to approach them.
License
-------
MIT (See the `LICENSE` file in this repository for more information.)

View File

@@ -1,31 +1,31 @@
#[macro_use]
extern crate criterion;
extern crate mime_guess;
use self::criterion::Criterion;
use mime_guess::from_ext;
include!("../src/mime_types.rs");
/// WARNING: this may take a while!
fn bench_mime_str(c: &mut Criterion) {
c.bench_function("from_ext", |b| {
for (mime_ext, _) in MIME_TYPES {
b.iter(|| from_ext(mime_ext).first_raw());
}
});
}
fn bench_mime_str_uppercase(c: &mut Criterion) {
c.bench_function("from_ext uppercased", |b| {
let uppercased = MIME_TYPES.into_iter().map(|(s, _)| s.to_uppercase());
for mime_ext in uppercased {
b.iter(|| from_ext(&mime_ext).first_raw());
}
});
}
criterion_group!(benches, bench_mime_str, bench_mime_str_uppercase);
criterion_main!(benches);
#[macro_use]
extern crate criterion;
extern crate mime_guess;
use self::criterion::Criterion;
use mime_guess::from_ext;
include!("../src/mime_types.rs");
/// WARNING: this may take a while!
fn bench_mime_str(c: &mut Criterion) {
c.bench_function("from_ext", |b| {
for (mime_ext, _) in MIME_TYPES {
b.iter(|| from_ext(mime_ext).first_raw());
}
});
}
fn bench_mime_str_uppercase(c: &mut Criterion) {
c.bench_function("from_ext uppercased", |b| {
let uppercased = MIME_TYPES.into_iter().map(|(s, _)| s.to_uppercase());
for mime_ext in uppercased {
b.iter(|| from_ext(&mime_ext).first_raw());
}
});
}
criterion_group!(benches, bench_mime_str, bench_mime_str_uppercase);
criterion_main!(benches);

View File

@@ -1,191 +1,196 @@
#[cfg(feature = "phf")]
extern crate phf_codegen;
extern crate unicase;
use unicase::UniCase;
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufWriter;
use std::path::Path;
use std::collections::BTreeMap;
use mime_types::MIME_TYPES;
#[path = "src/mime_types.rs"]
mod mime_types;
#[cfg(feature = "phf")]
const PHF_PATH: &str = "::impl_::phf";
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("mime_types_generated.rs");
let mut outfile = BufWriter::new(File::create(dest_path).unwrap());
#[cfg(feature = "phf")]
build_forward_map(&mut outfile);
#[cfg(feature = "rev-mappings")]
build_rev_map(&mut outfile);
}
// Build forward mappings (ext -> mime type)
#[cfg(feature = "phf")]
fn build_forward_map<W: Write>(out: &mut W) {
use phf_codegen::Map as PhfMap;
let mut forward_map = PhfMap::new();
forward_map.phf_path(PHF_PATH);
let mut map_entries: Vec<(&str, Vec<&str>)> = Vec::new();
for &(key, types) in MIME_TYPES {
if let Some(&mut (key_, ref mut values)) = map_entries.last_mut() {
// deduplicate extensions
if key == key_ {
values.extend_from_slice(types);
continue;
}
}
map_entries.push((key, types.into()));
}
for (key, values) in map_entries {
forward_map.entry(
UniCase::new(key),
&format!("&{:?}", values),
);
}
writeln!(
out,
"static MIME_TYPES: phf::Map<UniCase<&'static str>, &'static [&'static str]> = \n{};",
forward_map.build()
)
.unwrap();
}
// Build reverse mappings (mime type -> ext)
#[cfg(all(feature = "phf", feature = "rev-mappings"))]
fn build_rev_map<W: Write>(out: &mut W) {
use phf_codegen::Map as PhfMap;
let dyn_map = get_rev_mappings();
let mut rev_map = PhfMap::new();
rev_map.phf_path(PHF_PATH);
let mut exts = Vec::new();
for (top, subs) in dyn_map {
let top_start = exts.len();
let mut sub_map = PhfMap::new();
sub_map.phf_path(PHF_PATH);
for (sub, sub_exts) in subs {
let sub_start = exts.len();
exts.extend(sub_exts);
let sub_end = exts.len();
sub_map.entry(sub, &format!("({}, {})", sub_start, sub_end));
}
let top_end = exts.len();
rev_map.entry(
top,
&format!(
"TopLevelExts {{ start: {}, end: {}, subs: {} }}",
top_start, top_end, sub_map.build()
),
);
}
writeln!(
out,
"static REV_MAPPINGS: phf::Map<UniCase<&'static str>, TopLevelExts> = \n{};",
rev_map.build()
).unwrap();
writeln!(out, "const EXTS: &'static [&'static str] = &{:?};", exts).unwrap();
}
#[cfg(all(not(feature = "phf"), feature = "rev-mappings"))]
fn build_rev_map<W: Write>(out: &mut W) {
use std::fmt::Write as _;
macro_rules! unicase_const {
($s:expr) => ({
format_args!("{}({:?})", (if $s.is_ascii() {
"UniCase::ascii"
} else {
"UniCase::unicode"
}), $s)
})
}
let dyn_map = get_rev_mappings();
write!(out, "static REV_MAPPINGS: &'static [(UniCase<&'static str>, TopLevelExts)] = &[").unwrap();
let mut exts = Vec::new();
for (top, subs) in dyn_map {
let top_start = exts.len();
let mut sub_map = String::new();
for (sub, sub_exts) in subs {
let sub_start = exts.len();
exts.extend(sub_exts);
let sub_end = exts.len();
write!(
sub_map,
"({}, ({}, {})),",
unicase_const!(sub), sub_start, sub_end
).unwrap();
}
let top_end = exts.len();
write!(
out,
"({}, TopLevelExts {{ start: {}, end: {}, subs: &[{}] }}),",
unicase_const!(top), top_start, top_end, sub_map
).unwrap();
}
writeln!(out, "];").unwrap();
writeln!(out, "const EXTS: &'static [&'static str] = &{:?};", exts).unwrap();
}
#[cfg(feature = "rev-mappings")]
fn get_rev_mappings(
) -> BTreeMap<UniCase<&'static str>, BTreeMap<UniCase<&'static str>, Vec<&'static str>>> {
// First, collect all the mime type -> ext mappings)
let mut dyn_map = BTreeMap::new();
for &(key, types) in MIME_TYPES {
for val in types {
let (top, sub) = split_mime(val);
dyn_map
.entry(UniCase::new(top))
.or_insert_with(BTreeMap::new)
.entry(UniCase::new(sub))
.or_insert_with(Vec::new)
.push(key);
}
}
dyn_map
}
fn split_mime(mime: &str) -> (&str, &str) {
let split_idx = mime.find('/').unwrap();
(&mime[..split_idx], &mime[split_idx + 1..])
}
#[cfg(feature = "phf")]
extern crate phf_codegen;
extern crate unicase;
use unicase::UniCase;
use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufWriter;
use std::path::Path;
use std::collections::BTreeMap;
use mime_types::MIME_TYPES;
#[path = "src/mime_types.rs"]
mod mime_types;
#[cfg(feature = "phf")]
const PHF_PATH: &str = "::impl_::phf";
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("mime_types_generated.rs");
let mut outfile = BufWriter::new(File::create(&dest_path).unwrap());
println!(
"cargo:rustc-env=MIME_TYPES_GENERATED_PATH={}",
dest_path.display()
);
#[cfg(feature = "phf")]
build_forward_map(&mut outfile);
#[cfg(feature = "rev-mappings")]
build_rev_map(&mut outfile);
}
// Build forward mappings (ext -> mime type)
#[cfg(feature = "phf")]
fn build_forward_map<W: Write>(out: &mut W) {
use phf_codegen::Map as PhfMap;
let mut forward_map = PhfMap::new();
forward_map.phf_path(PHF_PATH);
let mut map_entries: Vec<(&str, Vec<&str>)> = Vec::new();
for &(key, types) in MIME_TYPES {
if let Some(&mut (key_, ref mut values)) = map_entries.last_mut() {
// deduplicate extensions
if key == key_ {
values.extend_from_slice(types);
continue;
}
}
map_entries.push((key, types.into()));
}
for (key, values) in map_entries {
forward_map.entry(
UniCase::new(key),
&format!("&{:?}", values),
);
}
writeln!(
out,
"static MIME_TYPES: phf::Map<UniCase<&'static str>, &'static [&'static str]> = \n{};",
forward_map.build()
)
.unwrap();
}
// Build reverse mappings (mime type -> ext)
#[cfg(all(feature = "phf", feature = "rev-mappings"))]
fn build_rev_map<W: Write>(out: &mut W) {
use phf_codegen::Map as PhfMap;
let dyn_map = get_rev_mappings();
let mut rev_map = PhfMap::new();
rev_map.phf_path(PHF_PATH);
let mut exts = Vec::new();
for (top, subs) in dyn_map {
let top_start = exts.len();
let mut sub_map = PhfMap::new();
sub_map.phf_path(PHF_PATH);
for (sub, sub_exts) in subs {
let sub_start = exts.len();
exts.extend(sub_exts);
let sub_end = exts.len();
sub_map.entry(sub, &format!("({}, {})", sub_start, sub_end));
}
let top_end = exts.len();
rev_map.entry(
top,
&format!(
"TopLevelExts {{ start: {}, end: {}, subs: {} }}",
top_start, top_end, sub_map.build()
),
);
}
writeln!(
out,
"static REV_MAPPINGS: phf::Map<UniCase<&'static str>, TopLevelExts> = \n{};",
rev_map.build()
).unwrap();
writeln!(out, "const EXTS: &'static [&'static str] = &{:?};", exts).unwrap();
}
#[cfg(all(not(feature = "phf"), feature = "rev-mappings"))]
fn build_rev_map<W: Write>(out: &mut W) {
use std::fmt::Write as _;
macro_rules! unicase_const {
($s:expr) => ({
format_args!("{}({:?})", (if $s.is_ascii() {
"UniCase::ascii"
} else {
"UniCase::unicode"
}), $s)
})
}
let dyn_map = get_rev_mappings();
write!(out, "static REV_MAPPINGS: &'static [(UniCase<&'static str>, TopLevelExts)] = &[").unwrap();
let mut exts = Vec::new();
for (top, subs) in dyn_map {
let top_start = exts.len();
let mut sub_map = String::new();
for (sub, sub_exts) in subs {
let sub_start = exts.len();
exts.extend(sub_exts);
let sub_end = exts.len();
write!(
sub_map,
"({}, ({}, {})),",
unicase_const!(sub), sub_start, sub_end
).unwrap();
}
let top_end = exts.len();
write!(
out,
"({}, TopLevelExts {{ start: {}, end: {}, subs: &[{}] }}),",
unicase_const!(top), top_start, top_end, sub_map
).unwrap();
}
writeln!(out, "];").unwrap();
writeln!(out, "const EXTS: &'static [&'static str] = &{:?};", exts).unwrap();
}
#[cfg(feature = "rev-mappings")]
fn get_rev_mappings(
) -> BTreeMap<UniCase<&'static str>, BTreeMap<UniCase<&'static str>, Vec<&'static str>>> {
// First, collect all the mime type -> ext mappings)
let mut dyn_map = BTreeMap::new();
for &(key, types) in MIME_TYPES {
for val in types {
let (top, sub) = split_mime(val);
dyn_map
.entry(UniCase::new(top))
.or_insert_with(BTreeMap::new)
.entry(UniCase::new(sub))
.or_insert_with(Vec::new)
.push(key);
}
}
dyn_map
}
fn split_mime(mime: &str) -> (&str, &str) {
let split_idx = mime.find('/').unwrap();
(&mime[..split_idx], &mime[split_idx + 1..])
}

View File

@@ -1,14 +1,14 @@
extern crate mime_guess;
fn main() {
print_exts("video/*");
print_exts("video/x-matroska");
}
fn print_exts(mime_type: &str) {
println!(
"Exts for {:?}: {:?}",
mime_type,
mime_guess::get_mime_extensions_str(mime_type)
);
}
extern crate mime_guess;
fn main() {
print_exts("video/*");
print_exts("video/x-matroska");
}
fn print_exts(mime_type: &str) {
println!(
"Exts for {:?}: {:?}",
mime_type,
mime_guess::get_mime_extensions_str(mime_type)
);
}

View File

@@ -1,41 +1,41 @@
use unicase::UniCase;
include!("mime_types.rs");
include!(concat!(env!("OUT_DIR"), "/mime_types_generated.rs"));
#[cfg(feature = "rev-mappings")]
#[derive(Copy, Clone)]
struct TopLevelExts {
start: usize,
end: usize,
subs: &'static [(UniCase<&'static str>, (usize, usize))],
}
pub fn get_mime_types(ext: &str) -> Option<&'static [&'static str]> {
let ext = UniCase::new(ext);
map_lookup(MIME_TYPES, &ext)
}
#[cfg(feature = "rev-mappings")]
pub fn get_extensions(toplevel: &str, sublevel: &str) -> Option<&'static [&'static str]> {
if toplevel == "*" {
return Some(EXTS);
}
let top = map_lookup(REV_MAPPINGS, toplevel)?;
if sublevel == "*" {
return Some(&EXTS[top.start..top.end]);
}
let sub = map_lookup(&top.subs, sublevel)?;
Some(&EXTS[sub.0..sub.1])
}
fn map_lookup<K, V>(map: &'static [(K, V)], key: &str) -> Option<V>
where K: Copy + Into<UniCase<&'static str>>, V: Copy {
map.binary_search_by_key(&UniCase::new(key), |(k, _)| (*k).into())
.ok()
.map(|i| map[i].1)
}
use unicase::UniCase;
include!("mime_types.rs");
include!(env!("MIME_TYPES_GENERATED_PATH"));
#[cfg(feature = "rev-mappings")]
#[derive(Copy, Clone)]
struct TopLevelExts {
start: usize,
end: usize,
subs: &'static [(UniCase<&'static str>, (usize, usize))],
}
pub fn get_mime_types(ext: &str) -> Option<&'static [&'static str]> {
let ext = UniCase::new(ext);
map_lookup(MIME_TYPES, &ext)
}
#[cfg(feature = "rev-mappings")]
pub fn get_extensions(toplevel: &str, sublevel: &str) -> Option<&'static [&'static str]> {
if toplevel == "*" {
return Some(EXTS);
}
let top = map_lookup(REV_MAPPINGS, toplevel)?;
if sublevel == "*" {
return Some(&EXTS[top.start..top.end]);
}
let sub = map_lookup(&top.subs, sublevel)?;
Some(&EXTS[sub.0..sub.1])
}
fn map_lookup<K, V>(map: &'static [(K, V)], key: &str) -> Option<V>
where K: Copy + Into<UniCase<&'static str>>, V: Copy {
map.binary_search_by_key(&UniCase::new(key), |(k, _)| (*k).into())
.ok()
.map(|i| map[i].1)
}

View File

@@ -1,40 +1,40 @@
extern crate phf;
use unicase::UniCase;
include!(concat!(env!("OUT_DIR"), "/mime_types_generated.rs"));
#[cfg(feature = "rev-mappings")]
struct TopLevelExts {
start: usize,
end: usize,
subs: phf::Map<UniCase<&'static str>, (usize, usize)>,
}
pub fn get_mime_types(ext: &str) -> Option<&'static [&'static str]> {
map_lookup(&MIME_TYPES, ext).cloned()
}
pub fn get_extensions(toplevel: &str, sublevel: &str) -> Option<&'static [&'static str]> {
if toplevel == "*" {
return Some(EXTS);
}
let top = map_lookup(&REV_MAPPINGS, toplevel)?;
if sublevel == "*" {
return Some(&EXTS[top.start..top.end]);
}
let sub = map_lookup(&top.subs, sublevel)?;
Some(&EXTS[sub.0..sub.1])
}
fn map_lookup<'key, 'map: 'key, V>(
map: &'map phf::Map<UniCase<&'static str>, V>,
key: &'key str,
) -> Option<&'map V> {
// FIXME: this doesn't compile unless we transmute `key` to `UniCase<&'static str>`
// https://github.com/sfackler/rust-phf/issues/169
map.get(&UniCase::new(key))
}
extern crate phf;
use unicase::UniCase;
include!(env!("MIME_TYPES_GENERATED_PATH"));
#[cfg(feature = "rev-mappings")]
struct TopLevelExts {
start: usize,
end: usize,
subs: phf::Map<UniCase<&'static str>, (usize, usize)>,
}
pub fn get_mime_types(ext: &str) -> Option<&'static [&'static str]> {
map_lookup(&MIME_TYPES, ext).cloned()
}
pub fn get_extensions(toplevel: &str, sublevel: &str) -> Option<&'static [&'static str]> {
if toplevel == "*" {
return Some(EXTS);
}
let top = map_lookup(&REV_MAPPINGS, toplevel)?;
if sublevel == "*" {
return Some(&EXTS[top.start..top.end]);
}
let sub = map_lookup(&top.subs, sublevel)?;
Some(&EXTS[sub.0..sub.1])
}
fn map_lookup<'key, 'map: 'key, V>(
map: &'map phf::Map<UniCase<&'static str>, V>,
key: &'key str,
) -> Option<&'map V> {
// FIXME: this doesn't compile unless we transmute `key` to `UniCase<&'static str>`
// https://github.com/sfackler/rust-phf/issues/169
map.get(&UniCase::new(key))
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -50,6 +50,7 @@ const FILE_EXTENSIONS = [
"jpg",
"jpeg",
"json",
"jxl",
"m4a",
"mdb",
"mid",

View File

@@ -104,6 +104,7 @@ const FILTER_IMAGES_EXTENSIONS = [
"raw",
"webp",
"heic",
"jxl",
];
const FILTER_XML_EXTENSIONS = ["xml"];

View File

@@ -5,7 +5,7 @@
allFilter=*
htmlFilter=*.html; *.htm; *.shtml; *.xhtml
textFilter=*.txt; *.text
imageFilter=*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw; *.webp; *.heic
imageFilter=*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw; *.webp; *.heic; *.avif; *.jxl
xmlFilter=*.xml
xulFilter=*.xul
audioFilter=*.aac; *.aif; *.flac; *.iff; *.m4a; *.m4b; *.mid; *.midi; *.mp3; *.mpa; *.mpc; *.oga; *.ogg; *.opus; *.ra; *.ram; *.snd; *.wav; *.wma

View File

@@ -932,9 +932,9 @@ set_config("MOZ_SYSTEM_AV1", True, when="--with-system-av1")
option("--disable-jxl", help="Disable jxl image support")
@depends("--disable-jxl", milestone.is_nightly)
def jxl(value, is_nightly):
if is_nightly and value:
@depends("--disable-jxl")
def jxl(value):
if value:
return True

View File

@@ -420,7 +420,8 @@ nsresult nsAppShell::Init() {
gchar* name = gdk_pixbuf_format_get_name(format);
if (strcmp(name, "jpeg") && strcmp(name, "png") && strcmp(name, "gif") &&
strcmp(name, "bmp") && strcmp(name, "ico") && strcmp(name, "xpm") &&
strcmp(name, "svg") && strcmp(name, "webp") && strcmp(name, "avif")) {
strcmp(name, "svg") && strcmp(name, "webp") && strcmp(name, "avif") &&
strcmp(name, "jxl")) {
gdk_pixbuf_format_set_disabled(format, TRUE);
}
g_free(name);