mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-25 10:36:56 -06:00
sonar: method paths instead of closures (rust:S1612)
Poison recovery, OsStr::to_str and char predicates only; S4325 casts are f64 to f32 and stay. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
eb5108786b
commit
4e9fa51f12
@@ -52,7 +52,7 @@ struct State {
|
||||
static STATE: LazyLock<Mutex<State>> = LazyLock::new(Mutex::default);
|
||||
|
||||
fn state() -> std::sync::MutexGuard<'static, State> {
|
||||
STATE.lock().unwrap_or_else(|e| e.into_inner())
|
||||
STATE.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
/// The web app's Media Browser.
|
||||
|
||||
@@ -48,14 +48,14 @@ pub fn list() -> Vec<(String, usize)> {
|
||||
|
||||
/// The next write of `path` goes to browser storage only (no download).
|
||||
pub fn save_quietly(path: &str) {
|
||||
QUIET.lock().unwrap_or_else(|e| e.into_inner()).push(path.to_string());
|
||||
QUIET.lock().unwrap_or_else(std::sync::PoisonError::into_inner).push(path.to_string());
|
||||
}
|
||||
|
||||
/// A rendered file (from the page's exporter or a worker): kept in the table unpersisted and
|
||||
/// downloaded at the next [`flush_downloads`].
|
||||
pub fn add_output(path: &str, data: Arc<[u8]>) {
|
||||
STORE.put_file(path, data, false);
|
||||
OUTPUTS.lock().unwrap_or_else(|e| e.into_inner()).push(path.to_string());
|
||||
OUTPUTS.lock().unwrap_or_else(std::sync::PoisonError::into_inner).push(path.to_string());
|
||||
}
|
||||
|
||||
/// The table path for a picked/dropped file name.
|
||||
@@ -120,7 +120,7 @@ impl Services for WebServices {
|
||||
fn write_file(&self, path: &str, data: &[u8]) -> std::io::Result<()> {
|
||||
put(path, data.into());
|
||||
let quiet = {
|
||||
let mut q = QUIET.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut q = QUIET.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let n = q.len();
|
||||
q.retain(|p| p != path);
|
||||
q.len() != n
|
||||
@@ -184,7 +184,7 @@ pub fn export_sink() -> Arc<effectcraft_export::Sink> {
|
||||
|
||||
/// Download the render outputs written since the last call.
|
||||
pub fn flush_downloads() {
|
||||
let paths = std::mem::take(&mut *OUTPUTS.lock().unwrap_or_else(|e| e.into_inner()));
|
||||
let paths = std::mem::take(&mut *OUTPUTS.lock().unwrap_or_else(std::sync::PoisonError::into_inner));
|
||||
let mut out: Vec<(String, Arc<[u8]>)> = paths.into_iter().filter_map(|p| get(&p).map(|d| (file_name(&p).to_string(), d))).collect();
|
||||
out.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
out.dedup_by(|a, b| a.0 == b.0);
|
||||
|
||||
@@ -181,7 +181,7 @@ impl Default for Store {
|
||||
|
||||
impl Store {
|
||||
pub fn lock(&self) -> std::sync::MutexGuard<'_, Mirror> {
|
||||
self.mirror.lock().unwrap_or_else(|e| e.into_inner())
|
||||
self.mirror.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
fn now(&self) -> f64 {
|
||||
|
||||
@@ -50,7 +50,7 @@ fn app_icon() -> egui::IconData {
|
||||
fn is_project_file(path: &str) -> bool {
|
||||
std::path::Path::new(path)
|
||||
.extension()
|
||||
.and_then(|ext| ext.to_str())
|
||||
.and_then(std::ffi::OsStr::to_str)
|
||||
.is_some_and(|ext| ext.eq_ignore_ascii_case("ecproj") || ext.eq_ignore_ascii_case("ecprojx"))
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ impl ColorSpace {
|
||||
|
||||
/// Parse an id or label (case-insensitive, loose).
|
||||
pub fn parse(s: &str) -> Option<ColorSpace> {
|
||||
let k: String = s.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>().to_ascii_lowercase();
|
||||
let k: String = s.chars().filter(char::is_ascii_alphanumeric).collect::<String>().to_ascii_lowercase();
|
||||
match k.as_str() {
|
||||
"srgb" | "srgbiec6196621" | "srgbiec61966" | "iec6196621" => Some(ColorSpace::Srgb),
|
||||
"rec709" | "bt709" | "hdtvrec709" | "hdtv" | "709" => Some(ColorSpace::Rec709),
|
||||
|
||||
@@ -136,11 +136,11 @@ type Cache<T> = Mutex<HashMap<u64, Arc<T>>>;
|
||||
fn cached<T>(c: &'static OnceLock<Cache<T>>, json: &str, parse: impl Fn(&str) -> Option<T>) -> Option<Arc<T>> {
|
||||
let key = fnv(json.as_bytes());
|
||||
let c = c.get_or_init(Default::default);
|
||||
if let Some(a) = c.lock().unwrap_or_else(|e| e.into_inner()).get(&key) {
|
||||
if let Some(a) = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&key) {
|
||||
return Some(a.clone());
|
||||
}
|
||||
let a = Arc::new(parse(json)?);
|
||||
let mut m = c.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 8 {
|
||||
m.clear();
|
||||
}
|
||||
|
||||
@@ -315,11 +315,11 @@ fn frozen_cache(j: &str) -> Option<Arc<FrozenCache>> {
|
||||
let mut h = 0xcbf2_9ce4_8422_2325;
|
||||
fnv(&mut h, j.as_bytes());
|
||||
let c = C.get_or_init(Default::default);
|
||||
if let Some(d) = c.lock().unwrap_or_else(|e| e.into_inner()).get(&h) {
|
||||
if let Some(d) = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&h) {
|
||||
return Some(d.clone());
|
||||
}
|
||||
let d = Arc::new(FrozenCache::from_json(j)?);
|
||||
let mut m = c.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 8 {
|
||||
m.clear();
|
||||
}
|
||||
|
||||
@@ -617,7 +617,7 @@ pub fn load_file(src: &str) -> Option<Arc<FileXform>> {
|
||||
let parsed = if inline {
|
||||
parse_file(src, "")
|
||||
} else {
|
||||
let ext = std::path::Path::new(src_t).extension().and_then(|e| e.to_str()).unwrap_or("");
|
||||
let ext = std::path::Path::new(src_t).extension().and_then(std::ffi::OsStr::to_str).unwrap_or("");
|
||||
std::fs::read_to_string(src_t).ok().and_then(|t| parse_file(&t, ext))
|
||||
}
|
||||
.map(Arc::new);
|
||||
|
||||
@@ -132,11 +132,11 @@ pub fn data(params: &Params) -> Arc<RotoData> {
|
||||
let mut h = 0xcbf2_9ce4_8422_2325;
|
||||
fnv(&mut h, j.as_bytes());
|
||||
let c = C.get_or_init(Default::default);
|
||||
if let Some(d) = c.lock().unwrap_or_else(|e| e.into_inner()).get(&h) {
|
||||
if let Some(d) = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&h) {
|
||||
return d.clone();
|
||||
}
|
||||
let d = Arc::new(RotoData::from_json(j));
|
||||
let mut m = c.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 64 {
|
||||
m.clear();
|
||||
}
|
||||
@@ -247,11 +247,11 @@ fn cache() -> &'static Mutex<SegCache> {
|
||||
|
||||
/// A cached segmentation (chain key, scale).
|
||||
pub fn cached(key: u64, scale: f64) -> Option<Arc<FrameSeg>> {
|
||||
cache().lock().unwrap_or_else(|e| e.into_inner()).map.get(&(key, scale.to_bits())).cloned()
|
||||
cache().lock().unwrap_or_else(std::sync::PoisonError::into_inner).map.get(&(key, scale.to_bits())).cloned()
|
||||
}
|
||||
|
||||
pub fn store(key: u64, scale: f64, seg: Arc<FrameSeg>) {
|
||||
let mut c = cache().lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut c = cache().lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let k = (key, scale.to_bits());
|
||||
if c.map.contains_key(&k) {
|
||||
return;
|
||||
@@ -301,7 +301,7 @@ fn from_store(key: u64, scale: f64) -> Option<Arc<FrameSeg>> {
|
||||
/// Drop the cached segmentations of these chain keys (every scale).
|
||||
pub fn forget(keys: impl IntoIterator<Item = u64>) {
|
||||
let keys: std::collections::HashSet<u64> = keys.into_iter().collect();
|
||||
let mut c = cache().lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut c = cache().lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let gone: Vec<(u64, u64)> = c.map.keys().filter(|k| keys.contains(&k.0)).copied().collect();
|
||||
for k in gone {
|
||||
if let Some(s) = c.map.remove(&k) {
|
||||
@@ -313,7 +313,7 @@ pub fn forget(keys: impl IntoIterator<Item = u64>) {
|
||||
|
||||
/// Drop every cached segmentation (Edit ▸ Purge).
|
||||
pub fn purge() {
|
||||
let mut c = cache().lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut c = cache().lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
c.map.clear();
|
||||
c.order.clear();
|
||||
c.bytes = 0;
|
||||
@@ -532,11 +532,11 @@ fn frozen(params: &Params) -> Option<Arc<FrozenCache>> {
|
||||
let mut h = 0xcbf2_9ce4_8422_2325;
|
||||
fnv(&mut h, j.as_bytes());
|
||||
let c = C.get_or_init(Default::default);
|
||||
if let Some(d) = c.lock().unwrap_or_else(|e| e.into_inner()).get(&h) {
|
||||
if let Some(d) = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&h) {
|
||||
return Some(d.clone());
|
||||
}
|
||||
let d = Arc::new(FrozenCache::from_json(j)?);
|
||||
let mut m = c.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 8 {
|
||||
m.clear();
|
||||
}
|
||||
|
||||
@@ -537,7 +537,7 @@ impl<S: Clone> SimCache<S> {
|
||||
pub fn run(&self, key: u64, target: u64, init: impl FnOnce() -> S, mut step: impl FnMut(&mut S, u64)) -> std::sync::Arc<S> {
|
||||
use std::sync::Arc;
|
||||
let start = {
|
||||
let mut g = self.inner.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut g = self.inner.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let tick = g.iter().map(|e| e.used).max().unwrap_or(0) + 1;
|
||||
g.iter_mut().find(|e| e.key == key).and_then(|e| {
|
||||
e.used = tick;
|
||||
@@ -563,7 +563,7 @@ impl<S: Clone> SimCache<S> {
|
||||
}
|
||||
let out = Arc::new(st);
|
||||
fresh.push((target, out.clone()));
|
||||
let mut g = self.inner.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut g = self.inner.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let tick = g.iter().map(|e| e.used).max().unwrap_or(0) + 1;
|
||||
let idx = match g.iter().position(|e| e.key == key) {
|
||||
Some(ix) => ix,
|
||||
|
||||
@@ -191,11 +191,11 @@ fn analysis_cached(json: &str) -> Option<(u64, Arc<WarpAnalysis>)> {
|
||||
static C: OnceLock<AnalysisCache> = OnceLock::new();
|
||||
let key = fnv(json.as_bytes());
|
||||
let c = C.get_or_init(Default::default);
|
||||
if let Some(a) = c.lock().unwrap_or_else(|e| e.into_inner()).get(&key) {
|
||||
if let Some(a) = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&key) {
|
||||
return Some((key, a.clone()));
|
||||
}
|
||||
let a = Arc::new(WarpAnalysis::from_json(json)?);
|
||||
let mut m = c.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 8 {
|
||||
m.clear();
|
||||
}
|
||||
@@ -294,7 +294,7 @@ pub fn store_summary(key: [u64; 2], summary: PlanSummary) {
|
||||
}
|
||||
|
||||
fn keep_summary(key: (u64, u64), summary: Arc<PlanSummary>) {
|
||||
let mut m = summaries().lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = summaries().lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 32 {
|
||||
m.clear();
|
||||
}
|
||||
@@ -305,7 +305,7 @@ fn keep_summary(key: (u64, u64), summary: Arc<PlanSummary>) {
|
||||
/// cached (seconds for a long Subspace Warp clip). `None` when not analysed.
|
||||
pub fn summary(params: &Params) -> Option<([u64; 2], Arc<PlanSummary>)> {
|
||||
let (key, a, st) = plan_key(params)?;
|
||||
let cached = summaries().lock().unwrap_or_else(|e| e.into_inner()).get(&key).cloned();
|
||||
let cached = summaries().lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&key).cloned();
|
||||
let sum = match cached {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
@@ -333,7 +333,7 @@ pub fn summary_at(params: &Params, time: f64) -> Option<(usize, Arc<PlanSummary>
|
||||
pub fn cached_summary_at(params: &Params, time: f64) -> Option<(usize, Arc<PlanSummary>)> {
|
||||
let (key, a, _) = plan_key(params)?;
|
||||
let k = a.frame_at(time)?;
|
||||
let sum = summaries().lock().unwrap_or_else(|e| e.into_inner()).get(&key).cloned();
|
||||
let sum = summaries().lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&key).cloned();
|
||||
let sum = match sum {
|
||||
Some(s) => s,
|
||||
None => {
|
||||
@@ -445,13 +445,13 @@ fn render(ctx: &EffectCtx, buf: Buf) -> Buf {
|
||||
}
|
||||
}
|
||||
if !local.is_empty() {
|
||||
let mut n = need_m.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut n = need_m.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
for (x, w) in local {
|
||||
n[y * ow as usize + x] = w;
|
||||
}
|
||||
}
|
||||
});
|
||||
let need = need_m.into_inner().unwrap_or_else(|e| e.into_inner());
|
||||
let need = need_m.into_inner().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if synth && need.iter().any(|w| *w > 0.0) {
|
||||
synthesize(ctx, &a, k, &src_of, &crop, sc, &mut out, &need);
|
||||
}
|
||||
|
||||
@@ -847,7 +847,7 @@ fn original_path(s: &Session) -> Option<String> {
|
||||
/// importer takes. Anything else (a folder or app bundle, a script, a shortcut) is refused.
|
||||
pub(crate) fn openable_original(path: &str) -> std::result::Result<(), String> {
|
||||
let media = |p: &std::path::Path| {
|
||||
let ext = p.extension().and_then(|e| e.to_str()).map(str::to_ascii_lowercase).unwrap_or_default();
|
||||
let ext = p.extension().and_then(std::ffi::OsStr::to_str).map(str::to_ascii_lowercase).unwrap_or_default();
|
||||
crate::media_browser::kind_of(&p.to_string_lossy()).is_some_and(|k| k != "project") || matches!(ext.as_str(), "pdf" | "ai" | "eps")
|
||||
};
|
||||
let name = std::path::Path::new(path).file_name().map(|n| n.to_string_lossy().into_owned()).unwrap_or_else(|| path.to_string());
|
||||
|
||||
@@ -560,7 +560,7 @@ pub const DATA_EXTENSIONS: &[&str] = &["json", "csv", "tsv"];
|
||||
|
||||
/// A data footage item for `path` (JSON / CSV / TSV), `None` for other files.
|
||||
pub(crate) fn data_footage(services: &dyn crate::Services, path: &str) -> Option<std::result::Result<effectcraft_project::Footage, String>> {
|
||||
let ext = std::path::Path::new(path).extension().and_then(|e| e.to_str()).unwrap_or("").to_ascii_lowercase();
|
||||
let ext = std::path::Path::new(path).extension().and_then(std::ffi::OsStr::to_str).unwrap_or("").to_ascii_lowercase();
|
||||
if !DATA_EXTENSIONS.contains(&ext.as_str()) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@@ -708,7 +708,7 @@ const BUNDLE_EXTENSIONS: &[&str] = &[
|
||||
/// Whether the system file manager would open folder `dir` as something other than a folder: a
|
||||
/// bundle (`Tool.app`), or a Windows folder with a `{CLSID}` extension.
|
||||
fn opens_as_bundle(dir: &std::path::Path) -> bool {
|
||||
let ext = dir.extension().and_then(|e| e.to_str()).unwrap_or_default().to_ascii_lowercase();
|
||||
let ext = dir.extension().and_then(std::ffi::OsStr::to_str).unwrap_or_default().to_ascii_lowercase();
|
||||
ext.starts_with('{') || BUNDLE_EXTENSIONS.contains(&ext.as_str())
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ impl Default for PaintOptions {
|
||||
}
|
||||
|
||||
fn norm(s: &str) -> String {
|
||||
s.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>().to_ascii_lowercase()
|
||||
s.chars().filter(char::is_ascii_alphanumeric).collect::<String>().to_ascii_lowercase()
|
||||
}
|
||||
|
||||
/// Index of `v` in `names` (by number or case/space-insensitive name).
|
||||
|
||||
@@ -103,7 +103,7 @@ fn run(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
let supported = matches!(old.kind, FootageKind::Still | FootageKind::Sequence | FootageKind::Video | FootageKind::Audio)
|
||||
&& old.layer.is_none() && old.page == 0;
|
||||
let name = Path::new(&old.path).file_name().and_then(|n| n.to_str()).unwrap_or("");
|
||||
let name = Path::new(&old.path).file_name().and_then(std::ffi::OsStr::to_str).unwrap_or("");
|
||||
let paths = index.get(name).cloned().unwrap_or_default();
|
||||
let mut candidates = vec![];
|
||||
let mut accepted = vec![];
|
||||
|
||||
@@ -80,10 +80,10 @@ impl MaskMethod {
|
||||
}
|
||||
}
|
||||
pub fn from_name(s: &str) -> Option<MaskMethod> {
|
||||
let n: String = s.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>().to_ascii_lowercase();
|
||||
let n: String = s.chars().filter(char::is_ascii_alphanumeric).collect::<String>().to_ascii_lowercase();
|
||||
MaskMethod::ALL
|
||||
.into_iter()
|
||||
.find(|m| m.id().to_ascii_lowercase() == n || m.label().chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>().to_ascii_lowercase() == n)
|
||||
.find(|m| m.id().to_ascii_lowercase() == n || m.label().chars().filter(char::is_ascii_alphanumeric).collect::<String>().to_ascii_lowercase() == n)
|
||||
}
|
||||
pub fn model(self) -> Model {
|
||||
match self {
|
||||
|
||||
@@ -289,10 +289,10 @@ pub struct Inbox(Mutex<Vec<WorkerReply>>);
|
||||
|
||||
impl Inbox {
|
||||
pub fn push(&self, r: WorkerReply) {
|
||||
self.0.lock().unwrap_or_else(|e| e.into_inner()).push(r);
|
||||
self.0.lock().unwrap_or_else(std::sync::PoisonError::into_inner).push(r);
|
||||
}
|
||||
pub fn take(&self) -> Vec<WorkerReply> {
|
||||
std::mem::take(&mut *self.0.lock().unwrap_or_else(|e| e.into_inner()))
|
||||
std::mem::take(&mut *self.0.lock().unwrap_or_else(std::sync::PoisonError::into_inner))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ pub struct JobShared {
|
||||
}
|
||||
|
||||
pub(crate) fn lock<T>(m: &Mutex<T>) -> std::sync::MutexGuard<'_, T> {
|
||||
m.lock().unwrap_or_else(|e| e.into_inner())
|
||||
m.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
impl JobShared {
|
||||
|
||||
@@ -20,7 +20,7 @@ use crate::render::{FootageSource, RenderOpts};
|
||||
struct Synthetic;
|
||||
|
||||
fn file_px(path: &str, x: u32, y: u32) -> [f32; 4] {
|
||||
let name = std::path::Path::new(path).file_name().and_then(|n| n.to_str()).unwrap_or("");
|
||||
let name = std::path::Path::new(path).file_name().and_then(std::ffi::OsStr::to_str).unwrap_or("");
|
||||
match name {
|
||||
"red16.png" => [1.0, 0.0, 0.0, 1.0],
|
||||
"blue8.png" => [0.0, 0.0, 1.0, 1.0],
|
||||
@@ -43,7 +43,7 @@ fn file_px(path: &str, x: u32, y: u32) -> [f32; 4] {
|
||||
}
|
||||
|
||||
fn size_of(path: &str) -> (u32, u32) {
|
||||
match std::path::Path::new(path).file_name().and_then(|n| n.to_str()).unwrap_or("") {
|
||||
match std::path::Path::new(path).file_name().and_then(std::ffi::OsStr::to_str).unwrap_or("") {
|
||||
"red16.png" => (16, 16),
|
||||
"blue8.png" => (8, 8),
|
||||
"lines.mov" | "matte_black.png" | "matte_white.png" | "half.png" => (4, 4),
|
||||
|
||||
@@ -157,7 +157,7 @@ pub struct TrackShared {
|
||||
}
|
||||
|
||||
pub(crate) fn lock<T>(m: &Mutex<T>) -> std::sync::MutexGuard<'_, T> {
|
||||
m.lock().unwrap_or_else(|e| e.into_inner())
|
||||
m.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
/// A running (or finished, not yet polled) analysis.
|
||||
|
||||
@@ -663,10 +663,10 @@ impl SimProfile {
|
||||
}
|
||||
|
||||
pub fn parse(s: &str) -> Option<SimProfile> {
|
||||
let k: String = s.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>().to_ascii_lowercase();
|
||||
let k: String = s.chars().filter(char::is_ascii_alphanumeric).collect::<String>().to_ascii_lowercase();
|
||||
SimProfile::ALL
|
||||
.into_iter()
|
||||
.find(|p| p.id().to_ascii_lowercase() == k || p.label().chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>().to_ascii_lowercase() == k)
|
||||
.find(|p| p.id().to_ascii_lowercase() == k || p.label().chars().filter(char::is_ascii_alphanumeric).collect::<String>().to_ascii_lowercase() == k)
|
||||
.or(match k.as_str() {
|
||||
"off" => Some(SimProfile::None),
|
||||
"hdtv" | "bt709" => Some(SimProfile::Rec709),
|
||||
|
||||
@@ -247,7 +247,7 @@ impl<'a> Cx<'a> {
|
||||
}
|
||||
let img = self.crop_resize(img);
|
||||
if let Some(ft) = &self.frame_times {
|
||||
ft.lock().unwrap_or_else(|e| e.into_inner()).push((i, t0.elapsed().as_secs_f64()));
|
||||
ft.lock().unwrap_or_else(std::sync::PoisonError::into_inner).push((i, t0.elapsed().as_secs_f64()));
|
||||
}
|
||||
img
|
||||
}
|
||||
@@ -327,7 +327,7 @@ impl<'a> Cx<'a> {
|
||||
for dir in &self.job.options.overflow {
|
||||
let p = std::path::Path::new(dir).join(&name).to_string_lossy().to_string();
|
||||
if q.has_room(&p, bytes) {
|
||||
self.overflowed.lock().unwrap_or_else(|e| e.into_inner()).push(p.clone());
|
||||
self.overflowed.lock().unwrap_or_else(std::sync::PoisonError::into_inner).push(p.clone());
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@@ -351,7 +351,7 @@ impl<'a> Cx<'a> {
|
||||
Ok(r) => s.push_str(&format!("Result: Done ({} frames, {}×{}, {} bytes) in {seconds:.2} s\n", r.frames, r.width, r.height, r.bytes)),
|
||||
Err(e) => s.push_str(&format!("Result: Failed\nError: {e}\n")),
|
||||
}
|
||||
let over = self.overflowed.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let over = self.overflowed.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if !over.is_empty() {
|
||||
s.push_str(&format!("Storage overflow: {} file(s) written to overflow folders (first: {})\n", over.len(), over[0]));
|
||||
}
|
||||
@@ -366,7 +366,7 @@ impl<'a> Cx<'a> {
|
||||
}
|
||||
}
|
||||
if let (RenderLog::PlusPerFrameInfo, Some(ft), Some(c)) = (level, &self.frame_times, comp) {
|
||||
let mut v = ft.lock().unwrap_or_else(|e| e.into_inner()).clone();
|
||||
let mut v = ft.lock().unwrap_or_else(std::sync::PoisonError::into_inner).clone();
|
||||
v.sort_by_key(|(i, _)| *i);
|
||||
s.push_str("\nFrames:\n");
|
||||
let f0 = self.job.settings.first_frame(c);
|
||||
|
||||
@@ -30,7 +30,7 @@ pub(crate) fn deferred_gpu() -> Option<(&'static Gpu, std::sync::MutexGuard<'sta
|
||||
g
|
||||
});
|
||||
let g = crate::tests::require_gpu("deferred gpu tests", g.as_ref())?;
|
||||
Some((g, LOCK.lock().unwrap_or_else(|e| e.into_inner())))
|
||||
Some((g, LOCK.lock().unwrap_or_else(std::sync::PoisonError::into_inner)))
|
||||
}
|
||||
|
||||
/// Footage with GPU effects around a CPU-only one, a solid with Glow, and a precomp whose
|
||||
|
||||
@@ -36,7 +36,7 @@ pub fn vector_doc(
|
||||
}
|
||||
|
||||
fn is_pdf_like(path: &str, bytes: &[u8]) -> bool {
|
||||
let ext = std::path::Path::new(path).extension().and_then(|e| e.to_str()).unwrap_or("").to_ascii_lowercase();
|
||||
let ext = std::path::Path::new(path).extension().and_then(std::ffi::OsStr::to_str).unwrap_or("").to_ascii_lowercase();
|
||||
effectcraft_pdf::sniff(bytes).is_some() && (effectcraft_pdf::EXTENSIONS.contains(&ext.as_str()) || bytes.starts_with(b"%PDF"))
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ pub fn is_importable(path: &std::path::Path) -> bool {
|
||||
}
|
||||
|
||||
pub(crate) fn ext_of(path: &std::path::Path) -> String {
|
||||
path.extension().and_then(|e| e.to_str()).unwrap_or("").to_ascii_lowercase()
|
||||
path.extension().and_then(std::ffi::OsStr::to_str).unwrap_or("").to_ascii_lowercase()
|
||||
}
|
||||
|
||||
/// The `image` crate format of a still: from its signature, else from its extension (Targa has
|
||||
|
||||
@@ -756,7 +756,7 @@ impl Inner {
|
||||
drop(c);
|
||||
return Ok(Arc::new(self.decode(&loc, footage)?));
|
||||
}
|
||||
c = self.done.wait(c).unwrap_or_else(|e| e.into_inner());
|
||||
c = self.done.wait(c).unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
}
|
||||
self.misses.fetch_add(1, Ordering::Relaxed);
|
||||
c.inflight.insert(loc.key.clone());
|
||||
@@ -972,7 +972,7 @@ fn describe_problem(codec: &str, e: &MediaError) -> String {
|
||||
}
|
||||
|
||||
fn lock<T>(m: &Mutex<T>) -> std::sync::MutexGuard<'_, T> {
|
||||
m.lock().unwrap_or_else(|e| e.into_inner())
|
||||
m.lock().unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -201,7 +201,7 @@ impl TimeDisplayStyle {
|
||||
}
|
||||
}
|
||||
pub fn parse(s: &str) -> Option<TimeDisplayStyle> {
|
||||
let k: String = s.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>().to_ascii_lowercase();
|
||||
let k: String = s.chars().filter(char::is_ascii_alphanumeric).collect::<String>().to_ascii_lowercase();
|
||||
match k.as_str() {
|
||||
"timecode" => Some(TimeDisplayStyle::Timecode),
|
||||
"frames" => Some(TimeDisplayStyle::Frames),
|
||||
@@ -1234,7 +1234,7 @@ impl Footage {
|
||||
if self.kind != FootageKind::Data {
|
||||
return None;
|
||||
}
|
||||
let ext = std::path::Path::new(&self.path).extension().and_then(|e| e.to_str()).unwrap_or("").to_ascii_lowercase();
|
||||
let ext = std::path::Path::new(&self.path).extension().and_then(std::ffi::OsStr::to_str).unwrap_or("").to_ascii_lowercase();
|
||||
Some(match ext.as_str() {
|
||||
"csv" => "csv",
|
||||
"tsv" | "tab" => "tsv",
|
||||
|
||||
@@ -331,7 +331,7 @@ impl DiskCache {
|
||||
let Ok(files) = std::fs::read_dir(shard.path()) else { continue };
|
||||
for f in files.flatten() {
|
||||
let p = f.path();
|
||||
let name = p.file_name().and_then(|n| n.to_str()).unwrap_or("");
|
||||
let name = p.file_name().and_then(std::ffi::OsStr::to_str).unwrap_or("");
|
||||
if name.contains(".tmp") {
|
||||
// A writer that died mid-write; old temporaries are removed.
|
||||
if f.metadata().and_then(|m| m.modified()).is_ok_and(|t| t.elapsed().is_ok_and(|e| e.as_secs() > 600)) {
|
||||
|
||||
@@ -408,7 +408,7 @@ impl View3D {
|
||||
}
|
||||
}
|
||||
pub fn from_id(s: &str) -> Option<View3D> {
|
||||
let k: String = s.chars().filter(|c| c.is_ascii_alphanumeric()).collect::<String>().to_ascii_lowercase();
|
||||
let k: String = s.chars().filter(char::is_ascii_alphanumeric).collect::<String>().to_ascii_lowercase();
|
||||
View3D::ALL.into_iter().find(|v| v.id().eq_ignore_ascii_case(&k) || v.label().replace(' ', "").eq_ignore_ascii_case(&k))
|
||||
}
|
||||
pub fn is_ortho(self) -> bool {
|
||||
|
||||
@@ -89,7 +89,7 @@ mod imp {
|
||||
Sock::Listener(_) => None,
|
||||
};
|
||||
let entry = Arc::new(Entry { sock: Mutex::new(s), wake, closed: AtomicBool::new(false) });
|
||||
let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut t = table().lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let id = t.next;
|
||||
t.next += 1;
|
||||
t.socks.insert(id, entry);
|
||||
@@ -98,12 +98,12 @@ mod imp {
|
||||
|
||||
/// The socket `id`, if open. The table is locked only for the lookup.
|
||||
fn get(id: u32) -> Option<Arc<Entry>> {
|
||||
table().lock().unwrap_or_else(|e| e.into_inner()).socks.get(&id).cloned()
|
||||
table().lock().unwrap_or_else(std::sync::PoisonError::into_inner).socks.get(&id).cloned()
|
||||
}
|
||||
|
||||
/// Forget socket `id`; a call blocked on it fails at once.
|
||||
fn close(id: u32) {
|
||||
let entry = table().lock().unwrap_or_else(|e| e.into_inner()).socks.remove(&id);
|
||||
let entry = table().lock().unwrap_or_else(std::sync::PoisonError::into_inner).socks.remove(&id);
|
||||
if let Some(entry) = entry {
|
||||
entry.closed.store(true, Ordering::Release);
|
||||
if let Some(w) = &entry.wake {
|
||||
@@ -261,7 +261,7 @@ mod imp {
|
||||
_ => err("the socket is not open"),
|
||||
};
|
||||
};
|
||||
let mut sock = entry.sock.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut sock = entry.sock.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// Recheck after locking: close or a failed mode transition may have retired it
|
||||
// while this caller waited with an Arc obtained from the table.
|
||||
if entry.closed.load(Ordering::Acquire) {
|
||||
|
||||
@@ -150,7 +150,9 @@ impl Reader<'_> {
|
||||
let mut files: Vec<PathBuf> = rd
|
||||
.flatten()
|
||||
.map(|e| e.path())
|
||||
.filter(|p| p.file_name().and_then(|n| n.to_str()).is_some_and(|n| n.ends_with(".conf") && n.starts_with(|c: char| c.is_ascii_digit())))
|
||||
.filter(|p| {
|
||||
p.file_name().and_then(std::ffi::OsStr::to_str).is_some_and(|n| n.ends_with(".conf") && n.starts_with(|c: char| c.is_ascii_digit()))
|
||||
})
|
||||
.collect();
|
||||
files.sort();
|
||||
for f in files {
|
||||
|
||||
+20
-20
@@ -116,7 +116,7 @@ fn walk(dir: &std::path::Path, depth: u32, out: &mut Vec<PathBuf>) {
|
||||
if depth < 8 {
|
||||
walk(&p, depth + 1, out);
|
||||
}
|
||||
} else if p.extension().and_then(|x| x.to_str()).is_some_and(|x| matches!(x.to_ascii_lowercase().as_str(), "ttf" | "otf" | "ttc" | "otc")) {
|
||||
} else if p.extension().and_then(std::ffi::OsStr::to_str).is_some_and(|x| matches!(x.to_ascii_lowercase().as_str(), "ttf" | "otf" | "ttc" | "otc")) {
|
||||
out.push(p);
|
||||
}
|
||||
}
|
||||
@@ -319,7 +319,7 @@ fn push(db: &mut Db, info: FaceInfo) -> FaceId {
|
||||
/// added.
|
||||
pub fn add_source(src: &dyn FontSource) -> usize {
|
||||
let faces = src.faces();
|
||||
let mut d = db().write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut d = db().write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let mut n = 0;
|
||||
for f in faces {
|
||||
let dup = d.faces.iter().any(|g| g.info.family.eq_ignore_ascii_case(&f.family) && g.info.style.eq_ignore_ascii_case(&f.style));
|
||||
@@ -329,7 +329,7 @@ pub fn add_source(src: &dyn FontSource) -> usize {
|
||||
}
|
||||
}
|
||||
// A new face can belong to one of a script's usual families.
|
||||
family_faces_cache().write().unwrap_or_else(|e| e.into_inner()).clear();
|
||||
family_faces_cache().write().unwrap_or_else(std::sync::PoisonError::into_inner).clear();
|
||||
n
|
||||
}
|
||||
|
||||
@@ -337,9 +337,9 @@ pub fn add_source(src: &dyn FontSource) -> usize {
|
||||
pub fn add_font_data(data: Vec<u8>) -> Vec<FaceId> {
|
||||
let data = Arc::new(data);
|
||||
let names = read_faces_bytes(&data);
|
||||
let mut d = db().write().unwrap_or_else(|e| e.into_inner());
|
||||
let mut d = db().write().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let ids = names.into_iter().map(|n| push(&mut d, info_from(n, FaceData::Shared(data.clone()), "user"))).collect();
|
||||
family_faces_cache().write().unwrap_or_else(|e| e.into_inner()).clear();
|
||||
family_faces_cache().write().unwrap_or_else(std::sync::PoisonError::into_inner).clear();
|
||||
ids
|
||||
}
|
||||
|
||||
@@ -353,21 +353,21 @@ pub fn scan_system() -> usize {
|
||||
if system_scanned() {
|
||||
return 0;
|
||||
}
|
||||
let _scan = SCAN.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let _scan = SCAN.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if system_scanned() {
|
||||
return 0;
|
||||
}
|
||||
let n = if cfg!(target_arch = "wasm32") { 0 } else { add_source(&DirectorySource::system()) };
|
||||
db().write().unwrap_or_else(|e| e.into_inner()).scanned = true;
|
||||
db().write().unwrap_or_else(std::sync::PoisonError::into_inner).scanned = true;
|
||||
n
|
||||
}
|
||||
|
||||
/// Scan the system font folders again, adding fonts installed since the last scan (faces already
|
||||
/// known are kept, so font ids stay valid). Returns the number of faces added.
|
||||
pub fn rescan_system() -> usize {
|
||||
let _scan = SCAN.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let _scan = SCAN.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
let n = if cfg!(target_arch = "wasm32") { 0 } else { add_source(&DirectorySource::system()) };
|
||||
db().write().unwrap_or_else(|e| e.into_inner()).scanned = true;
|
||||
db().write().unwrap_or_else(std::sync::PoisonError::into_inner).scanned = true;
|
||||
n
|
||||
}
|
||||
|
||||
@@ -388,12 +388,12 @@ pub fn scan_system_in_background() {
|
||||
}
|
||||
|
||||
pub fn system_scanned() -> bool {
|
||||
db().read().unwrap_or_else(|e| e.into_inner()).scanned
|
||||
db().read().unwrap_or_else(std::sync::PoisonError::into_inner).scanned
|
||||
}
|
||||
|
||||
/// A face by id (panics never: unknown ids give the default face).
|
||||
pub fn face(id: FaceId) -> Arc<Face> {
|
||||
let d = db().read().unwrap_or_else(|e| e.into_inner());
|
||||
let d = db().read().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
// The bundled fonts are compiled in and always parse (`tests::bundled_families_and_resolution` checks them), so
|
||||
// the database is never empty.
|
||||
#[allow(clippy::expect_used)]
|
||||
@@ -402,7 +402,7 @@ pub fn face(id: FaceId) -> Arc<Face> {
|
||||
|
||||
/// All faces (bundled first).
|
||||
pub fn all_faces() -> Vec<Arc<Face>> {
|
||||
db().read().unwrap_or_else(|e| e.into_inner()).faces.clone()
|
||||
db().read().unwrap_or_else(std::sync::PoisonError::into_inner).faces.clone()
|
||||
}
|
||||
|
||||
/// Family names in the fonts' own languages: English family → native family (only families
|
||||
@@ -743,15 +743,15 @@ static REQUESTED_CJK_LOCALE: RwLock<Option<String>> = RwLock::new(None);
|
||||
pub fn set_cjk_locale(tag: &str) {
|
||||
let tag = tag.trim().to_ascii_lowercase();
|
||||
let requested = if tag.is_empty() || tag == "c" || tag == "posix" { None } else { Some(tag) };
|
||||
*REQUESTED_CJK_LOCALE.write().unwrap_or_else(|e| e.into_inner()) = requested;
|
||||
*REQUESTED_CJK_LOCALE.write().unwrap_or_else(std::sync::PoisonError::into_inner) = requested;
|
||||
// The order of the CJK families follows the language, so a change of language drops the cached
|
||||
// fallbacks.
|
||||
fallback_cache().write().unwrap_or_else(|e| e.into_inner()).clear();
|
||||
family_faces_cache().write().unwrap_or_else(|e| e.into_inner()).clear();
|
||||
fallback_cache().write().unwrap_or_else(std::sync::PoisonError::into_inner).clear();
|
||||
family_faces_cache().write().unwrap_or_else(std::sync::PoisonError::into_inner).clear();
|
||||
}
|
||||
|
||||
fn requested_cjk_locale() -> Option<String> {
|
||||
REQUESTED_CJK_LOCALE.read().unwrap_or_else(|e| e.into_inner()).clone()
|
||||
REQUESTED_CJK_LOCALE.read().unwrap_or_else(std::sync::PoisonError::into_inner).clone()
|
||||
}
|
||||
|
||||
/// The CJK locale to use: [`set_cjk_locale`] when the host asked for one, otherwise the locale
|
||||
@@ -981,7 +981,7 @@ fn fallback_with_locale(c: char, prefer: FaceId, locale: impl FnOnce() -> CjkLoc
|
||||
}
|
||||
}
|
||||
let key = (c as u32 >> 8, prefer);
|
||||
if let Some(cached) = fallback_cache().read().unwrap_or_else(|e| e.into_inner()).get(&key).copied() {
|
||||
if let Some(cached) = fallback_cache().read().unwrap_or_else(std::sync::PoisonError::into_inner).get(&key).copied() {
|
||||
match cached {
|
||||
Some(id) if face(id).has_char(c) => return id,
|
||||
Some(_) => {}
|
||||
@@ -992,7 +992,7 @@ fn fallback_with_locale(c: char, prefer: FaceId, locale: impl FnOnce() -> CjkLoc
|
||||
scan_system();
|
||||
}
|
||||
let found = system_fallback(c, &p.info.style);
|
||||
fallback_cache().write().unwrap_or_else(|e| e.into_inner()).insert(key, found);
|
||||
fallback_cache().write().unwrap_or_else(std::sync::PoisonError::into_inner).insert(key, found);
|
||||
found.unwrap_or(prefer)
|
||||
}
|
||||
|
||||
@@ -1000,7 +1000,7 @@ fn fallback_with_locale(c: char, prefer: FaceId, locale: impl FnOnce() -> CjkLoc
|
||||
/// for `script`, in the order they are tried, each in the style of `prefer`. For CJK, the other CJK
|
||||
/// languages' families follow in the locale's order.
|
||||
fn family_faces(script: FallbackScript, prefer: &Face, locale: CjkLocale) -> Arc<Vec<FaceId>> {
|
||||
if let Some(faces) = family_faces_cache().read().unwrap_or_else(|e| e.into_inner()).get(&(script, prefer.id, locale)) {
|
||||
if let Some(faces) = family_faces_cache().read().unwrap_or_else(std::sync::PoisonError::into_inner).get(&(script, prefer.id, locale)) {
|
||||
return faces.clone();
|
||||
}
|
||||
let order: Vec<FallbackScript> = match script {
|
||||
@@ -1016,7 +1016,7 @@ fn family_faces(script: FallbackScript, prefer: &Face, locale: CjkLocale) -> Arc
|
||||
let style = &prefer.info.style;
|
||||
let faces: Arc<Vec<FaceId>> =
|
||||
Arc::new(order.into_iter().flat_map(|s| families_for(s, locale)).filter_map(|fam| resolve_in(fam, style)).map(|r| r.face).collect());
|
||||
family_faces_cache().write().unwrap_or_else(|e| e.into_inner()).insert((script, prefer.id, locale), faces.clone());
|
||||
family_faces_cache().write().unwrap_or_else(std::sync::PoisonError::into_inner).insert((script, prefer.id, locale), faces.clone());
|
||||
faces
|
||||
}
|
||||
|
||||
|
||||
@@ -399,7 +399,7 @@ enum Form {
|
||||
pub fn feature_substitutes(face: FaceId, tag: &[u8; 4], c: char) -> bool {
|
||||
static C: OnceLock<Mutex<HashMap<(FaceId, [u8; 4], char), bool>>> = OnceLock::new();
|
||||
let cache = C.get_or_init(Default::default);
|
||||
if let Some(v) = cache.lock().unwrap_or_else(|e| e.into_inner()).get(&(face, *tag, c)) {
|
||||
if let Some(v) = cache.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&(face, *tag, c)) {
|
||||
return *v;
|
||||
}
|
||||
let f = fonts::face(face);
|
||||
@@ -419,7 +419,7 @@ pub fn feature_substitutes(face: FaceId, tag: &[u8; 4], c: char) -> bool {
|
||||
}
|
||||
_ => false,
|
||||
};
|
||||
let mut m = cache.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = cache.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 100_000 {
|
||||
m.clear();
|
||||
}
|
||||
@@ -1123,12 +1123,12 @@ pub fn layout_rich(text: &str, runs: &[(Range<usize>, TextStyle)], paras: &[Para
|
||||
let key = h.finish();
|
||||
static CLOCK: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(0);
|
||||
let now = CLOCK.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
|
||||
if let Some(e) = cache().lock().unwrap_or_else(|e| e.into_inner()).get_mut(&key) {
|
||||
if let Some(e) = cache().lock().unwrap_or_else(std::sync::PoisonError::into_inner).get_mut(&key) {
|
||||
e.0 = now;
|
||||
return e.1.clone();
|
||||
}
|
||||
let l = Arc::new(layout_rich_uncached(text, runs, paras));
|
||||
let mut c = cache().lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut c = cache().lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if c.len() >= 512 {
|
||||
// evict the oldest quarter
|
||||
let mut ages: Vec<u64> = c.values().map(|v| v.0).collect();
|
||||
|
||||
@@ -54,7 +54,7 @@ impl OutlinePen for Pen {
|
||||
pub(crate) fn outline_units(face: FaceId, gid: u32) -> Option<Arc<BezPath>> {
|
||||
static C: OnceLock<Mutex<HashMap<(FaceId, u32), Option<Arc<BezPath>>>>> = OnceLock::new();
|
||||
let c = C.get_or_init(Default::default);
|
||||
if let Some(v) = c.lock().unwrap_or_else(|e| e.into_inner()).get(&(face, gid)) {
|
||||
if let Some(v) = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&(face, gid)) {
|
||||
return v.clone();
|
||||
}
|
||||
let f = fonts::face(face);
|
||||
@@ -64,7 +64,7 @@ pub(crate) fn outline_units(face: FaceId, gid: u32) -> Option<Arc<BezPath>> {
|
||||
g.draw(DrawSettings::unhinted(Size::unscaled(), LocationRef::default()), &mut pen).ok()?;
|
||||
Some(Arc::new(pen.0))
|
||||
});
|
||||
let mut m = c.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 50_000 {
|
||||
m.clear();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ pub fn intern(coords: &[(String, f32)]) -> u32 {
|
||||
if key.windows(2).any(|w| w[0].0 == w[1].0) {
|
||||
return 0;
|
||||
}
|
||||
let mut t = table().lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut t = table().lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if let Some(id) = t.by_coords.get(&key) {
|
||||
return *id;
|
||||
}
|
||||
@@ -55,7 +55,7 @@ pub fn coords(id: u32) -> Arc<Vec<(String, f32)>> {
|
||||
if id == 0 {
|
||||
return Arc::new(Vec::new());
|
||||
}
|
||||
table().lock().unwrap_or_else(|e| e.into_inner()).values.get(id as usize - 1).cloned().unwrap_or_default()
|
||||
table().lock().unwrap_or_else(std::sync::PoisonError::into_inner).values.get(id as usize - 1).cloned().unwrap_or_default()
|
||||
}
|
||||
|
||||
fn table() -> &'static Mutex<Table> {
|
||||
@@ -109,7 +109,7 @@ pub fn outline_units_at(face: FaceId, gid: u32, coords: &[(String, f32)]) -> Opt
|
||||
let c = C.get_or_init(Default::default);
|
||||
// Quantise to 1/100 of a unit so animation frames reuse outlines.
|
||||
let key: Key = (face, gid, coords.iter().map(|(t, v)| (t.clone(), (v * 100.0).round() as i32)).collect());
|
||||
if let Some(v) = c.lock().unwrap_or_else(|e| e.into_inner()).get(&key) {
|
||||
if let Some(v) = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner).get(&key) {
|
||||
return v.clone();
|
||||
}
|
||||
let f = fonts::face(face);
|
||||
@@ -120,7 +120,7 @@ pub fn outline_units_at(face: FaceId, gid: u32, coords: &[(String, f32)]) -> Opt
|
||||
g.draw(DrawSettings::unhinted(Size::unscaled(), LocationRef::from(&loc)), &mut pen).ok()?;
|
||||
Some(Arc::new(pen.0))
|
||||
});
|
||||
let mut m = c.lock().unwrap_or_else(|e| e.into_inner());
|
||||
let mut m = c.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||
if m.len() > 20_000 {
|
||||
m.clear();
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ pub fn format_size(bytes: u64) -> String {
|
||||
|
||||
/// The Kind column: what a recent file is, by its extension, in the interface language.
|
||||
fn kind_of(path: &str) -> &'static str {
|
||||
tr(match std::path::Path::new(path).extension().and_then(|e| e.to_str()).map(str::to_ascii_lowercase).as_deref() {
|
||||
tr(match std::path::Path::new(path).extension().and_then(std::ffi::OsStr::to_str).map(str::to_ascii_lowercase).as_deref() {
|
||||
Some("ecproj") => "EffectCraft project",
|
||||
Some("aep" | "aepx") => "After Effects project",
|
||||
Some("json" | "lottie") => "Lottie animation",
|
||||
|
||||
+2
-2
@@ -176,7 +176,7 @@ fn repo_files() -> Result<Vec<String>, String> {
|
||||
}
|
||||
|
||||
fn is_asset(path: &str) -> bool {
|
||||
std::path::Path::new(path).extension().and_then(|e| e.to_str()).is_some_and(|e| ASSET_EXT.contains(&e.to_ascii_lowercase().as_str()))
|
||||
std::path::Path::new(path).extension().and_then(std::ffi::OsStr::to_str).is_some_and(|e| ASSET_EXT.contains(&e.to_ascii_lowercase().as_str()))
|
||||
}
|
||||
|
||||
fn assets() -> Result<(), String> {
|
||||
@@ -384,7 +384,7 @@ fn serve_dir(dir: &std::path::Path, port: u16) -> Result<(), String> {
|
||||
Ok(b) => ("200 OK", b),
|
||||
Err(_) => ("404 Not Found", b"not found".to_vec()),
|
||||
};
|
||||
let mime = match file.extension().and_then(|e| e.to_str()).unwrap_or("") {
|
||||
let mime = match file.extension().and_then(std::ffi::OsStr::to_str).unwrap_or("") {
|
||||
"html" => "text/html; charset=utf-8",
|
||||
"js" => "text/javascript",
|
||||
"wasm" => "application/wasm",
|
||||
|
||||
Reference in New Issue
Block a user