feat!: introduce Path as a subset of Url to enforce type safety (#3361)

This commit is contained in:
sxyazi 2025-11-24 15:23:06 +08:00
parent 76fe6d7244
commit 449450d0db
No known key found for this signature in database
10 changed files with 28 additions and 24 deletions

View file

@ -12,7 +12,7 @@ jobs:
os: [ubuntu-latest, macos-latest] os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@v31 uses: cachix/install-nix-action@v31

View file

@ -14,7 +14,7 @@ jobs:
clippy: clippy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Setup Rust toolchain - name: Setup Rust toolchain
run: | run: |
@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v5 uses: actions/checkout@v6
- name: Setup Rust toolchain - name: Setup Rust toolchain
run: | run: |
@ -47,7 +47,7 @@ jobs:
stylua: stylua:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: JohnnyMorganz/stylua-action@v4 - uses: JohnnyMorganz/stylua-action@v4
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}

View file

@ -39,7 +39,7 @@ jobs:
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc
CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER: sparc64-linux-gnu-gcc CARGO_TARGET_SPARC64_UNKNOWN_LINUX_GNU_LINKER: sparc64-linux-gnu-gcc
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Install gcc - name: Install gcc
if: matrix.gcc != '' if: matrix.gcc != ''
@ -78,7 +78,7 @@ jobs:
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER: lld-link.exe CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER: lld-link.exe
CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER: lld-link.exe CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER: lld-link.exe
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@stable
with: with:
@ -117,7 +117,7 @@ jobs:
container: container:
image: docker://ghcr.io/cross-rs/${{ matrix.target }}:edge image: docker://ghcr.io/cross-rs/${{ matrix.target }}:edge
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable - uses: dtolnay/rust-toolchain@stable
with: with:
@ -147,7 +147,7 @@ jobs:
arch: arm64 arch: arm64
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
with: with:
fetch-depth: 0 fetch-depth: 0
@ -229,7 +229,7 @@ jobs:
echo "Generated on: $(date -u +"%Y-%m-%d %H:%M") UTC" >> $GITHUB_ENV echo "Generated on: $(date -u +"%Y-%m-%d %H:%M") UTC" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- uses: actions/download-artifact@v6 - uses: actions/download-artifact@v6
with: with:

View file

@ -18,7 +18,7 @@ jobs:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Setup Rust toolchain - name: Setup Rust toolchain
run: rustup toolchain install stable --profile minimal run: rustup toolchain install stable --profile minimal

View file

@ -12,7 +12,7 @@ jobs:
permissions: permissions:
issues: write issues: write
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v6
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@v6

View file

