PR fixes - constants for path separator, UTF-8 instead of unicode for encoding, test for empty vs root paths
This commit is contained in:
parent
b1733fdbfa
commit
449d2ac0da
@ -41,7 +41,7 @@ impl EmbeddedWatcher {
|
|||||||
};
|
};
|
||||||
let watcher = new_asset_event_debouncer(
|
let watcher = new_asset_event_debouncer(
|
||||||
root.to_str()
|
root.to_str()
|
||||||
.expect("non unicode characters found in path")
|
.expect("non UTF-8 characters found in path")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
debounce_wait_time,
|
debounce_wait_time,
|
||||||
handler,
|
handler,
|
||||||
|
@ -546,7 +546,7 @@ impl AssetSource {
|
|||||||
Some(Box::new(
|
Some(Box::new(
|
||||||
super::file::FileWatcher::new(
|
super::file::FileWatcher::new(
|
||||||
path.to_str()
|
path.to_str()
|
||||||
.expect("non unicode characters found in path")
|
.expect("non UTF-8 characters found in path")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
sender,
|
sender,
|
||||||
file_debounce_wait_time,
|
file_debounce_wait_time,
|
||||||
|
@ -15,6 +15,9 @@ use serde::{de::Visitor, Deserialize, Serialize};
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
pub(crate) const PATH_SEPARATOR: char = '/';
|
||||||
|
pub(crate) const PATH_SEPARATOR_STR: &str = "/";
|
||||||
|
|
||||||
/// Represents a path to an asset in a "virtual filesystem".
|
/// Represents a path to an asset in a "virtual filesystem".
|
||||||
///
|
///
|
||||||
/// Asset paths consist of three main parts:
|
/// Asset paths consist of three main parts:
|
||||||
@ -71,10 +74,10 @@ impl<'a> PartialEq for AssetPath<'a> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let self_trailing_slash = self.path.len() > 1
|
let self_trailing_slash = self.path.len() > 1
|
||||||
&& self.path.ends_with("/")
|
&& self.path.ends_with(PATH_SEPARATOR)
|
||||||
&& self.path[..self.path.len() - 1] == other.path[..other.path.len()];
|
&& self.path[..self.path.len() - 1] == other.path[..other.path.len()];
|
||||||
let other_trailing_slash = other.path.len() > 1
|
let other_trailing_slash = other.path.len() > 1
|
||||||
&& other.path.ends_with("/")
|
&& other.path.ends_with(PATH_SEPARATOR)
|
||||||
&& self.path[..self.path.len()] == other.path[..other.path.len() - 1];
|
&& self.path[..self.path.len()] == other.path[..other.path.len() - 1];
|
||||||
self.path == other.path || self_trailing_slash || other_trailing_slash
|
self.path == other.path || self_trailing_slash || other_trailing_slash
|
||||||
}
|
}
|
||||||
@ -82,7 +85,7 @@ impl<'a> PartialEq for AssetPath<'a> {
|
|||||||
|
|
||||||
impl<'a> Hash for AssetPath<'a> {
|
impl<'a> Hash for AssetPath<'a> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
let path = if self.path.ends_with('/') {
|
let path = if self.path.ends_with(PATH_SEPARATOR) {
|
||||||
&self.path[..self.path.len() - 1]
|
&self.path[..self.path.len() - 1]
|
||||||
} else {
|
} else {
|
||||||
&self.path
|
&self.path
|
||||||
@ -191,7 +194,7 @@ impl<'a> AssetPath<'a> {
|
|||||||
':' => {
|
':' => {
|
||||||
source_delimiter_chars_matched = 1;
|
source_delimiter_chars_matched = 1;
|
||||||
}
|
}
|
||||||
'/' => {
|
PATH_SEPARATOR => {
|
||||||
match source_delimiter_chars_matched {
|
match source_delimiter_chars_matched {
|
||||||
1 => {
|
1 => {
|
||||||
source_delimiter_chars_matched = 2;
|
source_delimiter_chars_matched = 2;
|
||||||
@ -348,17 +351,20 @@ impl<'a> AssetPath<'a> {
|
|||||||
/// Splits the internal path into components
|
/// Splits the internal path into components
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn path_components(&self) -> impl Iterator<Item = &str> {
|
pub fn path_components(&self) -> impl Iterator<Item = &str> {
|
||||||
self.path.split('/')
|
self.path.split(PATH_SEPARATOR)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an [`AssetPath`] for the parent folder of this path, if there is a parent folder in the path.
|
/// Returns an [`AssetPath`] for the parent folder of this path, if there is a parent folder in the path.
|
||||||
pub fn parent(&self) -> Option<AssetPath<'a>> {
|
pub fn parent(&self) -> Option<AssetPath<'a>> {
|
||||||
if self.path.as_ref() == "/" || self.path.starts_with('#') || self.path.is_empty() {
|
if self.path.as_ref() == PATH_SEPARATOR_STR
|
||||||
|
|| self.path.starts_with('#')
|
||||||
|
|| self.path.is_empty()
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let mut path: Vec<_> = self.path_components().map(ToString::to_string).collect();
|
let mut path: Vec<_> = self.path_components().map(ToString::to_string).collect();
|
||||||
path.pop();
|
path.pop();
|
||||||
let path = path.join("/");
|
let path = path.join(PATH_SEPARATOR_STR);
|
||||||
Some(AssetPath {
|
Some(AssetPath {
|
||||||
source: self.source.clone(),
|
source: self.source.clone(),
|
||||||
label: None,
|
label: None,
|
||||||
@ -467,14 +473,14 @@ impl<'a> AssetPath<'a> {
|
|||||||
} else {
|
} else {
|
||||||
let (source, rpath, rlabel) = AssetPath::parse_internal(path)?;
|
let (source, rpath, rlabel) = AssetPath::parse_internal(path)?;
|
||||||
let mut base_path: Vec<_> = self.path_components().filter(|s| !s.is_empty()).collect();
|
let mut base_path: Vec<_> = self.path_components().filter(|s| !s.is_empty()).collect();
|
||||||
if replace && !self.path.ends_with('/') {
|
if replace && !self.path.ends_with(PATH_SEPARATOR) {
|
||||||
// No error if base is empty (per RFC 1808).
|
// No error if base is empty (per RFC 1808).
|
||||||
base_path.pop();
|
base_path.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Strip off leading slash
|
// Strip off leading slash
|
||||||
let mut is_absolute = false;
|
let mut is_absolute = false;
|
||||||
let rpath = match rpath.strip_prefix("/") {
|
let rpath = match rpath.strip_prefix(PATH_SEPARATOR) {
|
||||||
Some(p) => {
|
Some(p) => {
|
||||||
is_absolute = true;
|
is_absolute = true;
|
||||||
p
|
p
|
||||||
@ -487,8 +493,8 @@ impl<'a> AssetPath<'a> {
|
|||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
result_path.extend(rpath.split("/").filter(|s| !s.is_empty()));
|
result_path.extend(rpath.split(PATH_SEPARATOR).filter(|s| !s.is_empty()));
|
||||||
let result_path = normalize_path(&result_path).join("/");
|
let result_path = normalize_path(&result_path).join(PATH_SEPARATOR_STR);
|
||||||
|
|
||||||
Ok(AssetPath {
|
Ok(AssetPath {
|
||||||
source: match source {
|
source: match source {
|
||||||
@ -556,7 +562,7 @@ impl<'a> AssetPath<'a> {
|
|||||||
/// assert!(path.is_unapproved());
|
/// assert!(path.is_unapproved());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn is_unapproved(&self) -> bool {
|
pub fn is_unapproved(&self) -> bool {
|
||||||
if self.path.starts_with("/") {
|
if self.path.starts_with(PATH_SEPARATOR_STR) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
let mut simplified = Vec::new();
|
let mut simplified = Vec::new();
|
||||||
@ -640,7 +646,7 @@ impl<'a> From<&'a Path> for AssetPath<'a> {
|
|||||||
source: AssetSourceId::Default,
|
source: AssetSourceId::Default,
|
||||||
path: CowArc::from(
|
path: CowArc::from(
|
||||||
path.to_str()
|
path.to_str()
|
||||||
.expect("non unicode characters found in file path")
|
.expect("non utf-8 characters found in file path")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
),
|
),
|
||||||
label: None,
|
label: None,
|
||||||
@ -655,7 +661,7 @@ impl From<PathBuf> for AssetPath<'static> {
|
|||||||
source: AssetSourceId::Default,
|
source: AssetSourceId::Default,
|
||||||
path: CowArc::from(
|
path: CowArc::from(
|
||||||
path.to_str()
|
path.to_str()
|
||||||
.expect("non unicode characters found in file path")
|
.expect("non UTF-8 characters found in file path")
|
||||||
.to_string(),
|
.to_string(),
|
||||||
),
|
),
|
||||||
label: None,
|
label: None,
|
||||||
@ -1087,6 +1093,11 @@ mod tests {
|
|||||||
assert_eq!(AssetPath::from("a/b/#c"), AssetPath::from("a/b#c"));
|
assert_eq!(AssetPath::from("a/b/#c"), AssetPath::from("a/b#c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_slash_inequality_to_empty() {
|
||||||
|
assert_ne!(AssetPath::from(""), AssetPath::from("/"));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_path_components() {
|
fn test_path_components() {
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
Loading…
Reference in New Issue
Block a user