Bug 1403213 - Move nsstring into servo/support/gecko/nsstring, r=froydnj
authorNika Layzell <nika@thelayzells.com>
Mon, 23 Oct 2017 15:37:25 -0400
changeset 685798 e07ca12a3b94509be582df83e4ecdc36c13bba4d
parent 685797 d79653ad062ba1735c0506fa4f2df1e2021b3599
child 685799 a172387463ec5fa13dd814dfd11a5e90e1ac84c6
push id86016
push userkgupta@mozilla.com
push dateWed, 25 Oct 2017 01:53:44 +0000
reviewersfroydnj
bugs1403213
milestone58.0a1
Bug 1403213 - Move nsstring into servo/support/gecko/nsstring, r=froydnj MozReview-Commit-ID: 8ucStGkxmj7
intl/encoding_glue/Cargo.toml
netwerk/base/rust-url-capi/Cargo.toml
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/gtest/rust/Cargo.toml
toolkit/library/rust/Cargo.lock
toolkit/library/rust/shared/Cargo.toml
xpcom/moz.build
xpcom/rust/gtest/moz.build
xpcom/rust/gtest/nsstring/Cargo.toml
xpcom/rust/gtest/nsstring/Test.cpp
xpcom/rust/gtest/nsstring/test.rs
xpcom/rust/nserror/Cargo.toml
xpcom/rust/nsstring/Cargo.toml
xpcom/rust/nsstring/gtest/Cargo.toml
xpcom/rust/nsstring/gtest/Test.cpp
xpcom/rust/nsstring/gtest/moz.build
xpcom/rust/nsstring/gtest/test.rs
xpcom/rust/nsstring/src/lib.rs
--- a/intl/encoding_glue/Cargo.toml
+++ b/intl/encoding_glue/Cargo.toml
@@ -7,10 +7,10 @@ license = "MIT/Apache-2.0"
 
 [features]
 simd-accel = ["encoding_rs/simd-accel"]
 no-static-ideograph-encoder-tables = ["encoding_rs/no-static-ideograph-encoder-tables"]
 parallel-utf8 = ["encoding_rs/parallel-utf8"]
 
 [dependencies]
 encoding_rs = "0.7.0"
-nsstring = { path = "../../xpcom/rust/nsstring" }
+nsstring = { path = "../../servo/support/gecko/nsstring" }
 nserror = { path = "../../xpcom/rust/nserror" }
--- a/netwerk/base/rust-url-capi/Cargo.toml
+++ b/netwerk/base/rust-url-capi/Cargo.toml
@@ -4,10 +4,10 @@ version = "0.0.1"
 authors = ["Valentin Gosu <valentin.gosu@gmail.com>"]
 
 [lib]
 name = "rust_url_capi"
 
 [dependencies]
 libc = "0.2.0"
 url = "1.5.1"
-nsstring = { path = "../../../xpcom/rust/nsstring" }
+nsstring = { path = "../../../servo/support/gecko/nsstring" }
 nserror = { path = "../../../xpcom/rust/nserror" }
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -550,17 +550,17 @@ name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
- "nsstring_vendor 0.1.0",
+ "nsstring 0.1.0",
  "parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.0.1",
  "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
 
