diff options
author | rohan.prinja <rohan.prinja@samsung.com> | 2015-10-27 17:58:34 +0900 |
---|---|---|
committer | rohan.prinja <rohan.prinja@samsung.com> | 2015-10-30 20:26:29 +0900 |
commit | 45224028dbc1d75e6dfc8add19ff8e997c7ebb99 (patch) | |
tree | f5a113706605564ec491dbf9710842d79e5b2e5c /components/script/dom/bindings | |
parent | bb2536cd014676263f5bfd5d98cf0fc69d2abee0 (diff) | |
download | servo-45224028dbc1d75e6dfc8add19ff8e997c7ebb99.tar.gz servo-45224028dbc1d75e6dfc8add19ff8e997c7ebb99.zip |
more refactoring
Diffstat (limited to 'components/script/dom/bindings')
-rw-r--r-- | components/script/dom/bindings/callback.rs | 2 | ||||
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 7 | ||||
-rw-r--r-- | components/script/dom/bindings/conversions.rs | 4 | ||||
-rw-r--r-- | components/script/dom/bindings/global.rs | 3 | ||||
-rw-r--r-- | components/script/dom/bindings/inheritance.rs | 4 | ||||
-rw-r--r-- | components/script/dom/bindings/js.rs | 3 | ||||
-rw-r--r-- | components/script/dom/bindings/mod.rs | 3 | ||||
-rw-r--r-- | components/script/dom/bindings/refcounted.rs | 3 | ||||
-rw-r--r-- | components/script/dom/bindings/reflector.rs | 79 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 3 | ||||
-rw-r--r-- | components/script/dom/bindings/utils.rs | 239 | ||||
-rw-r--r-- | components/script/dom/bindings/xmlname.rs | 176 |
12 files changed, 276 insertions, 250 deletions
diff --git a/components/script/dom/bindings/callback.rs b/components/script/dom/bindings/callback.rs index a879e469e27..1b067c5c596 100644 --- a/components/script/dom/bindings/callback.rs +++ b/components/script/dom/bindings/callback.rs @@ -6,7 +6,7 @@ use dom::bindings::error::{Error, Fallible}; use dom::bindings::global::global_object_for_js_object; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use js::jsapi::GetGlobalForObjectCrossCompartment; use js::jsapi::{Heap, MutableHandleObject, RootedObject, RootedValue}; use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject}; diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 51a4653279f..bd81592d43c 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -5197,6 +5197,7 @@ class CGBindingRoot(CGThing): 'dom::bindings::global::global_object_for_js_object', 'dom::bindings::js::{JS, Root, RootedReference}', 'dom::bindings::js::{OptionalRootedReference}', + 'dom::bindings::reflector::{Reflectable}', 'dom::bindings::utils::{create_dom_global, do_create_interface_objects}', 'dom::bindings::utils::ConstantSpec', 'dom::bindings::utils::{DOMClass}', @@ -5206,7 +5207,6 @@ class CGBindingRoot(CGThing): 'dom::bindings::utils::{finalize_global, trace_global}', 'dom::bindings::utils::has_property_on_prototype', 'dom::bindings::utils::is_platform_object', - 'dom::bindings::utils::{Reflectable}', 'dom::bindings::utils::throwing_constructor', 'dom::bindings::utils::get_dictionary_property', 'dom::bindings::utils::set_dictionary_property', @@ -5915,10 +5915,11 @@ class GlobalGenRoots(): descriptors = config.getDescriptors(register=True, isCallback=False) imports = [CGGeneric("use dom::types::*;\n"), - CGGeneric("use dom::bindings::conversions::{Castable, DerivedFrom, get_dom_class};\n"), + CGGeneric("use dom::bindings::conversions::{DerivedFrom, get_dom_class};\n"), + CGGeneric("use dom::bindings::inheritance::Castable;\n"), CGGeneric("use dom::bindings::js::{JS, LayoutJS, Root};\n"), CGGeneric("use dom::bindings::trace::JSTraceable;\n"), - CGGeneric("use dom::bindings::utils::Reflectable;\n"), + CGGeneric("use dom::bindings::reflector::Reflectable;\n"), CGGeneric("use js::jsapi::JSTracer;\n\n"), CGGeneric("use std::mem;\n\n")] allprotos = [] diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index c8f3b986623..1da266efe4c 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -38,7 +38,8 @@ use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; use dom::bindings::num::Finite; use dom::bindings::str::{ByteString, USVString}; -use dom::bindings::utils::{DOMClass, Reflectable, Reflector}; +use dom::bindings::reflector::{Reflectable, Reflector}; +use dom::bindings::utils::DOMClass; use js; use js::glue::{GetProxyPrivate, IsWrapper, RUST_JS_NumberValue}; use js::glue::{RUST_JSID_IS_STRING, RUST_JSID_TO_STRING, UnwrapObject}; @@ -56,7 +57,6 @@ use libc; use num::Float; use num::traits::{Bounded, Zero}; use std::borrow::ToOwned; -use std::mem; use std::rc::Rc; use std::{char, ptr, slice}; use util::str::DOMString; diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index a1a1c68c8c0..d0b38196608 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -11,7 +11,8 @@ use devtools_traits::ScriptToDevtoolsControlMsg; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::conversions::native_from_reflector_jsmanaged; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::reflector::Reflector; +use dom::bindings::reflector::Reflectable; use dom::window::{self, ScriptHelpers}; use dom::workerglobalscope::WorkerGlobalScope; use ipc_channel::ipc::IpcSender; diff --git a/components/script/dom/bindings/inheritance.rs b/components/script/dom/bindings/inheritance.rs index 5878c44c5f3..6ee06999563 100644 --- a/components/script/dom/bindings/inheritance.rs +++ b/components/script/dom/bindings/inheritance.rs @@ -2,9 +2,11 @@ * 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/. */ +//! The `Castable` trait. + use dom::bindings::conversions::get_dom_class; use dom::bindings::conversions::{DerivedFrom, IDLInterface}; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use std::mem; /// A trait to hold the cast functions of IDL interfaces that either derive diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 388a8ba81ef..d347b00bb4f 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -28,7 +28,8 @@ use dom::bindings::conversions::DerivedFrom; use dom::bindings::inheritance::Castable; use dom::bindings::trace::JSTraceable; use dom::bindings::trace::trace_reflector; -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::reflector::Reflector; +use dom::bindings::reflector::Reflectable; use dom::node::Node; use js::jsapi::{Heap, JSObject, JSTracer}; use js::jsval::JSVal; diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs index 394c7b722bf..f4b795f8c58 100644 --- a/components/script/dom/bindings/mod.rs +++ b/components/script/dom/bindings/mod.rs @@ -137,14 +137,17 @@ pub mod cell; pub mod conversions; pub mod error; pub mod global; +pub mod inheritance; pub mod js; pub mod num; pub mod proxyhandler; pub mod refcounted; +pub mod reflector; pub mod str; pub mod structuredclone; pub mod trace; pub mod utils; +pub mod xmlname; /// Generated JS-Rust bindings. #[allow(missing_docs, non_snake_case)] diff --git a/components/script/dom/bindings/refcounted.rs b/components/script/dom/bindings/refcounted.rs index ee8647be3ce..e101d2bbd83 100644 --- a/components/script/dom/bindings/refcounted.rs +++ b/components/script/dom/bindings/refcounted.rs @@ -25,7 +25,8 @@ use core::nonzero::NonZero; use dom::bindings::js::Root; use dom::bindings::trace::trace_reflector; -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::reflector::Reflector; +use dom::bindings::reflector::Reflectable; use js::jsapi::{JSContext, JSTracer}; use libc; use script_task::{CommonScriptMsg, ScriptChan}; diff --git a/components/script/dom/bindings/reflector.rs b/components/script/dom/bindings/reflector.rs new file mode 100644 index 00000000000..3279f4de55e --- /dev/null +++ b/components/script/dom/bindings/reflector.rs @@ -0,0 +1,79 @@ +/* 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/. */ + +//! The `Reflector` struct. + +use dom::bindings::global::GlobalRef; +use dom::bindings::js::Root; +use js::jsapi::{HandleObject, JSContext, JSObject}; +use std::cell::UnsafeCell; +use std::ptr; + +/// Create the reflector for a new DOM object and yield ownership to the +/// reflector. +pub fn reflect_dom_object<T: Reflectable> + (obj: Box<T>, + global: GlobalRef, + wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>) + -> Root<T> { + wrap_fn(global.get_cx(), global, obj) +} + +/// A struct to store a reference to the reflector of a DOM object. +#[allow(raw_pointer_derive, unrooted_must_root)] +#[must_root] +#[servo_lang = "reflector"] +#[derive(HeapSizeOf)] +// If you're renaming or moving this field, update the path in plugins::reflector as well +pub struct Reflector { + #[ignore_heap_size_of = "defined and measured in rust-mozjs"] + object: UnsafeCell<*mut JSObject>, +} + +#[allow(unrooted_must_root)] +impl PartialEq for Reflector { + fn eq(&self, other: &Reflector) -> bool { + unsafe { *self.object.get() == *other.object.get() } + } +} + +impl Reflector { + /// Get the reflector. + #[inline] + pub fn get_jsobject(&self) -> HandleObject { + unsafe { HandleObject::from_marked_location(self.object.get()) } + } + + /// Initialize the reflector. (May be called only once.) + pub fn set_jsobject(&mut self, object: *mut JSObject) { + unsafe { + let obj = self.object.get(); + assert!((*obj).is_null()); + assert!(!object.is_null()); + *obj = object; + } + } + + /// Return a pointer to the memory location at which the JS reflector + /// object is stored. Used to root the reflector, as + /// required by the JSAPI rooting APIs. + pub fn rootable(&self) -> *mut *mut JSObject { + self.object.get() + } + + /// Create an uninitialized `Reflector`. + pub fn new() -> Reflector { + Reflector { + object: UnsafeCell::new(ptr::null_mut()) + } + } +} + +/// A trait to provide access to the `Reflector` for a DOM object. +pub trait Reflectable { + /// Returns the receiver's reflector. + fn reflector(&self) -> &Reflector; + /// Initializes the Reflector + fn init_reflector(&mut self, obj: *mut JSObject); +}
\ No newline at end of file diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index c78429f8368..6ed7e45c45a 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -35,7 +35,8 @@ use canvas_traits::{CompositionOrBlending, LineCapStyle, LineJoinStyle, Repetiti use cssparser::RGBA; use dom::bindings::js::{JS, Root}; use dom::bindings::refcounted::Trusted; -use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler}; +use dom::bindings::reflector::{Reflectable, Reflector}; +use dom::bindings::utils::WindowProxyHandler; use encoding::types::EncodingRef; use euclid::length::Length as EuclidLength; use euclid::matrix2d::Matrix2D; diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 6fae276271c..72c0745d3b1 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -49,14 +49,10 @@ use js::rust::{GCMethods, ToString, define_methods, define_properties}; use js::{JSFUN_CONSTRUCTOR, JSPROP_ENUMERATE, JS_CALLEE}; use js::{JSPROP_PERMANENT, JSPROP_READONLY}; use libc::{self, c_uint}; -use std::cell::UnsafeCell; -use std::cmp::PartialEq; use std::default::Default; use std::ffi::CString; use std::ptr; -use string_cache::{Atom, Namespace}; use util::mem::HeapSizeOf; -use util::str::DOMString; /// Proxy handler for a WindowProxy. #[allow(raw_pointer_derive)] @@ -391,74 +387,6 @@ pub fn initialize_global(global: *mut JSObject) { } } -/// A trait to provide access to the `Reflector` for a DOM object. -pub trait Reflectable { - /// Returns the receiver's reflector. - fn reflector(&self) -> &Reflector; - /// Initializes the Reflector - fn init_reflector(&mut self, obj: *mut JSObject); -} - -/// Create the reflector for a new DOM object and yield ownership to the -/// reflector. -pub fn reflect_dom_object<T: Reflectable> - (obj: Box<T>, - global: GlobalRef, - wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>) - -> Root<T> { - wrap_fn(global.get_cx(), global, obj) -} - -/// A struct to store a reference to the reflector of a DOM object. -#[allow(raw_pointer_derive, unrooted_must_root)] -#[must_root] -#[servo_lang = "reflector"] -#[derive(HeapSizeOf)] -// If you're renaming or moving this field, update the path in plugins::reflector as well -pub struct Reflector { - #[ignore_heap_size_of = "defined and measured in rust-mozjs"] - object: UnsafeCell<*mut JSObject>, -} - -#[allow(unrooted_must_root)] -impl PartialEq for Reflector { - fn eq(&self, other: &Reflector) -> bool { - unsafe { *self.object.get() == *other.object.get() } - } -} - -impl Reflector { - /// Get the reflector. - #[inline] - pub fn get_jsobject(&self) -> HandleObject { - unsafe { HandleObject::from_marked_location(self.object.get()) } - } - - /// Initialize the reflector. (May be called only once.) - pub fn set_jsobject(&mut self, object: *mut JSObject) { - unsafe { - let obj = self.object.get(); - assert!((*obj).is_null()); - assert!(!object.is_null()); - *obj = object; - } - } - - /// Return a pointer to the memory location at which the JS reflector - /// object is stored. Used to root the reflector, as - /// required by the JSAPI rooting APIs. - pub fn rootable(&self) -> *mut *mut JSObject { - self.object.get() - } - - /// Create an uninitialized `Reflector`. - pub fn new() -> Reflector { - Reflector { - object: UnsafeCell::new(ptr::null_mut()) - } - } -} - /// Gets the property `id` on `proxy`'s prototype. If it exists, `*found` is /// set to true and `*vp` to the value, otherwise `*found` is set to false. /// @@ -800,21 +728,6 @@ pub unsafe extern fn generic_lenient_setter(cx: *mut JSContext, generic_call(cx, argc, vp, true, call_setter) } -/// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details. -pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult { - match xml_name_type(qualified_name) { - XMLName::InvalidXMLName => { - // Step 1. - Err(Error::InvalidCharacter) - }, - XMLName::Name => { - // Step 2. - Err(Error::Namespace) - }, - XMLName::QName => Ok(()) - } -} - unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi::Class, proto_id: u32, depth: u32) -> bool { @@ -827,155 +740,3 @@ unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi:: pub const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks { instanceClassMatchesProto: Some(instance_class_has_proto_at_depth), }; - -/// Validate a namespace and qualified name and extract their parts. -/// See https://dom.spec.whatwg.org/#validate-and-extract for details. -pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str) - -> Fallible<(Namespace, Option<Atom>, Atom)> { - // Step 1. - let namespace = namespace_from_domstring(namespace); - - // Step 2. - try!(validate_qualified_name(qualified_name)); - - let colon = ':'; - - // Step 5. - let mut parts = qualified_name.splitn(2, colon); - - let (maybe_prefix, local_name) = { - let maybe_prefix = parts.next(); - let maybe_local_name = parts.next(); - - debug_assert!(parts.next().is_none()); - - if let Some(local_name) = maybe_local_name { - debug_assert!(!maybe_prefix.unwrap().is_empty()); - - (maybe_prefix, local_name) - } else { - (None, maybe_prefix.unwrap()) - } - }; - - debug_assert!(!local_name.contains(colon)); - - match (namespace, maybe_prefix) { - (ns!(""), Some(_)) => { - // Step 6. - Err(Error::Namespace) - }, - (ref ns, Some("xml")) if ns != &ns!(XML) => { - // Step 7. - Err(Error::Namespace) - }, - (ref ns, p) if ns != &ns!(XMLNS) && - (qualified_name == "xmlns" || p == Some("xmlns")) => { - // Step 8. - Err(Error::Namespace) - }, - (ns!(XMLNS), p) if qualified_name != "xmlns" && p != Some("xmlns") => { - // Step 9. - Err(Error::Namespace) - }, - (ns, p) => { - // Step 10. - Ok((ns, p.map(Atom::from_slice), Atom::from_slice(local_name))) - } - } -} - -/// Results of `xml_name_type`. -#[derive(PartialEq)] -#[allow(missing_docs)] -pub enum XMLName { - QName, - Name, - InvalidXMLName -} - -/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name -/// for details. -pub fn xml_name_type(name: &str) -> XMLName { - fn is_valid_start(c: char) -> bool { - match c { - ':' | - 'A' ... 'Z' | - '_' | - 'a' ... 'z' | - '\u{C0}' ... '\u{D6}' | - '\u{D8}' ... '\u{F6}' | - '\u{F8}' ... '\u{2FF}' | - '\u{370}' ... '\u{37D}' | - '\u{37F}' ... '\u{1FFF}' | - '\u{200C}' ... '\u{200D}' | - '\u{2070}' ... '\u{218F}' | - '\u{2C00}' ... '\u{2FEF}' | - '\u{3001}' ... '\u{D7FF}' | - '\u{F900}' ... '\u{FDCF}' | - '\u{FDF0}' ... '\u{FFFD}' | - '\u{10000}' ... '\u{EFFFF}' => true, - _ => false, - } - } - - fn is_valid_continuation(c: char) -> bool { - is_valid_start(c) || match c { - '-' | - '.' | - '0' ... '9' | - '\u{B7}' | - '\u{300}' ... '\u{36F}' | - '\u{203F}' ... '\u{2040}' => true, - _ => false, - } - } - - let mut iter = name.chars(); - let mut non_qname_colons = false; - let mut seen_colon = false; - let mut last = match iter.next() { - None => return XMLName::InvalidXMLName, - Some(c) => { - if !is_valid_start(c) { - return XMLName::InvalidXMLName; - } - if c == ':' { - non_qname_colons = true; - } - c - } - }; - - for c in iter { - if !is_valid_continuation(c) { - return XMLName::InvalidXMLName; - } - if c == ':' { - match seen_colon { - true => non_qname_colons = true, - false => seen_colon = true - } - } - last = c - } - - if last == ':' { - non_qname_colons = true - } - - match non_qname_colons { - false => XMLName::QName, - true => XMLName::Name - } -} - -/// Convert a possibly-null URL to a namespace. -/// -/// If the URL is None, returns the empty namespace. -pub fn namespace_from_domstring(url: Option<DOMString>) -> Namespace { - match url { - None => ns!(""), - Some(ref s) => Namespace(Atom::from_slice(s)), - } -} diff --git a/components/script/dom/bindings/xmlname.rs b/components/script/dom/bindings/xmlname.rs new file mode 100644 index 00000000000..e8a53707420 --- /dev/null +++ b/components/script/dom/bindings/xmlname.rs @@ -0,0 +1,176 @@ +/* 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/. */ + +//! Functions for validating and extracting qualified XML names. + +use dom::bindings::error::{Error, ErrorResult, Fallible}; +use string_cache::{Atom, Namespace}; +use util::str::DOMString; + +/// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details. +pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult { + match xml_name_type(qualified_name) { + XMLName::InvalidXMLName => { + // Step 1. + Err(Error::InvalidCharacter) + }, + XMLName::Name => { + // Step 2. + Err(Error::Namespace) + }, + XMLName::QName => Ok(()) + } +} + +/// Validate a namespace and qualified name and extract their parts. +/// See https://dom.spec.whatwg.org/#validate-and-extract for details. +pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str) + -> Fallible<(Namespace, Option<Atom>, Atom)> { + // Step 1. + let namespace = namespace_from_domstring(namespace); + + // Step 2. + try!(validate_qualified_name(qualified_name)); + + let colon = ':'; + + // Step 5. + let mut parts = qualified_name.splitn(2, colon); + + let (maybe_prefix, local_name) = { + let maybe_prefix = parts.next(); + let maybe_local_name = parts.next(); + + debug_assert!(parts.next().is_none()); + + if let Some(local_name) = maybe_local_name { + debug_assert!(!maybe_prefix.unwrap().is_empty()); + + (maybe_prefix, local_name) + } else { + (None, maybe_prefix.unwrap()) + } + }; + + debug_assert!(!local_name.contains(colon)); + + match (namespace, maybe_prefix) { + (ns!(""), Some(_)) => { + // Step 6. + Err(Error::Namespace) + }, + (ref ns, Some("xml")) if ns != &ns!(XML) => { + // Step 7. + Err(Error::Namespace) + }, + (ref ns, p) if ns != &ns!(XMLNS) && + (qualified_name == "xmlns" || p == Some("xmlns")) => { + // Step 8. + Err(Error::Namespace) + }, + (ns!(XMLNS), p) if qualified_name != "xmlns" && p != Some("xmlns") => { + // Step 9. + Err(Error::Namespace) + }, + (ns, p) => { + // Step 10. + Ok((ns, p.map(Atom::from_slice), Atom::from_slice(local_name))) + } + } +} + +/// Results of `xml_name_type`. +#[derive(PartialEq)] +#[allow(missing_docs)] +pub enum XMLName { + QName, + Name, + InvalidXMLName +} + +/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name +/// for details. +pub fn xml_name_type(name: &str) -> XMLName { + fn is_valid_start(c: char) -> bool { + match c { + ':' | + 'A' ... 'Z' | + '_' | + 'a' ... 'z' | + '\u{C0}' ... '\u{D6}' | + '\u{D8}' ... '\u{F6}' | + '\u{F8}' ... '\u{2FF}' | + '\u{370}' ... '\u{37D}' | + '\u{37F}' ... '\u{1FFF}' | + '\u{200C}' ... '\u{200D}' | + '\u{2070}' ... '\u{218F}' | + '\u{2C00}' ... '\u{2FEF}' | + '\u{3001}' ... '\u{D7FF}' | + '\u{F900}' ... '\u{FDCF}' | + '\u{FDF0}' ... '\u{FFFD}' | + '\u{10000}' ... '\u{EFFFF}' => true, + _ => false, + } + } + + fn is_valid_continuation(c: char) -> bool { + is_valid_start(c) || match c { + '-' | + '.' | + '0' ... '9' | + '\u{B7}' | + '\u{300}' ... '\u{36F}' | + '\u{203F}' ... '\u{2040}' => true, + _ => false, + } + } + + let mut iter = name.chars(); + let mut non_qname_colons = false; + let mut seen_colon = false; + let mut last = match iter.next() { + None => return XMLName::InvalidXMLName, + Some(c) => { + if !is_valid_start(c) { + return XMLName::InvalidXMLName; + } + if c == ':' { + non_qname_colons = true; + } + c + } + }; + + for c in iter { + if !is_valid_continuation(c) { + return XMLName::InvalidXMLName; + } + if c == ':' { + match seen_colon { + true => non_qname_colons = true, + false => seen_colon = true + } + } + last = c + } + + if last == ':' { + non_qname_colons = true + } + + match non_qname_colons { + false => XMLName::QName, + true => XMLName::Name + } +} + +/// Convert a possibly-null URL to a namespace. +/// +/// If the URL is None, returns the empty namespace. +pub fn namespace_from_domstring(url: Option<DOMString>) -> Namespace { + match url { + None => ns!(""), + Some(ref s) => Namespace(Atom::from_slice(s)), + } +} |