Files
servo/components/config/pref_util.rs
Narfinger 44f3f34f88 net: Implement eviction in the HTTP cache using quick_cache (#40613)
This uses quick_cache to have a proper cache for http.

Previously, the http cache would just grow over the lifetime of the
servo instance. Now we use the quick_cache crate to have a cache with
proper eviction procedures.

We currently weight the entries by the number of responses for the url.
The cache size is configurable.

Testing: Tested WPT run
(https://github.com/Narfinger/servo/actions/runs/19338794789) and
websites.

---------

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com>
Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
Co-authored-by: gterzian <2792687+gterzian@users.noreply.github.com>
Co-authored-by: Taym Haddadi <haddadi.taym@gmail.com>
2025-12-16 12:08:15 +00:00

158 lines
4.6 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub enum PrefValue {
Float(f64),
Int(i64),
UInt(u64),
Str(String),
Bool(bool),
Array(Vec<PrefValue>),
}
impl PrefValue {
pub fn from_booleanish_str(input: &str) -> Self {
match input {
"false" => PrefValue::Bool(false),
"true" => PrefValue::Bool(true),
_ => input
.parse::<i64>()
.map(PrefValue::Int)
.or_else(|_| input.parse::<f64>().map(PrefValue::Float))
.unwrap_or_else(|_| PrefValue::from(input)),
}
}
}
impl TryFrom<&Value> for PrefValue {
type Error = String;
fn try_from(value: &Value) -> Result<Self, Self::Error> {
match value {
Value::Null => Err("Cannot turn null into preference".into()),
Value::Bool(value) => Ok((*value).into()),
Value::Number(number) => number
.as_i64()
.map(Into::into)
.or_else(|| number.as_f64().map(Into::into))
.map(Ok)
.unwrap_or(Err("Could not parse number from JSON".into())),
Value::String(value) => Ok(value.clone().into()),
Value::Array(array) => {
let array = array
.iter()
.map(TryInto::<PrefValue>::try_into)
.collect::<Result<Vec<_>, _>>()?;
Ok(PrefValue::Array(array))
},
Value::Object(_) => Err("Cannot turn object into preference".into()),
}
}
}
macro_rules! impl_pref_from {
($($t: ty => $variant: path,)*) => {
$(
impl From<$t> for PrefValue {
fn from(other: $t) -> Self {
$variant(other.into())
}
}
)+
}
}
macro_rules! impl_from_pref {
($($variant: path => $t: ty,)*) => {
$(
impl TryFrom<PrefValue> for $t {
type Error = String;
fn try_from(other: PrefValue) -> Result<Self, Self::Error> {
match other {
$variant(value) => Ok(value.into()),
_ => Err(format!("Cannot convert {other:?} to {}", std::any::type_name::<$t>())),
}
}
}
)+
}
}
impl_pref_from! {
f64 => PrefValue::Float,
i64 => PrefValue::Int,
u64 => PrefValue::UInt,
String => PrefValue::Str,
&str => PrefValue::Str,
bool => PrefValue::Bool,
}
impl_from_pref! {
PrefValue::Float => f64,
PrefValue::Int => i64,
PrefValue::UInt => u64,
PrefValue::Str => String,
PrefValue::Bool => bool,
}
impl From<[f64; 4]> for PrefValue {
fn from(other: [f64; 4]) -> PrefValue {
PrefValue::Array(IntoIterator::into_iter(other).map(|v| v.into()).collect())
}
}
impl From<PrefValue> for [f64; 4] {
fn from(other: PrefValue) -> [f64; 4] {
match other {
PrefValue::Array(values) if values.len() == 4 => {
let values: Vec<f64> = values
.into_iter()
.map(TryFrom::try_from)
.filter_map(Result::ok)
.collect();
if values.len() == 4 {
[values[0], values[1], values[2], values[3]]
} else {
panic!(
"Cannot convert PrefValue to {:?}",
std::any::type_name::<[f64; 4]>()
)
}
},
_ => panic!(
"Cannot convert {:?} to {:?}",
other,
std::any::type_name::<[f64; 4]>()
),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_pref_value_from_str() {
let value = PrefValue::from_booleanish_str("21");
assert_eq!(value, PrefValue::Int(21));
let value = PrefValue::from_booleanish_str("12.5");
assert_eq!(value, PrefValue::Float(12.5));
let value = PrefValue::from_booleanish_str("a string");
assert_eq!(value, PrefValue::Str("a string".into()));
let value = PrefValue::from_booleanish_str("false");
assert_eq!(value, PrefValue::Bool(false));
let value = PrefValue::from_booleanish_str("true");
assert_eq!(value, PrefValue::Bool(true));
}
}