Bug 1661583 - Update mp4parse-rust to fe90285. r=kinetik

- Enable fallible allocation in mp4parse_capi by default
- Switch from local implementation of fallible allocation to using
  fallible_collections crate
- Return error if any of the primary item data is missing

Differential Revision: https://phabricator.services.mozilla.com/D89091
This commit is contained in:
Jon Bauman 2020-09-02 14:59:02 +00:00
Родитель 3c2aa8f90e
Коммит 5db1fd1dd5
32 изменённых файлов: 7398 добавлений и 564 удалений

Просмотреть файл

@ -15,7 +15,7 @@ tag = "v0.4.10"
[source."https://github.com/mozilla/mp4parse-rust"]
git = "https://github.com/mozilla/mp4parse-rust"
replace-with = "vendored-sources"
rev = "d5a37fd0bd51e06a53274c68213b00136aba83a6"
rev = "fe9028570e44f3a725dd78bbb58428909c4618bf"
[source."https://github.com/mozilla/application-services"]
git = "https://github.com/mozilla/application-services"

15
Cargo.lock сгенерированный
Просмотреть файл

@ -1384,6 +1384,15 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fallible_collections"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3301bcde54d3fc19c626ff4bf962630fe1f94cb6cdc3f18a26727a2d1f4a67"
dependencies = [
"hashbrown",
]
[[package]]
name = "ffi-support"
version = "0.4.0"
@ -3121,10 +3130,11 @@ dependencies = [
[[package]]
name = "mp4parse"
version = "0.11.4"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=d5a37fd0bd51e06a53274c68213b00136aba83a6#d5a37fd0bd51e06a53274c68213b00136aba83a6"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=fe9028570e44f3a725dd78bbb58428909c4618bf#fe9028570e44f3a725dd78bbb58428909c4618bf"
dependencies = [
"bitreader",
"byteorder",
"fallible_collections",
"hashbrown",
"log",
"num-traits",
@ -3138,9 +3148,10 @@ version = "0.1.0"
[[package]]
name = "mp4parse_capi"
version = "0.11.4"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=d5a37fd0bd51e06a53274c68213b00136aba83a6#d5a37fd0bd51e06a53274c68213b00136aba83a6"
source = "git+https://github.com/mozilla/mp4parse-rust?rev=fe9028570e44f3a725dd78bbb58428909c4618bf#fe9028570e44f3a725dd78bbb58428909c4618bf"
dependencies = [
"byteorder",
"fallible_collections",
"log",
"mp4parse",
"num-traits",

1
third_party/rust/fallible_collections/.cargo-checksum.json поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
{"files":{"Cargo.toml":"63f9088664a4a87c994e96e43e096a2a9b5746339a0689057ab669364536652b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"0621878e61f0d0fda054bcbe02df75192c28bde1ecc8289cbd86aeba2dd72720","README.md":"6d74a8ddac747e9fd6d8c2000c6d0ae05bc28bb9e47e629e86d4b8d05115f546","src/arc.rs":"60742619b7404d8c46237e9a3f98c49f75f88e4c24513ebca1d0ddad0274b6d6","src/boxed.rs":"8d9b1bc84e3bfb59f59f0c7df93ccd225ffc044166db6e2aa5976cc968203712","src/btree.rs":"b83820fc2a00e2e34127b3037abde8b945f0ca2785f3def725787e6813c3d3e0","src/btree/map.rs":"4d8710cf6f00bd889045a6144de692d9f752d51089db493e859d55e5ba12430a","src/btree/node.rs":"f6b4557d30ca0e30c7c7b6752c7a2c67432aab5c18c08392a28040326620a109","src/btree/search.rs":"ae78f73f3e56ea277b0a02cc39454447b75e12a6c817ecfee00065b3ddbfff67","src/btree/set.rs":"29cc3bff736007b21e14017d880edbcc7c76c30e0c256e811cae1fff0dad13fa","src/format.rs":"cee32d75cf260b19c8db74b50852bc50b8c47189d22b7424b647d084c4a76857","src/hashmap.rs":"cf02762085d9968fc235ef2c0626358661cb21aca2c8c19961b3969225c96dce","src/lib.rs":"deaf67958a1b8ae537a04a4eca3d424d20a6d9cf08cc9dfa2f6969a586976247","src/rc.rs":"102ad49f2201b9f69b50cf5a35af1e0039094936354b12572702551970c2f53c","src/try_clone.rs":"32c790435c71dec116756c284d2b953d382292b7727675740229a6b53d8c8b41","src/vec.rs":"95900e8d2f9a8902d5505e13c0d8ec17ac3ddc2ed8ae8f25b56962cdb4d8398c"},"package":"ba3301bcde54d3fc19c626ff4bf962630fe1f94cb6cdc3f18a26727a2d1f4a67"}

28
third_party/rust/fallible_collections/Cargo.toml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,28 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies
#
# If you believe there's an error in this file please file an
# issue against the rust-lang/cargo repository. If you're
# editing this file be aware that the upstream Cargo.toml
# will likely look very different (and much more reasonable)
[package]
edition = "2018"
name = "fallible_collections"
version = "0.1.3"
authors = ["vcombey <vcombey@student.42.fr>"]
description = "a crate which adds fallible allocation api to std collections"
readme = "README.md"
keywords = ["fallible", "collections"]
license = "MIT/Apache-2.0"
repository = "https://github.com/vcombey/fallible_collections.git"
[dependencies.hashbrown]
version = "0.7.1"
[features]
std_io = []
unstable = []

201
third_party/rust/fallible_collections/LICENSE-APACHE поставляемый Normal file
Просмотреть файл

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

25
third_party/rust/fallible_collections/LICENSE-MIT поставляемый Normal file
Просмотреть файл

@ -0,0 +1,25 @@
Copyright (c) 2010 The Rust Project Developers
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.

73
third_party/rust/fallible_collections/README.md поставляемый Normal file
Просмотреть файл

@ -0,0 +1,73 @@
Fallible Collections.rs
==============
Implement api on rust collection wich returns a result when an allocation error occurs.
This is inspired a lot by [RFC 2116](https://github.com/rust-lang/rfcs/blob/master/text/2116-alloc-me-maybe.md).
The api currently propose a fallible interface for Vec, Box, Arc, Btree and Rc,
a TryClone trait wich is implemented for primitive rust traits and a fallible format macro.
You can use this with try_clone_derive crate wich derive TryClone for your own types.
# Getting Started
[fallible collections is available on crates.io](https://crates.io/crates/fallible_collections).
It is recommended to look there for the newest released version, as well as links to the newest builds of the docs.
At the point of the last update of this README, the latest published version could be used like this:
Add the following dependency to your Cargo manifest...
```toml
[dependencies]
fallible_collections = "0.1.3"
```
...and see the [docs](https://docs.rs/fallible_collections) for how to use it.
# Example
Exemple of using the FallibleBox interface.
```rust
use fallible_collections::FallibleBox;
fn main() {
// this crate an Ordinary box but return an error on allocation failure
let mut a = Box::try_new(5).unwrap();
let mut b = Box::new(5);
assert_eq!(a, b);
*a = 3;
assert_eq!(*a, 3);
}
```
Exemple of using the FallibleVec interface.
```rust
use fallible_collections::FallibleVec;
fn main() {
// this crate an Ordinary Vec<Vec<u8>> but return an error on allocation failure
let a: Vec<Vec<u8>> = try_vec![try_vec![42; 10].unwrap(); 100].unwrap();
let b: Vec<Vec<u8>> = vec![vec![42; 10]; 100];
assert_eq!(a, b);
assert_eq!(a.try_clone().unwrap(), a);
...
}
```
## License
Licensed under either of
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.

46
third_party/rust/fallible_collections/src/arc.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,46 @@
//! Implement a Fallible Arc
use super::FallibleBox;
use super::TryClone;
use crate::TryReserveError;
use alloc::boxed::Box;
use alloc::sync::Arc;
/// trait to implement Fallible Arc
pub trait FallibleArc<T> {
/// try creating a new Arc, returning a Result<Box<T>,
/// TryReserveError> if allocation failed
fn try_new(t: T) -> Result<Self, TryReserveError>
where
Self: Sized;
}
impl<T> FallibleArc<T> for Arc<T> {
fn try_new(t: T) -> Result<Self, TryReserveError> {
// doesn't work as the inner variable of arc are also stocked in the box
let b = Box::try_new(t)?;
Ok(Arc::from(b))
}
}
/// Just a TryClone boilerplate for Arc
impl<T: ?Sized> TryClone for Arc<T> {
fn try_clone(&self) -> Result<Self, TryReserveError> {
Ok(self.clone())
}
}
#[cfg(test)]
mod test {
#[test]
fn fallible_rc() {
use std::sync::Arc;
let mut x = Arc::new(3);
*Arc::get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);
let _y = Arc::clone(&x);
assert!(Arc::get_mut(&mut x).is_none());
}
}

121
third_party/rust/fallible_collections/src/boxed.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,121 @@
//! Implement Fallible Box
use super::TryClone;
use crate::TryReserveError;
use alloc::alloc::Layout;
use alloc::boxed::Box;
use core::borrow::Borrow;
use core::ptr::NonNull;
/// trait to implement Fallible Box
pub trait FallibleBox<T> {
/// try creating a new box, returning a Result<Box<T>,
/// TryReserveError> if allocation failed
fn try_new(t: T) -> Result<Self, TryReserveError>
where
Self: Sized;
}
/// TryBox is a thin wrapper around alloc::boxed::Box to provide support for
/// fallible allocation.
///
/// See the crate documentation for more.
pub struct TryBox<T> {
inner: Box<T>,
}
impl<T> TryBox<T> {
pub fn try_new(t: T) -> Result<Self, TryReserveError> {
Ok(Self {
inner: Box::try_new(t)?,
})
}
pub fn into_raw(b: TryBox<T>) -> *mut T {
Box::into_raw(b.inner)
}
/// # Safety
///
/// See std::boxed::from_raw
pub unsafe fn from_raw(raw: *mut T) -> Self {
Self {
inner: Box::from_raw(raw),
}
}
}
impl<T: TryClone> TryClone for TryBox<T> {
fn try_clone(&self) -> Result<Self, TryReserveError> {
let clone: T = (*self.inner).try_clone()?;
Self::try_new(clone)
}
}
fn alloc(layout: Layout) -> Result<NonNull<u8>, TryReserveError> {
#[cfg(feature = "unstable")] // requires allocator_api
{
use core::alloc::AllocRef as _;
let mut g = alloc::alloc::Global;
g.alloc(layout, alloc::alloc::AllocInit::Uninitialized)
.map_err(|_e| TryReserveError::AllocError {
layout,
non_exhaustive: (),
})
.map(|memory_block| memory_block.ptr)
}
#[cfg(not(feature = "unstable"))]
{
match layout.size() {
0 => {
// Required for alloc safety
// See https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#safety-1
Ok(NonNull::dangling())
}
1..=core::usize::MAX => {
let ptr = unsafe { alloc::alloc::alloc(layout) };
core::ptr::NonNull::new(ptr).ok_or(TryReserveError::AllocErr { layout })
}
_ => unreachable!("size must be non-negative"),
}
}
}
impl<T> FallibleBox<T> for Box<T> {
fn try_new(t: T) -> Result<Self, TryReserveError> {
let layout = Layout::for_value(&t);
let ptr = alloc(layout)?.as_ptr() as *mut T;
unsafe {
core::ptr::write(ptr, t);
Ok(Box::from_raw(ptr))
}
}
}
impl<T: TryClone> TryClone for Box<T> {
fn try_clone(&self) -> Result<Self, TryReserveError> {
Self::try_new(Borrow::<T>::borrow(self).try_clone()?)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn boxed() {
let mut v = Box::try_new(5).unwrap();
assert_eq!(*v, 5);
*v = 3;
assert_eq!(*v, 3);
}
// #[test]
// fn big_alloc() {
// let layout = Layout::from_size_align(1_000_000_000_000, 8).unwrap();
// let ptr = unsafe { alloc::alloc::alloc(layout) };
// assert!(ptr.is_null());
// }
#[test]
fn trybox_zst() {
let b = Box::try_new(()).expect("ok");
assert_eq!(b, Box::new(()));
}
}

20
third_party/rust/fallible_collections/src/btree.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,20 @@
//! Implement Fallible Btree, As there is no try_reserve methods on btree, I add no choice but to fork the std implementation and change return types.
//! Currently this functionality is only available when building this crate with nightly and the `unstable` feature.
pub mod map;
pub use map::BTreeMap;
pub mod set;
pub use set::BTreeSet;
mod node;
mod search;
use crate::TryReserveError;
#[doc(hidden)]
trait Recover<Q: ?Sized> {
type Key;
fn get(&self, key: &Q) -> Option<&Self::Key>;
fn take(&mut self, key: &Q) -> Option<Self::Key>;
fn replace(&mut self, key: Self::Key) -> Result<Option<Self::Key>, TryReserveError>;
}

2642
third_party/rust/fallible_collections/src/btree/map.rs поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1673
third_party/rust/fallible_collections/src/btree/node.rs поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

66
third_party/rust/fallible_collections/src/btree/search.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,66 @@
use core::borrow::Borrow;
use core::cmp::Ordering;
use super::node::{marker, ForceResult::*, Handle, NodeRef};
use SearchResult::*;
pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>),
GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>),
}
pub fn search_tree<BorrowType, K, V, Q: ?Sized>(
mut node: NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
key: &Q,
) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
where
Q: Ord,
K: Borrow<Q>,
{
loop {
match search_node(node, key) {
Found(handle) => return Found(handle),
GoDown(handle) => match handle.force() {
Leaf(leaf) => return GoDown(leaf),
Internal(internal) => {
node = internal.descend();
continue;
}
},
}
}
}
pub fn search_node<BorrowType, K, V, Type, Q: ?Sized>(
node: NodeRef<BorrowType, K, V, Type>,
key: &Q,
) -> SearchResult<BorrowType, K, V, Type, Type>
where
Q: Ord,
K: Borrow<Q>,
{
match search_linear(&node, key) {
(idx, true) => Found(Handle::new_kv(node, idx)),
(idx, false) => SearchResult::GoDown(Handle::new_edge(node, idx)),
}
}
pub fn search_linear<BorrowType, K, V, Type, Q: ?Sized>(
node: &NodeRef<BorrowType, K, V, Type>,
key: &Q,
) -> (usize, bool)
where
Q: Ord,
K: Borrow<Q>,
{
for (i, k) in node.keys().iter().enumerate() {
match key.cmp(k.borrow()) {
Ordering::Greater => {}
Ordering::Equal => return (i, true),
Ordering::Less => return (i, false),
}
}
(node.keys().len(), false)
}

1306
third_party/rust/fallible_collections/src/btree/set.rs поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

47
third_party/rust/fallible_collections/src/format.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,47 @@
//! A try_format! macro replacing format!
use super::FallibleVec;
use crate::TryReserveError;
use alloc::fmt::{Arguments, Write};
use alloc::string::String;
use alloc::vec::Vec;
/// Take a max capacity a try allocating a string with it.
///
/// # Warning:
///
/// the max capacity must be > to the formating of the
/// arguments. If writing the argument on the string exceed the
/// capacity, no error is return and an allocation can occurs which
/// can lead to a panic
pub fn try_format(max_capacity: usize, args: Arguments<'_>) -> Result<String, TryReserveError> {
let v = Vec::try_with_capacity(max_capacity)?;
let mut s = String::from_utf8(v).expect("wtf an empty vec should be valid utf8");
s.write_fmt(args)
.expect("a formatting trait implementation returned an error");
Ok(s)
}
#[macro_export]
/// Take a max capacity a try allocating a string with it.
///
/// # Warning:
///
/// the max capacity must be > to the formating of the
/// arguments. If writing the argument on the string exceed the
/// capacity, no error is return and an allocation can occurs which
/// can lead to a panic
macro_rules! tryformat {
($max_capacity:tt, $($arg:tt)*) => (
$crate::format::try_format($max_capacity, format_args!($($arg)*))
)
}
#[cfg(test)]
mod tests {
#[test]
fn format() {
assert_eq!(tryformat!(1, "1").unwrap(), format!("1"));
assert_eq!(tryformat!(1, "{}", 1).unwrap(), format!("{}", 1));
assert_eq!(tryformat!(3, "{}", 123).unwrap(), format!("{}", 123));
}
}

66
third_party/rust/fallible_collections/src/hashmap.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,66 @@
//! Implement Fallible HashMap
use super::TryClone;
use crate::TryReserveError;
use core::default::Default;
use core::hash::Hash;
type HashMap<K, V> = hashbrown::hash_map::HashMap<K, V>;
#[derive(Default)]
pub struct TryHashMap<K, V> {
inner: HashMap<K, V>,
}
impl<K, V> TryHashMap<K, V>
where
K: Eq + Hash,
{
pub fn with_capacity(capacity: usize) -> Result<Self, TryReserveError> {
let mut map = Self {
inner: HashMap::new(),
};
map.reserve(capacity)?;
Ok(map)
}
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: core::borrow::Borrow<Q>,
Q: Hash + Eq,
{
self.inner.get(k)
}
pub fn insert(&mut self, k: K, v: V) -> Result<Option<V>, TryReserveError> {
self.reserve(if self.inner.capacity() == 0 { 4 } else { 1 })?;
Ok(self.inner.insert(k, v))
}
fn reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.inner.try_reserve(additional)
}
}
impl<K, V> TryClone for TryHashMap<K, V>
where
K: Eq + Hash + TryClone,
V: TryClone,
{
fn try_clone(&self) -> Result<Self, TryReserveError> {
let mut clone = Self::with_capacity(self.inner.len())?;
for (key, value) in self.inner.iter() {
clone.insert(key.try_clone()?, value.try_clone()?)?;
}
Ok(clone)
}
}
#[test]
fn tryhashmap_oom() {
match TryHashMap::<char, char>::default().reserve(core::usize::MAX) {
Ok(_) => panic!("it should be OOM"),
_ => (),
}
}

81
third_party/rust/fallible_collections/src/lib.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,81 @@
//! impl Fallible collections on allocation errors, quite as describe
//! in [RFC 2116](https://github.com/rust-lang/rfcs/blob/master/text/2116-alloc-me-maybe.md)
//! This was used in the turbofish OS hobby project to mitigate the
//! the lack of faillible allocation in rust.
//!
//! The `Try*` types in this module are thin wrappers around the stdlib types to add
//! support for fallible allocation. The API differences from the stdlib types ensure
//! that all operations which allocate return a `Result`. For the most part, this simply
//! means adding a `Result` return value to functions which return nothing or a
//! non-`Result` value. However, these types implement some traits whose API cannot
//! communicate failure, but which do require allocation, so it is important that these
//! wrapper types do not implement these traits.
//!
//! Specifically, these types must not implement any of the following traits:
//! - Clone
//! - Extend
//! - From
//! - FromIterator
//!
//! This list may not be exhaustive. Exercise caution when implementing
//! any new traits to ensure they won't potentially allocate in a way that
//! can't return a Result to indicate allocation failure.
#![cfg_attr(not(test), no_std)]
#![cfg_attr(feature = "unstable", feature(try_reserve))]
#![cfg_attr(feature = "unstable", feature(specialization))]
#![cfg_attr(feature = "unstable", feature(allocator_api))]
#![cfg_attr(feature = "unstable", feature(dropck_eyepatch))]
#![cfg_attr(feature = "unstable", feature(ptr_internals))]
#![cfg_attr(feature = "unstable", feature(core_intrinsics))]
#![cfg_attr(feature = "unstable", feature(maybe_uninit_ref))]
#![cfg_attr(feature = "unstable", feature(maybe_uninit_slice))]
#![cfg_attr(feature = "unstable", feature(maybe_uninit_extra))]
#![cfg_attr(feature = "unstable", feature(internal_uninit_const))]
extern crate alloc;
#[cfg(feature = "std_io")]
extern crate std;
pub mod boxed;
pub use boxed::*;
#[macro_use]
pub mod vec;
pub use vec::*;
pub mod rc;
pub use rc::*;
pub mod arc;
pub use arc::*;
#[cfg(feature = "unstable")]
pub mod btree;
#[cfg(not(feature = "unstable"))]
pub mod hashmap;
#[cfg(not(feature = "unstable"))]
pub use hashmap::*;
#[macro_use]
pub mod format;
pub mod try_clone;
#[cfg(feature = "unstable")]
pub use alloc::collections::TryReserveError;
#[cfg(not(feature = "unstable"))]
pub use hashbrown::CollectionAllocErr as TryReserveError;
#[cfg(feature = "std_io")]
pub use vec::std_io::*;
/// trait for trying to clone an elem, return an error instead of
/// panic if allocation failed
/// # Examples
///
/// ```
/// use fallible_collections::TryClone;
/// let mut vec = vec![42, 100];
/// assert_eq!(vec.try_clone().unwrap(), vec)
/// ```
pub trait TryClone {
/// try clone method, (Self must be sized because of Result
/// constraint)
fn try_clone(&self) -> Result<Self, TryReserveError>
where
Self: core::marker::Sized;
}

35
third_party/rust/fallible_collections/src/rc.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,35 @@
//! Implement a Fallible Rc
use super::FallibleBox;
use crate::TryReserveError;
use alloc::boxed::Box;
use alloc::rc::Rc;
/// trait to implement Fallible Rc
pub trait FallibleRc<T> {
/// try creating a new Rc, returning a Result<Box<T>,
/// TryReserveError> if allocation failed
fn try_new(t: T) -> Result<Self, TryReserveError>
where
Self: Sized;
}
impl<T> FallibleRc<T> for Rc<T> {
fn try_new(t: T) -> Result<Self, TryReserveError> {
let b = Box::try_new(t)?;
Ok(Rc::from(b))
}
}
#[cfg(test)]
mod test {
#[test]
fn fallible_rc() {
use std::rc::Rc;
let mut x = Rc::new(3);
*Rc::get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);
let _y = Rc::clone(&x);
assert!(Rc::get_mut(&mut x).is_none());
}
}

38
third_party/rust/fallible_collections/src/try_clone.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,38 @@
//! this module implements try clone for primitive rust types
use super::TryClone;
use crate::TryReserveError;
macro_rules! impl_try_clone {
($($e: ty),*) => {
$(impl TryClone for $e {
#[inline(always)]
fn try_clone(&self) -> Result<Self, TryReserveError>
where
Self: core::marker::Sized,
{
Ok(*self)
}
}
)*
}
}
impl_try_clone!(u8, u16, u32, u64, i8, i16, i32, i64, usize, isize, bool);
impl<T: TryClone> TryClone for Option<T> {
fn try_clone(&self) -> Result<Self, TryReserveError> {
Ok(match self {
Some(t) => Some(t.try_clone()?),
None => None,
})
}
}
// impl<T: Copy> TryClone for T {
// fn try_clone(&self) -> Result<Self, TryReserveError>
// where
// Self: core::marker::Sized,
// {
// Ok(*self)
// }
// }

864
third_party/rust/fallible_collections/src/vec.rs поставляемый Normal file
Просмотреть файл

@ -0,0 +1,864 @@
//! Implement Fallible Vec
use super::TryClone;
use crate::TryReserveError;
#[allow(unused_imports)]
use alloc::alloc::{alloc, realloc, Layout};
use alloc::vec::Vec;
use core::convert::TryInto as _;
#[cfg(feature = "unstable")]
#[macro_export]
/// macro trying to create a vec, return a
/// Result<Vec<T>,TryReserveError>
macro_rules! try_vec {
($elem:expr; $n:expr) => (
$crate::vec::try_from_elem($elem, $n)
);
($($x:expr),*) => (
match <alloc::boxed::Box<_> as $crate::boxed::FallibleBox<_>>::try_new([$($x),*]) {
Err(e) => Err(e),
Ok(b) => Ok(<[_]>::into_vec(b)),
}
);
($($x:expr,)*) => ($crate::try_vec![$($x),*])
}
/// trait implementing all fallible methods on vec
pub trait FallibleVec<T> {
/// see reserve
fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError>;
/// see push
fn try_push(&mut self, elem: T) -> Result<(), TryReserveError>;
/// try push and give back ownership in case of error
fn try_push_give_back(&mut self, elem: T) -> Result<(), (T, TryReserveError)>;
/// see with capacity, (Self must be sized by the constraint of Result)
fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError>
where
Self: core::marker::Sized;
/// see insert
fn try_insert(&mut self, index: usize, element: T) -> Result<(), (T, TryReserveError)>;
/// see append
fn try_append(&mut self, other: &mut Self) -> Result<(), TryReserveError>;
/// see resize, only works when the `value` implements Copy, otherwise, look at try_resize_no_copy
fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
where
T: Copy + Clone;
fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), TryReserveError>
where
F: FnMut() -> T;
/// resize the vec by trying to clone the value repeatingly
fn try_resize_no_copy(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
where
T: TryClone;
/// see resize, only works when the `value` implements Copy, otherwise, look at try_extend_from_slice_no_copy
fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError>
where
T: Copy + Clone;
/// extend the vec by trying to clone the value in `other`
fn try_extend_from_slice_no_copy(&mut self, other: &[T]) -> Result<(), TryReserveError>
where
T: TryClone;
}
/// TryVec is a thin wrapper around alloc::vec::Vec to provide support for
/// fallible allocation.
///
/// See the crate documentation for more.
#[derive(Default, PartialEq)]
pub struct TryVec<T> {
inner: Vec<T>,
}
impl<T: core::fmt::Debug> core::fmt::Debug for TryVec<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}", self.inner)
}
}
impl<T> TryVec<T> {
pub fn new() -> Self {
Self { inner: Vec::new() }
}
pub fn with_capacity(capacity: usize) -> Result<Self, TryReserveError> {
Ok(Self {
inner: FallibleVec::try_with_capacity(capacity)?,
})
}
pub fn append(&mut self, other: &mut Self) -> Result<(), TryReserveError> {
FallibleVec::try_append(&mut self.inner, &mut other.inner)
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
self
}
pub fn as_slice(&self) -> &[T] {
self
}
pub fn clear(&mut self) {
self.inner.clear()
}
#[cfg(test)]
pub fn into_inner(self) -> Vec<T> {
self.inner
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
inner: self.inner.iter_mut(),
}
}
pub fn iter(&self) -> Iter<T> {
Iter {
inner: self.inner.iter(),
}
}
pub fn pop(&mut self) -> Option<T> {
self.inner.pop()
}
pub fn push(&mut self, value: T) -> Result<(), TryReserveError> {
FallibleVec::try_push(&mut self.inner, value)
}
pub fn reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
FallibleVec::try_reserve(&mut self.inner, additional)
}
pub fn resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), TryReserveError>
where
F: FnMut() -> T,
{
FallibleVec::try_resize_with(&mut self.inner, new_len, f)
}
}
impl<T: TryClone> TryClone for TryVec<T> {
fn try_clone(&self) -> Result<Self, TryReserveError> {
self.as_slice().try_into()
}
}
impl<T: TryClone> TryVec<TryVec<T>> {
pub fn concat(&self) -> Result<TryVec<T>, TryReserveError> {
let size = self.iter().map(|v| v.inner.len()).sum();
let mut result = TryVec::with_capacity(size)?;
for v in self.iter() {
result.inner.try_extend_from_slice_no_copy(&v.inner)?;
}
Ok(result)
}
}
impl<T: TryClone> TryVec<T> {
pub fn extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError> {
self.inner.try_extend_from_slice_no_copy(other)
}
}
impl<T> IntoIterator for TryVec<T> {
type Item = T;
type IntoIter = alloc::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
impl<'a, T> IntoIterator for &'a TryVec<T> {
type Item = &'a T;
type IntoIter = alloc::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.inner.iter()
}
}
#[cfg(feature = "std_io")]
pub mod std_io {
use super::*;
use std::io::{self, Read, Take, Write};
pub trait TryRead {
fn try_read_to_end(&mut self, buf: &mut TryVec<u8>) -> io::Result<usize>;
fn read_into_try_vec(&mut self) -> io::Result<TryVec<u8>> {
let mut buf = TryVec::new();
self.try_read_to_end(&mut buf)?;
Ok(buf)
}
}
impl<T: Read> TryRead for Take<T> {
/// This function reserves the upper limit of what `src` can generate before
/// reading all bytes until EOF in this source, placing them into `buf`. If the
/// allocation is unsuccessful, or reading from the source generates an error
/// before reaching EOF, this will return an error. Otherwise, it will return
/// the number of bytes read.
///
/// Since `Take::limit()` may return a value greater than the number of bytes
/// which can be read from the source, it's possible this function may fail
/// in the allocation phase even though allocating the number of bytes available
/// to read would have succeeded. In general, it is assumed that the callers
/// have accurate knowledge of the number of bytes of interest and have created
/// `src` accordingly.
fn try_read_to_end(&mut self, buf: &mut TryVec<u8>) -> io::Result<usize> {
try_read_up_to(self, self.limit(), buf)
}
}
/// Read up to `limit` bytes from `src`, placing them into `buf` and returning the
/// number of bytes read. Space for `limit` additional bytes is reserved in `buf`, so
/// this function will return an error if the allocation fails.
pub fn try_read_up_to<R: Read>(
src: &mut R,
limit: u64,
buf: &mut TryVec<u8>,
) -> io::Result<usize> {
let additional = limit
.try_into()
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
buf.reserve(additional)
.map_err(|_| io::Error::new(io::ErrorKind::Other, "reserve allocation failed"))?;
let bytes_read = src.take(limit).read_to_end(&mut buf.inner)?;
Ok(bytes_read)
}
impl Write for TryVec<u8> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.extend_from_slice(buf)
.map_err(|_| io::Error::new(io::ErrorKind::Other, "extend_from_slice failed"))?;
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn try_read_to_end() {
let mut src = b"1234567890".take(5);
let mut buf = TryVec::new();
src.try_read_to_end(&mut buf).unwrap();
assert_eq!(buf.len(), 5);
assert_eq!(buf, b"12345".as_ref());
}
#[test]
fn read_into_try_vec() {
let mut src = b"1234567890".take(5);
let buf = src.read_into_try_vec().unwrap();
assert_eq!(buf.len(), 5);
assert_eq!(buf, b"12345".as_ref());
}
#[test]
fn read_into_try_vec_oom() {
let mut src = b"1234567890".take(core::usize::MAX.try_into().expect("usize < u64"));
assert!(src.read_into_try_vec().is_err());
}
#[test]
fn try_read_up_to() {
let src = b"1234567890";
let mut buf = TryVec::new();
super::try_read_up_to(&mut src.as_ref(), 5, &mut buf).unwrap();
assert_eq!(buf.len(), 5);
assert_eq!(buf, b"12345".as_ref());
}
#[test]
fn try_read_up_to_oom() {
let src = b"1234567890";
let mut buf = TryVec::new();
let limit = core::usize::MAX.try_into().expect("usize < u64");
let res = super::try_read_up_to(&mut src.as_ref(), limit, &mut buf);
assert!(res.is_err());
}
}
}
impl<T: PartialEq> PartialEq<Vec<T>> for TryVec<T> {
fn eq(&self, other: &Vec<T>) -> bool {
self.inner.eq(other)
}
}
impl<'a, T: PartialEq> PartialEq<&'a [T]> for TryVec<T> {
fn eq(&self, other: &&[T]) -> bool {
self.inner.eq(other)
}
}
impl PartialEq<&str> for TryVec<u8> {
fn eq(&self, other: &&str) -> bool {
self.as_slice() == other.as_bytes()
}
}
impl core::convert::AsRef<[u8]> for TryVec<u8> {
fn as_ref(&self) -> &[u8] {
self.inner.as_ref()
}
}
impl<T> core::convert::From<Vec<T>> for TryVec<T> {
fn from(value: Vec<T>) -> Self {
Self { inner: value }
}
}
impl<T: TryClone> core::convert::TryFrom<&[T]> for TryVec<T> {
type Error = TryReserveError;
fn try_from(value: &[T]) -> Result<Self, Self::Error> {
let mut v = Self::new();
v.inner.try_extend_from_slice_no_copy(value)?;
Ok(v)
}
}
impl core::convert::TryFrom<&str> for TryVec<u8> {
type Error = TryReserveError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let mut v = Self::new();
v.extend_from_slice(value.as_bytes())?;
Ok(v)
}
}
impl<T> core::ops::Deref for TryVec<T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.inner.deref()
}
}
impl<T> core::ops::DerefMut for TryVec<T> {
fn deref_mut(&mut self) -> &mut [T] {
self.inner.deref_mut()
}
}
pub struct Iter<'a, T> {
inner: alloc::slice::Iter<'a, T>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
pub struct IterMut<'a, T> {
inner: alloc::slice::IterMut<'a, T>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[cfg(not(feature = "unstable"))]
fn vec_try_reserve<T>(v: &mut Vec<T>, additional: usize) -> Result<(), TryReserveError> {
let available = v.capacity().checked_sub(v.len()).expect("capacity >= len");
if additional > available {
let increase = additional
.checked_sub(available)
.expect("additional > available");
let new_cap = v
.capacity()
.checked_add(increase)
.ok_or(TryReserveError::CapacityOverflow)?;
vec_try_extend(v, new_cap)?;
debug_assert!(v.capacity() == new_cap);
}
Ok(())
}
#[cfg(not(feature = "unstable"))]
fn vec_try_extend<T>(v: &mut Vec<T>, new_cap: usize) -> Result<(), TryReserveError> {
let old_len = v.len();
let old_cap: usize = v.capacity();
if old_cap >= new_cap {
return Ok(());
}
let elem_size = core::mem::size_of::<T>();
let new_alloc_size = new_cap
.checked_mul(elem_size)
.ok_or(TryReserveError::CapacityOverflow)?;
// required for alloc safety
// See https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#safety-1
// Should be unreachable given prior `old_cap >= new_cap` check.
assert!(new_alloc_size > 0);
let align = core::mem::align_of::<T>();
let (new_ptr, layout) = {
if old_cap == 0 {
let layout = Layout::from_size_align(new_alloc_size, align).expect("Invalid layout");
let new_ptr = unsafe { alloc(layout) };
(new_ptr, layout)
} else {
let old_alloc_size = old_cap
.checked_mul(elem_size)
.ok_or(TryReserveError::CapacityOverflow)?;
let layout = Layout::from_size_align(old_alloc_size, align).expect("Invalid layout");
let new_ptr = unsafe { realloc(v.as_mut_ptr() as *mut u8, layout, new_alloc_size) };
(new_ptr, layout)
}
};
if new_ptr.is_null() {
return Err(TryReserveError::AllocErr { layout });
}
let new_vec = unsafe { Vec::from_raw_parts(new_ptr.cast(), old_len, new_cap) };
core::mem::forget(core::mem::replace(v, new_vec));
Ok(())
}
impl<T> FallibleVec<T> for Vec<T> {
fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
#[cfg(feature = "unstable")]
{
self.try_reserve(additional)
}
#[cfg(not(feature = "unstable"))]
{
vec_try_reserve(self, additional)
}
}
fn try_push(&mut self, elem: T) -> Result<(), TryReserveError> {
FallibleVec::try_reserve(self, 1)?;
Ok(self.push(elem))
}
fn try_push_give_back(&mut self, elem: T) -> Result<(), (T, TryReserveError)> {
if let Err(e) = FallibleVec::try_reserve(self, 1) {
return Err((elem, e));
}
Ok(self.push(elem))
}
fn try_with_capacity(capacity: usize) -> Result<Self, TryReserveError>
where
Self: core::marker::Sized,
{
let mut n = Self::new();
FallibleVec::try_reserve(&mut n, capacity)?;
Ok(n)
}
fn try_insert(&mut self, index: usize, element: T) -> Result<(), (T, TryReserveError)> {
if let Err(e) = FallibleVec::try_reserve(self, 1) {
return Err((element, e));
}
Ok(self.insert(index, element))
}
fn try_append(&mut self, other: &mut Self) -> Result<(), TryReserveError> {
FallibleVec::try_reserve(self, other.len())?;
Ok(self.append(other))
}
fn try_resize(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
where
T: Copy + Clone,
{
let len = self.len();
if new_len > len {
FallibleVec::try_reserve(self, new_len - len)?;
}
Ok(self.resize(new_len, value))
}
fn try_resize_with<F>(&mut self, new_len: usize, f: F) -> Result<(), TryReserveError>
where
F: FnMut() -> T,
{
let len = self.len();
if new_len > len {
FallibleVec::try_reserve(self, new_len - len)?;
}
Ok(self.resize_with(new_len, f))
}
fn try_resize_no_copy(&mut self, new_len: usize, value: T) -> Result<(), TryReserveError>
where
T: TryClone,
{
let len = self.len();
if new_len > len {
self.try_extend_with(new_len - len, TryExtendElement(value))
} else {
Ok(self.truncate(new_len))
}
}
fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), TryReserveError>
where
T: Clone,
{
FallibleVec::try_reserve(self, other.len())?;
Ok(self.extend_from_slice(other))
}
fn try_extend_from_slice_no_copy(&mut self, other: &[T]) -> Result<(), TryReserveError>
where
T: TryClone,
{
let mut len = self.len();
FallibleVec::try_reserve(self, other.len())?;
let mut iterator = other.iter();
while let Some(element) = iterator.next() {
unsafe {
core::ptr::write(self.get_unchecked_mut(len), element.try_clone()?);
// NB can't overflow since we would have had to alloc the address space
len += 1;
self.set_len(len);
}
}
Ok(())
}
}
trait ExtendWith<T> {
fn next(&mut self) -> Result<T, TryReserveError>;
fn last(self) -> T;
}
struct TryExtendElement<T: TryClone>(T);
impl<T: TryClone> ExtendWith<T> for TryExtendElement<T> {
fn next(&mut self) -> Result<T, TryReserveError> {
self.0.try_clone()
}
fn last(self) -> T {
self.0
}
}
trait TryExtend<T> {
fn try_extend_with<E: ExtendWith<T>>(
&mut self,
n: usize,
value: E,
) -> Result<(), TryReserveError>;
}
impl<T> TryExtend<T> for Vec<T> {
/// Extend the vector by `n` values, using the given generator.
fn try_extend_with<E: ExtendWith<T>>(
&mut self,
n: usize,
mut value: E,
) -> Result<(), TryReserveError> {
FallibleVec::try_reserve(self, n)?;
unsafe {
let mut ptr = self.as_mut_ptr().add(self.len());
let mut local_len = self.len();
// Write all elements except the last one
for _ in 1..n {
core::ptr::write(ptr, value.next()?);
ptr = ptr.offset(1);
// Increment the length in every step in case next() panics
local_len += 1;
self.set_len(local_len);
}
if n > 0 {
// We can write the last element directly without cloning needlessly
core::ptr::write(ptr, value.last());
local_len += 1;
self.set_len(local_len);
}
// len set by scope guard
}
Ok(())
}
}
trait Truncate {
fn truncate(&mut self, len: usize);
}
impl<T> Truncate for Vec<T> {
fn truncate(&mut self, len: usize) {
let current_len = self.len();
unsafe {
let mut ptr = self.as_mut_ptr().add(current_len);
// Set the final length at the end, keeping in mind that
// dropping an element might panic. Works around a missed
// optimization, as seen in the following issue:
// https://github.com/rust-lang/rust/issues/51802
let mut local_len = self.len();
// drop any extra elements
for _ in len..current_len {
ptr = ptr.offset(-1);
core::ptr::drop_in_place(ptr);
local_len -= 1;
self.set_len(local_len);
}
}
}
}
/// try creating a vec from an `elem` cloned `n` times, see std::from_elem
#[cfg(feature = "unstable")]
pub fn try_from_elem<T: TryClone>(elem: T, n: usize) -> Result<Vec<T>, TryReserveError> {
<T as SpecFromElem>::try_from_elem(elem, n)
}
// Specialization trait used for Vec::from_elem
#[cfg(feature = "unstable")]
trait SpecFromElem: Sized {
fn try_from_elem(elem: Self, n: usize) -> Result<Vec<Self>, TryReserveError>;
}
#[cfg(feature = "unstable")]
impl<T: TryClone> SpecFromElem for T {
default fn try_from_elem(elem: Self, n: usize) -> Result<Vec<T>, TryReserveError> {
let mut v = Vec::new();
v.try_resize_no_copy(n, elem)?;
Ok(v)
}
}
#[cfg(feature = "unstable")]
impl SpecFromElem for u8 {
#[inline]
fn try_from_elem(elem: u8, n: usize) -> Result<Vec<u8>, TryReserveError> {
unsafe {
let mut v = Vec::try_with_capacity(n)?;
core::ptr::write_bytes(v.as_mut_ptr(), elem, n);
v.set_len(n);
Ok(v)
}
}
}
impl<T: TryClone> TryClone for Vec<T> {
fn try_clone(&self) -> Result<Self, TryReserveError>
where
Self: core::marker::Sized,
{
let mut v = Vec::new();
v.try_extend_from_slice_no_copy(self)?;
Ok(v)
}
}
pub trait TryFromIterator<I>: Sized {
fn try_from_iterator<T: IntoIterator<Item = I>>(iterator: T) -> Result<Self, TryReserveError>;
}
impl<I> TryFromIterator<I> for Vec<I> {
fn try_from_iterator<T: IntoIterator<Item = I>>(iterator: T) -> Result<Self, TryReserveError>
where
T: IntoIterator<Item = I>,
{
let mut new = Self::new();
for i in iterator {
new.try_push(i)?;
}
Ok(new)
}
}
pub trait TryCollect<I> {
fn try_collect<C: TryFromIterator<I>>(self) -> Result<C, TryReserveError>;
}
impl<I, T> TryCollect<I> for T
where
T: IntoIterator<Item = I>,
{
fn try_collect<C: TryFromIterator<I>>(self) -> Result<C, TryReserveError> {
C::try_from_iterator(self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[cfg(feature = "unstable")]
fn vec() {
// let v: Vec<u8> = from_elem(1, 10);
let v: Vec<Vec<u8>> = try_vec![try_vec![42; 10].unwrap(); 100].unwrap();
println!("{:?}", v);
let v2 = try_vec![0, 1, 2];
println!("{:?}", v2);
assert_eq!(2 + 2, 4);
}
#[test]
fn try_clone_vec() {
// let v: Vec<u8> = from_elem(1, 10);
let v = vec![42; 100];
assert_eq!(v.try_clone().unwrap(), v);
}
#[test]
fn try_clone_oom() {
let layout = Layout::new::<u8>();
let v =
unsafe { Vec::<u8>::from_raw_parts(alloc(layout), core::usize::MAX, core::usize::MAX) };
assert!(v.try_clone().is_err());
}
#[test]
fn tryvec_try_clone_oom() {
let layout = Layout::new::<u8>();
let inner =
unsafe { Vec::<u8>::from_raw_parts(alloc(layout), core::usize::MAX, core::usize::MAX) };
let tv = TryVec { inner };
assert!(tv.try_clone().is_err());
}
// #[test]
// fn try_out_of_mem() {
// let v = try_vec![42_u8; 1000000000];
// assert_eq!(v.try_clone().unwrap(), v);
// }
#[test]
fn oom() {
let mut vec: Vec<char> = Vec::new();
match FallibleVec::try_reserve(&mut vec, core::usize::MAX) {
Ok(_) => panic!("it should be OOM"),
_ => (),
}
}
#[test]
fn tryvec_oom() {
let mut vec: TryVec<char> = TryVec::new();
match vec.reserve(core::usize::MAX) {
Ok(_) => panic!("it should be OOM"),
_ => (),
}
}
#[test]
fn try_reserve() {
let mut vec: Vec<_> = vec![1];
let additional_room = vec.capacity() - vec.len();
let additional = additional_room + 1;
let old_cap = vec.capacity();
FallibleVec::try_reserve(&mut vec, additional).unwrap();
assert!(vec.capacity() > old_cap);
}
#[test]
fn tryvec_reserve() {
let mut vec: TryVec<_> = vec![1].into();
let old_cap = vec.inner.capacity();
let new_cap = old_cap + 1;
vec.reserve(new_cap).unwrap();
assert!(vec.inner.capacity() >= new_cap);
}
#[test]
fn try_reserve_idempotent() {
let mut vec: Vec<_> = vec![1];
let additional_room = vec.capacity() - vec.len();
let additional = additional_room + 1;
FallibleVec::try_reserve(&mut vec, additional).unwrap();
let cap_after_reserve = vec.capacity();
FallibleVec::try_reserve(&mut vec, additional).unwrap();
assert_eq!(vec.capacity(), cap_after_reserve);
}
#[test]
fn tryvec_reserve_idempotent() {
let mut vec: TryVec<_> = vec![1].into();
let old_cap = vec.inner.capacity();
let new_cap = old_cap + 1;
vec.reserve(new_cap).unwrap();
let cap_after_reserve = vec.inner.capacity();
vec.reserve(new_cap).unwrap();
assert_eq!(cap_after_reserve, vec.inner.capacity());
}
#[test]
fn capacity_overflow() {
let mut vec: Vec<_> = vec![1];
match FallibleVec::try_reserve(&mut vec, core::usize::MAX) {
Ok(_) => panic!("capacity calculation should overflow"),
_ => (),
}
}
#[test]
fn tryvec_capacity_overflow() {
let mut vec: TryVec<_> = vec![1].into();
match vec.reserve(core::usize::MAX) {
Ok(_) => panic!("capacity calculation should overflow"),
_ => (),
}
}
#[test]
fn extend_from_slice() {
let mut vec: Vec<u8> = b"foo".as_ref().into();
vec.try_extend_from_slice(b"bar").unwrap();
assert_eq!(vec, b"foobar".as_ref());
}
#[test]
fn tryvec_extend_from_slice() {
let mut vec: TryVec<u8> = b"foo".as_ref().try_into().unwrap();
vec.extend_from_slice(b"bar").unwrap();
assert_eq!(vec, b"foobar".as_ref());
}
#[test]
#[cfg(not(feature = "unstable"))]
fn try_extend_zst() {
let mut vec: Vec<()> = Vec::new();
assert_eq!(vec.capacity(), core::usize::MAX);
assert!(vec_try_extend(&mut vec, 10).is_ok());
assert!(vec_try_extend(&mut vec, core::usize::MAX).is_ok());
}
#[test]
fn try_reserve_zst() {
let mut vec: Vec<()> = Vec::new();
assert!(FallibleVec::try_reserve(&mut vec, core::usize::MAX).is_ok());
}
}

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"f48619a9cfbcfcaf657d6b1e4894d2c68afd4b1c620d42d6923f814611bf6186","src/boxes.rs":"5f84805435af90034075709867e02c74a198e26dc628a9fc95df034928ee5bbc","src/fallible.rs":"7dc89699f1e75433ab5c6bbd23807383b3b918fe572d41e68e5a270591b0a4ab","src/lib.rs":"ff16461743a5e09c2dc8ade092206e4c84ddcae061766b38d53eff6f94916b2e","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"f1a27e785d4006cd910ca3c48c8a972da1db9c9b4a67185f67a191ddc3c69328","tests/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"fd646ffd5fab8beed5949b87482048ba400438fa90860f86f357a7f6141dc649"},"package":null}
{"files":{"Cargo.toml":"3707c837d19aeefff4bf899274055db9cd1fd8c7dcbbd5067622acb0f25ddd1f","src/boxes.rs":"7f989f8e91d173f323db22a8748ea911dd143c6304f66ccaf6ebc97d68ca5536","src/lib.rs":"4d4152c72ef49ced0a467879c51ff9e2430f704cd13a8eea4dc891b5f5843280","src/macros.rs":"76c840f9299797527fe71aa5b378ffb01312767372b45cc62deddb19775400ae","src/tests.rs":"6c1b8822410f5410d991f553925d3591f9c7ce41891191da8b3da62e783ebb02","tests/bug-1655846.avif":"e0a5a06225800fadf05f5352503a4cec11af73eef705c43b4acab5f4a99dea50","tests/bug-1661347.avif":"31c26561e1d9eafb60f7c5968b82a0859d203d73f17f26b29276256acee12966","tests/overflow.rs":"16b591d8def1a155b3b997622f6ea255536870d99c3d8f97c51755b77a50de3c","tests/public.rs":"5ff2282b0f84f55e25e18dcca9acc5bffde806d885c897354e5f65292f295557"},"package":null}