@ -45,6 +45,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
- Rename `name` to `url` for open, fetchers, spotters, preloaders, previewers, filetype, and `globs` icon rules to support virtual file system ([#3034]) - Rename `name` to `url` for open, fetchers, spotters, preloaders, previewers, filetype, and `globs` icon rules to support virtual file system ([#3034])
- Rename `mime` fetcher to `mime.local`, and introduce `mime.dir` fetcher to support folder MIME types ([#3222]) - Rename `mime` fetcher to `mime.local`, and introduce `mime.dir` fetcher to support folder MIME types ([#3222])
- Remove `$0` parameter in opener rules to make the `open` command work under empty directories ([#3226]) - Remove `$0` parameter in opener rules to make the `open` command work under empty directories ([#3226])
- Return `Path` instead of `Url` from `Url:strip_prefix()` to enforce type safety ([#3361])
- Use `body` instead of the term `content` in confirmations ([#2921]) - Use `body` instead of the term `content` in confirmations ([#2921])
- Use `u16` instead of `u32` as the type of `max_width` and `max_height` options to avoid memory exhaustion ([#3313]) - Use `u16` instead of `u32` as the type of `max_width` and `max_height` options to avoid memory exhaustion ([#3313])
- Implement `__pairs` metamethod instead of `__index` for the callback argument of the `@yank` DDS event ([#2997]) - Implement `__pairs` metamethod instead of `__index` for the callback argument of the `@yank` DDS event ([#2997])

View file

@ -115,6 +115,9 @@ impl UserData for Path {
cached_field!(fields, stem, |lua, me| { cached_field!(fields, stem, |lua, me| {
me.stem().map(|s| lua.create_string(s.encoded_bytes())).transpose() me.stem().map(|s| lua.create_string(s.encoded_bytes())).transpose()
}); });
fields.add_field_method_get("is_absolute", |_, me| Ok(me.is_absolute()));
fields.add_field_method_get("has_root", |_, me| Ok(me.has_root()));
} }
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) { fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {

View file

@ -2,12 +2,11 @@ use std::path::PathBuf;
use futures::executor::block_on; use futures::executor::block_on;
use hashbrown::HashSet; use hashbrown::HashSet;
use serde::Serialize;
use yazi_fs::{CWD, Xdg, path::expand_url}; use yazi_fs::{CWD, Xdg, path::expand_url};
use yazi_shared::{strand::StrandBuf, url::{UrlBuf, UrlLike}}; use yazi_shared::{strand::StrandBuf, url::{UrlBuf, UrlLike}};
use yazi_vfs::provider; use yazi_vfs::provider;
#[derive(Debug, Default, Serialize)] #[derive(Debug, Default)]
pub struct Boot { pub struct Boot {
pub cwds: Vec<UrlBuf>, pub cwds: Vec<UrlBuf>,
pub files: Vec<StrandBuf>, pub files: Vec<StrandBuf>,

View file

@ -1,13 +1,11 @@
use std::{borrow::Cow, ffi::OsString}; use std::{borrow::Cow, ffi::OsString, hash::{Hash, Hasher}};
use anyhow::Result; use anyhow::Result;
use serde::Serialize;
use crate::{FromWtf8Vec, path::PathDyn, strand::{AsStrand, Strand, StrandCow, StrandError, StrandKind}}; use crate::{FromWtf8Vec, path::PathDyn, strand::{AsStrand, Strand, StrandCow, StrandError, StrandKind}};
// --- StrandBuf // --- StrandBuf
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] #[derive(Clone, Debug, Eq)]
#[serde(untagged)]
pub enum StrandBuf { pub enum StrandBuf {
Os(OsString), Os(OsString),
Utf8(String), Utf8(String),
@ -43,10 +41,18 @@ impl From<StrandCow<'_>> for StrandBuf {
fn from(value: StrandCow<'_>) -> Self { value.into_owned() } fn from(value: StrandCow<'_>) -> Self { value.into_owned() }
} }
impl PartialEq for StrandBuf {
fn eq(&self, other: &Self) -> bool { self.as_strand() == other.as_strand() }
}
impl PartialEq<Strand<'_>> for StrandBuf { impl PartialEq<Strand<'_>> for StrandBuf {
fn eq(&self, other: &Strand<'_>) -> bool { self.as_strand() == *other } fn eq(&self, other: &Strand<'_>) -> bool { self.as_strand() == *other }
} }
impl Hash for StrandBuf {
fn hash<H: Hasher>(&self, state: &mut H) { self.as_strand().hash(state); }
}
impl StrandBuf { impl StrandBuf {
pub fn clear(&mut self) { pub fn clear(&mut self) {
match self { match self {

View file

@ -2,7 +2,7 @@ use std::{borrow::Cow, ffi::{OsStr, OsString}};
use anyhow::Result; use anyhow::Result;
use crate::strand::{Strand, StrandBuf, StrandKind}; use crate::strand::{AsStrand, Strand, StrandBuf, StrandKind};
pub enum StrandCow<'a> { pub enum StrandCow<'a> {
Borrowed(Strand<'a>), Borrowed(Strand<'a>),
@ -35,12 +35,7 @@ impl From<StrandBuf> for StrandCow<'_> {
} }
impl PartialEq<Strand<'_>> for StrandCow<'_> { impl PartialEq<Strand<'_>> for StrandCow<'_> {
fn eq(&self, other: &Strand) -> bool { fn eq(&self, other: &Strand) -> bool { self.as_strand() == *other }
match self {
Self::Borrowed(s) => s == other,
Self::Owned(s) => s == other,
}
}
} }
impl<'a> StrandCow<'a> { impl<'a> StrandCow<'a> {