camino-rs / camino Goto Github PK
View Code? Open in Web Editor NEWLike Rust's std::path::Path, but UTF-8.
Home Page: https://docs.rs/camino
License: Apache License 2.0
Like Rust's std::path::Path, but UTF-8.
Home Page: https://docs.rs/camino
License: Apache License 2.0
With rust 1.68.0 DerefMut will be implemented for PathBuf (rust-lang/rust#105018) , so I assume it is desirable to mirror that change in camino.
Return a &Path
.
This can be done through AsRef
, but requires a type annotation sometimes.
When I try to compile my binary with the new version of camino
, it fails with error:
error[E0658]: use of unstable library feature 'try_reserve_2'
--> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/camino-1.1.0/src/lib.rs:430:16
|
430 | self.0.try_reserve(additional)
| ^^^^^^^^^^^
|
= note: see issue #91789 <https://github.com/rust-lang/rust/issues/91789> for more information
= help: add `#![feature(try_reserve_2)]` to the crate attributes to enable
Hi!
I just opened a PR that introduces camino to the tool I'm working on, and I seem to be relying on Utf8PathBuf::from_path_buf
quite a bit when interacting with std::path::PathBuf
s coming from places like std::env::current_dir
.
I'd love to just use ?
like I would any other fallible function that returns a Result
type, but it seems that Utf8PathBuf::from_path_buf
returns a Result<Utf8PathBuf, PathBuf>
which requires me to write .map_err
every time I call it.
Am I doing something wrong here? Is there a better way to do these conversions that I'm missing? If not, it seems like that Result
type should implement std::error::Error
and possibly wrap the old PathBuf
up in it.
Love the library! Thanks for all of the work you've put in to make it a reality ๐
Refer to #3 , I found these api is helpful when we want to convert from Utf8Path to Path(because some api needs it), and maybe it's also useful to convert from Utf8PathBuf to PathBuf?
If it's okey, I can try to help on this :-)
Calling Utf8Path::try_from
on an std::path::Path
fails with "the size for values of type [u8]
cannot be known at compilation time".
Example code:
use camino::Utf8Path;
use std::path::Path;
fn main() {
let path1 = Path::new("/test");
// This works:
let path2 = Utf8Path::from_path(path1).unwrap();
// But this fails with "the size for values of type `[u8]` cannot be known at compilation time"
let path3 = Utf8Path::try_from(path1).unwrap();
}
Full error output:
$ cargo build
Compiling camino-test v0.1.0 (/home/nicholasbishop/tmp/camino-test)
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> src/main.rs:9:17
|
9 | let path3 = Utf8Path::try_from(path1).unwrap();
| ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `Utf8Path`, the trait `Sized` is not implemented for `[u8]`
note: required because it appears within the type `Utf8Path`
--> /home/nicholasbishop/.cargo/registry/src/index.crates.io-6f17d22bba15001f/camino-1.1.6/src/lib.rs:545:12
|
545 | pub struct Utf8Path(Path);
| ^^^^^^^^
note: required by a bound in `try_from`
--> /home/nicholasbishop/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:638:23
|
638 | pub trait TryFrom<T>: Sized {
| ^^^^^ required by this bound in `TryFrom::try_from`
...
645 | fn try_from(value: T) -> Result<Self, Self::Error>;
| -------- required by a bound in this associated function
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> src/main.rs:9:17
|
9 | let path3 = Utf8Path::try_from(path1).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: within `Utf8Path`, the trait `Sized` is not implemented for `[u8]`
= help: the trait `TryFrom<&'a Path>` is implemented for `&'a Utf8Path`
note: required because it appears within the type `Utf8Path`
--> /home/nicholasbishop/.cargo/registry/src/index.crates.io-6f17d22bba15001f/camino-1.1.6/src/lib.rs:545:12
|
545 | pub struct Utf8Path(Path);
| ^^^^^^^^
= note: required for `Utf8Path` to implement `TryFrom<_>`
error[E0277]: the trait bound `Utf8Path: From<&Path>` is not satisfied
--> src/main.rs:9:36
|
9 | let path3 = Utf8Path::try_from(path1).unwrap();
| ------------------ ^^^^^ the trait `From<&Path>` is not implemented for `Utf8Path`
| |
| required by a bound introduced by this call
|
= help: the trait `From<&'a str>` is implemented for `&'a Utf8Path`
= note: required for `&Path` to implement `Into<Utf8Path>`
= note: required for `Utf8Path` to implement `TryFrom<&Path>`
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
--> src/main.rs:9:36
|
9 | let path3 = Utf8Path::try_from(path1).unwrap();
| ------------------ ^^^^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: within `Utf8Path`, the trait `Sized` is not implemented for `[u8]`
= help: the trait `TryFrom<&'a Path>` is implemented for `&'a Utf8Path`
note: required because it appears within the type `Utf8Path`
--> /home/nicholasbishop/.cargo/registry/src/index.crates.io-6f17d22bba15001f/camino-1.1.6/src/lib.rs:545:12
|
545 | pub struct Utf8Path(Path);
| ^^^^^^^^
= note: required for `&Path` to implement `Into<Utf8Path>`
= note: required for `Utf8Path` to implement `TryFrom<&Path>`
error[E0599]: the method `unwrap` exists for enum `Result<Utf8Path, Infallible>`, but its trait bounds were not satisfied
--> src/main.rs:9:43
|
9 | let path3 = Utf8Path::try_from(path1).unwrap();
| ^^^^^^ method cannot be called on `Result<Utf8Path, Infallible>` due to unsatisfied trait bounds
|
::: /home/nicholasbishop/.cargo/registry/src/index.crates.io-6f17d22bba15001f/camino-1.1.6/src/lib.rs:545:1
|
545 | pub struct Utf8Path(Path);
| ------------------- doesn't satisfy `Utf8Path: Sized`
|
= note: the following trait bounds were not satisfied:
`Utf8Path: Sized`
error[E0277]: the trait bound `Utf8Path: From<&Path>` is not satisfied
--> src/main.rs:9:17
|
9 | let path3 = Utf8Path::try_from(path1).unwrap();
| ^^^^^^^^^^^^^^^^^^ the trait `From<&Path>` is not implemented for `Utf8Path`
|
= help: the trait `From<&'a str>` is implemented for `&'a Utf8Path`
= note: required for `&Path` to implement `Into<Utf8Path>`
= note: required for `Utf8Path` to implement `TryFrom<&Path>`
Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
This might help certain read_dir_utf8()
cases. For example, say you want to collect only file entries:
path
.read_dir_utf8()
.unwrap()
.filter_map(|entry| {
let entry = entry.unwrap();
if entry.file_type().map(|ft| ft.is_file()).unwrap_or(false) {
Some(entry.into_path()) // <--- not (yet) possible directly
} else {
None
}
})
.collect::<Vec<Utf8PathBuf>>()
Currently, this requires entry.path().to_path_buf()
(as far as I can see?). There's a mismatch here between Utf8DirEntry::path()
(pub fn path(&self) -> &Utf8Path
) and fs::DirEntry::path()
(pub fn path(&self) -> PathBuf
). On many platforms, the underlying DirEntry
structs don't actually hold the path until path()
is called.
Utf8DirEntry
contains the inner fs::DirEntry
, and a path, which is already a Utf8PathBuf
:
Lines 2078 to 2081 in d6c6896
It can also be converted to fs::DirEntry
via into_inner()
. For the path, no such method exists. I wouldn't suggest a breaking change to Utf8DirEntry::path()
, but a direct conversion would be nice.
One extra benefit is that this helps camino users avoiding holding onto Utf8DirEntry
for longer than needed. As is, the most convenient owned struct is Utf8DirEntry
. Currently and on Unix, the Rust docs indicate that "holding DirEntry objects will consume a file handle even after the ReadDir iterator is dropped."
The into_path()
name was just chosen for the example to mirror into_inner()
. (Tangentally, Utf8DirEntry
doesn't implement Into<fs::DirEntry>
, so you have to use into_inner()
.)
Edit: The walkdir crate allows for something very similar/into_path()
. Possibly I've seen code in the past that used this, which is why the pattern felt familiar.
Anyway, that turned out longer than expected. Let me know your thoughts. I'd be happy to cut a tiny PR to add what is likely a tiny extra method + docs, or if it's easier for you to make the changes, also fine. Thanks for this great library!
I would like to use the schemars
crate in a project that heavily uses camino
, but am currently prevented from doing so because Utf8Path[Buf]
does not implement schemars::JsonSchema
.
This PR in schemars
has not gone anywhere because the maintainer has not reviewed it.
GREsau/schemars#214
Could we add these impls in camino
instead?
Mostly because I am curious, what is the rationale for requiring base
to implement AsRef<Path>
instead of AsRef<Self>
in Utf8Path::starts_with
?
Line 817 in 8aa7205
Utf8PathBuf
implements Borrow<Utf8Path>
but the following invariant of Borrow
does not hold:
In particular Eq, Ord and Hash must be equivalent for borrowed and owned values: x.borrow() == y.borrow() should give the same result as x == y.
That means that Utf8PathBuf and Utf8Path of the same content (i.e. partial_cmp returning Same) need to Hash the same. This does not currently seem to be true:
[src/main.rs:10] hash(camino::Utf8Path::new("db4")) = 2500477520987573830
[src/main.rs:14] hash(camino::Utf8PathBuf::from("db4")) = 12412650977873828595
with
fn hash(value: impl Hash) -> u64 {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
value.hash(&mut hasher);
hasher.finish()
}
What it says on the tin. Why declare separate features on top of the ones defined by the optional dependencies?
Serde supports Box and Box for read-only, owned values of these types.
I have a project that does a bunch of path manipulation and benefits a bit from using a wrapper with the simdutf8
crate.
If I find time, and there is interest, I would happily work on a PR to add optional simdutf8 support. It's not ready for production so it definitely should be optional.
I'd love to be able to simplify a bunch of this code the way camino
would normally let me.
let path = Utf8Path::new("/some/path");
for entry in path.read_dir()? {
let entry = entry?;
let this_returns_an_OsString = entry.file_name(); // should be String
let this_returns_a_PathBuf = entry.path(); // should be Utf8Path
}
Thanks for this terrific crate!
I found myself needing to convert between Cow<'a, str>
and Cow<'a, Utf8Path>
. This is a bit awkward with the current crate APIs because you need to explicitly construct a Cow
or Utf8Path
/Utf8PathBuf
at the call site. I'd prefer to e.g. just .into()
on a Cow<'a, str>
to get a Cow<'a, Utf8Path>
.
What do you think about adding explicit Cow<'a, str>
type conversions to Utf8Path
and Utf8PathBuf
?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.