Skip to content

Commit

Permalink
Add no_std support (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
h33p authored Nov 4, 2023
1 parent 3869589 commit bbc4361
Show file tree
Hide file tree
Showing 45 changed files with 262 additions and 148 deletions.
25 changes: 14 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@ on:

jobs:
clippy:
name: "Lint with clippy (${{ matrix.os }})"
name: "Lint with clippy (${{ matrix.os }}, ${{ matrix.flags }})"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { os: windows-latest }
- { os: ubuntu-latest }
os: ["windows-latest", "ubuntu-latest"]
flags: ["--all-features", "--no-default-features"]
env:
RUSTFLAGS: -Dwarnings
steps:
Expand All @@ -33,7 +32,7 @@ jobs:
profile: minimal
toolchain: stable
components: clippy
- run: cargo clippy --all-targets --all-features
- run: cargo clippy --all-targets ${{ matrix.flags }}
rustfmt:
name: "Verify code formatting (${{ matrix.os }})"
runs-on: ${{ matrix.os }}
Expand All @@ -58,16 +57,20 @@ jobs:
components: rustfmt
- run: cargo fmt --all -- --check
tests:
name: "Test Rust ${{ matrix.rust }} (${{ matrix.os }})"
name: "Test Rust ${{ matrix.rust }} (${{ matrix.os }}, ${{ matrix.flags }})"
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { rust: stable, os: windows-latest, target: x86_64-pc-windows-msvc }
- { rust: stable, os: macos-latest }
- { rust: stable, os: ubuntu-latest }
- { rust: 1.58.1, os: ubuntu-latest }
- { rust: stable, os: windows-latest, target: x86_64-pc-windows-msvc, flags: "--all-features" }
- { rust: stable, os: windows-latest, target: x86_64-pc-windows-msvc, flags: "--no-default-features" }
- { rust: stable, os: macos-latest, flags: "--all-features" }
- { rust: stable, os: macos-latest, flags: "--no-default-features" }
- { rust: stable, os: ubuntu-latest, flags: "--all-features" }
- { rust: stable, os: ubuntu-latest, flags: "--no-default-features" }
- { rust: 1.58.1, os: ubuntu-latest, flags: "--all-features" }
- { rust: 1.58.1, os: ubuntu-latest, flags: "--no-default-features" }
steps:
- uses: actions/checkout@v2
- name: Install Rust ${{ matrix.rust }} ${{ matrix.target }}
Expand All @@ -76,7 +79,7 @@ jobs:
profile: minimal
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
- run: cargo test --all-features
- run: cargo test ${{ matrix.flags }}
examples:
name: "Run examples using Rust ${{ matrix.rust }} (${{ matrix.os }})"
runs-on: ${{ matrix.os }}
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

* Support `no_std` environments, when `default-features = false` is set for the crate

## [0.6.0] - 2023-10-12

* Refactor crate exports such that everything other than constants are now
Expand Down
28 changes: 28 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,32 @@ repository = "https://github.com/chipsenkbeil/typed-path"
readme = "README.md"
license = "MIT OR Apache-2.0"

[[example]]
name = "windows_utf8"
required-features = ["std"]

[[example]]
name = "unix"
required-features = ["std"]

[[example]]
name = "typed"
required-features = ["std"]

[[example]]
name = "typed_utf8"
required-features = ["std"]

[[example]]
name = "unix_utf8"
required-features = ["std"]

[[example]]
name = "windows"
required-features = ["std"]

[dependencies]

[features]
default = ["std"]
std = []
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,13 @@ assert_eq!(

In addition, you can leverage `absolutize` to convert a path to an absolute
form by prepending the current working directory if the path is relative and
then normalizing it:
then normalizing it (requires `std` feature):

```rust
# fn main() {
# // absolutize is only supported with standard library
# #[cfg(feature = "std")]
# {
use typed_path::{utils, Utf8UnixPath};

// With an absolute path, it is just normalized
Expand All @@ -202,15 +206,21 @@ assert_eq!(path.absolutize().unwrap(), Utf8UnixPath::new("/a/c/d"));
let cwd = utils::utf8_current_dir().unwrap().with_unix_encoding();
let path = cwd.join(Utf8UnixPath::new("a/b/../c/./d"));
assert_eq!(path.absolutize().unwrap(), cwd.join(Utf8UnixPath::new("a/c/d")));
# }
# }
```

### Current directory

Helper functions are available in the [`utils`][utils] module, and one of those
provides an identical experience to
Helper functions are available in the [`utils`][utils] module (requires `std`
feature), and one of those provides an identical experience to
[`std::env::current_dir`](https://doc.rust-lang.org/std/env/fn.current_dir.html):

```rust
# fn main() {
# // utils::current_dir is only supported with standard library
# #[cfg(feature = "std")]
# {
// Retrieves the current directory as a NativePath:
//
// * For Unix family, this would be Path<UnixEncoding>
Expand All @@ -222,6 +232,8 @@ let _cwd = typed_path::utils::current_dir().unwrap();
// * For Unix family, this would be Utf8Path<Utf8UnixEncoding>
// * For Windows family, this would be Utf8Path<Utf8WindowsEncoding>
let _utf8_cwd = typed_path::utils::utf8_current_dir().unwrap();
# }
# }
```

## License
Expand Down
6 changes: 3 additions & 3 deletions src/common/errors.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::error::Error;
use std::fmt;
use core::fmt;

/// An error returned if the prefix was not found.
///
Expand All @@ -17,4 +16,5 @@ impl fmt::Display for StripPrefixError {
}
}

impl Error for StripPrefixError {}
#[cfg(feature = "std")]
impl std::error::Error for StripPrefixError {}
3 changes: 2 additions & 1 deletion src/common/non_utf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ mod pathbuf;
#[macro_use]
pub(crate) mod parser;

use std::hash::Hasher;
use core::hash::Hasher;

pub use components::*;
pub use iter::*;
pub use parser::ParseError;
pub use path::*;
pub use pathbuf::*;

use crate::no_std_compat::*;
use crate::private;

/// Interface to provide meaning to a byte slice such that paths can be derived
Expand Down
2 changes: 1 addition & 1 deletion src/common/non_utf8/components.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod component;

use std::{cmp, fmt, iter};
use core::{cmp, fmt, iter};

pub use component::*;

Expand Down
2 changes: 1 addition & 1 deletion src/common/non_utf8/components/component.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::fmt;
use core::fmt;

use crate::private;

Expand Down
6 changes: 3 additions & 3 deletions src/common/non_utf8/iter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt;
use std::iter::FusedIterator;
use std::marker::PhantomData;
use core::fmt;
use core::iter::FusedIterator;
use core::marker::PhantomData;

use crate::{Component, Components, Encoding, Path};

Expand Down
2 changes: 2 additions & 0 deletions src/common/non_utf8/parser.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use crate::no_std_compat::*;

pub type ParseResult<'a, T> = Result<(ParseInput<'a>, T), ParseError>;
pub type ParseInput<'a> = &'a [u8];
pub type ParseError = &'static str;
Expand Down
22 changes: 12 additions & 10 deletions src/common/non_utf8/path.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
mod display;

use std::borrow::{Cow, ToOwned};
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::Arc;
use std::{cmp, fmt, io};
use alloc::borrow::{Cow, ToOwned};
use alloc::rc::Rc;
use alloc::sync::Arc;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::{cmp, fmt};

pub use display::Display;

use crate::{utils, Ancestors, Component, Components, Encoding, Iter, PathBuf, StripPrefixError};
use crate::no_std_compat::*;
use crate::{Ancestors, Component, Components, Encoding, Iter, PathBuf, StripPrefixError};

/// A slice of a path (akin to [`str`]).
///
Expand Down Expand Up @@ -159,7 +160,7 @@ where
/// ```
#[inline]
pub fn to_str(&self) -> Option<&str> {
std::str::from_utf8(&self.inner).ok()
core::str::from_utf8(&self.inner).ok()
}

/// Converts a `Path` to a [`Cow<str>`].
Expand Down Expand Up @@ -628,12 +629,13 @@ where
/// let path = cwd.join(Path::new("a/b/../c/./d"));
/// assert_eq!(path.absolutize().unwrap(), cwd.join(Path::new("a/c/d")));
/// ```
pub fn absolutize(&self) -> io::Result<PathBuf<T>> {
#[cfg(feature = "std")]
pub fn absolutize(&self) -> std::io::Result<PathBuf<T>> {
if self.is_absolute() {
Ok(self.normalize())
} else {
// Get the cwd as a native path and convert to this path's encoding
let cwd = utils::current_dir()?.with_encoding();
let cwd = crate::utils::current_dir()?.with_encoding();

Ok(cwd.join(self).normalize())
}
Expand Down
3 changes: 2 additions & 1 deletion src/common/non_utf8/path/display.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fmt;
use core::fmt;

use crate::no_std_compat::*;
use crate::{Encoding, Path};

/// Helper struct for safely printing paths with [`format!`] and `{}`.
Expand Down
20 changes: 11 additions & 9 deletions src/common/non_utf8/pathbuf.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::borrow::{Borrow, Cow};
use std::collections::TryReserveError;
use std::hash::{Hash, Hasher};
use std::iter::{Extend, FromIterator};
use std::marker::PhantomData;
use std::ops::Deref;
use std::str::FromStr;
use std::{cmp, fmt};

use alloc::borrow::Cow;
use alloc::collections::TryReserveError;
use core::borrow::Borrow;
use core::hash::{Hash, Hasher};
use core::iter::{Extend, FromIterator};
use core::marker::PhantomData;
use core::ops::Deref;
use core::str::FromStr;
use core::{cmp, fmt};

use crate::no_std_compat::*;
use crate::{Encoding, Iter, Path};

/// An owned, mutable path that mirrors [`std::path::PathBuf`], but operatings using an
Expand Down
3 changes: 2 additions & 1 deletion src/common/utf8.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ mod iter;
mod path;
mod pathbuf;

use std::hash::Hasher;
use core::hash::Hasher;

pub use components::*;
pub use iter::*;
pub use path::*;
pub use pathbuf::*;

use crate::no_std_compat::*;
use crate::private;

/// Interface to provide meaning to a byte slice such that paths can be derived
Expand Down
2 changes: 1 addition & 1 deletion src/common/utf8/components.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod component;

use std::{cmp, fmt, iter};
use core::{cmp, fmt, iter};

pub use component::*;

Expand Down
2 changes: 1 addition & 1 deletion src/common/utf8/components/component.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::fmt;
use core::fmt;

use crate::private;

Expand Down
6 changes: 3 additions & 3 deletions src/common/utf8/iter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::fmt;
use std::iter::FusedIterator;
use std::marker::PhantomData;
use core::fmt;
use core::iter::FusedIterator;
use core::marker::PhantomData;

use crate::{Utf8Component, Utf8Components, Utf8Encoding, Utf8Path};

Expand Down
30 changes: 16 additions & 14 deletions src/common/utf8/path.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use std::borrow::{Cow, ToOwned};
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::rc::Rc;
use std::str::Utf8Error;
use std::sync::Arc;
use std::{cmp, fmt, io};

use alloc::borrow::{Cow, ToOwned};
use alloc::rc::Rc;
use alloc::sync::Arc;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::str::Utf8Error;
use core::{cmp, fmt};

use crate::no_std_compat::*;
use crate::{
utils, Encoding, Path, StripPrefixError, Utf8Ancestors, Utf8Component, Utf8Components,
Utf8Encoding, Utf8Iter, Utf8PathBuf,
Encoding, Path, StripPrefixError, Utf8Ancestors, Utf8Component, Utf8Components, Utf8Encoding,
Utf8Iter, Utf8PathBuf,
};

/// A slice of a path (akin to [`str`]).
Expand Down Expand Up @@ -580,12 +581,13 @@ where
/// let path = cwd.join(Utf8Path::new("a/b/../c/./d"));
/// assert_eq!(path.absolutize().unwrap(), cwd.join(Utf8Path::new("a/c/d")));
/// ```
pub fn absolutize(&self) -> io::Result<Utf8PathBuf<T>> {
#[cfg(feature = "std")]
pub fn absolutize(&self) -> std::io::Result<Utf8PathBuf<T>> {
if self.is_absolute() {
Ok(self.normalize())
} else {
// Get the cwd as a native path and convert to this path's encoding
let cwd = utils::utf8_current_dir()?.with_encoding();
let cwd = crate::utils::utf8_current_dir()?.with_encoding();

Ok(cwd.join(self).normalize())
}
Expand Down Expand Up @@ -837,7 +839,7 @@ where
where
U: for<'enc> Encoding<'enc>,
{
Ok(Self::new(std::str::from_utf8(path.as_bytes())?))
Ok(Self::new(core::str::from_utf8(path.as_bytes())?))
}

/// Converts a non-UTF-8 [`Path`] to a UTF-8 [`Utf8Path`] without checking that the path
Expand Down Expand Up @@ -866,7 +868,7 @@ where
where
U: for<'enc> Encoding<'enc>,
{
Self::new(std::str::from_utf8_unchecked(path.as_bytes()))
Self::new(core::str::from_utf8_unchecked(path.as_bytes()))
}

/// Converts a UTF-8 [`Utf8Path`] to a non-UTF-8 [`Path`].
Expand Down
Loading

0 comments on commit bbc4361

Please sign in to comment.