7
third_party/rust/mp4parse/Cargo.toml поставляемый
Просмотреть файл

@ -27,6 +27,7 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" }
[dependencies]
byteorder = "1.2.1"
bitreader = { version = "0.3.2" }
fallible_collections = { version = "0.1.3", features = ["std_io"] }
hashbrown = "0.7.1"
num-traits = "=0.2.10"
log = "0.4"
@ -36,9 +37,3 @@ static_assertions = "1.1.0"
test-assembler = "0.1.2"
env_logger = "0.7.1"
walkdir = "2.3.1"
[features]
# Enable mp4parse_fallible to use fallible memory allocation rather than
# panicking on OOM. Note that this is only safe within Gecko where the system
# allocator has been globally overridden (see BMO 1457359).
mp4parse_fallible = []

9
third_party/rust/mp4parse/src/boxes.rs поставляемый
Просмотреть файл

@ -44,7 +44,7 @@ macro_rules! box_database {
impl fmt::Debug for BoxType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let fourcc: FourCC = From::from(self.clone());
write!(f, "{}", fourcc)
fourcc.fmt(f)
}
}
}
@ -79,7 +79,7 @@ impl From<[u8; 4]> for FourCC {
impl fmt::Debug for FourCC {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match std::str::from_utf8(&self.value) {
Ok(s) => write!(f, "{}", s),
Ok(s) => f.write_str(s),
Err(_) => self.value.fmt(f),
}
}
@ -87,10 +87,7 @@ impl fmt::Debug for FourCC {
impl fmt::Display for FourCC {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match std::str::from_utf8(&self.value) {
Ok(s) => write!(f, "{}", s),
Err(_) => write!(f, "null"),
}
f.write_str(std::str::from_utf8(&self.value).unwrap_or("null"))
}
}

520
third_party/rust/mp4parse/src/fallible.rs поставляемый
Просмотреть файл

@ -1,520 +0,0 @@
//! The types in this module are thin wrappers around the stdlib types to add
//! support for fallible allocation. Though the fallible allocator is only
//! enabled with the mp4parse_fallible feature, the API differences from the
//! stdlib types ensure that all operations which allocate return a Result.
//! For the most part, this simply means adding a Result return value to
//! functions which return nothing or a non-Result value. However, these types
//! implement some traits whose API cannot communicate failure, but which do
//! require allocation, so it is important that these wrapper types do not
//! implement these traits.
//!
//! Specifically, do not implement any of the following traits:
//! - Clone
//! - Extend
//! - From
//! - FromIterator
//!
//! This list may not be exhaustive. Exercise caution when implementing
//! any new traits to ensure they won't potentially allocate in a way that
//! can't return a Result to indicate allocation failure.
#[cfg(feature = "mp4parse_fallible")]
extern "C" {
fn malloc(bytes: usize) -> *mut u8;
fn realloc(ptr: *mut u8, bytes: usize) -> *mut u8;
}
use std::convert::TryInto as _;
use std::hash::Hash;
use std::io::Read;
use std::io::Take;
use std::iter::IntoIterator;
use BMFFBox;
type Result<T> = std::result::Result<T, super::Error>;
pub trait TryRead {
fn try_read_to_end(&mut self, buf: &mut TryVec<u8>) -> Result<usize>;
fn read_into_try_vec(&mut self) -> Result<TryVec<u8>> {
let mut buf = TryVec::new();
let _ = self.try_read_to_end(&mut buf)?;
Ok(buf)
}
}
impl<'a, T: Read> TryRead for BMFFBox<'a, T> {
fn try_read_to_end(&mut self, buf: &mut TryVec<u8>) -> Result<usize> {
try_read_up_to(self, self.bytes_left(), buf)
}
}
impl<T: Read> TryRead for Take<T> {
/// With the `mp4parse_fallible` feature enabled, this function reserves the
/// upper limit of what `src` can generate before reading all bytes until EOF
/// in this source, placing them into buf. If the allocation is unsuccessful,
/// or reading from the source generates an error before reaching EOF, this
/// will return an error. Otherwise, it will return the number of bytes read.
///
/// Since `Take::limit()` may return a value greater than the number of bytes
/// which can be read from the source, it's possible this function may fail
/// in the allocation phase even though allocating the number of bytes available
/// to read would have succeeded. In general, it is assumed that the callers
/// have accurate knowledge of the number of bytes of interest and have created
/// `src` accordingly.
///
/// With the `mp4parse_fallible` feature disabled, this is essentially a wrapper
/// around `std::io::Read::read_to_end()`.
fn try_read_to_end(&mut self, buf: &mut TryVec<u8>) -> Result<usize> {
try_read_up_to(self, self.limit(), buf)
}
}
fn try_read_up_to<R: Read>(src: &mut R, limit: u64, buf: &mut TryVec<u8>) -> Result<usize> {
let additional = limit.try_into()?;
buf.reserve(additional)?;
let bytes_read = src.read_to_end(&mut buf.inner)?;
Ok(bytes_read)
}
/// TryBox is a thin wrapper around std::boxed::Box to provide support for
/// fallible allocation.
///
/// See the `fallible` module documentation for more.
pub struct TryBox<T> {
inner: std::boxed::Box<T>,
}
impl<T> TryBox<T> {
pub fn try_new(x: T) -> Result<Self> {
let inner;
#[cfg(feature = "mp4parse_fallible")]
{
let size = std::mem::size_of::<T>();
let new_ptr = unsafe { malloc(size) as *mut T };
if new_ptr.is_null() {
return Err(super::Error::OutOfMemory);
}
// If we did a simple assignment: *new_ptr = x, then the value
// pointed to by new_ptr would immediately be dropped, but
// that would cause an invalid memory access. Instead, we use
// replace() to avoid the immediate drop and forget() to
// ensure that drop never happens.
inner = unsafe {
std::mem::forget(std::mem::replace(&mut *new_ptr, x));
Box::from_raw(new_ptr)
};
}
#[cfg(not(feature = "mp4parse_fallible"))]
{
inner = Box::new(x);
}
Ok(Self { inner })
}
pub fn into_raw(b: TryBox<T>) -> *mut T {
Box::into_raw(b.inner)
}
/// # Safety
///
/// See std::boxed::from_raw
pub unsafe fn from_raw(raw: *mut T) -> Self {
Self {
inner: Box::from_raw(raw),
}
}
}
/// TryHashMap is a thin wrapper around the hashbrown HashMap to provide
/// support for fallible allocation. This is the same library that stdlib
/// currently uses, but we use it directly since it provides try_reserve().
///
/// See the `fallible` module documentation for more.
#[derive(Default)]
pub struct TryHashMap<K, V> {
inner: hashbrown::hash_map::HashMap<K, V>,
}
impl<K, V> TryHashMap<K, V>
where
K: Eq + Hash,
{
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: std::borrow::Borrow<Q>,
Q: Hash + Eq,
{
self.inner.get(k)
}
pub fn insert(&mut self, k: K, v: V) -> Result<Option<V>> {
self.reserve(if self.inner.capacity() == 0 { 4 } else { 1 })?;
Ok(self.inner.insert(k, v))
}
fn reserve(&mut self, additional: usize) -> Result<()> {
#[cfg(feature = "mp4parse_fallible")]
{
self.inner
.try_reserve(additional)
.map_err(|_| super::Error::OutOfMemory)
}
#[cfg(not(feature = "mp4parse_fallible"))]
{
self.inner.reserve(additional);
Ok(())
}
}
}
#[test]
#[cfg(feature = "mp4parse_fallible")]
fn tryhashmap_oom() {
match TryHashMap::<char, char>::default().reserve(std::usize::MAX) {
Ok(_) => panic!("it should be OOM"),
_ => (),
}
}
#[derive(Default, PartialEq)]
pub struct TryVec<T> {
inner: std::vec::Vec<T>,
}
impl<T: std::fmt::Debug> std::fmt::Debug for TryVec<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.inner)
}
}
/// TryVec is a thin wrapper around std::vec::Vec to provide support for
/// fallible allocation.
///
/// See the `fallible` module documentation for more.
impl<T> TryVec<T> {
pub fn new() -> Self {
Self { inner: Vec::new() }
}
pub fn with_capacity(capacity: usize) -> Result<Self> {
let mut v = Self::new();
v.reserve(capacity)?;
Ok(v)
}
pub fn append(&mut self, other: &mut Self) -> Result<()> {
self.reserve(other.inner.len())?;
self.inner.append(&mut other.inner);
Ok(())
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
self
}
pub fn as_slice(&self) -> &[T] {
self
}
pub fn clear(&mut self) {
self.inner.clear()
}
#[cfg(test)]
pub fn into_inner(self) -> Vec<T> {
self.inner
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut {
inner: self.inner.iter_mut(),
}
}
pub fn iter(&self) -> Iter<T> {
Iter {
inner: self.inner.iter(),
}
}
pub fn pop(&mut self) -> Option<T> {
self.inner.pop()
}
pub fn push(&mut self, value: T) -> Result<()> {
self.reserve(if self.inner.capacity() == 0 { 4 } else { 1 })?;
self.inner.push(value);
Ok(())
}
pub fn reserve(&mut self, additional: usize) -> Result<()> {
#[cfg(feature = "mp4parse_fallible")]
{
let available = self
.inner
.capacity()
.checked_sub(self.inner.len())
.expect("capacity >= len");
if additional > available {
let increase = additional
.checked_sub(available)
.expect("additional > available");
let new_cap = self
.inner
.capacity()
.checked_add(increase)
.ok_or(super::Error::OutOfMemory)?;
self.try_extend(new_cap)?;
debug_assert!(self.inner.capacity() == new_cap);
}
Ok(())
}
#[cfg(not(feature = "mp4parse_fallible"))]
{
self.inner.reserve(additional);
Ok(())
}
}
pub fn resize_with<F>(&mut self, new_len: usize, f: F) -> Result<()>
where
F: FnMut() -> T,
{
self.reserve(new_len)?;
self.inner.resize_with(new_len, f);
Ok(())
}
#[cfg(feature = "mp4parse_fallible")]
fn try_extend(&mut self, new_cap: usize) -> Result<()> {
let old_ptr = self.as_mut_ptr();
let old_len = self.inner.len();
let old_cap: usize = self.inner.capacity();
if old_cap >= new_cap {
return Ok(());
}
let new_size_bytes = new_cap
.checked_mul(std::mem::size_of::<T>())
.ok_or(super::Error::OutOfMemory)?;
let new_ptr = unsafe {
if old_cap == 0 {
malloc(new_size_bytes)
} else {
realloc(old_ptr as *mut u8, new_size_bytes)
}
};
if new_ptr.is_null() {
return Err(super::Error::OutOfMemory);
}
let new_vec = unsafe { Vec::from_raw_parts(new_ptr as *mut T, old_len, new_cap) };
std::mem::forget(std::mem::replace(&mut self.inner, new_vec));
Ok(())
}
}
impl<T: Clone> TryVec<TryVec<T>> {
pub fn concat(&self) -> Result<TryVec<T>> {
let size = self.iter().map(|v| v.inner.len()).sum();
let mut result = TryVec::with_capacity(size)?;
for v in self.iter() {
result.extend_from_slice(&v.inner)?;
}
Ok(result)
}
}
impl<T: Clone> TryVec<T> {
pub fn extend_from_slice(&mut self, other: &[T]) -> Result<()> {
self.reserve(other.len())?;
self.inner.extend_from_slice(other);
Ok(())
}
}
#[test]
#[cfg(feature = "mp4parse_fallible")]
fn oom() {
let mut vec: TryVec<char> = TryVec::new();
match vec.reserve(std::usize::MAX) {
Ok(_) => panic!("it should be OOM"),
_ => (),
}
}
#[test]
fn try_reserve() {
let mut vec: TryVec<_> = vec![1].into();
let old_cap = vec.inner.capacity();
let new_cap = old_cap + 1;
vec.reserve(new_cap).unwrap();
assert!(vec.inner.capacity() >= new_cap);
}
#[test]
fn try_reserve_idempotent() {
let mut vec: TryVec<_> = vec![1].into();
let old_cap = vec.inner.capacity();
let new_cap = old_cap + 1;
vec.reserve(new_cap).unwrap();
let cap_after_reserve = vec.inner.capacity();
vec.reserve(new_cap).unwrap();
assert_eq!(cap_after_reserve, vec.inner.capacity());
}
#[test]
#[cfg(feature = "mp4parse_fallible")]
fn capacity_overflow() {
let mut vec: TryVec<_> = vec![1].into();
match vec.reserve(std::usize::MAX) {
Ok(_) => panic!("capacity calculation should overflow"),
_ => (),
}
}
#[test]
fn extend_from_slice() {
let mut vec: TryVec<u8> = b"foo".as_ref().try_into().unwrap();
vec.extend_from_slice(b"bar").unwrap();
assert_eq!(vec, b"foobar".as_ref());
}
impl<T> IntoIterator for TryVec<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.inner.into_iter()
}
}
impl<'a, T> IntoIterator for &'a TryVec<T> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.inner.iter()
}
}
impl std::io::Write for TryVec<u8> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.extend_from_slice(buf)?;
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
impl<T: PartialEq> PartialEq<Vec<T>> for TryVec<T> {
fn eq(&self, other: &Vec<T>) -> bool {
self.inner.eq(other)
}
}
impl<'a, T: PartialEq> PartialEq<&'a [T]> for TryVec<T> {
fn eq(&self, other: &&[T]) -> bool {
self.inner.eq(other)
}
}
impl PartialEq<&str> for TryVec<u8> {
fn eq(&self, other: &&str) -> bool {
self.as_slice() == other.as_bytes()
}
}
impl std::convert::AsRef<[u8]> for TryVec<u8> {
fn as_ref(&self) -> &[u8] {
self.inner.as_ref()
}
}
impl<T> std::convert::From<Vec<T>> for TryVec<T> {
fn from(value: Vec<T>) -> Self {
Self { inner: value }
}
}
impl<T: Clone> std::convert::TryFrom<&[T]> for TryVec<T> {
type Error = super::Error;
fn try_from(value: &[T]) -> Result<Self> {
let mut v = Self::new();
v.extend_from_slice(value)?;
Ok(v)
}
}
impl std::convert::TryFrom<&str> for TryVec<u8> {
type Error = super::Error;
fn try_from(value: &str) -> Result<Self> {
let mut v = Self::new();
v.extend_from_slice(value.as_bytes())?;
Ok(v)
}
}
impl<T> std::ops::Deref for TryVec<T> {
type Target = [T];
fn deref(&self) -> &[T] {
self.inner.deref()
}
}
impl<T> std::ops::DerefMut for TryVec<T> {
fn deref_mut(&mut self) -> &mut [T] {
self.inner.deref_mut()
}
}
pub struct Iter<'a, T> {
inner: std::slice::Iter<'a, T>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
pub struct IterMut<'a, T> {
inner: std::slice::IterMut<'a, T>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}

