diff --git a/ci/script.sh b/ci/script.sh index 64fafc0d37..664349c374 100755 --- a/ci/script.sh +++ b/ci/script.sh @@ -22,6 +22,10 @@ ci/run-shootout-test cargo test --verbose --manifest-path regex-syntax/Cargo.toml cargo doc --verbose --manifest-path regex-syntax/Cargo.toml +if [ "$TRAVIS_RUST_VERSION" = "nightly" ]; then + cargo test --verbose --manifest-path regex-syntax/Cargo.toml --no-default-features --features "alloc" +fi + # Run tests on regex-capi crate. cargo build --verbose --manifest-path regex-capi/Cargo.toml (cd regex-capi/ctest && ./compile && LD_LIBRARY_PATH=../../target/debug ./test) diff --git a/regex-syntax/Cargo.toml b/regex-syntax/Cargo.toml index 2128945bb5..f14d3f8a66 100644 --- a/regex-syntax/Cargo.toml +++ b/regex-syntax/Cargo.toml @@ -9,5 +9,12 @@ homepage = "https://github.com/rust-lang/regex" description = "A regular expression parser." workspace = ".." +[features] +default = ["std"] +# Disable this on-by-default feature and add "alloc" to allow use in no_std builds +std = [] +# Required for use in no_std builds, presently nightly-only +alloc = [] + [dependencies] ucd-util = "0.1.0" diff --git a/regex-syntax/src/ast/mod.rs b/regex-syntax/src/ast/mod.rs index 884fcfa35c..e41cd92b58 100644 --- a/regex-syntax/src/ast/mod.rs +++ b/regex-syntax/src/ast/mod.rs @@ -13,8 +13,10 @@ Defines an abstract syntax for regular expressions. */ use std::cmp::Ordering; +#[cfg(feature = "std")] use std::error; use std::fmt; +use prelude::*; pub use ast::visitor::{Visitor, visit}; @@ -179,6 +181,7 @@ pub enum ErrorKind { __Nonexhaustive, } +#[cfg(feature = "std")] impl error::Error for Error { fn description(&self) -> &str { use self::ErrorKind::*; @@ -1488,7 +1491,7 @@ mod tests { #[test] #[cfg(any(unix, windows))] fn no_stack_overflow_on_drop() { - use std::thread; + use std_test::thread; let run = || { let span = || Span::splat(Position::new(0, 0, 0)); diff --git a/regex-syntax/src/ast/parse.rs b/regex-syntax/src/ast/parse.rs index b73baee735..8762658f45 100644 --- a/regex-syntax/src/ast/parse.rs +++ b/regex-syntax/src/ast/parse.rs @@ -12,7 +12,7 @@ This module provides a regular expression parser. */ -use std::borrow::Borrow; +use prelude::{Borrow, Box, String, ToString, Vec}; use std::cell::{Cell, RefCell}; use std::mem; use std::result; @@ -2255,6 +2255,7 @@ impl<'p, 's, P: Borrow> ast::Visitor for NestLimiter<'p, 's, P> { #[cfg(test)] mod tests { + use std_test::prelude::v1::*; use std::ops::Range; use ast::{self, Ast, Position, Span}; diff --git a/regex-syntax/src/ast/print.rs b/regex-syntax/src/ast/print.rs index 4441b4d580..63a44b9b90 100644 --- a/regex-syntax/src/ast/print.rs +++ b/regex-syntax/src/ast/print.rs @@ -415,6 +415,7 @@ impl<'p, W: fmt::Write> Writer<'p, W> { #[cfg(test)] mod tests { use ast::parse::ParserBuilder; + use std_test::prelude::v1::*; use super::Printer; fn roundtrip(given: &str) { diff --git a/regex-syntax/src/ast/visitor.rs b/regex-syntax/src/ast/visitor.rs index 9b93a1ae15..c0bb4a3025 100644 --- a/regex-syntax/src/ast/visitor.rs +++ b/regex-syntax/src/ast/visitor.rs @@ -9,6 +9,7 @@ // except according to those terms. use std::fmt; +use prelude::Vec; use ast::{self, Ast}; diff --git a/regex-syntax/src/error.rs b/regex-syntax/src/error.rs index 1f5b8f817d..ef8877045c 100644 --- a/regex-syntax/src/error.rs +++ b/regex-syntax/src/error.rs @@ -1,7 +1,9 @@ use std::cmp; +#[cfg(feature = "std")] use std::error; use std::fmt; use std::result; +use prelude::*; use ast; use hir; @@ -39,6 +41,7 @@ impl From for Error { } } +#[cfg(feature = "std")] impl error::Error for Error { fn description(&self) -> &str { match *self { @@ -285,6 +288,7 @@ fn repeat_char(c: char, count: usize) -> String { #[cfg(test)] mod tests { + use std_test::prelude::v1::*; use ast::parse::Parser; // See: https://github.com/rust-lang/regex/issues/464 diff --git a/regex-syntax/src/hir/interval.rs b/regex-syntax/src/hir/interval.rs index a7e70ef596..ea46ef04b6 100644 --- a/regex-syntax/src/hir/interval.rs +++ b/regex-syntax/src/hir/interval.rs @@ -3,6 +3,7 @@ use std::cmp; use std::fmt::Debug; use std::slice; use std::u8; +use prelude::Vec; // This module contains an *internal* implementation of interval sets. // diff --git a/regex-syntax/src/hir/literal/mod.rs b/regex-syntax/src/hir/literal/mod.rs index b7d9c1db27..33185b535f 100644 --- a/regex-syntax/src/hir/literal/mod.rs +++ b/regex-syntax/src/hir/literal/mod.rs @@ -17,6 +17,7 @@ use std::fmt; use std::iter; use std::mem; use std::ops; +use prelude::*; use hir::{self, Hir, HirKind}; @@ -999,6 +1000,7 @@ fn cls_byte_count(cls: &hir::ClassBytes) -> usize { #[cfg(test)] mod tests { + use std_test::prelude::v1::*; use std::fmt; use ParserBuilder; diff --git a/regex-syntax/src/hir/mod.rs b/regex-syntax/src/hir/mod.rs index 903e6085be..269273e5fd 100644 --- a/regex-syntax/src/hir/mod.rs +++ b/regex-syntax/src/hir/mod.rs @@ -11,11 +11,14 @@ /*! Defines a high-level intermediate representation for regular expressions. */ + use std::char; use std::cmp; +#[cfg(feature = "std")] use std::error; use std::fmt; use std::u8; +use prelude::*; use ast::Span; use hir::interval::{Interval, IntervalSet, IntervalSetIter}; @@ -104,6 +107,7 @@ impl ErrorKind { } } +#[cfg(feature = "std")] impl error::Error for Error { fn description(&self) -> &str { self.kind.description() @@ -209,8 +213,7 @@ impl Hir { /// Consumes ownership of this HIR expression and returns its underlying /// `HirKind`. pub fn into_kind(mut self) -> HirKind { - use std::mem; - mem::replace(&mut self.kind, HirKind::Empty) + ::std::mem::replace(&mut self.kind, HirKind::Empty) } /// Returns an empty HIR expression. @@ -2016,7 +2019,7 @@ mod tests { #[test] #[cfg(any(unix, windows))] fn no_stack_overflow_on_drop() { - use std::thread; + use std_test::thread; let run = || { let mut expr = Hir::empty(); diff --git a/regex-syntax/src/hir/print.rs b/regex-syntax/src/hir/print.rs index a40a670bf7..6da438192d 100644 --- a/regex-syntax/src/hir/print.rs +++ b/regex-syntax/src/hir/print.rs @@ -247,6 +247,7 @@ impl<'p, W: fmt::Write> Writer<'p, W> { #[cfg(test)] mod tests { use ParserBuilder; + use std_test::prelude::v1::*; use super::Printer; fn roundtrip(given: &str, expected: &str) { diff --git a/regex-syntax/src/hir/translate.rs b/regex-syntax/src/hir/translate.rs index 7939ab59ad..b4228fe47d 100644 --- a/regex-syntax/src/hir/translate.rs +++ b/regex-syntax/src/hir/translate.rs @@ -14,7 +14,7 @@ Defines a translator that converts an `Ast` to an `Hir`. use std::cell::{Cell, RefCell}; use std::result; - +use prelude::{Box, ToString, Vec}; use ast::{self, Ast, Span, Visitor}; use hir::{self, Error, ErrorKind, Hir}; use unicode::{self, ClassQuery}; @@ -1094,6 +1094,7 @@ mod tests { use ast::{self, Ast, Position, Span}; use ast::parse::ParserBuilder; use hir::{self, Hir, HirKind}; + use std_test::prelude::v1::*; use unicode::{self, ClassQuery}; use super::{TranslatorBuilder, ascii_class}; diff --git a/regex-syntax/src/hir/visitor.rs b/regex-syntax/src/hir/visitor.rs index 58be7ad078..134e6fb5ec 100644 --- a/regex-syntax/src/hir/visitor.rs +++ b/regex-syntax/src/hir/visitor.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use prelude::Vec; use hir::{self, Hir, HirKind}; /// A trait for visiting the high-level IR (HIR) in depth first order. diff --git a/regex-syntax/src/lib.rs b/regex-syntax/src/lib.rs index 2c785bfc5f..d4514bd4d3 100644 --- a/regex-syntax/src/lib.rs +++ b/regex-syntax/src/lib.rs @@ -105,6 +105,21 @@ done automatically in the `regex` crate. #![deny(missing_docs)] +#![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(alloc))] +#![cfg_attr(all(feature = "alloc", not(feature = "std")), feature(slice_concat_ext))] + +#[cfg(test)] +extern crate std as std_test; + +#[cfg(not(feature = "std"))] +#[macro_use] +extern crate core as std; + +#[cfg(all(feature = "alloc", not(feature = "std")))] +#[macro_use] +extern crate alloc; + extern crate ucd_util; pub use error::{Error, Result}; @@ -115,9 +130,12 @@ mod either; mod error; pub mod hir; mod parser; +mod prelude; mod unicode; mod unicode_tables; +use prelude::String; + /// Escapes all regular expression meta characters in `text`. /// /// The string returned may be safely used as a literal in a regular @@ -199,6 +217,7 @@ pub fn is_word_byte(c: u8) -> bool { #[cfg(test)] mod tests { + use std_test::prelude::v1::*; use super::*; #[test] diff --git a/regex-syntax/src/prelude.rs b/regex-syntax/src/prelude.rs new file mode 100644 index 0000000000..918f856e5c --- /dev/null +++ b/regex-syntax/src/prelude.rs @@ -0,0 +1,54 @@ +//! This module provides access to items available in both the standard library +//! and the `alloc` facade crate while concealing the feature-flag based compile +//! time selection between those options. +#![allow(unused_imports)] + +macro_rules! multiplex_alloc { + ($($alloc: path, $std: path),*) => { + $( + #[cfg(all(feature = "alloc", not(feature = "std")))] + pub(crate) use $alloc; + #[cfg(feature = "std")] + pub(crate) use $std; + )* + }; +} + +macro_rules! multiplex_core { + ($($core: path, $std: path),*) => { + $( + #[cfg(not(feature = "std"))] + pub(crate) use $core; + #[cfg(feature = "std")] + pub(crate) use $std; + )* + }; +} + +macro_rules! alloc_only { + ($($alloc: path),*) => { + $( + #[cfg(all(feature = "alloc", not(feature = "std")))] + pub(crate) use $alloc; + )* + }; +} + +multiplex_alloc! { + alloc::borrow::Borrow, ::std::borrow::Borrow, + alloc::borrow::ToOwned, ::std::borrow::ToOwned, + alloc::boxed::Box, ::std::boxed::Box, + alloc::String, ::std::string::String, + alloc::string::ToString, ::std::string::ToString, + alloc::Vec, ::std::vec::Vec +} + +multiplex_core! { + core::fmt, ::std::fmt, + core::slice, ::std::slice +} + +alloc_only! { + alloc::slice::SliceConcatExt +} + diff --git a/regex-syntax/src/unicode.rs b/regex-syntax/src/unicode.rs index ed84d98b07..1818061395 100644 --- a/regex-syntax/src/unicode.rs +++ b/regex-syntax/src/unicode.rs @@ -1,5 +1,6 @@ use std::cmp::Ordering; use std::result; +use prelude::{String, ToString, Vec}; use ucd_util::{self, PropertyValues}; @@ -372,6 +373,7 @@ impl Iterator for AgeIter { #[cfg(test)] mod tests { + use std_test::prelude::v1::*; use super::{contains_simple_case_mapping, simple_fold}; #[test]