Skip to content

Commit

Permalink
Improve generalization (fflorent#58)
Browse files Browse the repository at this point in the history
* checkpoint

* Compare generalization

* Implement Deref

* core::ops::Deref

* Add deprecated macros for backwards-compatibility

* Deprecation message updated

* Word choice

* Cleanup

* Cleanup

* Update version numbers for macro deprecations
  • Loading branch information
kenaniah authored May 24, 2020
1 parent edefce7 commit 79cf042
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 73 deletions.
98 changes: 25 additions & 73 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ pub struct LocatedSpan<T, X = ()> {
pub extra: X,
}

impl<T, X> core::ops::Deref for LocatedSpan<T, X> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.fragment
}
}

impl<T: AsBytes> LocatedSpan<T, ()> {
/// Create a span for a particular input with default `offset` and
/// `line` values and empty extra data.
Expand Down Expand Up @@ -516,68 +523,26 @@ impl_input_iter!(
Map<Iter<'a, Self::Item>, fn(&u8) -> u8>
);

/// Implement nom::Compare for a specific fragment type.
///
/// # Parameters
/// * `$fragment_type` - The LocatedSpan's `fragment` type
/// * `$compare_to_type` - The type to be comparable to `LocatedSpan<$fragment_type, X>`
///
/// # Example of use
///
/// NB: This example is an extract from the nom_locate source code.
///
/// ````ignore
/// #[macro_use]
/// extern crate nom_locate;
/// impl_compare!(&'b str, &'a str);
/// impl_compare!(&'b [u8], &'a [u8]);
/// impl_compare!(&'b [u8], &'a str);
/// ````
#[macro_export]
macro_rules! impl_compare {
( $fragment_type:ty, $compare_to_type:ty ) => {
impl<'a, 'b, X> Compare<$compare_to_type> for LocatedSpan<$fragment_type, X> {
#[inline(always)]
fn compare(&self, t: $compare_to_type) -> CompareResult {
self.fragment.compare(t)
}

#[inline(always)]
fn compare_no_case(&self, t: $compare_to_type) -> CompareResult {
self.fragment.compare_no_case(t)
}
}
};
}

impl_compare!(&'b str, &'a str);
impl_compare!(&'b [u8], &'a [u8]);
impl_compare!(&'b [u8], &'a str);

impl<A: Compare<B>, B, X, Y> Compare<LocatedSpan<B, X>> for LocatedSpan<A, Y> {
impl<A: Compare<B>, B: Into<LocatedSpan<B>>, X> Compare<B> for LocatedSpan<A, X> {
#[inline(always)]
fn compare(&self, t: LocatedSpan<B, X>) -> CompareResult {
self.fragment.compare(t.fragment)
fn compare(&self, t: B) -> CompareResult {
self.fragment.compare(t.into().fragment)
}

#[inline(always)]
fn compare_no_case(&self, t: LocatedSpan<B, X>) -> CompareResult {
self.fragment.compare_no_case(t.fragment)
fn compare_no_case(&self, t: B) -> CompareResult {
self.fragment.compare_no_case(t.into().fragment)
}
}

// TODO(future): replace impl_compare! with below default specialization?
// default impl<A: Compare<B>, B, X> Compare<B> for LocatedSpan<A, X> {
// #[inline(always)]
// fn compare(&self, t: B) -> CompareResult {
// self.fragment.compare(t)
// }
//
// #[inline(always)]
// fn compare_no_case(&self, t: B) -> CompareResult {
// self.fragment.compare_no_case(t)
// }
// }
#[macro_export]
#[deprecated(
since = "2.1.0",
note = "this implementation has been generalized and no longer requires a macro"
)]
macro_rules! impl_compare {
( $fragment_type:ty, $compare_to_type:ty ) => {};
}

/// Implement nom::Slice for a specific fragment type and range type.
///
Expand Down Expand Up @@ -767,28 +732,15 @@ impl_extend_into!(&'a [u8], u8, Vec<u8>);

#[cfg(feature = "std")]
#[macro_export]
#[deprecated(
since = "2.1.0",
note = "this implementation has been generalized and no longer requires a macro"
)]
macro_rules! impl_hex_display {
($fragment_type:ty) => {
#[cfg(feature = "alloc")]
impl<'a, X> nom::HexDisplay for LocatedSpan<$fragment_type, X> {
fn to_hex(&self, chunk_size: usize) -> String {
self.fragment.to_hex(chunk_size)
}

fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
self.fragment.to_hex_from(chunk_size, from)
}
}
};
($fragment_type:ty) => {};
}

#[cfg(feature = "std")]
impl_hex_display!(&'a str);
#[cfg(feature = "std")]
impl_hex_display!(&'a [u8]);

/// Capture the position of the current fragment
#[macro_export]
macro_rules! position {
($input:expr,) => {
Expand Down
22 changes: 22 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,3 +392,25 @@ fn it_should_capture_position() {
assert_eq!(s.line, 2);
assert_eq!(t, "def");
}

#[test]
fn it_should_deref_to_fragment() {
let input = &"foobar"[..];
assert_eq!(*StrSpanEx::new_extra(input, "extra"), input);
let input = &b"foobar"[..];
assert_eq!(*BytesSpanEx::new_extra(input, "extra"), input);
}

#[cfg(feature = "std")]
#[test]
fn it_should_display_hex() {
use nom::HexDisplay;
assert_eq!(
StrSpan::new(&"abc"[..]).to_hex(4),
"00000000\t61 62 63 \tabc\n".to_owned()
);
assert_eq!(
BytesSpanEx::new_extra(&b"abc"[..], "extra").to_hex(4),
"00000000\t61 62 63 \tabc\n".to_owned()
);
}

0 comments on commit 79cf042

Please sign in to comment.