From 98bc465a8ef6b3365be10849756714167bf7a368 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Sun, 27 May 2018 11:15:30 +0100 Subject: [PATCH] Include the namespace-separating solidus in NamespaceableName. --- edn/src/namespaceable_name.rs | 24 +++++++++++++++++++----- edn/src/symbols.rs | 19 ++++++++++--------- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/edn/src/namespaceable_name.rs b/edn/src/namespaceable_name.rs index a0aa1d99..4c59ada1 100644 --- a/edn/src/namespaceable_name.rs +++ b/edn/src/namespaceable_name.rs @@ -32,11 +32,12 @@ use serde::ser::{ #[derive(Clone, Eq, Hash, PartialEq)] pub struct NamespaceableName { // The bytes that make up the namespace followed directly by those - // that make up the name. + // that make up the name. If there is a namespace, a solidus ('/') is between + // the two parts. components: String, - // The index (in bytes) into `components` where the namespace ends and - // name begins. + // The index (in bytes) into `components` of the dividing solidus — the place + // where the namespace ends and the name begins. // // If this is zero, it means that this is _not_ a namespaced value! // @@ -79,6 +80,7 @@ impl NamespaceableName { let mut dest = String::with_capacity(n.len() + ns.len()); dest.push_str(ns); + dest.push('/'); dest.push_str(n); let boundary = ns.len(); @@ -135,13 +137,19 @@ impl NamespaceableName { if self.boundary == 0 { &self.components } else { - &self.components[self.boundary..] + &self.components[(self.boundary + 1)..] } } #[inline] pub fn components<'a>(&'a self) -> (&'a str, &'a str) { - self.components.split_at(self.boundary) + if self.boundary > 0 { + (&self.components[0..self.boundary], + &self.components[(self.boundary + 1)..]) + } else { + (&self.components[0..0], + &self.components) + } } } @@ -177,6 +185,12 @@ impl fmt::Debug for NamespaceableName { } } +impl fmt::Display for NamespaceableName { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(&self.components) + } +} + // This is convoluted, but the basic idea is that since we don't want to rely on our input being // correct, we'll need to implement a custom serializer no matter what (e.g. we can't just // `derive(Deserialize)` since `unsafe` code depends on `self.boundary` being a valid index). diff --git a/edn/src/symbols.rs b/edn/src/symbols.rs index 9c2c2cb9..95ba3c81 100644 --- a/edn/src/symbols.rs +++ b/edn/src/symbols.rs @@ -8,7 +8,12 @@ // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. -use std::fmt::{Display, Formatter}; +use std::fmt::{ + Display, + Formatter, + Write, +}; + use namespaceable_name::NamespaceableName; #[macro_export] @@ -264,7 +269,7 @@ impl Display for PlainSymbol { /// assert_eq!("baz", PlainSymbol::plain("baz").to_string()); /// ``` fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result { - write!(f, "{}", self.0) + self.0.fmt(f) } } @@ -278,7 +283,7 @@ impl Display for NamespacedSymbol { /// assert_eq!("bar/baz", NamespacedSymbol::namespaced("bar", "baz").to_string()); /// ``` fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result { - write!(f, "{}/{}", self.namespace(), self.name()) + self.0.fmt(f) } } @@ -295,12 +300,8 @@ impl Display for Keyword { /// assert_eq!(":bar/baz", Keyword::namespaced("bar", "baz").to_reversed().to_reversed().to_string()); /// ``` fn fmt(&self, f: &mut Formatter) -> ::std::fmt::Result { - if self.0.is_namespaced() { - let (ns, name) = self.0.components(); - write!(f, ":{}/{}", ns, name) - } else { - write!(f, ":{}", self.0.name()) - } + f.write_char(':')?; + self.0.fmt(f) } }