servo: Merge #18642 - nsString bindings update (from mystor:nsstring_vendor_bump); r=emilio

<!-- Please describe your changes on the following line: -->
This fixes bugzilla bug [1403170](https://bugzilla.mozilla.org/show_bug.cgi?id=1403170).

We've missed a few updates of the nsstring bindings in servo compared to the changes in gecko, so we really ought to find a better solution than these manual updates. For example, recently the way flags in nsstring are implemented was completely redone, and this version wasn't updated. It happened to be that the representation of the new form was identical to the old one, so it wasn't a problem, but technically this was wrong.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build-geckolib` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix bugzilla bug [1403170](https://bugzilla.mozilla.org/show_bug.cgi?id=1403170)

<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because they are a dependency version bump.

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: e68509b2e37983179a33c9f8cf4ad41c8a85d9a9

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : eb9e40bec9ced7f4972ac2fe276d0fcd52254436
This commit is contained in:
Michael Layzell 2017-09-26 11:38:58 -05:00
Родитель 09191cce06
Коммит 9c98ebe759
7 изменённых файлов: 395 добавлений и 125 удалений

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

@ -2045,6 +2045,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "nsstring_vendor"
version = "0.1.0"
dependencies = [
"bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"

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

@ -14,7 +14,7 @@ use gecko_bindings::structs::{CounterStylePtr, nsStyleCoord};
use gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius};
use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
use media_queries::Device;
use nsstring::{nsACString, nsCString};
use nsstring::{nsACString, nsCStr};
use std::cmp::max;
use values::{Auto, Either, ExtremumLength, None_, Normal};
use values::computed::{Angle, Length, LengthOrPercentage, LengthOrPercentageOrAuto};
@ -465,7 +465,7 @@ impl CounterStyleOrNone {
},
CounterStyleOrNone::Symbols(symbols_type, symbols) => {
let symbols: Vec<_> = symbols.0.iter().map(|symbol| match *symbol {
Symbol::String(ref s) => nsCString::from(s),
Symbol::String(ref s) => nsCStr::from(s),
Symbol::Ident(_) => unreachable!("Should not have identifier in symbols()"),
}).collect();
let symbols: Vec<_> = symbols.iter()

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

@ -9,6 +9,7 @@ description = "Rust bindings to xpcom string types"
# Revendoring nsstring from m-c into Servo
[dependencies]
bitflags = "0.8"
[features]
gecko_debug = []

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

@ -9,12 +9,18 @@
//! Use `&{mut,} nsA[C]String` for functions in rust which wish to take or
//! mutate XPCOM strings. The other string types `Deref` to this type.
//!
//! Use `ns[C]String<'a>` (`ns[C]String` in C++) for string struct members, and
//! as an intermediate between rust string data structures (such as `String`,
//! `Vec<u16>`, `&str`, and `&[u16]`) and `&{mut,} nsA[C]String` (using
//! `ns[C]String::from(value)`). These conversions, when possible, will not
//! perform any allocations. When using this type in structs shared with C++,
//! the correct lifetime argument is usually `'static`.
//! Use `ns[C]String` (`ns[C]String` in C++) for string struct members, and as
//! an intermediate between rust string data structures (such as `String` or
//! `Vec<u16>`) and `&{mut,} nsA[C]String` (using `ns[C]String::from(value)`).
//! These conversions will attempt to re-use the passed-in buffer, appending a
//! null.
//!
//! Use `ns[C]Str` (`nsDependent[C]String` in C++) as an intermediate between
//! borrowed rust data structures (such as `&str` and `&[u16]`) and `&{mut,}
//! nsA[C]String` (using `ns[C]Str::from(value)`). These conversions should not
//! perform any allocations. This type is not safe to share with `C++` as a
//! struct field, but passing the borrowed `&{mut,} nsA[C]String` over FFI is
//! safe.
//!
//! Use `nsFixed[C]String` or `ns_auto_[c]string!` for dynamic stack allocated
//! strings which are expected to hold short string values.
@ -52,7 +58,7 @@
//! with the methods `.append`, `.append_utf{8,16}`, and with the `write!`
//! macro, and can be assigned to with `.assign`.
//!
//! ## `ns[C]String<'a>`
//! ## `ns[C]Str<'a>`
//!
//! This type is an maybe-owned string type. It acts similarially to a
//! `Cow<[{u8,u16}]>`. This type provides `Deref` and `DerefMut` implementations
@ -61,20 +67,36 @@
//! storage. When modified this type may re-allocate in order to ensure that it
//! does not mutate its backing storage.
//!
//! `ns[C]String`s can be constructed either with `ns[C]String::new()`, which
//! creates an empty `ns[C]String<'static>`, or through one of the provided
//! `From` implementations. Both string types may be constructed `From<&'a
//! str>`, with `nsCString` having a `'a` lifetime, as the storage is shared
//! with the `str`, while `nsString` has a `'static` lifetime, as its storage
//! has to be transcoded.
//! `ns[C]Str`s can be constructed either with `ns[C]Str::new()`, which creates
//! an empty `ns[C]Str<'static>`, or through one of the provided `From`
//! implementations. Only `nsCStr` can be constructed `From<'a str>`, as
//! constructing a `nsStr` would require transcoding. Use `ns[C]String` instead.
//!
//! When passing this type by reference, prefer passing a `&nsA[C]String` or
//! `&mut nsA[C]String`. to passing this type.
//!
//! When passing this type across the language boundary, pass it as `*const
//! nsA[C]String` for an immutable reference, or `*mut nsA[C]String` for a
//! mutable reference. This struct may also be included in `#[repr(C)]`
//! structs shared with C++.
//! mutable reference.
//!
//! ## `ns[C]String`
//!
//! This type is an owned, null-terminated string type. This type provides
//! `Deref` and `DerefMut` implementations to `nsA[C]String`, which provides the
//! methods for manipulating this type.
//!
//! `ns[C]String`s can be constructed either with `ns[C]String::new()`, which
//! creates an empty `ns[C]String`, or through one of the provided `From`
//! implementations, which will try to avoid reallocating when possible,
//! although a terminating `null` will be added.
//!
//! When passing this type by reference, prefer passing a `&nsA[C]String` or
//! `&mut nsA[C]String`. to passing this type.
//!
//! When passing this type across the language boundary, pass it as `*const
//! nsA[C]String` for an immutable reference, or `*mut nsA[C]String` for a
//! mutable reference. This struct may also be included in `#[repr(C)]` structs
//! shared with C++.
//!
//! ## `nsFixed[C]String<'a>`
//!
@ -109,7 +131,7 @@
//! ## `ns[C]StringRepr`
//!
//! This crate also provides the type `ns[C]StringRepr` which acts conceptually
//! similar to an `ns[C]String<'static>`, however, it does not have a `Drop`
//! similar to an `ns[C]String`, however, it does not have a `Drop`
//! implementation.
//!
//! If this type is dropped in rust, it will not free its backing storage. This
@ -119,11 +141,13 @@
#![allow(non_camel_case_types)]
#![deny(warnings)]
#[macro_use]
extern crate bitflags;
use std::ops::{Deref, DerefMut};
use std::marker::PhantomData;
use std::borrow;
use std::slice;
use std::ptr;
use std::mem;
use std::fmt;
use std::cmp;
@ -135,13 +159,36 @@ use std::os::raw::c_void;
// Internal Implemenation Flags //
//////////////////////////////////
const F_NONE: u32 = 0; // no flags
mod data_flags {
bitflags! {
// While this has the same layout as u16, it cannot be passed
// over FFI safely as a u16.
#[repr(C)]
pub flags DataFlags : u16 {
const TERMINATED = 1 << 0, // IsTerminated returns true
const VOIDED = 1 << 1, // IsVoid returns true
const SHARED = 1 << 2, // mData points to a heap-allocated, shared buffer
const OWNED = 1 << 3, // mData points to a heap-allocated, raw buffer
const FIXED = 1 << 4, // mData points to a fixed-size writable, dependent buffer
const LITERAL = 1 << 5, // mData points to a string literal; TERMINATED will also be set
}
}
}
// data flags are in the lower 16-bits
const F_OWNED: u32 = 1 << 3; // mData points to a heap-allocated, raw buffer
mod class_flags {
bitflags! {
// While this has the same layout as u16, it cannot be passed
// over FFI safely as a u16.
#[repr(C)]
pub flags ClassFlags : u16 {
const FIXED = 1 << 0, // |this| is of type nsTFixedString
const NULL_TERMINATED = 1 << 1, // |this| requires its buffer is null-terminated
}
}
}
// class flags are in the upper 16-bits
const F_CLASS_FIXED: u32 = 1 << 16; // indicates that |this| is of type nsTFixedString
use data_flags::DataFlags;
use class_flags::ClassFlags;
////////////////////////////////////
// Generic String Bindings Macros //
@ -153,6 +200,7 @@ macro_rules! define_string_types {
AString = $AString: ident;
String = $String: ident;
Str = $Str: ident;
FixedString = $FixedString: ident;
StringLike = $StringLike: ident;
@ -162,8 +210,10 @@ macro_rules! define_string_types {
drop = $drop: ident;
assign = $assign: ident, $fallible_assign: ident;
take_from = $take_from: ident, $fallible_take_from: ident;
append = $append: ident, $fallible_append: ident;
set_length = $set_length: ident, $fallible_set_length: ident;
begin_writing = $begin_writing: ident, $fallible_begin_writing: ident;
} => {
/// The representation of a ns[C]String type in C++. This type is
/// used internally by our definition of ns[C]String to ensure layout
@ -180,7 +230,20 @@ macro_rules! define_string_types {
pub struct $StringRepr {
data: *const $char_t,
length: u32,
flags: u32,
dataflags: DataFlags,
classflags: ClassFlags,
}
impl $StringRepr {
fn new(classflags: ClassFlags) -> $StringRepr {
static NUL: $char_t = 0;
$StringRepr {
data: &NUL,
length: 0,
dataflags: data_flags::TERMINATED | data_flags::LITERAL,
classflags: classflags,
}
}
}
impl Deref for $StringRepr {
@ -239,6 +302,25 @@ macro_rules! define_string_types {
}
}
/// Take the value of `other` and set `self`, overwriting any value
/// currently stored. The passed-in string will be truncated.
pub fn take_from(&mut self, other: &mut $AString) {
unsafe { $take_from(self, other) };
}
/// Take the value of `other` and set `self`, overwriting any value
/// currently stored. If this function fails, the source string will
/// be left untouched, otherwise it will be truncated.
///
/// Returns Ok(()) on success, and Err(()) if the allocation failed.
pub fn fallible_take_from(&mut self, other: &mut $AString) -> Result<(), ()> {
if unsafe { $fallible_take_from(self, other) } {
Ok(())
} else {
Err(())
}
}
/// Append the value of `other` into self.
pub fn append<T: $StringLike + ?Sized>(&mut self, other: &T) {
unsafe { $append(self, other.adapt().as_ptr()) };
@ -282,6 +364,45 @@ macro_rules! define_string_types {
self.set_length(0);
}
}
/// Get a `&mut` reference to the backing data for this string.
/// This method will allocate and copy if the current backing buffer
/// is immutable or shared.
pub fn to_mut(&mut self) -> &mut [$char_t] {
unsafe {
let len = self.len();
if len == 0 {
// Use an arbitrary non-null value as the pointer
slice::from_raw_parts_mut(0x1 as *mut $char_t, 0)
} else {
slice::from_raw_parts_mut($begin_writing(self), len)
}
}
}
/// Get a `&mut` reference to the backing data for this string.
/// This method will allocate and copy if the current backing buffer
/// is immutable or shared.
///
/// Returns `Ok(&mut [T])` on success, and `Err(())` if the
/// allocation failed.
pub fn fallible_to_mut(&mut self) -> Result<&mut [$char_t], ()> {
unsafe {
let len = self.len();
if len == 0 {
// Use an arbitrary non-null value as the pointer
Ok(slice::from_raw_parts_mut(0x1 as *mut $char_t, 0))
} else {
let ptr = $fallible_begin_writing(self);
if ptr.is_null() {
Err(())
} else {
Ok(slice::from_raw_parts_mut(ptr, len))
}
}
}
}
}
impl Deref for $AString {
@ -322,8 +443,14 @@ macro_rules! define_string_types {
}
}
impl<'a> cmp::PartialEq<$String<'a>> for $AString {
fn eq(&self, other: &$String<'a>) -> bool {
impl cmp::PartialEq<$String> for $AString {
fn eq(&self, other: &$String) -> bool {
self.eq(&**other)
}
}
impl<'a> cmp::PartialEq<$Str<'a>> for $AString {
fn eq(&self, other: &$Str<'a>) -> bool {
self.eq(&**other)
}
}
@ -335,25 +462,21 @@ macro_rules! define_string_types {
}
#[repr(C)]
pub struct $String<'a> {
pub struct $Str<'a> {
hdr: $StringRepr,
_marker: PhantomData<&'a [$char_t]>,
}
impl $String<'static> {
pub fn new() -> $String<'static> {
$String {
hdr: $StringRepr {
data: ptr::null(),
length: 0,
flags: F_NONE,
},
impl $Str<'static> {
pub fn new() -> $Str<'static> {
$Str {
hdr: $StringRepr::new(ClassFlags::empty()),
_marker: PhantomData,
}
}
}
impl<'a> Drop for $String<'a> {
impl<'a> Drop for $Str<'a> {
fn drop(&mut self) {
unsafe {
$drop(&mut **self);
@ -361,64 +484,184 @@ macro_rules! define_string_types {
}
}
impl<'a> Deref for $String<'a> {
impl<'a> Deref for $Str<'a> {
type Target = $AString;
fn deref(&self) -> &$AString {
&self.hdr
}
}
impl<'a> DerefMut for $String<'a> {
impl<'a> DerefMut for $Str<'a> {
fn deref_mut(&mut self) -> &mut $AString {
&mut self.hdr
}
}
impl<'a> AsRef<[$char_t]> for $String<'a> {
impl<'a> AsRef<[$char_t]> for $Str<'a> {
fn as_ref(&self) -> &[$char_t] {
&self
}
}
impl<'a> From<&'a String> for $String<'a> {
fn from(s: &'a String) -> $String<'a> {
$String::from(&s[..])
}
}
impl<'a> From<&'a Vec<$char_t>> for $String<'a> {
fn from(s: &'a Vec<$char_t>) -> $String<'a> {
$String::from(&s[..])
}
}
impl<'a> From<&'a [$char_t]> for $String<'a> {
fn from(s: &'a [$char_t]) -> $String<'a> {
impl<'a> From<&'a [$char_t]> for $Str<'a> {
fn from(s: &'a [$char_t]) -> $Str<'a> {
assert!(s.len() < (u32::MAX as usize));
$String {
if s.is_empty() {
return $Str::new();
}
$Str {
hdr: $StringRepr {
data: if s.is_empty() { ptr::null() } else { s.as_ptr() },
data: s.as_ptr(),
length: s.len() as u32,
flags: F_NONE,
dataflags: DataFlags::empty(),
classflags: ClassFlags::empty(),
},
_marker: PhantomData,
}
}
}
impl From<Box<[$char_t]>> for $String<'static> {
fn from(s: Box<[$char_t]>) -> $String<'static> {
impl<'a> From<&'a Vec<$char_t>> for $Str<'a> {
fn from(s: &'a Vec<$char_t>) -> $Str<'a> {
$Str::from(&s[..])
}
}
impl<'a> From<&'a $AString> for $Str<'a> {
fn from(s: &'a $AString) -> $Str<'a> {
$Str::from(&s[..])
}
}
impl<'a> fmt::Write for $Str<'a> {
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
$AString::write_str(self, s)
}
}
impl<'a> fmt::Display for $Str<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
<$AString as fmt::Display>::fmt(self, f)
}
}
impl<'a> fmt::Debug for $Str<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
<$AString as fmt::Debug>::fmt(self, f)
}
}
impl<'a> cmp::PartialEq for $Str<'a> {
fn eq(&self, other: &$Str<'a>) -> bool {
$AString::eq(self, other)
}
}
impl<'a> cmp::PartialEq<[$char_t]> for $Str<'a> {
fn eq(&self, other: &[$char_t]) -> bool {
$AString::eq(self, other)
}
}
impl<'a, 'b> cmp::PartialEq<&'b [$char_t]> for $Str<'a> {
fn eq(&self, other: &&'b [$char_t]) -> bool {
$AString::eq(self, *other)
}
}
impl<'a> cmp::PartialEq<str> for $Str<'a> {
fn eq(&self, other: &str) -> bool {
$AString::eq(self, other)
}
}
impl<'a, 'b> cmp::PartialEq<&'b str> for $Str<'a> {
fn eq(&self, other: &&'b str) -> bool {
$AString::eq(self, *other)
}
}
#[repr(C)]
pub struct $String {
hdr: $StringRepr,
}
impl $String {
pub fn new() -> $String {
$String {
hdr: $StringRepr::new(class_flags::NULL_TERMINATED),
}
}
}
impl Drop for $String {
fn drop(&mut self) {
unsafe {
$drop(&mut **self);
}
}
}
impl Deref for $String {
type Target = $AString;
fn deref(&self) -> &$AString {
&self.hdr
}
}
impl DerefMut for $String {
fn deref_mut(&mut self) -> &mut $AString {
&mut self.hdr
}
}
impl AsRef<[$char_t]> for $String {
fn as_ref(&self) -> &[$char_t] {
&self
}
}
impl<'a> From<&'a [$char_t]> for $String {
fn from(s: &'a [$char_t]) -> $String {
let mut res = $String::new();
res.assign(&$Str::from(&s[..]));
res
}
}
impl<'a> From<&'a Vec<$char_t>> for $String {
fn from(s: &'a Vec<$char_t>) -> $String {
$String::from(&s[..])
}
}
impl<'a> From<&'a $AString> for $String {
fn from(s: &'a $AString) -> $String {
$String::from(&s[..])
}
}
impl From<Box<[$char_t]>> for $String {
fn from(s: Box<[$char_t]>) -> $String {
s.to_vec().into()
}
}
impl From<Vec<$char_t>> for $String {
fn from(mut s: Vec<$char_t>) -> $String {
assert!(s.len() < (u32::MAX as usize));
if s.is_empty() {
return $String::new();
}
// SAFETY NOTE: This method produces an F_OWNED ns[C]String from
// a Box<[$char_t]>. this is only safe because in the Gecko
// tree, we use the same allocator for Rust code as for C++
// code, meaning that our box can be legally freed with
// libc::free().
let length = s.len() as u32;
s.push(0); // null terminator
// SAFETY NOTE: This method produces an data_flags::OWNED
// ns[C]String from a Box<[$char_t]>. this is only safe
// because in the Gecko tree, we use the same allocator for
// Rust code as for C++ code, meaning that our box can be
// legally freed with libc::free().
let ptr = s.as_ptr();
mem::forget(s);
unsafe {
@ -428,71 +671,57 @@ macro_rules! define_string_types {
hdr: $StringRepr {
data: ptr,
length: length,
flags: F_OWNED,
},
_marker: PhantomData,
dataflags: data_flags::OWNED | data_flags::TERMINATED,
classflags: class_flags::NULL_TERMINATED,
}
}
}
}
impl From<Vec<$char_t>> for $String<'static> {
fn from(s: Vec<$char_t>) -> $String<'static> {
s.into_boxed_slice().into()
}
}
impl<'a> From<&'a $AString> for $String<'static> {
fn from(s: &'a $AString) -> $String<'static> {
let mut string = $String::new();
string.assign(s);
string
}
}
impl<'a> fmt::Write for $String<'a> {
impl fmt::Write for $String {
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
$AString::write_str(self, s)
}
}
impl<'a> fmt::Display for $String<'a> {
impl fmt::Display for $String {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
<$AString as fmt::Display>::fmt(self, f)
}
}
impl<'a> fmt::Debug for $String<'a> {
impl fmt::Debug for $String {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
<$AString as fmt::Debug>::fmt(self, f)
}
}
impl<'a> cmp::PartialEq for $String<'a> {
fn eq(&self, other: &$String<'a>) -> bool {
impl cmp::PartialEq for $String {
fn eq(&self, other: &$String) -> bool {
$AString::eq(self, other)
}
}
impl<'a> cmp::PartialEq<[$char_t]> for $String<'a> {
impl cmp::PartialEq<[$char_t]> for $String {
fn eq(&self, other: &[$char_t]) -> bool {
$AString::eq(self, other)
}
}
impl<'a, 'b> cmp::PartialEq<&'b [$char_t]> for $String<'a> {
fn eq(&self, other: &&'b [$char_t]) -> bool {
impl<'a> cmp::PartialEq<&'a [$char_t]> for $String {
fn eq(&self, other: &&'a [$char_t]) -> bool {
$AString::eq(self, *other)
}
}
impl<'a> cmp::PartialEq<str> for $String<'a> {
impl cmp::PartialEq<str> for $String {
fn eq(&self, other: &str) -> bool {
$AString::eq(self, other)
}
}
impl<'a, 'b> cmp::PartialEq<&'b str> for $String<'a> {
fn eq(&self, other: &&'b str) -> bool {
impl<'a> cmp::PartialEq<&'a str> for $String {
fn eq(&self, other: &&'a str) -> bool {
$AString::eq(self, *other)
}
}
@ -502,7 +731,7 @@ macro_rules! define_string_types {
/// buffer, rather than using heap allocations.
#[repr(C)]
pub struct $FixedString<'a> {
base: $String<'a>,
base: $String,
capacity: u32,
buffer: *mut $char_t,
_marker: PhantomData<&'a mut [$char_t]>,
@ -515,12 +744,7 @@ macro_rules! define_string_types {
let buf_ptr = buf.as_mut_ptr();
$FixedString {
base: $String {
hdr: $StringRepr {
data: ptr::null(),
length: 0,
flags: F_CLASS_FIXED,
},
_marker: PhantomData,
hdr: $StringRepr::new(class_flags::FIXED | class_flags::NULL_TERMINATED),
},
capacity: len as u32,
buffer: buf_ptr,
@ -600,7 +824,7 @@ macro_rules! define_string_types {
/// &[$char_type], and &$AString to a function, while still performing
/// optimized operations when passed the $AString.
pub enum $StringAdapter<'a> {
Borrowed($String<'a>),
Borrowed($Str<'a>),
Abstract(&'a $AString),
}
@ -653,7 +877,13 @@ macro_rules! define_string_types {
}
}
impl<'a> $StringLike for $String<'a> {
impl<'a> $StringLike for $Str<'a> {
fn adapt(&self) -> $StringAdapter {
$StringAdapter::Abstract(self)
}
}
impl $StringLike for $String {
fn adapt(&self) -> $StringAdapter {
$StringAdapter::Abstract(self)
}
@ -667,19 +897,19 @@ macro_rules! define_string_types {
impl $StringLike for [$char_t] {
fn adapt(&self) -> $StringAdapter {
$StringAdapter::Borrowed($String::from(self))
$StringAdapter::Borrowed($Str::from(self))
}
}
impl $StringLike for Vec<$char_t> {
fn adapt(&self) -> $StringAdapter {
$StringAdapter::Borrowed($String::from(&self[..]))
$StringAdapter::Borrowed($Str::from(&self[..]))
}
}
impl $StringLike for Box<[$char_t]> {
fn adapt(&self) -> $StringAdapter {
$StringAdapter::Borrowed($String::from(&self[..]))
$StringAdapter::Borrowed($Str::from(&self[..]))
}
}
}
@ -694,6 +924,7 @@ define_string_types! {
AString = nsACString;
String = nsCString;
Str = nsCStr;
FixedString = nsFixedCString;
StringLike = nsCStringLike;
@ -703,8 +934,10 @@ define_string_types! {
drop = Gecko_FinalizeCString;
assign = Gecko_AssignCString, Gecko_FallibleAssignCString;
take_from = Gecko_TakeFromCString, Gecko_FallibleTakeFromCString;
append = Gecko_AppendCString, Gecko_FallibleAppendCString;
set_length = Gecko_SetLengthCString, Gecko_FallibleSetLengthCString;
begin_writing = Gecko_BeginWritingCString, Gecko_FallibleBeginWritingCString;
}
impl nsACString {
@ -737,20 +970,38 @@ impl nsACString {
}
}
impl<'a> From<&'a str> for nsCString<'a> {
fn from(s: &'a str) -> nsCString<'a> {
impl<'a> From<&'a str> for nsCStr<'a> {
fn from(s: &'a str) -> nsCStr<'a> {
s.as_bytes().into()
}
}
impl From<Box<str>> for nsCString<'static> {
fn from(s: Box<str>) -> nsCString<'static> {
impl<'a> From<&'a String> for nsCStr<'a> {
fn from(s: &'a String) -> nsCStr<'a> {
nsCStr::from(&s[..])
}
}
impl<'a> From<&'a str> for nsCString {
fn from(s: &'a str) -> nsCString {
s.as_bytes().into()
}
}
impl<'a> From<&'a String> for nsCString {
fn from(s: &'a String) -> nsCString {
nsCString::from(&s[..])
}
}
impl From<Box<str>> for nsCString {
fn from(s: Box<str>) -> nsCString {
s.into_string().into()
}
}
impl From<String> for nsCString<'static> {
fn from(s: String) -> nsCString<'static> {
impl From<String> for nsCString {
fn from(s: String) -> nsCString {
s.into_bytes().into()
}
}
@ -783,19 +1034,19 @@ impl cmp::PartialEq<str> for nsACString {
impl nsCStringLike for str {
fn adapt(&self) -> nsCStringAdapter {
nsCStringAdapter::Borrowed(nsCString::from(self))
nsCStringAdapter::Borrowed(nsCStr::from(self))
}
}
impl nsCStringLike for String {
fn adapt(&self) -> nsCStringAdapter {
nsCStringAdapter::Borrowed(nsCString::from(&self[..]))
nsCStringAdapter::Borrowed(nsCStr::from(&self[..]))
}
}
impl nsCStringLike for Box<str> {
fn adapt(&self) -> nsCStringAdapter {
nsCStringAdapter::Borrowed(nsCString::from(&self[..]))
nsCStringAdapter::Borrowed(nsCStr::from(&self[..]))
}
}
@ -816,6 +1067,7 @@ define_string_types! {
AString = nsAString;
String = nsString;
Str = nsStr;
FixedString = nsFixedString;
StringLike = nsStringLike;
@ -825,8 +1077,10 @@ define_string_types! {
drop = Gecko_FinalizeString;
assign = Gecko_AssignString, Gecko_FallibleAssignString;
take_from = Gecko_TakeFromString, Gecko_FallibleTakeFromString;
append = Gecko_AppendString, Gecko_FallibleAppendString;
set_length = Gecko_SetLengthString, Gecko_FallibleSetLengthString;
begin_writing = Gecko_BeginWritingString, Gecko_FallibleBeginWritingString;
}
impl nsAString {
@ -857,12 +1111,18 @@ impl nsAString {
// NOTE: The From impl for a string slice for nsString produces a <'static>
// lifetime, as it allocates.
impl<'a> From<&'a str> for nsString<'static> {
fn from(s: &'a str) -> nsString<'static> {
impl<'a> From<&'a str> for nsString {
fn from(s: &'a str) -> nsString {
s.encode_utf16().collect::<Vec<u16>>().into()
}
}
impl<'a> From<&'a String> for nsString {
fn from(s: &'a String) -> nsString {
nsString::from(&s[..])
}
}
// Support for the write!() macro for writing to nsStrings
impl fmt::Write for nsAString {
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
@ -911,20 +1171,28 @@ extern "C" {
fn Gecko_FinalizeCString(this: *mut nsACString);
fn Gecko_AssignCString(this: *mut nsACString, other: *const nsACString);
fn Gecko_TakeFromCString(this: *mut nsACString, other: *mut nsACString);
fn Gecko_AppendCString(this: *mut nsACString, other: *const nsACString);
fn Gecko_SetLengthCString(this: *mut nsACString, length: u32);
fn Gecko_BeginWritingCString(this: *mut nsACString) -> *mut u8;
fn Gecko_FallibleAssignCString(this: *mut nsACString, other: *const nsACString) -> bool;
fn Gecko_FallibleTakeFromCString(this: *mut nsACString, other: *mut nsACString) -> bool;
fn Gecko_FallibleAppendCString(this: *mut nsACString, other: *const nsACString) -> bool;
fn Gecko_FallibleSetLengthCString(this: *mut nsACString, length: u32) -> bool;
fn Gecko_FallibleBeginWritingCString(this: *mut nsACString) -> *mut u8;
fn Gecko_FinalizeString(this: *mut nsAString);
fn Gecko_AssignString(this: *mut nsAString, other: *const nsAString);
fn Gecko_TakeFromString(this: *mut nsAString, other: *mut nsAString);
fn Gecko_AppendString(this: *mut nsAString, other: *const nsAString);
fn Gecko_SetLengthString(this: *mut nsAString, length: u32);
fn Gecko_BeginWritingString(this: *mut nsAString) -> *mut u16;
fn Gecko_FallibleAssignString(this: *mut nsAString, other: *const nsAString) -> bool;
fn Gecko_FallibleTakeFromString(this: *mut nsAString, other: *mut nsAString) -> bool;
fn Gecko_FallibleAppendString(this: *mut nsAString, other: *const nsAString) -> bool;
fn Gecko_FallibleSetLengthString(this: *mut nsAString, length: u32) -> bool;
fn Gecko_FallibleBeginWritingString(this: *mut nsAString) -> *mut u16;
// Gecko implementation in nsReadableUtils.cpp
fn Gecko_AppendUTF16toCString(this: *mut nsACString, other: *const nsAString);

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

@ -11,7 +11,7 @@ use gecko_bindings::bindings::Gecko_Atomize;
use gecko_bindings::bindings::Gecko_Atomize16;
use gecko_bindings::bindings::Gecko_ReleaseAtom;
use gecko_bindings::structs::{nsIAtom, nsIAtom_AtomKind};
use nsstring::{nsAString, nsString};
use nsstring::{nsAString, nsStr};
use precomputed_hash::PrecomputedHash;
use std::ascii::AsciiExt;
use std::borrow::{Cow, Borrow};
@ -346,7 +346,7 @@ impl<'a> From<&'a str> for Atom {
impl<'a> From<&'a [u16]> for Atom {
#[inline]
fn from(slice: &[u16]) -> Atom {
Atom::from(&*nsString::from(slice))
Atom::from(&*nsStr::from(slice))
}
}

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

@ -4086,13 +4086,13 @@ fn static_assert() {
pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T, device: &Device) {
use gecko_bindings::bindings::Gecko_SetCounterStyleToString;
use nsstring::{nsACString, nsCString};
use nsstring::{nsACString, nsCStr};
use self::longhands::list_style_type::computed_value::T;
match v {
T::CounterStyle(s) => s.to_gecko_value(&mut self.gecko.mCounterStyle, device),
T::String(s) => unsafe {
Gecko_SetCounterStyleToString(&mut self.gecko.mCounterStyle,
&nsCString::from(s) as &nsACString)
&nsCStr::from(&s) as &nsACString)
}
}
}
@ -4679,9 +4679,8 @@ fn static_assert() {
<%call expr="impl_coord_copy('word_spacing', 'mWordSpacing')"></%call>
fn clear_text_emphasis_style_if_string(&mut self) {
use nsstring::nsString;
if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
self.gecko.mTextEmphasisStyleString.assign(&nsString::new());
self.gecko.mTextEmphasisStyleString.truncate();
self.gecko.mTextEmphasisStyle = structs::NS_STYLE_TEXT_EMPHASIS_STYLE_NONE as u8;
}
}
@ -4797,10 +4796,9 @@ fn static_assert() {
fn clear_overflow_sides_if_string(&mut self) {
use gecko_bindings::structs::nsStyleTextOverflowSide;
use nsstring::nsString;
fn clear_if_string(side: &mut nsStyleTextOverflowSide) {
if side.mType == structs::NS_STYLE_TEXT_OVERFLOW_STRING as u8 {
side.mString.assign(&nsString::new());
side.mString.truncate();
side.mType = structs::NS_STYLE_TEXT_OVERFLOW_CLIP as u8;
}
}

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

@ -138,7 +138,7 @@ impl UrlMatchingFunction {
pub fn evaluate(&self, device: &Device) -> bool {
use gecko_bindings::bindings::Gecko_DocumentRule_UseForPresentation;
use gecko_bindings::structs::URLMatchingFunction as GeckoUrlMatchingFunction;
use nsstring::nsCString;
use nsstring::nsCStr;
let func = match *self {
UrlMatchingFunction::Url(_) => GeckoUrlMatchingFunction::eURL,
@ -147,7 +147,7 @@ impl UrlMatchingFunction {
UrlMatchingFunction::RegExp(_) => GeckoUrlMatchingFunction::eRegExp,
};
let pattern = nsCString::from(match *self {
let pattern = nsCStr::from(match *self {
UrlMatchingFunction::Url(ref url) => url.as_str(),
UrlMatchingFunction::UrlPrefix(ref pat) |
UrlMatchingFunction::Domain(ref pat) |