@@ -904,23 +904,16 @@ dependencies = [
 [[package]]
 name = "nsstring-gtest"
 version = "0.1.0"
 dependencies = [
  "nsstring 0.1.0",
 ]
 
 [[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"
 version = "0.1.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1297,17 +1290,17 @@ dependencies = [
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lru_cache 0.0.1",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "nsstring_vendor 0.1.0",
+ "nsstring 0.1.0",
  "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/toolkit/library/gtest/rust/Cargo.toml
+++ b/toolkit/library/gtest/rust/Cargo.toml
@@ -12,17 +12,17 @@ quantum_render = ["gkrust-shared/quantum
 cubeb-remoting = ["gkrust-shared/cubeb-remoting"]
 cubeb_pulse_rust = ["gkrust-shared/cubeb_pulse_rust"]
 gecko_debug = ["gkrust-shared/gecko_debug"]
 simd-accel = ["gkrust-shared/simd-accel"]
 no-static-ideograph-encoder-tables = ["gkrust-shared/no-static-ideograph-encoder-tables"]
 
 [dependencies]
 mp4parse-gtest = { path = "../../../../dom/media/gtest" }
-nsstring-gtest = { path = "../../../../xpcom/rust/nsstring/gtest" }
+nsstring-gtest = { path = "../../../../xpcom/rust/gtest/nsstring" }
 gkrust-shared = { path = "../../rust/shared" }
 
 [lib]
 path = "lib.rs"
 crate-type = ["staticlib"]
 test = false
 doctest = false
 bench = false
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -549,17 +549,17 @@ name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.22.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
- "nsstring_vendor 0.1.0",
+ "nsstring 0.1.0",
  "parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.0.1",
  "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
 ]
 
@@ -892,23 +892,16 @@ dependencies = [
 [[package]]
 name = "nsstring"
 version = "0.1.0"
 dependencies = [
  "bitflags 0.8.2 (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"
 version = "0.1.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1289,17 +1282,17 @@ dependencies = [
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lru_cache 0.0.1",
  "malloc_size_of 0.0.1",
  "malloc_size_of_derive 0.0.1",
  "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "nsstring_vendor 0.1.0",
+ "nsstring 0.1.0",
  "num-integer 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -3,17 +3,17 @@ name = "gkrust-shared"
 version = "0.1.0"
 authors = ["nobody@mozilla.org"]
 license = "MPL-2.0"
 description = "Shared Rust code for libxul"
 
 [dependencies]
 geckoservo = { path = "../../../../servo/ports/geckolib", optional = true }
 mp4parse_capi = { path = "../../../../media/libstagefright/binding/mp4parse_capi" }
-nsstring = { path = "../../../../xpcom/rust/nsstring" }
+nsstring = { path = "../../../../servo/support/gecko/nsstring" }
 nserror = { path = "../../../../xpcom/rust/nserror" }
 netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }
 rust_url_capi = { path = "../../../../netwerk/base/rust-url-capi" }
 webrender_bindings = { path = "../../../../gfx/webrender_bindings", optional = true }
 cubeb-pulse = { path = "../../../../media/libcubeb/cubeb-pulse-rs", optional = true, features=["pulse-dlopen"] }
 cubeb-core = { path = "../../../../media/cubeb-rs/cubeb-core", optional = true }
 cubeb = { path = "../../../../media/cubeb-rs/cubeb-api", optional = true }
 cubeb-backend = { path = "../../../../media/cubeb-rs/cubeb-backend", optional = true }
@@ -28,17 +28,17 @@ syn = { version = "0.11", features = ["f
 
 [features]
 default = []
 bindgen = ["geckoservo/bindgen"]
 servo = ["geckoservo"]
 quantum_render = ["webrender_bindings"]
 cubeb-remoting = ["cubeb-core", "cubeb", "cubeb-backend", "audioipc-client", "audioipc-server"]
 cubeb_pulse_rust = ["cubeb-pulse"]
-gecko_debug = ["geckoservo/gecko_debug"]
+gecko_debug = ["geckoservo/gecko_debug", "nsstring/gecko_debug"]
 simd-accel = ["encoding_c/simd-accel", "encoding_glue/simd-accel"]
 no-static-ideograph-encoder-tables = ["encoding_c/no-static-ideograph-encoder-tables", "encoding_glue/no-static-ideograph-encoder-tables"]
 
 [lib]
 path = "lib.rs"
 test = false
 doctest = false
 bench = false
--- a/xpcom/moz.build
+++ b/xpcom/moz.build
@@ -25,18 +25,18 @@ DIRS += [
     '../chrome',
     'build',
 ]
 
 if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_DEBUG']:
     DIRS += ['windbgdlg']
 
 TEST_DIRS += [
+    'rust/gtest',
     'tests',
-    'rust/nsstring/gtest',
 ]
 
 #  Can't build internal xptcall tests that use symbols which are not exported.
 #TEST_DIRS += [
 #    'reflect/xptinfo/tests',
 #    'reflect/xptcall/tests,
 #]
 
new file mode 100644
--- /dev/null
+++ b/xpcom/rust/gtest/moz.build
@@ -0,0 +1,11 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+UNIFIED_SOURCES += [
+    'nsstring/Test.cpp',
+]
+
+FINAL_LIBRARY = 'xul-gtest'
new file mode 100644
--- /dev/null
+++ b/xpcom/rust/gtest/nsstring/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "nsstring-gtest"
+version = "0.1.0"
+authors = ["nobody@mozilla.com"]
+license = "MPL-2.0"
+description = "Tests for rust bindings to xpcom string types"
+
+[dependencies]
+nsstring = { path = "../../../../servo/support/gecko/nsstring" }
+
+[lib]
+path = "test.rs"
rename from xpcom/rust/nsstring/gtest/Test.cpp
rename to xpcom/rust/gtest/nsstring/Test.cpp
rename from xpcom/rust/nsstring/gtest/test.rs
rename to xpcom/rust/gtest/nsstring/test.rs
--- a/xpcom/rust/nserror/Cargo.toml
+++ b/xpcom/rust/nserror/Cargo.toml
@@ -1,9 +1,9 @@
 [package]
 name = "nserror"
 version = "0.1.0"
 authors = ["Michael Layzell <michael@thelayzells.com>"]
 license = "MPL-2.0"
 description = "Rust bindings to xpcom nsresult and NS_ERROR_ values"
 
 [dependencies]
-nsstring = { path = "../nsstring" }
+nsstring = { path = "../../../servo/support/gecko/nsstring" }
deleted file mode 100644
--- a/xpcom/rust/nsstring/Cargo.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-[package]
-name = "nsstring"
-version = "0.1.0"
-authors = ["nobody@mozilla.com"]
-license = "MPL-2.0"
-description = "Rust bindings to xpcom string types"
-
-[dependencies]
-bitflags = "0.8"
deleted file mode 100644
--- a/xpcom/rust/nsstring/gtest/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "nsstring-gtest"
-version = "0.1.0"
-authors = ["nobody@mozilla.com"]
-license = "MPL-2.0"
-description = "Tests for rust bindings to xpcom string types"
-
-[dependencies]
-nsstring = { path = "../" }
-
-[lib]
-path = "test.rs"
deleted file mode 100644
--- a/xpcom/rust/nsstring/gtest/moz.build
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-UNIFIED_SOURCES += [
-    'Test.cpp'
-]
-
-FINAL_LIBRARY = 'xul-gtest'
deleted file mode 100644
--- a/xpcom/rust/nsstring/src/lib.rs
+++ /dev/null
@@ -1,1208 +0,0 @@
-//! This module provides rust bindings for the XPCOM string types.
-//!
-//! # TL;DR (what types should I use)
-//!
-//! 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` (`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 `*{const,mut} nsA[C]String` (`{const,} nsA[C]String*` in C++) for
-//! function arguments passed across the rust/C++ language boundary.
-//!
-//! There is currently no Rust equivalent to nsAuto[C]String. Implementing a
-//! type that contains a pointer to an inline buffer is difficult in Rust due
-//! to its move semantics, which require that it be safe to move a value by
-//! copying its bits. If such a type is genuinely needed at some point,
-//! https://bugzilla.mozilla.org/show_bug.cgi?id=1403506#c6 has a sketch of how
-//! to emulate it via macros.
-//!
-//! # String Types
-//!
-//! ## `nsA[C]String`
-//!
-//! The core types in this module are `nsAString` and `nsACString`. These types
-//! are zero-sized as far as rust is concerned, and are safe to pass around
-//! behind both references (in rust code), and pointers (in C++ code). They
-//! represent a handle to a XPCOM string which holds either `u16` or `u8`
-//! characters respectively. The backing character buffer is guaranteed to live
-//! as long as the reference to the `nsAString` or `nsACString`.
-//!
-//! These types in rust are simply used as dummy types. References to them
-//! represent a pointer to the beginning of a variable-sized `#[repr(C)]` struct
-//! which is common between both C++ and Rust implementations. In C++, their
-//! corresponding types are also named `nsAString` or `nsACString`, and they are
-//! defined within the `nsTSubstring.{cpp,h}` file.
-//!
-//! ### Valid Operations
-//!
-//! An `&nsA[C]String` acts like rust's `&str`, in that it is a borrowed
-//! reference to the backing data. When used as an argument to other functions
-//! on `&mut nsA[C]String`, optimizations can be performed to avoid copying
-//! buffers, as information about the backing storage is preserved.
-//!
-//! An `&mut nsA[C]String` acts like rust's `&mut Cow<str>`, in that it is a
-//! mutable reference to a potentially borrowed string, which when modified will
-//! ensure that it owns its own backing storage. This type can be appended to
-//! with the methods `.append`, `.append_utf{8,16}`, and with the `write!`
-//! macro, and can be assigned to with `.assign`.
-//!
-//! ## `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
-//! to `nsA[C]String`, which provides the methods for manipulating this type.
-//! This type's lifetime parameter, `'a`, represents the lifetime of the backing
-//! storage. When modified this type may re-allocate in order to ensure that it
-//! does not mutate its backing storage.
-//!
-//! `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.
-//!
-//! ## `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++.
-//!
-//! ## `ns[C]StringRepr`
-//!
-//! This crate also provides the type `ns[C]StringRepr` which acts conceptually
-//! 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
-//! can be useful when implementing FFI types which contain `ns[C]String` members
-//! which invoke their member's destructors through C++ code.
-
-#![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::mem;
-use std::fmt;
-use std::cmp;
-use std::str;
-use std::u32;
-use std::os::raw::c_void;
-
-///////////////////////////////////
-// Internal Implementation 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 INLINE = 1 << 4, // mData points to a writable, inline buffer
-            const LITERAL = 1 << 5, // mData points to a string literal; TERMINATED will also be set
-        }
-    }
-}
-
-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 INLINE = 1 << 0, // |this|'s buffer is inline
-            const NULL_TERMINATED = 1 << 1, // |this| requires its buffer is null-terminated
-        }
-    }
-}
-
-use data_flags::DataFlags;
-use class_flags::ClassFlags;
-
-////////////////////////////////////
-// Generic String Bindings Macros //
-////////////////////////////////////
-
-macro_rules! define_string_types {
-    {
-        char_t = $char_t: ty;
-
-        AString = $AString: ident;
-        String = $String: ident;
-        Str = $Str: ident;
-
-        StringLike = $StringLike: ident;
-        StringAdapter = $StringAdapter: ident;
-
-        StringRepr = $StringRepr: ident;
-
-        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
-        /// compatibility with the C++ ns[C]String type.
-        ///
-        /// This type may also be used in place of a C++ ns[C]String inside of
-        /// struct definitions which are shared with C++, as it has identical
-        /// layout to our ns[C]String type.
-        ///
-        /// This struct will leak its data if dropped from rust. See the module
-        /// documentation for more information on this type.
-        #[repr(C)]
-        #[derive(Debug)]
-        pub struct $StringRepr {
-            data: *const $char_t,
-            length: 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 {
-            type Target = $AString;
-            fn deref(&self) -> &$AString {
-                unsafe {
-                    mem::transmute(self)
-                }
-            }
-        }
-
-        impl DerefMut for $StringRepr {
-            fn deref_mut(&mut self) -> &mut $AString {
-                unsafe {
-                    mem::transmute(self)
-                }
-            }
-        }
-
-        /// This type is the abstract type which is used for interacting with
-        /// strings in rust. Each string type can derefence to an instance of
-        /// this type, which provides the useful operations on strings.
-        ///
-        /// NOTE: Rust thinks this type has a size of 0, because the data
-        /// associated with it is not necessarially safe to move. It is not safe
-        /// to construct a nsAString yourself, unless it is received by
-        /// dereferencing one of these types.
-        ///
-        /// NOTE: The `[u8; 0]` member is zero sized, and only exists to prevent
-        /// the construction by code outside of this module. It is used instead
-        /// of a private `()` member because the `improper_ctypes` lint complains
-        /// about some ZST members in `extern "C"` function declarations.
-        #[repr(C)]
-        pub struct $AString {
-            _prohibit_constructor: [u8; 0],
-        }
-
-        impl $AString {
-            /// Assign the value of `other` into self, overwriting any value
-            /// currently stored. Performs an optimized assignment when possible
-            /// if `other` is a `nsA[C]String`.
-            pub fn assign<T: $StringLike + ?Sized>(&mut self, other: &T) {
-                unsafe { $assign(self, other.adapt().as_ptr()) };
-            }
-
-            /// Assign the value of `other` into self, overwriting any value
-            /// currently stored. Performs an optimized assignment when possible
-            /// if `other` is a `nsA[C]String`.
-            ///
-            /// Returns Ok(()) on success, and Err(()) if the allocation failed.
-            pub fn fallible_assign<T: $StringLike + ?Sized>(&mut self, other: &T) -> Result<(), ()> {
-                if unsafe { $fallible_assign(self, other.adapt().as_ptr()) } {
-                    Ok(())
-                } else {
-                    Err(())
-                }
-            }
-
-            /// 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()) };
-            }
-
-            /// Append the value of `other` into self.
-            ///
-            /// Returns Ok(()) on success, and Err(()) if the allocation failed.
-            pub fn fallible_append<T: $StringLike + ?Sized>(&mut self, other: &T) -> Result<(), ()> {
-                if unsafe { $fallible_append(self, other.adapt().as_ptr()) } {
-                    Ok(())
-                } else {
-                    Err(())
-                }
-            }
-
-            /// Set the length of the string to the passed-in length, and expand
-            /// the backing capacity to match. This method is unsafe as it can
-            /// expose uninitialized memory when len is greater than the current
-            /// length of the string.
-            pub unsafe fn set_length(&mut self, len: u32) {
-                $set_length(self, len);
-            }
-
-            /// Set the length of the string to the passed-in length, and expand
-            /// the backing capacity to match. This method is unsafe as it can
-            /// expose uninitialized memory when len is greater than the current
-            /// length of the string.
-            ///
-            /// Returns Ok(()) on success, and Err(()) if the allocation failed.
-            pub unsafe fn fallible_set_length(&mut self, len: u32) -> Result<(), ()> {
-                if $fallible_set_length(self, len) {
-                    Ok(())
-                } else {
-                    Err(())
-                }
-            }
-
-            pub fn truncate(&mut self) {
-                unsafe {
-                    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 {
-            type Target = [$char_t];
-            fn deref(&self) -> &[$char_t] {
-                unsafe {
-                    // All $AString values point to a struct prefix which is
-                    // identical to $StringRepr, this we can transmute `self`
-                    // into $StringRepr to get the reference to the underlying
-                    // data.
-                    let this: &$StringRepr = mem::transmute(self);
-                    if this.data.is_null() {
-                        debug_assert!(this.length == 0);
-                        // Use an arbitrary non-null value as the pointer
-                        slice::from_raw_parts(0x1 as *const $char_t, 0)
-                    } else {
-                        slice::from_raw_parts(this.data, this.length as usize)
-                    }
-                }
-            }
-        }
-
-        impl AsRef<[$char_t]> for $AString {
-            fn as_ref(&self) -> &[$char_t] {
-                self
-            }
-        }
-
-        impl cmp::PartialEq for $AString {
-            fn eq(&self, other: &$AString) -> bool {
-                &self[..] == &other[..]
-            }
-        }
-
-        impl cmp::PartialEq<[$char_t]> for $AString {
-            fn eq(&self, other: &[$char_t]) -> bool {
-                &self[..] == other
-            }
-        }
-
-        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)
-            }
-        }
-
-        #[repr(C)]
-        pub struct $Str<'a> {
-            hdr: $StringRepr,
-            _marker: PhantomData<&'a [$char_t]>,
-        }
-
-        impl $Str<'static> {
-            pub fn new() -> $Str<'static> {
-                $Str {
-                    hdr: $StringRepr::new(ClassFlags::empty()),
-                    _marker: PhantomData,
-                }
-            }
-        }
-
-        impl<'a> Drop for $Str<'a> {
-            fn drop(&mut self) {
-                unsafe {
-                    $drop(&mut **self);
-                }
-            }
-        }
-
-        impl<'a> Deref for $Str<'a> {
-            type Target = $AString;
-            fn deref(&self) -> &$AString {
-                &self.hdr
-            }
-        }
-
-        impl<'a> DerefMut for $Str<'a> {
-            fn deref_mut(&mut self) -> &mut $AString {
-                &mut self.hdr
-            }
-        }
-
-        impl<'a> AsRef<[$char_t]> for $Str<'a> {
-            fn as_ref(&self) -> &[$char_t] {
-                &self
-            }
-        }
-
-        impl<'a> From<&'a [$char_t]> for $Str<'a> {
-            fn from(s: &'a [$char_t]) -> $Str<'a> {
-                assert!(s.len() < (u32::MAX as usize));
-                if s.is_empty() {
-                    return $Str::new();
-                }
-                $Str {
-                    hdr: $StringRepr {
-                        data: s.as_ptr(),
-                        length: s.len() as u32,
-                        dataflags: DataFlags::empty(),
-                        classflags: ClassFlags::empty(),
-                    },
-                    _marker: PhantomData,
-                }
-            }
-        }
-
-        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();
-                }
-
-                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 {
-                    Gecko_IncrementStringAdoptCount(ptr as *mut _);
-                }
-                $String {
-                    hdr: $StringRepr {
-                        data: ptr,
-                        length: length,
-                        dataflags: data_flags::OWNED | data_flags::TERMINATED,
-                        classflags: class_flags::NULL_TERMINATED,
-                    }
-                }
-            }
-        }
-
-        impl fmt::Write for $String {
-            fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
-                $AString::write_str(self, s)
-            }
-        }
-
-        impl fmt::Display for $String {
-            fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-                <$AString as fmt::Display>::fmt(self, f)
-            }
-        }
-
-        impl fmt::Debug for $String {
-            fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-                <$AString as fmt::Debug>::fmt(self, f)
-            }
-        }
-
-        impl cmp::PartialEq for $String {
-            fn eq(&self, other: &$String) -> bool {
-                $AString::eq(self, other)
-            }
-        }
-
-        impl cmp::PartialEq<[$char_t]> for $String {
-            fn eq(&self, other: &[$char_t]) -> bool {
-                $AString::eq(self, other)
-            }
-        }
-
-        impl<'a> cmp::PartialEq<&'a [$char_t]> for $String {
-            fn eq(&self, other: &&'a [$char_t]) -> bool {
-                $AString::eq(self, *other)
-            }
-        }
-
-        impl cmp::PartialEq<str> for $String {
-            fn eq(&self, other: &str) -> bool {
-                $AString::eq(self, other)
-            }
-        }
-
-        impl<'a> cmp::PartialEq<&'a str> for $String {
-            fn eq(&self, other: &&'a str) -> bool {
-                $AString::eq(self, *other)
-            }
-        }
-
-        /// An adapter type to allow for passing both types which coerce to
-        /// &[$char_type], and &$AString to a function, while still performing
-        /// optimized operations when passed the $AString.
-        pub enum $StringAdapter<'a> {
-            Borrowed($Str<'a>),
-            Abstract(&'a $AString),
-        }
-
-        impl<'a> $StringAdapter<'a> {
-            fn as_ptr(&self) -> *const $AString {
-                &**self
-            }
-        }
-
-        impl<'a> Deref for $StringAdapter<'a> {
-            type Target = $AString;
-
-            fn deref(&self) -> &$AString {
-                match *self {
-                    $StringAdapter::Borrowed(ref s) => s,
-                    $StringAdapter::Abstract(ref s) => s,
-                }
-            }
-        }
-
-        /// This trait is implemented on types which are `ns[C]String`-like, in
-        /// that they can at very low cost be converted to a borrowed
-        /// `&nsA[C]String`. Unfortunately, the intermediate type
-        /// `ns[C]StringAdapter` is required as well due to types like `&[u8]`
-        /// needing to be (cheaply) wrapped in a `nsCString` on the stack to
-        /// create the `&nsACString`.
-        ///
-        /// This trait is used to DWIM when calling the methods on
-        /// `nsA[C]String`.
-        pub trait $StringLike {
-            fn adapt(&self) -> $StringAdapter;
-        }
-
-        impl<'a, T: $StringLike + ?Sized> $StringLike for &'a T {
-            fn adapt(&self) -> $StringAdapter {
-                <T as $StringLike>::adapt(*self)
-            }
-        }
-
-        impl<'a, T> $StringLike for borrow::Cow<'a, T>
-            where T: $StringLike + borrow::ToOwned + ?Sized {
-            fn adapt(&self) -> $StringAdapter {
-                <T as $StringLike>::adapt(self.as_ref())
-            }
-        }
-
-        impl $StringLike for $AString {
-            fn adapt(&self) -> $StringAdapter {
-                $StringAdapter::Abstract(self)
-            }
-        }
-
-        impl<'a> $StringLike for $Str<'a> {
-            fn adapt(&self) -> $StringAdapter {
-                $StringAdapter::Abstract(self)
-            }
-        }
-
-        impl $StringLike for $String {
-            fn adapt(&self) -> $StringAdapter {
-                $StringAdapter::Abstract(self)
-            }
-        }
-
-        impl $StringLike for [$char_t] {
-            fn adapt(&self) -> $StringAdapter {
-                $StringAdapter::Borrowed($Str::from(self))
-            }
-        }
-
-        impl $StringLike for Vec<$char_t> {
-            fn adapt(&self) -> $StringAdapter {
-                $StringAdapter::Borrowed($Str::from(&self[..]))
-            }
-        }
-
-        impl $StringLike for Box<[$char_t]> {
-            fn adapt(&self) -> $StringAdapter {
-                $StringAdapter::Borrowed($Str::from(&self[..]))
-            }
-        }
-    }
-}
-
-///////////////////////////////////////////
-// Bindings for nsCString (u8 char type) //
-///////////////////////////////////////////
-
-define_string_types! {
-    char_t = u8;
-
-    AString = nsACString;
-    String = nsCString;
-    Str = nsCStr;
-
-    StringLike = nsCStringLike;
-    StringAdapter = nsCStringAdapter;
-
-    StringRepr = nsCStringRepr;
-
-    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 {
-    pub fn assign_utf16<T: nsStringLike + ?Sized>(&mut self, other: &T) {
-        self.truncate();
-        self.append_utf16(other);
-    }
-
-    pub fn fallible_assign_utf16<T: nsStringLike + ?Sized>(&mut self, other: &T) -> Result<(), ()> {
-        self.truncate();
-        self.fallible_append_utf16(other)
-    }
-
-    pub fn append_utf16<T: nsStringLike + ?Sized>(&mut self, other: &T) {
-        unsafe {
-            Gecko_AppendUTF16toCString(self, other.adapt().as_ptr());
-        }
-    }
-
-    pub fn fallible_append_utf16<T: nsStringLike + ?Sized>(&mut self, other: &T) -> Result<(), ()> {
-        if unsafe { Gecko_FallibleAppendUTF16toCString(self, other.adapt().as_ptr()) } {
-            Ok(())
-        } else {
-            Err(())
-        }
-    }
-
-    pub unsafe fn as_str_unchecked(&self) -> &str {
-        str::from_utf8_unchecked(self)
-    }
-}
-
-impl<'a> From<&'a str> for nsCStr<'a> {
-    fn from(s: &'a str) -> nsCStr<'a> {
-        s.as_bytes().into()
-    }
-}
-
-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 {
-    fn from(s: String) -> nsCString {
-        s.into_bytes().into()
-    }
-}
-
-// Support for the write!() macro for appending to nsACStrings
-impl fmt::Write for nsACString {
-    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
-        self.append(s);
-        Ok(())
-    }
-}
-
-impl fmt::Display for nsACString {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        fmt::Display::fmt(&String::from_utf8_lossy(&self[..]), f)
-    }
-}
-
-impl fmt::Debug for nsACString {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        fmt::Debug::fmt(&String::from_utf8_lossy(&self[..]), f)
-    }
-}
-
-impl cmp::PartialEq<str> for nsACString {
-    fn eq(&self, other: &str) -> bool {
-        &self[..] == other.as_bytes()
-    }
-}
-
-impl nsCStringLike for str {
-    fn adapt(&self) -> nsCStringAdapter {
-        nsCStringAdapter::Borrowed(nsCStr::from(self))
-    }
-}
-
-impl nsCStringLike for String {
-    fn adapt(&self) -> nsCStringAdapter {
-        nsCStringAdapter::Borrowed(nsCStr::from(&self[..]))
-    }
-}
-
-impl nsCStringLike for Box<str> {
-    fn adapt(&self) -> nsCStringAdapter {
-        nsCStringAdapter::Borrowed(nsCStr::from(&self[..]))
-    }
-}
-
-///////////////////////////////////////////
-// Bindings for nsString (u16 char type) //
-///////////////////////////////////////////
-
-define_string_types! {
-    char_t = u16;
-
-    AString = nsAString;
-    String = nsString;
-    Str = nsStr;
-
-    StringLike = nsStringLike;
-    StringAdapter = nsStringAdapter;
-
-    StringRepr = nsStringRepr;
-
-    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 {
-    pub fn assign_utf8<T: nsCStringLike + ?Sized>(&mut self, other: &T) {
-        self.truncate();
-        self.append_utf8(other);
-    }
-
-    pub fn fallible_assign_utf8<T: nsCStringLike + ?Sized>(&mut self, other: &T) -> Result<(), ()> {
-        self.truncate();
-        self.fallible_append_utf8(other)
-    }
-
-    pub fn append_utf8<T: nsCStringLike + ?Sized>(&mut self, other: &T) {
-        unsafe {
-            Gecko_AppendUTF8toString(self, other.adapt().as_ptr());
-        }
-    }
-
-    pub fn fallible_append_utf8<T: nsCStringLike + ?Sized>(&mut self, other: &T) -> Result<(), ()> {
-        if unsafe { Gecko_FallibleAppendUTF8toString(self, other.adapt().as_ptr()) } {
-            Ok(())
-        } else {
-            Err(())
-        }
-    }
-}
-
-// NOTE: The From impl for a string slice for nsString produces a <'static>
-// lifetime, as it allocates.
-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> {
-        // Directly invoke gecko's routines for appending utf8 strings to
-        // nsAString values, to avoid as much overhead as possible
-        self.append_utf8(s);
-        Ok(())
-    }
-}
-
-impl fmt::Display for nsAString {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        fmt::Display::fmt(&String::from_utf16_lossy(&self[..]), f)
-    }
-}
-
-impl fmt::Debug for nsAString {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
-        fmt::Debug::fmt(&String::from_utf16_lossy(&self[..]), f)
-    }
-}
-
-impl cmp::PartialEq<str> for nsAString {
-    fn eq(&self, other: &str) -> bool {
-        other.encode_utf16().eq(self.iter().cloned())
-    }
-}
-
-#[cfg(not(debug_assertions))]
-#[allow(non_snake_case)]
-unsafe fn Gecko_IncrementStringAdoptCount(_: *mut c_void) {}
-
-extern "C" {
-    #[cfg(debug_assertions)]
-    fn Gecko_IncrementStringAdoptCount(data: *mut c_void);
-
-    // Gecko implementation in nsSubstring.cpp
-    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);
-    fn Gecko_AppendUTF8toString(this: *mut nsAString, other: *const nsACString);
-    fn Gecko_FallibleAppendUTF16toCString(this: *mut nsACString, other: *const nsAString) -> bool;
-    fn Gecko_FallibleAppendUTF8toString(this: *mut nsAString, other: *const nsACString) -> bool;
-}
-
-//////////////////////////////////////
-// Repr Validation Helper Functions //
-//////////////////////////////////////
-
-pub mod test_helpers {
-    //! This module only exists to help with ensuring that the layout of the
-    //! structs inside of rust and C++ are identical.
-    //!
-    //! It is public to ensure that these testing functions are avaliable to
-    //! gtest code.
-
-    use super::{
-        nsCString,
-        nsString,
-        nsCStr,
-        nsStr,
-        nsCStringRepr,
-        nsStringRepr,
-        data_flags,
-        class_flags,
-    };
-    use std::mem;
-
-    /// Generates an #[no_mangle] extern "C" function which returns the size and
-    /// alignment of the given type with the given name.
-    macro_rules! size_align_check {
-        ($T:ty, $fname:ident) => {
-            #[no_mangle]
-            #[allow(non_snake_case)]
-            pub extern fn $fname(size: *mut usize, align: *mut usize) {
-                unsafe {
-                    *size = mem::size_of::<$T>();
-                    *align = mem::align_of::<$T>();
-                }
-            }
-        };
-        ($T:ty, $U:ty, $V:ty, $fname:ident) => {
-            #[no_mangle]
-            #[allow(non_snake_case)]
-            pub extern fn $fname(size: *mut usize, align: *mut usize) {
-                unsafe {
-                    *size = mem::size_of::<$T>();
-                    *align = mem::align_of::<$T>();
-
-                    assert_eq!(*size, mem::size_of::<$U>());
-                    assert_eq!(*align, mem::align_of::<$U>());
-                    assert_eq!(*size, mem::size_of::<$V>());
-                    assert_eq!(*align, mem::align_of::<$V>());
-                }
-            }
-        }
-    }
-
-    size_align_check!(nsStringRepr, nsString, nsStr<'static>,
-                      Rust_Test_ReprSizeAlign_nsString);
-    size_align_check!(nsCStringRepr, nsCString, nsCStr<'static>,
-                      Rust_Test_ReprSizeAlign_nsCString);
-
-    /// Generates a $[no_mangle] extern "C" function which returns the size,
-    /// alignment and offset in the parent struct of a given member, with the
-    /// given name.
-    ///
-    /// This method can trigger Undefined Behavior if the accessing the member
-    /// $member on a given type would use that type's `Deref` implementation.
-    macro_rules! member_check {
-        ($T:ty, $member:ident, $method:ident) => {
-            #[no_mangle]
-            #[allow(non_snake_case)]
-            pub extern fn $method(size: *mut usize,
-                                  align: *mut usize,
-                                  offset: *mut usize) {
-                unsafe {
-                    // Create a temporary value of type T to get offsets, sizes
-                    // and aligns off of
-                    let tmp: $T = mem::zeroed();
-                    *size = mem::size_of_val(&tmp.$member);
-                    *align = mem::align_of_val(&tmp.$member);
-                    *offset =
-                        (&tmp.$member as *const _ as usize) -
-                        (&tmp as *const _ as usize);
-                    mem::forget(tmp);
-                }
-            }
-        };
-        ($T:ty, $U:ty, $V:ty, $member:ident, $method:ident) => {
-            #[no_mangle]
-            #[allow(non_snake_case)]
-            pub extern fn $method(size: *mut usize,
-                                  align: *mut usize,
-                                  offset: *mut usize) {
-                unsafe {
-                    // Create a temporary value of type T to get offsets, sizes
-                    // and alignments from.
-                    let tmp: $T = mem::zeroed();
-                    *size = mem::size_of_val(&tmp.$member);
-                    *align = mem::align_of_val(&tmp.$member);
-                    *offset =
-                        (&tmp.$member as *const _ as usize) -
-                        (&tmp as *const _ as usize);
-                    mem::forget(tmp);
-
-                    let tmp: $U = mem::zeroed();
-                    assert_eq!(*size, mem::size_of_val(&tmp.hdr.$member));
-                    assert_eq!(*align, mem::align_of_val(&tmp.hdr.$member));
-                    assert_eq!(*offset,
-                               (&tmp.hdr.$member as *const _ as usize) -
-                               (&tmp as *const _ as usize));
-                    mem::forget(tmp);
-
-                    let tmp: $V = mem::zeroed();
-                    assert_eq!(*size, mem::size_of_val(&tmp.hdr.$member));
-                    assert_eq!(*align, mem::align_of_val(&tmp.hdr.$member));
-                    assert_eq!(*offset,
-                               (&tmp.hdr.$member as *const _ as usize) -
-                               (&tmp as *const _ as usize));
-                    mem::forget(tmp);
-                }
-            }
-        }
-    }
-
-    member_check!(nsStringRepr, nsString, nsStr<'static>,
-                  data, Rust_Test_Member_nsString_mData);
-    member_check!(nsStringRepr, nsString, nsStr<'static>,
-                  length, Rust_Test_Member_nsString_mLength);
-    member_check!(nsStringRepr, nsString, nsStr<'static>,
-                  dataflags, Rust_Test_Member_nsString_mDataFlags);
-    member_check!(nsStringRepr, nsString, nsStr<'static>,
-                  classflags, Rust_Test_Member_nsString_mClassFlags);
-    member_check!(nsCStringRepr, nsCString, nsCStr<'static>,
-                  data, Rust_Test_Member_nsCString_mData);
-    member_check!(nsCStringRepr, nsCString, nsCStr<'static>,
-                  length, Rust_Test_Member_nsCString_mLength);
-    member_check!(nsCStringRepr, nsCString, nsCStr<'static>,
-                  dataflags, Rust_Test_Member_nsCString_mDataFlags);
-    member_check!(nsCStringRepr, nsCString, nsCStr<'static>,
-                  classflags, Rust_Test_Member_nsCString_mClassFlags);
-
-    #[no_mangle]
-    #[allow(non_snake_case)]
-    pub extern fn Rust_Test_NsStringFlags(f_terminated: *mut u16,
-                                          f_voided: *mut u16,
-                                          f_shared: *mut u16,
-                                          f_owned: *mut u16,
-                                          f_inline: *mut u16,
-                                          f_literal: *mut u16,
-                                          f_class_inline: *mut u16,
-                                          f_class_null_terminated: *mut u16) {
-        unsafe {
-            *f_terminated = data_flags::TERMINATED.bits();
-            *f_voided = data_flags::VOIDED.bits();
-            *f_shared = data_flags::SHARED.bits();
-            *f_owned = data_flags::OWNED.bits();
-            *f_inline = data_flags::INLINE.bits();
-            *f_literal = data_flags::LITERAL.bits();
-            *f_class_inline = class_flags::INLINE.bits();
-            *f_class_null_terminated = class_flags::NULL_TERMINATED.bits();
-        }
-    }
-}