37
third_party/rust/mp4parse/src/lib.rs поставляемый
Просмотреть файл

@ -9,10 +9,11 @@ extern crate log;
extern crate bitreader;
extern crate byteorder;
extern crate fallible_collections;
extern crate num_traits;
use bitreader::{BitReader, ReadInto};
use byteorder::{ReadBytesExt, WriteBytesExt};
use fallible::TryRead as _;
use fallible_collections::TryRead;
use num_traits::Num;
use std::convert::{TryFrom, TryInto as _};
use std::io::Cursor;
@ -25,8 +26,6 @@ mod macros;
mod boxes;
use boxes::{BoxType, FourCC};
mod fallible;
// Unit tests.
#[cfg(test)]
mod tests;
@ -119,14 +118,10 @@ impl<'a, T: Read> Read for OffsetReader<'a, T> {
}
}
// TODO: all the functions that rely on the mp4parse_fallible feature need to
// be updated when Rust supports fallible memory allocation in raw_vec.
// See https://github.com/mozilla/mp4parse-rust/issues/146
pub type TryVec<T> = fallible::TryVec<T>;
pub type TryString = TryVec<u8>;
pub type TryHashMap<K, V> = fallible::TryHashMap<K, V>;
pub type TryBox<T> = fallible::TryBox<T>;
pub type TryVec<T> = fallible_collections::TryVec<T>;
pub type TryString = fallible_collections::TryVec<u8>;
pub type TryHashMap<K, V> = fallible_collections::TryHashMap<K, V>;
pub type TryBox<T> = fallible_collections::TryBox<T>;
// To ensure we don't use stdlib allocating types by accident
#[allow(dead_code)]
@ -205,6 +200,12 @@ impl From<Error> for std::io::Error {
}
}
impl From<fallible_collections::TryReserveError> for Error {
fn from(_: fallible_collections::TryReserveError) -> Error {
Error::OutOfMemory
}
}
/// Result shorthand using our Error enum.
pub type Result<T> = std::result::Result<T, Error>;
@ -1050,6 +1051,12 @@ impl<'a, T: Read> Read for BMFFBox<'a, T> {
}
}
impl<'a, T: Read> TryRead for BMFFBox<'a, T> {
fn try_read_to_end(&mut self, buf: &mut TryVec<u8>) -> std::io::Result<usize> {
fallible_collections::try_read_up_to(self, self.bytes_left(), buf)
}
}
impl<'a, T: Offset> Offset for BMFFBox<'a, T> {
fn offset(&self) -> u64 {
self.content.get_ref().offset()
@ -1318,7 +1325,11 @@ pub fn read_avif<T: Read>(f: &mut T, context: &mut AvifContext) -> Result<()> {
context.primary_item = primary_item_extents_data.concat()?;
Ok(())
if primary_item_extents_data.iter().any(TryVec::is_empty) {
Err(Error::InvalidData("Primary item data incomplete"))
} else {
Ok(())
}
}
/// Parse a metadata box in the context of an AVIF
@ -1455,7 +1466,7 @@ struct U32BE(u32);
impl std::fmt::Display for U32BE {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match std::str::from_utf8(&self.0.to_be_bytes()) {
Ok(s) => write!(f, "{}", s),
Ok(s) => f.write_str(s),
Err(_) => write!(f, "{:x?}", self.0),
}
}

6
third_party/rust/mp4parse/src/tests.rs поставляемый
Просмотреть файл

@ -5,12 +5,11 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
use super::fallible::TryRead as _;
use super::read_mp4;
use super::Error;
use super::MediaContext;
use fallible_collections::TryRead as _;
#[cfg(feature = "mp4parse_fallible")]
use std::convert::TryInto as _;
use std::io::Cursor;
use std::io::Read as _;
@ -1297,11 +1296,10 @@ fn read_to_end_() {
let mut src = b"1234567890".take(5);
let buf = src.read_into_try_vec().unwrap();
assert_eq!(buf.len(), 5);
assert_eq!(buf.into_inner(), b"12345");
assert_eq!(buf, b"12345".as_ref());
}
#[test]
#[cfg(feature = "mp4parse_fallible")]
fn read_to_end_oom() {
let mut src = b"1234567890".take(std::usize::MAX.try_into().expect("usize < u64"));
assert!(src.read_into_try_vec().is_err());

Двоичные данные
third_party/rust/mp4parse/tests/bug-1661347.avif поставляемый Normal file

Двоичный файл не отображается.

8
third_party/rust/mp4parse/tests/public.rs поставляемый
Просмотреть файл

@ -29,6 +29,7 @@ static VIDEO_EME_CBCS_MP4: &str = "tests/bipbop_cbcs_video_init.mp4";
static VIDEO_AV1_MP4: &str = "tests/tiny_av1.mp4";
static IMAGE_AVIF: &str = "av1-avif/testFiles/Microsoft/Monochrome.avif";
static IMAGE_AVIF_CORRUPT: &str = "tests/bug-1655846.avif";
static IMAGE_AVIF_CORRUPT_2: &str = "tests/bug-1661347.avif";
static IMAGE_AVIF_GRID: &str = "av1-avif/testFiles/Microsoft/Summer_in_Tomsk_720p_5x4_grid.avif";
static AVIF_TEST_DIR: &str = "av1-avif/testFiles";
@ -635,6 +636,13 @@ fn public_avif_bug_1655846() {
assert!(mp4::read_avif(input, context).is_err());
}
#[test]
fn public_avif_bug_1661347() {
let context = &mut mp4::AvifContext::new();
let input = &mut File::open(IMAGE_AVIF_CORRUPT_2).expect("Unknown file");
assert!(mp4::read_avif(input, context).is_err());
}
#[test]
#[ignore] // Remove when we add support; see https://github.com/mozilla/mp4parse-rust/issues/198
fn public_avif_primary_item_is_grid() {

Просмотреть файл

@ -1 +1 @@
{"files":{"Cargo.toml":"12f3f7561fa1d5facc70b63b68288997ca6fde3dd5d6fabcfe2e7d8ec5940ab2","cbindgen.toml":"5c9429f271d6e914d81b63e6509c04ffe84cab11ed3a53a2ed4715e5d5ace80e","examples/dump.rs":"83462422315c22e496960bae922edb23105c0aa272d2b106edd7574ff068513a","src/lib.rs":"e90c6bdfcf321115b19f0148b5f273c9516bc7dfdae16c7c01a76ba8be51dad3","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"ca98516ff423c03b5fcc17b05f993f13b32485e4cf3ba86faf1bea72681d75ce","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"185755909b2f4e0ea99604bb423a07623d614a180accdaebd1c98aef2c2e3ae6","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null}
{"files":{"Cargo.toml":"589072f91823f3ae58e4ccf0c2fc756c6512921497d8df648049ad620233059c","cbindgen.toml":"5c9429f271d6e914d81b63e6509c04ffe84cab11ed3a53a2ed4715e5d5ace80e","examples/dump.rs":"83462422315c22e496960bae922edb23105c0aa272d2b106edd7574ff068513a","src/lib.rs":"76fb7cd35bbe56463d43f452fd7ebaf5b4619bd661fb71fb45f69e980877b424","tests/test_chunk_out_of_range.rs":"b5da583218d98027ed973a29c67434a91a1306f2d2fb39ec4d640d4824c308ce","tests/test_encryption.rs":"ca98516ff423c03b5fcc17b05f993f13b32485e4cf3ba86faf1bea72681d75ce","tests/test_fragment.rs":"e90eb5a4418d30002655466c0c4b3125c7fd70a74b6871471eaa172f1def9db8","tests/test_rotation.rs":"fb43c2f2dfa496d151c33bdd46c0fd3252387c23cc71e2cac9ed0234de715a81","tests/test_sample_table.rs":"185755909b2f4e0ea99604bb423a07623d614a180accdaebd1c98aef2c2e3ae6","tests/test_workaround_stsc.rs":"7dd419f3d55b9a3a039cac57e58a9240a9c8166bcd4356c24f69f731c3ced83b"},"package":null}

8
third_party/rust/mp4parse_capi/Cargo.toml поставляемый
Просмотреть файл

@ -24,16 +24,10 @@ travis-ci = { repository = "https://github.com/mozilla/mp4parse-rust" }
[dependencies]
byteorder = "1.2.1"
fallible_collections = { version = "0.1.3", features = ["std_io"] }
log = "0.4"
mp4parse = {version = "0.11.2", path = "../mp4parse"}
num-traits = "=0.2.10"
[dev-dependencies]
env_logger = "0.7.1"
[features]
# Enable mp4parse_fallible to use fallible memory allocation rather than
# panicking on OOM. Note that this is only safe within Gecko where the system
# allocator has been globally overridden (see BMO 1457359).
mp4parse_fallible = ["mp4parse/mp4parse_fallible"]

9
third_party/rust/mp4parse_capi/src/lib.rs поставляемый
Просмотреть файл

@ -36,6 +36,7 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
extern crate byteorder;
extern crate log;
extern crate mp4parse;
extern crate num_traits;
@ -600,7 +601,7 @@ fn mp4parse_new_common_safe<T: Read, P: ContextParser>(
P::read(io, &mut context)
.map(|_| P::with_context(context))
.and_then(TryBox::try_new)
.and_then(|x| TryBox::try_new(x).map_err(mp4parse::Error::from))
.map(TryBox::into_raw)
.map_err(Mp4parseStatus::from)
}
@ -632,6 +633,12 @@ impl From<Result<(), Mp4parseStatus>> for Mp4parseStatus {
}
}
impl From<fallible_collections::TryReserveError> for Mp4parseStatus {
fn from(_: fallible_collections::TryReserveError) -> Self {
Mp4parseStatus::Oom
}
}
/// Free an `Mp4parseParser*` allocated by `mp4parse_new()`.
///
/// # Safety

Просмотреть файл

@ -9,7 +9,7 @@ description = "Shared Rust code for libxul"
geckoservo = { path = "../../../../servo/ports/geckolib" }
kvstore = { path = "../../../components/kvstore" }
lmdb-rkv-sys = { version = "0.11", features = ["mdb_idl_logn_9"] }
mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "d5a37fd0bd51e06a53274c68213b00136aba83a6" }
mp4parse_capi = { git = "https://github.com/mozilla/mp4parse-rust", rev = "fe9028570e44f3a725dd78bbb58428909c4618bf" }
nserror = { path = "../../../../xpcom/rust/nserror" }
nsstring = { path = "../../../../xpcom/rust/nsstring" }
netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }
@ -83,7 +83,7 @@ cubeb_pulse_rust = ["cubeb-sys", "cubeb-pulse"]
gecko_debug = ["geckoservo/gecko_debug", "nsstring/gecko_debug"]
gecko_refcount_logging = ["geckoservo/gecko_refcount_logging"]
simd-accel = ["encoding_glue/simd-accel", "jsrust_shared/simd-accel"]
moz_memory = ["mp4parse_capi/mp4parse_fallible"]
moz_memory = []
moz_places = ["bookmark_sync"]
spidermonkey_rust = ["jsrust_shared/baldrdash"]
cranelift_x86 = ["jsrust_shared/cranelift_x86"]