path-slash-0.1.1/.appveyor.yml010064400007650000024000000015371341635523700144610ustar0000000000000000cache: - c:\cargo\registry - c:\cargo\git init: - mkdir c:\cargo - mkdir c:\rustup - SET PATH=c:\cargo\bin;%PATH% clone_folder: c:\path-slash environment: CARGO_HOME: "c:\\cargo" RUSTUP_HOME: "c:\\rustup" CARGO_TARGET_DIR: "c:\\path-slash\\target" global: RUST_BACKTRACE: full # Install Rust and Cargo # (Based on from https://github.com/rust-lang/libc/blob/master/appveyor.yml) install: - curl -sSf -o rustup-init.exe https://win.rustup.rs/ - rustup-init.exe -y - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin - if defined MSYS2 set PATH=C:\msys64\mingw%BITS%\bin;%PATH% - rustc -V - cargo -V build: false test_script: - cd "c:\\path-slash" - cargo test --verbose notifications: - provider: Email to: lin90162@yahoo.co.jp on_build_status_changed: true on_build_success: false on_build_failure: false path-slash-0.1.1/.gitignore010064400007650000024000000000361341635523700137740ustar0000000000000000/target **/*.rs.bk Cargo.lock path-slash-0.1.1/.travis.yml010064400007650000024000000004761341635523700141250ustar0000000000000000language: rust rust: stable dist: xenial env: global: - RUST_STACKTRACE=full matrix: include: - os: osx rust: stable - os: linux rust: stable before_script: - rustc -V - cargo -V script: - cargo test --verbose notifications: email: on_success: never on_failure: change path-slash-0.1.1/Cargo.toml.orig010064400007650000024000000010711341636200300146600ustar0000000000000000[package] name = "path-slash" version = "0.1.1" authors = ["rhysd "] edition = "2018" description = "Conversion to/from a file path from/to slash path" repository = "https://github.com/rhysd/path-slash" readme = "README.md" license-file = "LICENSE.txt" categories = ["filesystem"] [badges] travis-ci = { repository = "rhysd/path-slash" } appveyor = { repository = "rhysd/path-slash" } maintenance = { status = "passively-maintained" } [package.metadata.release] no-dev-version = true [dependencies] [dev-dependencies] lazy_static = "1.2.0" path-slash-0.1.1/Cargo.toml0000644000000021140000000000000111320ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g. crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "path-slash" version = "0.1.1" authors = ["rhysd "] description = "Conversion to/from a file path from/to slash path" readme = "README.md" categories = ["filesystem"] license-file = "LICENSE.txt" repository = "https://github.com/rhysd/path-slash" [package.metadata.release] no-dev-version = true [dependencies] [dev-dependencies.lazy_static] version = "1.2.0" [badges.appveyor] repository = "rhysd/path-slash" [badges.maintenance] status = "passively-maintained" [badges.travis-ci] repository = "rhysd/path-slash" path-slash-0.1.1/LICENSE.txt010064400007650000024000000020531341635523700136300ustar0000000000000000the MIT License Copyright (c) 2018 rhysd Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. path-slash-0.1.1/README.md010064400007650000024000000053331341635523700132700ustar0000000000000000Rust library to convert a file path from/to slash path ====================================================== [![crates.io][crates-io-badge]][crates-io] [![documentation][doc-badge]][doc] [![CI on Linux and macOS][travis-ci-badge]][travis-ci] [![CI on Windows][appveyor-badge]][appveyor] [`path-slash`][crates-io] is a tiny library to convert a file path (e.g. `foo/bar`, `foo\bar` or `C:\\foo\bar`) from/to slash path (e.g. `foo/bar`, `C://foo/bar`). In Unix-like OS, path separator is slash `/` by default. So any conversion is not necessary. But on Windows, file path separator `\` needs to be replaced with slash `/` (and of course `\` for escaping character should not be replaced). This package was inspired by Go's [`path/filepath.FromSlash`](https://golang.org/pkg/path/filepath/#FromSlash) and [`path/filepath.ToSlash`](https://golang.org/pkg/path/filepath/#ToSlash). ## Usage `path_slash::PathExt` and `path_slash::PathBufExt` traits are defined. By using them, `std::path::Path` and `std::path::PathBuf` gains some methods and associated functions - `PathExt` - `Path::to_slash(&self) -> Option` - `Path::to_slash_lossy(&self) -> String` - `PathBufExt` - `PathBuf::from_slash>(s: S) -> PathBuf` - `PathBuf::from_slash_lossy>(s: S) -> PathBuf` - `PathBuf::to_slash(&self) -> Option` - `PathBuf::to_slash_lossy(&self) -> String` ```rust fn example_path_ext() { // Trait for extending std::path::Path use path_slash::PathExt; // On Windows assert_eq!( Path::new(r"foo\bar\piyo.txt").to_slash(), Some("foo/bar/piyo.txt".to_string()), ); assert_eq!( Path::new(r"C:\\foo\bar\piyo.txt").to_slash(), Some("C://foo/bar/piyo.txt".to_string()), ); } fn example_pathbuf_ext() { // Trait for extending std::path::PathBuf use path_slash::PathBufExt; // On Windows let p = PathBuf::from_slash("foo/bar/piyo.txt"); assert_eq!(p, PathBuf::from(r"foo\bar\piyo.txt")); assert_eq!(p.to_slash(), Some("foo/bar/piyo.txt".to_string())); } ``` Please read [documents][doc] for more details. ## Installation Add `path-slash` to dependencies: ```toml [dependencies] path-slash = "0.x" ``` ## License [the MIT License](LICENSE.txt) [doc-badge]: https://docs.rs/path-slash/badge.svg [doc]: https://docs.rs/path-slash [crates-io-badge]: https://img.shields.io/crates/v/path-slash.svg [crates-io]: https://crates.io/crates/path-slash [appveyor-badge]: https://ci.appveyor.com/api/projects/status/44t8q0viea89fm2e/branch/master?svg=true [appveyor]: https://ci.appveyor.com/project/rhysd/path-slash/branch/master [travis-ci-badge]: https://travis-ci.org/rhysd/path-slash.svg?branch=master [travis-ci]: https://travis-ci.org/rhysd/path-slash path-slash-0.1.1/src/lib.rs010064400007650000024000000321061341635523700137120ustar0000000000000000//! A library for converting file paths from/to slash paths //! //! A slash path is a path whose components are separated by separator '/' always. //! //! In Unix-like OS, path separator is slash '/' by default. So any conversion is not necessary. //! But on Windows, file path separator '\' needs to be replaced with slash '/' (and of course '\' //! for escaping character should not be replaced). //! //! For example, a file path 'foo\bar\piyo.txt' can be converted to/from a slash path 'foo/bar/piyo.txt' //! //! This package was inspired by Go's `path/filepath.FromSlash` and `path/filepath.ToSlash`. //! - https://golang.org/pkg/path/filepath/#FromSlash //! - https://golang.org/pkg/path/filepath/#ToSlash //! //! ```rust //! use std::path::{Path, PathBuf}; //! //! // Trait for extending std::path::Path //! use path_slash::PathExt; //! // Trait for extending std::path::PathBuf //! use path_slash::PathBufExt; //! //! #[cfg(target_os = "windows")] //! { //! assert_eq!( //! Path::new(r"foo\bar\piyo.txt").to_slash(), //! Some("foo/bar/piyo.txt".to_string()), //! ); //! assert_eq!( //! Path::new(r"C:\\foo\bar\piyo.txt").to_slash(), //! Some("C://foo/bar/piyo.txt".to_string()), //! ); //! //! let p = PathBuf::from_slash("foo/bar/piyo.txt"); //! assert_eq!(p, PathBuf::from(r"foo\bar\piyo.txt")); //! assert_eq!(p.to_slash(), Some("foo/bar/piyo.txt".to_string())); //! } //! //! #[cfg(not(target_os = "windows"))] //! { //! assert_eq!( //! Path::new("foo/bar/piyo.txt").to_slash(), //! Some("foo/bar/piyo.txt".to_string()), //! ); //! assert_eq!( //! Path::new("/foo/bar/piyo.txt").to_slash(), //! Some("/foo/bar/piyo.txt".to_string()), //! ); //! //! let p = PathBuf::from_slash("foo/bar/piyo.txt"); //! assert_eq!(p, PathBuf::from(r"foo/bar/piyo.txt")); //! assert_eq!(p.to_slash(), Some("foo/bar/piyo.txt".to_string())); //! } //! ``` use std::ffi::OsStr; use std::path::{Path, PathBuf}; /// Trait to extend std::path::Path. /// /// ``` /// use path_slash::PathExt; /// /// assert_eq!( /// std::path::Path::new("foo").to_slash(), /// Some("foo".to_string()), /// ); /// ``` pub trait PathExt { fn to_slash(&self) -> Option; fn to_slash_lossy(&self) -> String; } impl PathExt for Path { /// Convert the file path into slash path as UTF-8 string. /// /// Any file path separators in the file path is replaced with '/'. /// Any non-Unicode sequences are replaced with U+FFFD. /// /// On non-Windows OS, it is equivalent to `to_string_lossy().to_string()` /// /// ``` /// use std::path::Path; /// use path_slash::PathExt; /// /// #[cfg(target_os = "windows")] /// let s = Path::new(r"foo\bar\piyo.txt"); /// /// #[cfg(not(target_os = "windows"))] /// let s = Path::new("foo/bar/piyo.txt"); /// /// assert_eq!(s.to_slash_lossy(), "foo/bar/piyo.txt".to_string()); /// ``` #[cfg(not(target_os = "windows"))] fn to_slash_lossy(&self) -> String { self.to_string_lossy().to_string() } /// Convert the file path into slash path as UTF-8 string. /// /// Any file path separators in the file path is replaced with '/'. /// Any non-Unicode sequences are replaced with U+FFFD. /// /// On non-Windows OS, it is equivalent to `.to_string_lossy().to_string()`. /// /// ``` /// use std::path::Path; /// use path_slash::PathExt; /// /// #[cfg(target_os = "windows")] /// let s = Path::new(r"foo\bar\piyo.txt"); /// /// #[cfg(not(target_os = "windows"))] /// let s = Path::new("foo/bar/piyo.txt"); /// /// assert_eq!(s.to_slash_lossy(), "foo/bar/piyo.txt".to_string()); /// ``` #[cfg(target_os = "windows")] fn to_slash_lossy(&self) -> String { use std::path; let mut buf = String::new(); for c in self.components() { match c { path::Component::RootDir => { /* empty */ } path::Component::CurDir => buf.push('.'), path::Component::ParentDir => buf.push_str(".."), path::Component::Prefix(ref prefix) => { let s = prefix.as_os_str(); match s.to_str() { Some(ref s) => buf.push_str(s), None => buf.push_str(&s.to_string_lossy()), } } path::Component::Normal(ref s) => match s.to_str() { Some(ref s) => buf.push_str(s), None => buf.push_str(&s.to_string_lossy()), }, } buf.push('/'); } if buf != "/" { buf.pop(); // Pop last '/' } buf } /// Convert the file path into slash path as UTF-8 string. /// /// Any file path separators in the file path is replaced with '/'. /// When the path contains non-Unicode sequence, this method returns None. /// /// On non-Windows OS, it is equivalent to `.to_str().map(std::to_string())` /// /// ``` /// use std::path::Path; /// use path_slash::PathExt; /// /// #[cfg(target_os = "windows")] /// let s = Path::new(r"foo\bar\piyo.txt"); /// /// #[cfg(not(target_os = "windows"))] /// let s = Path::new("foo/bar/piyo.txt"); /// /// assert_eq!(s.to_slash(), Some("foo/bar/piyo.txt".to_string())); /// ``` #[cfg(not(target_os = "windows"))] fn to_slash(&self) -> Option { self.to_str().map(str::to_string) } /// Convert the file path into slash path as UTF-8 string. /// /// Any file path separators in the file path is replaced with '/'. /// When the path contains non-Unicode sequence, this method returns None. /// /// On non-Windows OS, it is equivalent to `.to_str().map(std::to_string())` /// /// ``` /// use std::path::Path; /// use path_slash::PathExt; /// /// #[cfg(target_os = "windows")] /// let s = Path::new(r"foo\bar\piyo.txt"); /// /// #[cfg(not(target_os = "windows"))] /// let s = Path::new("foo/bar/piyo.txt"); /// /// assert_eq!(s.to_slash(), Some("foo/bar/piyo.txt".to_string())); /// ``` #[cfg(target_os = "windows")] fn to_slash(&self) -> Option { use std::path; let components = self .components() .map(|c| match c { path::Component::RootDir => Some(""), path::Component::CurDir => Some("."), path::Component::ParentDir => Some(".."), path::Component::Prefix(ref p) => p.as_os_str().to_str(), path::Component::Normal(ref s) => s.to_str(), }) .collect::>>(); components.map(|v| { if v.len() == 1 && v[0].is_empty() { // Special case for '/' "/".to_string() } else { v.join("/") } }) } } /// Trait to extend std::path::PathBuf. /// /// ``` /// use path_slash::PathBufExt; /// /// assert_eq!( /// std::path::PathBuf::from_slash("foo/bar/piyo.txt").to_slash(), /// Some("foo/bar/piyo.txt".to_string()), /// ); /// ``` pub trait PathBufExt { fn from_slash>(s: S) -> Self; fn from_slash_lossy>(s: S) -> Self; fn to_slash(&self) -> Option; fn to_slash_lossy(&self) -> String; } impl PathBufExt for PathBuf { /// Convert the slash path (path separated with '/') to std::path::PathBuf. /// /// Any '/' in the slash path is replaced with the file path separator. /// The replacements only happen on Windows since the file path separators on other OSes are the /// same as '/'. /// /// On non-Windows OS, it is simply equivalent to std::path::PathBuf::from(). /// /// ``` /// use std::path::PathBuf; /// use path_slash::PathBufExt; /// /// let p = PathBuf::from_slash("foo/bar/piyo.txt"); /// /// #[cfg(target_os = "windows")] /// assert_eq!(p, PathBuf::from(r"foo\bar\piyo.txt")); /// /// #[cfg(not(target_os = "windows"))] /// assert_eq!(p, PathBuf::from("foo/bar/piyo.txt")); /// ``` #[cfg(not(target_os = "windows"))] fn from_slash>(s: S) -> Self { PathBuf::from(s.as_ref()) } /// Convert the slash path (path separated with '/') to std::path::PathBuf. /// /// Any '/' in the slash path is replaced with the file path separator. /// The replacements only happen on Windows since the file path separators on other OSes are the /// same as '/'. /// /// On non-Windows OS, it is simply equivalent to std::path::PathBuf::from(). /// /// ``` /// use std::path::PathBuf; /// use path_slash::PathBufExt; /// /// let p = PathBuf::from_slash("foo/bar/piyo.txt"); /// /// #[cfg(target_os = "windows")] /// assert_eq!(p, PathBuf::from(r"foo\bar\piyo.txt")); /// /// #[cfg(not(target_os = "windows"))] /// assert_eq!(p, PathBuf::from("foo/bar/piyo.txt")); /// ``` #[cfg(target_os = "windows")] fn from_slash>(s: S) -> Self { use std::path; let s = s .as_ref() .chars() .map(|c| match c { '/' => path::MAIN_SEPARATOR, c => c, }) .collect::(); PathBuf::from(s) } /// Convert the slash path (path separated with '/') to std::path::PathBuf. /// /// Any '/' in the slash path is replaced with the file path separator. /// The replacements only happen on Windows since the file path separators on other OSes are the /// same as '/'. /// /// On Windows, any non-Unicode sequences are replaced with U+FFFD while the conversion. /// On non-Windows OS, it is simply equivalent to std::path::PathBuf::from() and there is no /// loss while conversion. /// /// ``` /// use std::ffi::OsStr; /// use std::path::PathBuf; /// use path_slash::PathBufExt; /// /// let s: &OsStr = "foo/bar/piyo.txt".as_ref(); /// let p = PathBuf::from_slash_lossy(s); /// /// #[cfg(target_os = "windows")] /// assert_eq!(p, PathBuf::from(r"foo\bar\piyo.txt")); /// /// #[cfg(not(target_os = "windows"))] /// assert_eq!(p, PathBuf::from("foo/bar/piyo.txt")); /// ``` #[cfg(not(target_os = "windows"))] fn from_slash_lossy>(s: S) -> Self { PathBuf::from(s.as_ref()) } /// Convert the slash path (path separated with '/') to std::path::PathBuf. /// /// Any '/' in the slash path is replaced with the file path separator. /// The replacements only happen on Windows since the file path separators on other OSes are the /// same as '/'. /// /// On Windows, any non-Unicode sequences are replaced with U+FFFD while the conversion. /// On non-Windows OS, it is simply equivalent to std::path::PathBuf::from() and there is no /// loss while conversion. /// /// ``` /// use std::ffi::OsStr; /// use std::path::PathBuf; /// use path_slash::PathBufExt; /// /// let s: &OsStr = "foo/bar/piyo.txt".as_ref(); /// let p = PathBuf::from_slash_lossy(s); /// /// #[cfg(target_os = "windows")] /// assert_eq!(p, PathBuf::from(r"foo\bar\piyo.txt")); /// /// #[cfg(not(target_os = "windows"))] /// assert_eq!(p, PathBuf::from("foo/bar/piyo.txt")); /// ``` #[cfg(target_os = "windows")] fn from_slash_lossy>(s: S) -> Self { Self::from_slash(s.as_ref().to_string_lossy().chars().as_str()) } /// Convert the file path into slash path as UTF-8 string. /// /// Any file path separators in the file path is replaced with '/'. /// Any non-Unicode sequences are replaced with U+FFFD. /// /// On non-Windows OS, it is equivalent to `to_string_lossy().to_string()` /// /// ``` /// use path_slash::PathBufExt; /// /// #[cfg(target_os = "windows")] /// let s = std::path::PathBuf::from(r"foo\bar\piyo.txt"); /// /// #[cfg(not(target_os = "windows"))] /// let s = std::path::PathBuf::from("foo/bar/piyo.txt"); /// /// assert_eq!(s.to_slash_lossy(), "foo/bar/piyo.txt".to_string()); /// ``` fn to_slash_lossy(&self) -> String { self.as_path().to_slash_lossy() } /// Convert the file path into slash path as UTF-8 string. /// /// Any file path separators in the file path is replaced with '/'. /// When the path contains non-Unicode sequence, this method returns None. /// /// On non-Windows OS, it is equivalent to `.to_str().map(std::to_string())` /// /// ``` /// use path_slash::PathBufExt; /// /// #[cfg(target_os = "windows")] /// let s = std::path::PathBuf::from(r"foo\bar\piyo.txt"); /// /// #[cfg(not(target_os = "windows"))] /// let s = std::path::PathBuf::from("foo/bar/piyo.txt"); /// /// assert_eq!(s.to_slash(), Some("foo/bar/piyo.txt".to_string())); /// ``` fn to_slash(&self) -> Option { self.as_path().to_slash() } } #[cfg(test)] #[macro_use] extern crate lazy_static; #[cfg(test)] mod test; path-slash-0.1.1/src/test.rs010064400007650000024000000066651341635523700141360ustar0000000000000000use super::*; use std::ffi::OsStr; use std::path; lazy_static! { static ref FROM_SLASH_TESTS: Vec<(String, PathBuf)> = { [ ("", ""), ("/", "/"), ("//", "/"), ("foo", "foo"), ("/foo", "/foo"), ("foo/", "foo"), ("/foo/", "/foo"), ("./foo", "./foo"), ("../foo", "../foo"), ("foo/.", "foo/."), ("foo/..", "foo/.."), ("foo/bar", "foo/bar"), ("foo//bar", "foo/bar"), ("foo/../bar", "foo/../bar"), ("foo/./bar", "foo/./bar"), ] .into_iter() .map(|item| { let (input, expected) = item; let expected = if cfg!(target_os = "windows") { let s = expected .chars() .map(|c| match c { '/' => path::MAIN_SEPARATOR, _ => c, }) .collect::(); PathBuf::from(s) } else { PathBuf::from(expected) }; (input.to_string(), expected) }) .collect::>() }; } #[test] fn from_slash() { for (input, expected) in FROM_SLASH_TESTS.iter() { assert_eq!(&PathBuf::from_slash(input), expected); } } #[test] fn from_slash_lossy() { for (input, expected) in FROM_SLASH_TESTS.iter() { let input: &OsStr = input.as_ref(); assert_eq!(&PathBuf::from_slash_lossy(input), expected); } } lazy_static! { static ref TO_SLASH_TESTS: Vec<(PathBuf, String)> = { [ "", "/", "foo", "/foo", "foo", "/foo", "./foo", "../foo", "foo/..", "foo/bar", "foo/../bar", ] .into_iter() .map(|expected| { let input = if cfg!(target_os = "windows") { let s = expected .chars() .map(|c| match c { '/' => path::MAIN_SEPARATOR, _ => c, }) .collect::(); PathBuf::from(s) } else { PathBuf::from(expected) }; (input, expected.to_string()) }) .collect::>() }; } #[test] fn to_slash_path() { for (input, expected) in TO_SLASH_TESTS.iter() { assert_eq!(input.as_path().to_slash(), Some(expected.clone())); } } #[test] fn to_slash_pathbuf() { for (input, expected) in TO_SLASH_TESTS.iter() { assert_eq!(input.to_slash(), Some(expected.clone())); } } #[test] fn to_slash_lossy_path() { for (input, expected) in TO_SLASH_TESTS.iter() { assert_eq!(&input.as_path().to_slash_lossy(), expected); } } #[test] fn to_slash_lossy_pathbuf() { for (input, expected) in TO_SLASH_TESTS.iter() { assert_eq!(&input.to_slash_lossy(), expected); } } #[test] fn from_slash_to_slash() { for (_, path) in TO_SLASH_TESTS.iter() { assert_eq!(PathBuf::from_slash(path).to_slash(), Some(path.clone())); } } #[test] #[cfg(target_os = "windows")] fn with_driver_letter() { let path = PathBuf::from_slash("C://foo/bar"); assert_eq!(path, PathBuf::from(r"C:\\foo\bar")); let slash = path.to_slash(); assert_eq!(slash, Some("C://foo/bar".to_string())); } path-slash-0.1.1/.cargo_vcs_info.json0000644000000001120000000000000131300ustar00{ "git": { "sha1": "250bc63aaa8d9db8d0dd1b1e8b0238d1cd0fc815" } }