mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 13:51:41 +00:00
Backed out 2 changesets (bug 1475197) for causing linux build bustages because of compile errors.
Backed out changeset 108e22d963cb (bug 1475197) Backed out changeset 4bd5f8588422 (bug 1475197)
This commit is contained in:
parent
103876749a
commit
fdafc33d90
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -1151,7 +1151,6 @@ dependencies = [
|
||||
"servo_arc 0.1.1",
|
||||
"smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thin-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1821,7 +1820,6 @@ dependencies = [
|
||||
"precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"servo_arc 0.1.1",
|
||||
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thin-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1989,7 +1987,6 @@ dependencies = [
|
||||
"smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"style_derive 0.0.1",
|
||||
"style_traits 0.0.1",
|
||||
"thin-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2119,11 +2116,6 @@ dependencies = [
|
||||
"unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thin-slice"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.5"
|
||||
@ -2745,7 +2737,6 @@ dependencies = [
|
||||
"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
|
||||
"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum thin-slice 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85b3e41c2cf31e81a7ec4ad3acd69abde19887e0f7f8e74dcdedc8cb7b158ef8"
|
||||
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
|
||||
"checksum thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf947d192a9be60ef5131cc7a4648886ba89d712f16700ebbf80c8a69d05d48f"
|
||||
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
|
||||
|
@ -303,14 +303,6 @@ function run() {
|
||||
// [attr] selector
|
||||
test_parseable("[attr]")
|
||||
test_parseable_via_api("[attr");
|
||||
test_parseable("[ATTR]")
|
||||
should_serialize_to("[attr]", "[attr]");
|
||||
should_serialize_to("[ATTR]", "[ATTR]");
|
||||
|
||||
// Whether we should drop the bar is debatable. This matches Edge
|
||||
// and Safari at the time of writing.
|
||||
should_serialize_to("[|attr]", "[attr]");
|
||||
should_serialize_to("[|ATTR]", "[ATTR]");
|
||||
|
||||
// [attr= ] selector
|
||||
test_parseable("[attr=\"x\"]");
|
||||
|
@ -37,7 +37,6 @@ servo_arc = { path = "../servo_arc" }
|
||||
smallbitvec = "2.1.0"
|
||||
smallvec = "0.6"
|
||||
string_cache = { version = "0.7", optional = true }
|
||||
thin-slice = "0.1.0"
|
||||
time = { version = "0.1.17", optional = true }
|
||||
url = { version = "1.2", optional = true }
|
||||
webrender_api = { git = "https://github.com/servo/webrender", features = ["ipc"], optional = true }
|
||||
|
@ -63,7 +63,6 @@ extern crate smallbitvec;
|
||||
extern crate smallvec;
|
||||
#[cfg(feature = "servo")]
|
||||
extern crate string_cache;
|
||||
extern crate thin_slice;
|
||||
#[cfg(feature = "servo")]
|
||||
extern crate time;
|
||||
#[cfg(feature = "url")]
|
||||
@ -232,24 +231,6 @@ impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MallocShallowSizeOf for thin_slice::ThinBoxedSlice<T> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = 0;
|
||||
unsafe {
|
||||
n += thin_slice::ThinBoxedSlice::spilled_storage(self)
|
||||
.map_or(0, |ptr| ops.malloc_size_of(ptr));
|
||||
n += ops.malloc_size_of(&**self);
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for thin_slice::ThinBoxedSlice<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.shallow_size_of(ops) + (**self).size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl MallocSizeOf for () {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
0
|
||||
@ -789,7 +770,7 @@ where
|
||||
}
|
||||
|
||||
impl<Impl: selectors::parser::SelectorImpl> MallocSizeOf
|
||||
for selectors::attr::AttrSelectorWithOptionalNamespace<Impl>
|
||||
for selectors::attr::AttrSelectorWithNamespace<Impl>
|
||||
{
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
0
|
||||
|
@ -29,7 +29,6 @@ phf = "0.7.18"
|
||||
precomputed-hash = "0.1"
|
||||
servo_arc = { version = "0.1", path = "../servo_arc" }
|
||||
smallvec = "0.6"
|
||||
thin-slice = "0.1.0"
|
||||
|
||||
[build-dependencies]
|
||||
phf_codegen = "0.7.18"
|
||||
|
@ -7,20 +7,20 @@ use parser::SelectorImpl;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
pub struct AttrSelectorWithOptionalNamespace<Impl: SelectorImpl> {
|
||||
pub namespace: Option<NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>>,
|
||||
pub struct AttrSelectorWithNamespace<Impl: SelectorImpl> {
|
||||
pub namespace: NamespaceConstraint<(Impl::NamespacePrefix, Impl::NamespaceUrl)>,
|
||||
pub local_name: Impl::LocalName,
|
||||
pub local_name_lower: Impl::LocalName,
|
||||
pub operation: ParsedAttrSelectorOperation<Impl::AttrValue>,
|
||||
pub never_matches: bool,
|
||||
}
|
||||
|
||||
impl<Impl: SelectorImpl> AttrSelectorWithOptionalNamespace<Impl> {
|
||||
pub fn namespace(&self) -> Option<NamespaceConstraint<&Impl::NamespaceUrl>> {
|
||||
self.namespace.as_ref().map(|ns| match ns {
|
||||
impl<Impl: SelectorImpl> AttrSelectorWithNamespace<Impl> {
|
||||
pub fn namespace(&self) -> NamespaceConstraint<&Impl::NamespaceUrl> {
|
||||
match self.namespace {
|
||||
NamespaceConstraint::Any => NamespaceConstraint::Any,
|
||||
NamespaceConstraint::Specific((_, ref url)) => NamespaceConstraint::Specific(url),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,6 @@ extern crate phf;
|
||||
extern crate precomputed_hash;
|
||||
extern crate servo_arc;
|
||||
extern crate smallvec;
|
||||
extern crate thin_slice;
|
||||
|
||||
pub mod attr;
|
||||
pub mod bloom;
|
||||
|
@ -699,6 +699,7 @@ where
|
||||
},
|
||||
Component::AttributeInNoNamespace {
|
||||
ref local_name,
|
||||
ref local_name_lower,
|
||||
ref value,
|
||||
operator,
|
||||
case_sensitivity,
|
||||
@ -710,7 +711,7 @@ where
|
||||
let is_html = element.is_html_element_in_html_document();
|
||||
element.attr_matches(
|
||||
&NamespaceConstraint::Specific(&::parser::namespace_empty_string::<E::Impl>()),
|
||||
local_name,
|
||||
select_name(is_html, local_name, local_name_lower),
|
||||
&AttrSelectorOperation::WithValue {
|
||||
operator: operator,
|
||||
case_sensitivity: case_sensitivity.to_unconditional(is_html),
|
||||
@ -723,16 +724,8 @@ where
|
||||
return false;
|
||||
}
|
||||
let is_html = element.is_html_element_in_html_document();
|
||||
let empty_string;
|
||||
let namespace = match attr_sel.namespace() {
|
||||
Some(ns) => ns,
|
||||
None => {
|
||||
empty_string = ::parser::namespace_empty_string::<E::Impl>();
|
||||
NamespaceConstraint::Specific(&empty_string)
|
||||
}
|
||||
};
|
||||
element.attr_matches(
|
||||
&namespace,
|
||||
&attr_sel.namespace(),
|
||||
select_name(is_html, &attr_sel.local_name, &attr_sel.local_name_lower),
|
||||
&match attr_sel.operation {
|
||||
ParsedAttrSelectorOperation::Exists => AttrSelectorOperation::Exists,
|
||||
|
@ -2,9 +2,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use attr::{AttrSelectorOperator, AttrSelectorWithOptionalNamespace};
|
||||
use attr::{NamespaceConstraint, ParsedAttrSelectorOperation};
|
||||
use attr::{ParsedCaseSensitivity, SELECTOR_WHITESPACE};
|
||||
use attr::{AttrSelectorOperator, AttrSelectorWithNamespace, ParsedAttrSelectorOperation};
|
||||
use attr::{NamespaceConstraint, ParsedCaseSensitivity, SELECTOR_WHITESPACE};
|
||||
use bloom::BLOOM_HASH_MASK;
|
||||
use builder::{SelectorBuilder, SpecificityAndFlags};
|
||||
use context::QuirksMode;
|
||||
@ -20,7 +19,6 @@ use std::borrow::{Borrow, Cow};
|
||||
use std::fmt::{self, Debug, Display, Write};
|
||||
use std::iter::Rev;
|
||||
use std::slice;
|
||||
use thin_slice::ThinBoxedSlice;
|
||||
pub use visitor::{SelectorVisitor, Visit};
|
||||
|
||||
/// A trait that represents a pseudo-element.
|
||||
@ -47,8 +45,6 @@ pub trait NonTSPseudoClass: Sized + ToCss {
|
||||
fn is_active_or_hover(&self) -> bool;
|
||||
}
|
||||
|
||||
/// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a
|
||||
/// Cow::Owned if `s` had to be converted into ASCII lowercase.
|
||||
fn to_ascii_lowercase(s: &str) -> Cow<str> {
|
||||
if let Some(first_uppercase) = s.bytes().position(|byte| byte >= b'A' && byte <= b'Z') {
|
||||
let mut string = s.to_owned();
|
||||
@ -432,6 +428,7 @@ where
|
||||
},
|
||||
AttributeInNoNamespace {
|
||||
ref local_name,
|
||||
ref local_name_lower,
|
||||
never_matches,
|
||||
..
|
||||
} if !never_matches =>
|
||||
@ -439,22 +436,14 @@ where
|
||||
if !visitor.visit_attribute_selector(
|
||||
&NamespaceConstraint::Specific(&namespace_empty_string::<Impl>()),
|
||||
local_name,
|
||||
local_name,
|
||||
local_name_lower,
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
AttributeOther(ref attr_selector) if !attr_selector.never_matches => {
|
||||
let empty_string;
|
||||
let namespace = match attr_selector.namespace() {
|
||||
Some(ns) => ns,
|
||||
None => {
|
||||
empty_string = ::parser::namespace_empty_string::<Impl>();
|
||||
NamespaceConstraint::Specific(&empty_string)
|
||||
}
|
||||
};
|
||||
if !visitor.visit_attribute_selector(
|
||||
&namespace,
|
||||
&attr_selector.namespace(),
|
||||
&attr_selector.local_name,
|
||||
&attr_selector.local_name_lower,
|
||||
) {
|
||||
@ -826,16 +815,16 @@ pub enum Component<Impl: SelectorImpl> {
|
||||
local_name: Impl::LocalName,
|
||||
local_name_lower: Impl::LocalName,
|
||||
},
|
||||
// Used only when local_name is already lowercase.
|
||||
AttributeInNoNamespace {
|
||||
local_name: Impl::LocalName,
|
||||
local_name_lower: Impl::LocalName,
|
||||
operator: AttrSelectorOperator,
|
||||
value: Impl::AttrValue,
|
||||
case_sensitivity: ParsedCaseSensitivity,
|
||||
never_matches: bool,
|
||||
},
|
||||
// Use a Box in the less common cases with more data to keep size_of::<Component>() small.
|
||||
AttributeOther(Box<AttrSelectorWithOptionalNamespace<Impl>>),
|
||||
AttributeOther(Box<AttrSelectorWithNamespace<Impl>>),
|
||||
|
||||
/// Pseudo-classes
|
||||
///
|
||||
@ -847,7 +836,7 @@ pub enum Component<Impl: SelectorImpl> {
|
||||
/// need to think about how this should interact with
|
||||
/// visit_complex_selector, and what the consumers of those APIs should do
|
||||
/// about the presence of combinators in negation.
|
||||
Negation(ThinBoxedSlice<Component<Impl>>),
|
||||
Negation(Box<[Component<Impl>]>),
|
||||
FirstChild,
|
||||
LastChild,
|
||||
OnlyChild,
|
||||
@ -959,7 +948,7 @@ impl<Impl: SelectorImpl> Debug for Component<Impl> {
|
||||
self.to_css(f)
|
||||
}
|
||||
}
|
||||
impl<Impl: SelectorImpl> Debug for AttrSelectorWithOptionalNamespace<Impl> {
|
||||
impl<Impl: SelectorImpl> Debug for AttrSelectorWithNamespace<Impl> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.to_css(f)
|
||||
}
|
||||
@ -1249,19 +1238,18 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Impl: SelectorImpl> ToCss for AttrSelectorWithOptionalNamespace<Impl> {
|
||||
impl<Impl: SelectorImpl> ToCss for AttrSelectorWithNamespace<Impl> {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where
|
||||
W: fmt::Write,
|
||||
{
|
||||
dest.write_char('[')?;
|
||||
match self.namespace {
|
||||
Some(NamespaceConstraint::Specific((ref prefix, _))) => {
|
||||
NamespaceConstraint::Specific((ref prefix, _)) => {
|
||||
display_to_css_identifier(prefix, dest)?;
|
||||
dest.write_char('|')?
|
||||
},
|
||||
Some(NamespaceConstraint::Any) => dest.write_str("*|")?,
|
||||
None => {}
|
||||
NamespaceConstraint::Any => dest.write_str("*|")?,
|
||||
}
|
||||
display_to_css_identifier(&self.local_name, dest)?;
|
||||
match self.operation {
|
||||
@ -1640,8 +1628,8 @@ where
|
||||
let local_name = local_name.as_ref().into();
|
||||
if let Some(namespace) = namespace {
|
||||
return Ok(Component::AttributeOther(Box::new(
|
||||
AttrSelectorWithOptionalNamespace {
|
||||
namespace: Some(namespace),
|
||||
AttrSelectorWithNamespace {
|
||||
namespace: namespace,
|
||||
local_name: local_name,
|
||||
local_name_lower: local_name_lower,
|
||||
operation: ParsedAttrSelectorOperation::Exists,
|
||||
@ -1697,7 +1685,6 @@ where
|
||||
|
||||
let value = value.as_ref().into();
|
||||
let local_name_lower;
|
||||
let local_name_is_ascii_lowercase;
|
||||
{
|
||||
let local_name_lower_cow = to_ascii_lowercase(&local_name);
|
||||
if let ParsedCaseSensitivity::CaseSensitive = case_sensitivity {
|
||||
@ -1712,16 +1699,15 @@ where
|
||||
}
|
||||
}
|
||||
local_name_lower = local_name_lower_cow.as_ref().into();
|
||||
local_name_is_ascii_lowercase = matches!(local_name_lower_cow, Cow::Borrowed(..));
|
||||
}
|
||||
let local_name = local_name.as_ref().into();
|
||||
if namespace.is_some() || !local_name_is_ascii_lowercase {
|
||||
if let Some(namespace) = namespace {
|
||||
Ok(Component::AttributeOther(Box::new(
|
||||
AttrSelectorWithOptionalNamespace {
|
||||
namespace,
|
||||
local_name,
|
||||
local_name_lower,
|
||||
never_matches,
|
||||
AttrSelectorWithNamespace {
|
||||
namespace: namespace,
|
||||
local_name: local_name,
|
||||
local_name_lower: local_name_lower,
|
||||
never_matches: never_matches,
|
||||
operation: ParsedAttrSelectorOperation::WithValue {
|
||||
operator: operator,
|
||||
case_sensitivity: case_sensitivity,
|
||||
@ -1732,6 +1718,7 @@ where
|
||||
} else {
|
||||
Ok(Component::AttributeInNoNamespace {
|
||||
local_name: local_name,
|
||||
local_name_lower: local_name_lower,
|
||||
operator: operator,
|
||||
value: value,
|
||||
case_sensitivity: case_sensitivity,
|
||||
@ -1798,7 +1785,7 @@ where
|
||||
}
|
||||
|
||||
// Success.
|
||||
Ok(Component::Negation(sequence.into_vec().into_boxed_slice().into()))
|
||||
Ok(Component::Negation(sequence.into_vec().into_boxed_slice()))
|
||||
}
|
||||
|
||||
/// simple_selector_sequence
|
||||
@ -2689,6 +2676,7 @@ pub mod tests {
|
||||
vec![
|
||||
Component::AttributeInNoNamespace {
|
||||
local_name: DummyAtom::from("attr"),
|
||||
local_name_lower: DummyAtom::from("attr"),
|
||||
operator: AttrSelectorOperator::DashMatch,
|
||||
value: DummyAtom::from("foo"),
|
||||
never_matches: false,
|
||||
|
@ -66,7 +66,6 @@ string_cache = { version = "0.7", optional = true }
|
||||
style_derive = {path = "../style_derive"}
|
||||
style_traits = {path = "../style_traits"}
|
||||
servo_url = {path = "../url", optional = true}
|
||||
thin-slice = "0.1.0"
|
||||
time = "0.1"
|
||||
uluru = "0.2"
|
||||
unicode-bidi = "0.3"
|
||||
|
@ -15,7 +15,6 @@ use properties::longhands::display::computed_value::T as Display;
|
||||
use selector_parser::{NonTSPseudoClass, PseudoElementCascadeType, SelectorImpl};
|
||||
use std::fmt;
|
||||
use string_cache::Atom;
|
||||
use thin_slice::ThinBoxedSlice;
|
||||
use values::serialize_atom_identifier;
|
||||
|
||||
include!(concat!(
|
||||
|
@ -8,7 +8,7 @@ pub enum PseudoElement {
|
||||
% for pseudo in PSEUDOS:
|
||||
/// ${pseudo.value}
|
||||
% if pseudo.is_tree_pseudo_element():
|
||||
${pseudo.capitalized()}(ThinBoxedSlice<Atom>),
|
||||
${pseudo.capitalized()}(Box<[Atom]>),
|
||||
% else:
|
||||
${pseudo.capitalized()},
|
||||
% endif
|
||||
@ -209,7 +209,7 @@ impl PseudoElement {
|
||||
% for pseudo in PSEUDOS:
|
||||
% if pseudo.is_tree_pseudo_element():
|
||||
if atom == &atom!("${pseudo.value}") {
|
||||
return Some(PseudoElement::${pseudo.capitalized()}(args.into()));
|
||||
return Some(PseudoElement::${pseudo.capitalized()}(args));
|
||||
}
|
||||
% endif
|
||||
% endfor
|
||||
@ -256,7 +256,7 @@ impl PseudoElement {
|
||||
let tree_part = &name[10..];
|
||||
% for pseudo in TREE_PSEUDOS:
|
||||
if tree_part.eq_ignore_ascii_case("${pseudo.value[11:]}") {
|
||||
return Some(${pseudo_element_variant(pseudo, "args.into()")});
|
||||
return Some(${pseudo_element_variant(pseudo, "args")});
|
||||
}
|
||||
% endfor
|
||||
None
|
||||
|
@ -13,13 +13,11 @@ use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||
use invalidation::element::document_state::InvalidationMatchingData;
|
||||
use selector_parser::{Direction, SelectorParser};
|
||||
use selectors::SelectorList;
|
||||
use selectors::parser::{self as selector_parser, Selector};
|
||||
use selectors::parser::{SelectorParseErrorKind, Visit};
|
||||
use selectors::parser::{self as selector_parser, Selector, SelectorParseErrorKind, Visit};
|
||||
use selectors::visitor::SelectorVisitor;
|
||||
use std::fmt;
|
||||
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
|
||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss as ToCss_};
|
||||
use thin_slice::ThinBoxedSlice;
|
||||
|
||||
pub use gecko::pseudo_element::{PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT, PSEUDO_COUNT};
|
||||
pub use gecko::snapshot::SnapshotMap;
|
||||
@ -36,7 +34,7 @@ bitflags! {
|
||||
}
|
||||
|
||||
/// The type used for storing pseudo-class string arguments.
|
||||
pub type PseudoClassStringArg = ThinBoxedSlice<u16>;
|
||||
pub type PseudoClassStringArg = Box<[u16]>;
|
||||
|
||||
macro_rules! pseudo_class_name {
|
||||
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
|
||||
@ -58,7 +56,7 @@ macro_rules! pseudo_class_name {
|
||||
///
|
||||
/// TODO(emilio): We disallow combinators and pseudos here, so we
|
||||
/// should use SimpleSelector instead
|
||||
MozAny(ThinBoxedSlice<Selector<SelectorImpl>>),
|
||||
MozAny(Box<[Selector<SelectorImpl>]>),
|
||||
/// The non-standard `:-moz-locale-dir` pseudo-class.
|
||||
MozLocaleDir(Box<Direction>),
|
||||
}
|
||||
@ -407,7 +405,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||
// convert to null terminated utf16 string
|
||||
// since that's what Gecko deals with
|
||||
let utf16: Vec<u16> = name.encode_utf16().chain(Some(0u16)).collect();
|
||||
NonTSPseudoClass::$s_name(utf16.into_boxed_slice().into())
|
||||
NonTSPseudoClass::$s_name(utf16.into_boxed_slice())
|
||||
}, )*
|
||||
"-moz-locale-dir" => {
|
||||
NonTSPseudoClass::MozLocaleDir(
|
||||
@ -424,7 +422,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> {
|
||||
selector_parser::parse_compound_selector_list(
|
||||
self,
|
||||
parser,
|
||||
)?.into()
|
||||
)?
|
||||
)
|
||||
}
|
||||
_ => return Err(parser.new_custom_error(
|
||||
|
@ -93,7 +93,6 @@ extern crate string_cache;
|
||||
#[macro_use]
|
||||
extern crate style_derive;
|
||||
extern crate style_traits;
|
||||
extern crate thin_slice;
|
||||
extern crate time;
|
||||
extern crate uluru;
|
||||
extern crate unicode_bidi;
|
||||
|
@ -1 +0,0 @@
|
||||
{"files":{"Cargo.toml":"4e814457b6228f1d617315305eeda7c1d4f3510074c394a44858daced98438af","README.md":"7bbdabe6f919f88d407a9b6361bd75bd43d09c533631776ae2db1851f93a77af","src/lib.rs":"5b1f2bfc9edfc6036a8880cde88f862931eec5036e6cf63690f82921053b29fe"},"package":"85b3e41c2cf31e81a7ec4ad3acd69abde19887e0f7f8e74dcdedc8cb7b158ef8"}
|
23
third_party/rust/thin-slice/Cargo.toml
vendored
23
third_party/rust/thin-slice/Cargo.toml
vendored
@ -1,23 +0,0 @@
|
||||
# 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]
|
||||
name = "thin-slice"
|
||||
version = "0.1.0"
|
||||
authors = ["Cameron McCormack <cam@mcc.id.au>"]
|
||||
description = "An owned slice that packs the slice storage into a single word when possible"
|
||||
readme = "README.md"
|
||||
keywords = ["slice", "tagged", "pointer"]
|
||||
license = "MPL-2.0"
|
||||
repository = "https://github.com/heycam/thin-slice"
|
||||
|
||||
[dependencies]
|
45
third_party/rust/thin-slice/README.md
vendored
45
third_party/rust/thin-slice/README.md
vendored
@ -1,45 +0,0 @@
|
||||
# thin-slice
|
||||
|
||||
An owned slice that packs the slice storage into a single word when possible.
|
||||
|
||||
## Usage
|
||||
|
||||
```rust
|
||||
extern crate thin_slice;
|
||||
|
||||
struct Ticket {
|
||||
numbers: Box<[u8]>,
|
||||
winning: bool,
|
||||
}
|
||||
|
||||
struct ThinTicket {
|
||||
numbers: ThinBoxedSlice<u8>,
|
||||
winning: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let nums = vec![4, 8, 15, 16, 23, 42].into_boxed_slice();
|
||||
let ticket = ThinTicket {
|
||||
numbers: nums.into(),
|
||||
winning: false,
|
||||
};
|
||||
println!("Numbers: {:?}", ticket.numbers);
|
||||
|
||||
println!("size_of::<usize>(): {}", mem::size_of::<usize>());
|
||||
println!("size_of::<Ticket>(): {}", mem::size_of::<Ticket>());
|
||||
println!("size_of::<ThinTicket>(): {}", mem::size_of::<ThinTicket>());
|
||||
}
|
||||
```
|
||||
|
||||
Output on `x86_64`:
|
||||
|
||||
```
|
||||
size_of::<usize>(): 8
|
||||
size_of::<Ticket>(): 24
|
||||
size_of::<ThinTicket>(): 16
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
thin-slice is distributed under the terms of the
|
||||
[Mozilla Public License, v. 2.0](https://www.mozilla.org/MPL/2.0/).
|
544
third_party/rust/thin-slice/src/lib.rs
vendored
544
third_party/rust/thin-slice/src/lib.rs
vendored
@ -1,544 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! An owned slice that tries to use only one word of storage.
|
||||
//!
|
||||
//! `ThinBoxedSlice<T>` can be used in place of `Box<[T]>` on the `x86_64`
|
||||
//! architecture to hold ownership of a slice when it's important to reduce
|
||||
//! memory usage of the box itself. When the slice length is less than
|
||||
//! `0xffff`, a single word is used to encode the slice pointer and length.
|
||||
//! When it is greater than `0xffff`, a heap allocation is used to store the
|
||||
//! fat pointer representing the slice.
|
||||
//!
|
||||
//! A `ThinBoxedSlice<T>` is always created by converting from a `Box<[T]>`.
|
||||
//!
|
||||
//! On any architecture other than `x86_64`, a `ThinBoxedSlice<T>` will simply
|
||||
//! use a `Box<[T]>` internally.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Creating a `ThinBoxedSlice`:
|
||||
//!
|
||||
//! ```
|
||||
//! # use thin_slice::ThinBoxedSlice;
|
||||
//! let fat_pointer = vec![10, 20, 30].into_boxed_slice();
|
||||
//! let thin_pointer: ThinBoxedSlice<_> = fat_pointer.into();
|
||||
//! ```
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, Hasher};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::marker::PhantomData;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::ptr::NonNull;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::slice;
|
||||
|
||||
/// An owned slice that tries to use only one word of storage.
|
||||
///
|
||||
/// See the [module-level documentation](index.html) for more.
|
||||
pub struct ThinBoxedSlice<T> {
|
||||
/// Storage for the slice.
|
||||
///
|
||||
/// Once `std::num::NonZeroUsize` has stabilized, we can switch to that.
|
||||
///
|
||||
/// The value stored here depends on the length of the slice.
|
||||
///
|
||||
/// If len = 0, `data` will be `1usize`.
|
||||
///
|
||||
/// If 0 < len < 0xffff, then len will be stored in the top 16 bits of
|
||||
/// data, and the lower 48 bits will be the pointer to the elements.
|
||||
///
|
||||
/// If len >= 0xffff, then the top 16 bits of data will be 0xffff, and
|
||||
/// the lower 48 bits will be a pointer to a heap allocated `Box<[T]>`.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
data: NonNull<()>,
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
data: Box<[T]>,
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
_phantom: PhantomData<Box<[T]>>,
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const TAG_MASK: usize = 0xffff000000000000;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const PTR_MASK: usize = 0x0000ffffffffffff;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const PTR_HIGH: usize = 0x0000800000000000;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const TAG_SHIFT: usize = 48;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const TAG_LIMIT: usize = TAG_MASK >> TAG_SHIFT;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
enum Storage<T> {
|
||||
Inline(*mut T, usize),
|
||||
Spilled(*mut Box<[T]>),
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl<T> ThinBoxedSlice<T> {
|
||||
/// Constructs a `ThinBoxedSlice` from a raw pointer.
|
||||
///
|
||||
/// Like `Box::from_raw`, after calling this function, the raw pointer is
|
||||
/// owned by the resulting `ThinBoxedSlice`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use thin_slice::ThinBoxedSlice;
|
||||
/// let x = vec![10, 20, 30].into_boxed_slice(); // a Box<[i32]>
|
||||
/// let ptr = Box::into_raw(x); // a *mut [i32]
|
||||
/// let x = unsafe { ThinBoxedSlice::from_raw(ptr) }; // a ThinBoxedSlice<i32>
|
||||
/// ```
|
||||
#[inline]
|
||||
pub unsafe fn from_raw(raw: *mut [T]) -> ThinBoxedSlice<T> {
|
||||
let len = (*raw).len();
|
||||
let ptr = (*raw).as_mut_ptr();
|
||||
let storage = if len == 0 {
|
||||
Storage::Inline(1usize as *mut _, 0)
|
||||
} else if len < TAG_LIMIT {
|
||||
Storage::Inline(ptr, len)
|
||||
} else {
|
||||
let boxed_slice = Box::from_raw(raw);
|
||||
Storage::Spilled(Box::into_raw(Box::new(boxed_slice)))
|
||||
};
|
||||
ThinBoxedSlice {
|
||||
data: storage.into_data(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes the `ThinBoxedSlice`, returning a raw pointer to the slice
|
||||
/// it owned.
|
||||
///
|
||||
/// Like `Box::into_raw`, after calling this function, the caller is
|
||||
/// responsible for the memory previously managed by the `ThinBoxedSlice`.
|
||||
/// In particular, the caller should properly destroy the `[T]` and release
|
||||
/// the memory. The proper way to do so is to convert the raw pointer back
|
||||
/// into a `Box` or a `ThinBoxedSlice`, with either the `Box::from_raw` or
|
||||
/// `ThinBoxedSlice::from_raw` functions.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use thin_slice::ThinBoxedSlice;
|
||||
/// let x = vec![10, 20, 30].into_boxed_slice();
|
||||
/// let x = ThinBoxedSlice::from(x);
|
||||
/// let ptr = ThinBoxedSlice::into_raw(x);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn into_raw(b: ThinBoxedSlice<T>) -> *mut [T] {
|
||||
unsafe {
|
||||
match b.into_storage() {
|
||||
Storage::Inline(ptr, len) => {
|
||||
slice::from_raw_parts_mut(ptr, len)
|
||||
}
|
||||
Storage::Spilled(ptr) => {
|
||||
Box::into_raw(*Box::from_raw(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes and leaks the `ThinBoxedSlice`, returning a mutable reference,
|
||||
/// `&'a mut [T]`. Here, the lifetime `'a` may be chosen to be `'static`.
|
||||
///
|
||||
/// Like `Box::leak`, this function is mainly useful for data that lives
|
||||
/// for the remainder of the program's life. Dropping the returned
|
||||
/// reference will cause a memory leak. If this is not acceptable, the
|
||||
/// reference should first be wrapped with the `Box::from_raw` function
|
||||
/// producing a `Box`, or with the `ThinBoxedSlice::from_raw` function
|
||||
/// producing a `ThinBoxedSlice`. This value can then be dropped which will
|
||||
/// properly destroy `[T]` and release the allocated memory.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use thin_slice::ThinBoxedSlice;
|
||||
/// fn main() {
|
||||
/// let x = ThinBoxedSlice::from(vec![1, 2, 3].into_boxed_slice());
|
||||
/// let static_ref = ThinBoxedSlice::leak(x);
|
||||
/// static_ref[0] = 4;
|
||||
/// assert_eq!(*static_ref, [4, 2, 3]);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn leak(b: ThinBoxedSlice<T>) -> &'static mut [T] {
|
||||
unsafe { &mut *ThinBoxedSlice::into_raw(b) }
|
||||
}
|
||||
|
||||
/// Returns a pointer to the heap allocation that stores the fat pointer
|
||||
/// to the slice, if any. This is useful for systems that need to measure
|
||||
/// memory allocation, but is otherwise an opaque pointer.
|
||||
#[inline]
|
||||
pub fn spilled_storage(&self) -> Option<*const ()> {
|
||||
match self.storage() {
|
||||
Storage::Inline(..) => None,
|
||||
Storage::Spilled(ptr) => Some(ptr as *const ()),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn storage(&self) -> Storage<T> {
|
||||
Storage::from_data(self.data.clone())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_storage(self) -> Storage<T> {
|
||||
let storage = self.storage();
|
||||
mem::forget(self);
|
||||
storage
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
impl<T> ThinBoxedSlice<T> {
|
||||
/// Constructs a `ThinBoxedSlice` from a raw pointer.
|
||||
///
|
||||
/// Like `Box::from_raw`, after calling this function, the raw pointer is
|
||||
/// owned by the resulting `ThinBoxedSlice`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use thin_slice::ThinBoxedSlice;
|
||||
/// let x = vec![10, 20, 30].into_boxed_slice(); // a Box<[i32]>
|
||||
/// let ptr = Box::into_raw(x); // a *mut [i32]
|
||||
/// let x = unsafe { ThinBoxedSlice::from_raw(ptr) }; // a ThinBoxedSlice<i32>
|
||||
/// ```
|
||||
#[inline]
|
||||
pub unsafe fn from_raw(raw: *mut [T]) -> ThinBoxedSlice<T> {
|
||||
ThinBoxedSlice {
|
||||
data: Box::from_raw(raw),
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes the `ThinBoxedSlice`, returning a raw pointer to the slice
|
||||
/// it owned.
|
||||
///
|
||||
/// Like `Box::into_raw`, after calling this function, the caller is
|
||||
/// responsible for the memory previously managed by the `ThinBoxedSlice`.
|
||||
/// In particular, the caller should properly destroy the `[T]` and release
|
||||
/// the memory. The proper way to do so is to convert the raw pointer back
|
||||
/// into a `Box` or a `ThinBoxedSlice`, with either the `Box::from_raw` or
|
||||
/// `ThinBoxedSlice::from_raw` functions.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use thin_slice::ThinBoxedSlice;
|
||||
/// let x = vec![10, 20, 30].into_boxed_slice();
|
||||
/// let x = ThinBoxedSlice::from(x);
|
||||
/// let ptr = ThinBoxedSlice::into_raw(x);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn into_raw(b: ThinBoxedSlice<T>) -> *mut [T] {
|
||||
Box::into_raw(b.data)
|
||||
}
|
||||
|
||||
/// Consumes and leaks the `ThinBoxedSlice`, returning a mutable reference,
|
||||
/// `&'a mut [T]`. Here, the lifetime `'a` may be chosen to be `'static`.
|
||||
///
|
||||
/// Like `Box::leak`, this function is mainly useful for data that lives
|
||||
/// for the remainder of the program's life. Dropping the returned
|
||||
/// reference will cause a memory leak. If this is not acceptable, the
|
||||
/// reference should first be wrapped with the `Box::from_raw` function
|
||||
/// producing a `Box`, or with the `ThinBoxedSlice::from_raw` function
|
||||
/// producing a `ThinBoxedSlice`. This value can then be dropped which will
|
||||
/// properly destroy `[T]` and release the allocated memory.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use thin_slice::ThinBoxedSlice;
|
||||
/// fn main() {
|
||||
/// let x = ThinBoxedSlice::from(vec![1, 2, 3].into_boxed_slice());
|
||||
/// let static_ref = ThinBoxedSlice::leak(x);
|
||||
/// static_ref[0] = 4;
|
||||
/// assert_eq!(*static_ref, [4, 2, 3]);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn leak<'a>(b: ThinBoxedSlice<T>) -> &'a mut [T] where T: 'a {
|
||||
Box::leak(b.data)
|
||||
}
|
||||
|
||||
/// Returns a pointer to the heap allocation that stores the fat pointer
|
||||
/// to the slice, if any. This is useful for systems that need to measure
|
||||
/// memory allocation, but is otherwise an opaque pointer.
|
||||
#[inline]
|
||||
pub fn spilled_storage(&self) -> Option<*const ()> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl<T> Storage<T> {
|
||||
#[inline]
|
||||
fn from_data(data: NonNull<()>) -> Storage<T> {
|
||||
let data = data.as_ptr() as usize;
|
||||
|
||||
let len = (data & TAG_MASK) >> TAG_SHIFT;
|
||||
let mut ptr = data & PTR_MASK;
|
||||
|
||||
if (ptr & PTR_HIGH) == PTR_HIGH {
|
||||
// Canonical linear addresses on x86_64 are sign extended from
|
||||
// bit 48.
|
||||
ptr |= TAG_MASK;
|
||||
}
|
||||
|
||||
if len < TAG_LIMIT {
|
||||
Storage::Inline(ptr as *mut T, len)
|
||||
} else {
|
||||
Storage::Spilled(ptr as *mut Box<[T]>)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_data(self) -> NonNull<()> {
|
||||
let data = match self {
|
||||
Storage::Inline(ptr, len) => {
|
||||
(len << TAG_SHIFT) | ((ptr as usize) & PTR_MASK)
|
||||
}
|
||||
Storage::Spilled(ptr) => {
|
||||
TAG_MASK | ((ptr as usize) & PTR_MASK)
|
||||
}
|
||||
};
|
||||
unsafe {
|
||||
NonNull::new_unchecked(data as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Box<[T]>> for ThinBoxedSlice<T> {
|
||||
fn from(value: Box<[T]>) -> ThinBoxedSlice<T> {
|
||||
let ptr = Box::into_raw(value);
|
||||
unsafe {
|
||||
ThinBoxedSlice::from_raw(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Into<Box<[T]>> for ThinBoxedSlice<T> {
|
||||
fn into(self) -> Box<[T]> {
|
||||
let ptr = ThinBoxedSlice::into_raw(self);
|
||||
unsafe {
|
||||
Box::from_raw(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Send> Send for ThinBoxedSlice<T> {}
|
||||
unsafe impl<T: Sync> Sync for ThinBoxedSlice<T> {}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl<T> Drop for ThinBoxedSlice<T> {
|
||||
fn drop(&mut self) {
|
||||
let _ = Into::<Box<[T]>>::into(
|
||||
ThinBoxedSlice {
|
||||
data: self.data.clone(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> Clone for ThinBoxedSlice<T> {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn clone(&self) -> Self {
|
||||
unsafe {
|
||||
match self.storage() {
|
||||
Storage::Inline(ptr, len) => {
|
||||
slice::from_raw_parts_mut(ptr, len)
|
||||
.to_vec()
|
||||
.into_boxed_slice()
|
||||
.into()
|
||||
}
|
||||
Storage::Spilled(ptr) => {
|
||||
(*ptr).clone().into()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
fn clone(&self) -> Self {
|
||||
ThinBoxedSlice {
|
||||
data: self.data.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<[T]> for ThinBoxedSlice<T> {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsMut<[T]> for ThinBoxedSlice<T> {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
&mut **self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for ThinBoxedSlice<T> {
|
||||
type Target = [T];
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn deref(&self) -> &[T] {
|
||||
unsafe {
|
||||
match self.storage() {
|
||||
Storage::Inline(ptr, len) => {
|
||||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
Storage::Spilled(ptr) => {
|
||||
&**ptr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
fn deref(&self) -> &[T] {
|
||||
&*self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DerefMut for ThinBoxedSlice<T> {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
unsafe {
|
||||
match self.storage() {
|
||||
Storage::Inline(ptr, len) => {
|
||||
slice::from_raw_parts_mut(ptr, len)
|
||||
}
|
||||
Storage::Spilled(ptr) => {
|
||||
&mut **ptr
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
fn deref_mut(&mut self) -> &mut [T] {
|
||||
&mut *self.data
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for ThinBoxedSlice<T> {
|
||||
fn default() -> Self {
|
||||
Box::<[T]>::default().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug> fmt::Debug for ThinBoxedSlice<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq> Eq for ThinBoxedSlice<T> {}
|
||||
|
||||
impl<T: Hash> Hash for ThinBoxedSlice<T> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq> PartialEq for ThinBoxedSlice<T> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &ThinBoxedSlice<T>) -> bool {
|
||||
PartialEq::eq(&**self, &**other)
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &ThinBoxedSlice<T>) -> bool {
|
||||
PartialEq::ne(&**self, &**other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd> PartialOrd for ThinBoxedSlice<T> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &ThinBoxedSlice<T>) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(&**self, &**other)
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &ThinBoxedSlice<T>) -> bool {
|
||||
PartialOrd::lt(&**self, &**other)
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: &ThinBoxedSlice<T>) -> bool {
|
||||
PartialOrd::le(&**self, &**other)
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: &ThinBoxedSlice<T>) -> bool {
|
||||
PartialOrd::ge(&**self, &**other)
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: &ThinBoxedSlice<T>) -> bool {
|
||||
PartialOrd::gt(&**self, &**other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Pointer for ThinBoxedSlice<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let ptr = &**self;
|
||||
fmt::Pointer::fmt(&ptr, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[test]
|
||||
fn test_spilled_storage() {
|
||||
let x = ThinBoxedSlice::from(vec![0; TAG_LIMIT - 1].into_boxed_slice());
|
||||
assert!(x.spilled_storage().is_none());
|
||||
|
||||
let x = ThinBoxedSlice::from(vec![0; TAG_LIMIT].into_boxed_slice());
|
||||
assert!(x.spilled_storage().is_some());
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[test]
|
||||
fn test_from_raw_large() {
|
||||
let mut vec = vec![0; TAG_LIMIT];
|
||||
vec[123] = 456;
|
||||
|
||||
let ptr = Box::into_raw(vec.into_boxed_slice());
|
||||
let x = unsafe { ThinBoxedSlice::from_raw(ptr) };
|
||||
assert_eq!(x[123], 456);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[test]
|
||||
fn test_into_raw_large() {
|
||||
let mut vec = vec![0; TAG_LIMIT];
|
||||
vec[123] = 456;
|
||||
|
||||
let x = ThinBoxedSlice::from(vec.into_boxed_slice());
|
||||
let ptr = ThinBoxedSlice::into_raw(x);
|
||||
let y = unsafe { Box::from_raw(ptr) };
|
||||
assert_eq!(y[123], 456);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[test]
|
||||
fn test_leak_large() {
|
||||
let mut vec = vec![0; TAG_LIMIT];
|
||||
vec[123] = 456;
|
||||
|
||||
let x = ThinBoxedSlice::from(vec.into_boxed_slice());
|
||||
let static_ref = ThinBoxedSlice::leak(x);
|
||||
static_ref[123] *= 1000;
|
||||
assert_eq!(static_ref[123], 456000);
|
||||
}
|
Loading…
Reference in New Issue
Block a user