mirror of
https://github.com/fafhrd91/actix-web
synced 2025-07-01 00:44:26 +02:00
Quality
/ QualityItem
improvements (#2486)
This commit is contained in:
@ -2,7 +2,7 @@ use std::cmp::Ordering;
|
||||
|
||||
use mime::Mime;
|
||||
|
||||
use super::{qitem, QualityItem};
|
||||
use super::QualityItem;
|
||||
use crate::http::header;
|
||||
|
||||
crate::http::header::common_header! {
|
||||
@ -34,46 +34,40 @@ crate::http::header::common_header! {
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{Accept, qitem};
|
||||
/// use actix_web::http::header::{Accept, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// Accept(vec![
|
||||
/// qitem(mime::TEXT_HTML),
|
||||
/// QualityItem::max(mime::TEXT_HTML),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{Accept, qitem};
|
||||
/// use actix_web::http::header::{Accept, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// Accept(vec![
|
||||
/// qitem(mime::APPLICATION_JSON),
|
||||
/// QualityItem::max(mime::APPLICATION_JSON),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{Accept, QualityItem, q, qitem};
|
||||
/// use actix_web::http::header::{Accept, QualityItem, q};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// Accept(vec![
|
||||
/// qitem(mime::TEXT_HTML),
|
||||
/// qitem("application/xhtml+xml".parse().unwrap()),
|
||||
/// QualityItem::new(
|
||||
/// mime::TEXT_XML,
|
||||
/// q(900)
|
||||
/// ),
|
||||
/// qitem("image/webp".parse().unwrap()),
|
||||
/// QualityItem::new(
|
||||
/// mime::STAR_STAR,
|
||||
/// q(800)
|
||||
/// ),
|
||||
/// QualityItem::max(mime::TEXT_HTML),
|
||||
/// QualityItem::max("application/xhtml+xml".parse().unwrap()),
|
||||
/// QualityItem::new(mime::TEXT_XML, q(0.9)),
|
||||
/// QualityItem::max("image/webp".parse().unwrap()),
|
||||
/// QualityItem::new(mime::STAR_STAR, q(0.8)),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
@ -85,20 +79,20 @@ crate::http::header::common_header! {
|
||||
test1,
|
||||
vec![b"audio/*; q=0.2, audio/basic"],
|
||||
Some(Accept(vec![
|
||||
QualityItem::new("audio/*".parse().unwrap(), q(200)),
|
||||
qitem("audio/basic".parse().unwrap()),
|
||||
QualityItem::new("audio/*".parse().unwrap(), q(0.2)),
|
||||
QualityItem::max("audio/basic".parse().unwrap()),
|
||||
])));
|
||||
|
||||
crate::http::header::common_header_test!(
|
||||
test2,
|
||||
vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"],
|
||||
Some(Accept(vec![
|
||||
QualityItem::new(mime::TEXT_PLAIN, q(500)),
|
||||
qitem(mime::TEXT_HTML),
|
||||
QualityItem::new(mime::TEXT_PLAIN, q(0.5)),
|
||||
QualityItem::max(mime::TEXT_HTML),
|
||||
QualityItem::new(
|
||||
"text/x-dvi".parse().unwrap(),
|
||||
q(800)),
|
||||
qitem("text/x-c".parse().unwrap()),
|
||||
q(0.8)),
|
||||
QualityItem::max("text/x-c".parse().unwrap()),
|
||||
])));
|
||||
|
||||
// Custom tests
|
||||
@ -106,14 +100,14 @@ crate::http::header::common_header! {
|
||||
test3,
|
||||
vec![b"text/plain; charset=utf-8"],
|
||||
Some(Accept(vec![
|
||||
qitem(mime::TEXT_PLAIN_UTF_8),
|
||||
QualityItem::max(mime::TEXT_PLAIN_UTF_8),
|
||||
])));
|
||||
crate::http::header::common_header_test!(
|
||||
test4,
|
||||
vec![b"text/plain; charset=utf-8; q=0.5"],
|
||||
Some(Accept(vec![
|
||||
QualityItem::new(mime::TEXT_PLAIN_UTF_8,
|
||||
q(500)),
|
||||
q(0.5)),
|
||||
])));
|
||||
|
||||
#[test]
|
||||
@ -130,27 +124,27 @@ crate::http::header::common_header! {
|
||||
impl Accept {
|
||||
/// Construct `Accept: */*`.
|
||||
pub fn star() -> Accept {
|
||||
Accept(vec![qitem(mime::STAR_STAR)])
|
||||
Accept(vec![QualityItem::max(mime::STAR_STAR)])
|
||||
}
|
||||
|
||||
/// Construct `Accept: application/json`.
|
||||
pub fn json() -> Accept {
|
||||
Accept(vec![qitem(mime::APPLICATION_JSON)])
|
||||
Accept(vec![QualityItem::max(mime::APPLICATION_JSON)])
|
||||
}
|
||||
|
||||
/// Construct `Accept: text/*`.
|
||||
pub fn text() -> Accept {
|
||||
Accept(vec![qitem(mime::TEXT_STAR)])
|
||||
Accept(vec![QualityItem::max(mime::TEXT_STAR)])
|
||||
}
|
||||
|
||||
/// Construct `Accept: image/*`.
|
||||
pub fn image() -> Accept {
|
||||
Accept(vec![qitem(mime::IMAGE_STAR)])
|
||||
Accept(vec![QualityItem::max(mime::IMAGE_STAR)])
|
||||
}
|
||||
|
||||
/// Construct `Accept: text/html`.
|
||||
pub fn html() -> Accept {
|
||||
Accept(vec![qitem(mime::TEXT_HTML)])
|
||||
Accept(vec![QualityItem::max(mime::TEXT_HTML)])
|
||||
}
|
||||
|
||||
/// Returns a sorted list of mime types from highest to lowest preference, accounting for
|
||||
@ -213,10 +207,10 @@ impl Accept {
|
||||
///
|
||||
/// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2
|
||||
pub fn preference(&self) -> Mime {
|
||||
use actix_http::header::q;
|
||||
use actix_http::header::Quality;
|
||||
|
||||
let mut max_item = None;
|
||||
let mut max_pref = q(0);
|
||||
let mut max_pref = Quality::MIN;
|
||||
|
||||
// uses manual max lookup loop since we want the first occurrence in the case of same
|
||||
// preference but `Iterator::max_by_key` would give us the last occurrence
|
||||
@ -244,11 +238,11 @@ mod tests {
|
||||
let test = Accept(vec![]);
|
||||
assert!(test.ranked().is_empty());
|
||||
|
||||
let test = Accept(vec![qitem(mime::APPLICATION_JSON)]);
|
||||
let test = Accept(vec![QualityItem::max(mime::APPLICATION_JSON)]);
|
||||
assert_eq!(test.ranked(), vec!(mime::APPLICATION_JSON));
|
||||
|
||||
let test = Accept(vec![
|
||||
qitem(mime::TEXT_HTML),
|
||||
QualityItem::max(mime::TEXT_HTML),
|
||||
"application/xhtml+xml".parse().unwrap(),
|
||||
QualityItem::new("application/xml".parse().unwrap(), q(0.9)),
|
||||
QualityItem::new(mime::STAR_STAR, q(0.8)),
|
||||
@ -264,9 +258,9 @@ mod tests {
|
||||
);
|
||||
|
||||
let test = Accept(vec![
|
||||
qitem(mime::STAR_STAR),
|
||||
qitem(mime::IMAGE_STAR),
|
||||
qitem(mime::IMAGE_PNG),
|
||||
QualityItem::max(mime::STAR_STAR),
|
||||
QualityItem::max(mime::IMAGE_STAR),
|
||||
QualityItem::max(mime::IMAGE_PNG),
|
||||
]);
|
||||
assert_eq!(
|
||||
test.ranked(),
|
||||
@ -277,7 +271,7 @@ mod tests {
|
||||
#[test]
|
||||
fn preference_selection() {
|
||||
let test = Accept(vec![
|
||||
qitem(mime::TEXT_HTML),
|
||||
QualityItem::max(mime::TEXT_HTML),
|
||||
"application/xhtml+xml".parse().unwrap(),
|
||||
QualityItem::new("application/xml".parse().unwrap(), q(0.9)),
|
||||
QualityItem::new(mime::STAR_STAR, q(0.8)),
|
||||
@ -286,9 +280,9 @@ mod tests {
|
||||
|
||||
let test = Accept(vec![
|
||||
QualityItem::new("video/*".parse().unwrap(), q(0.8)),
|
||||
qitem(mime::IMAGE_PNG),
|
||||
QualityItem::max(mime::IMAGE_PNG),
|
||||
QualityItem::new(mime::STAR_STAR, q(0.5)),
|
||||
qitem(mime::IMAGE_SVG),
|
||||
QualityItem::max(mime::IMAGE_SVG),
|
||||
QualityItem::new(mime::IMAGE_STAR, q(0.8)),
|
||||
]);
|
||||
assert_eq!(test.preference(), mime::IMAGE_PNG);
|
||||
|
@ -22,11 +22,11 @@ crate::http::header::common_header! {
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{AcceptCharset, Charset, qitem};
|
||||
/// use actix_web::http::header::{AcceptCharset, Charset, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// AcceptCharset(vec![qitem(Charset::Us_Ascii)])
|
||||
/// AcceptCharset(vec![QualityItem::max(Charset::Us_Ascii)])
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
@ -37,19 +37,19 @@ crate::http::header::common_header! {
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// AcceptCharset(vec![
|
||||
/// QualityItem::new(Charset::Us_Ascii, q(900)),
|
||||
/// QualityItem::new(Charset::Iso_8859_10, q(200)),
|
||||
/// QualityItem::new(Charset::Us_Ascii, q(0.9)),
|
||||
/// QualityItem::new(Charset::Iso_8859_10, q(0.2)),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{AcceptCharset, Charset, qitem};
|
||||
/// use actix_web::http::header::{AcceptCharset, Charset, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// AcceptCharset(vec![qitem(Charset::Ext("utf-8".to_owned()))])
|
||||
/// AcceptCharset(vec![QualityItem::max(Charset::Ext("utf-8".to_owned()))])
|
||||
/// );
|
||||
/// ```
|
||||
(AcceptCharset, ACCEPT_CHARSET) => (QualityItem<Charset>)+
|
||||
|
@ -29,36 +29,38 @@ common_header! {
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{AcceptEncoding, Encoding, qitem};
|
||||
/// use actix_web::http::header::{AcceptEncoding, Encoding, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// AcceptEncoding(vec![qitem(Encoding::Chunked)])
|
||||
/// AcceptEncoding(vec![QualityItem::max(Encoding::Chunked)])
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{AcceptEncoding, Encoding, qitem};
|
||||
/// use actix_web::http::header::{AcceptEncoding, Encoding, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// AcceptEncoding(vec![
|
||||
/// qitem(Encoding::Chunked),
|
||||
/// qitem(Encoding::Gzip),
|
||||
/// qitem(Encoding::Deflate),
|
||||
/// QualityItem::max(Encoding::Chunked),
|
||||
/// QualityItem::max(Encoding::Gzip),
|
||||
/// QualityItem::max(Encoding::Deflate),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{AcceptEncoding, Encoding, QualityItem, q, qitem};
|
||||
/// use actix_web::http::header::{AcceptEncoding, Encoding, QualityItem, q};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// AcceptEncoding(vec![
|
||||
/// qitem(Encoding::Chunked),
|
||||
/// QualityItem::new(Encoding::Gzip, q(600)),
|
||||
/// QualityItem::new(Encoding::EncodingExt("*".to_owned()), q(0)),
|
||||
/// QualityItem::max(Encoding::Chunked),
|
||||
/// QualityItem::new(Encoding::Gzip, q(0.60)),
|
||||
/// QualityItem::min(Encoding::EncodingExt("*".to_owned())),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
@ -77,3 +79,5 @@ common_header! {
|
||||
common_header_test!(test5, vec![b"gzip, identity; q=0.5, *;q=0"]);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: shortcut for EncodingExt(*) = Any
|
||||
|
@ -1,6 +1,6 @@
|
||||
use language_tags::LanguageTag;
|
||||
|
||||
use super::{common_header, Preference, QualityItem};
|
||||
use super::{common_header, Preference, Quality, QualityItem};
|
||||
use crate::http::header;
|
||||
|
||||
common_header! {
|
||||
@ -32,26 +32,26 @@ common_header! {
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{AcceptLanguage, qitem};
|
||||
/// use actix_web::http::header::{AcceptLanguage, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// AcceptLanguage(vec![
|
||||
/// qitem("en-US".parse().unwrap())
|
||||
/// QualityItem::max("en-US".parse().unwrap())
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{AcceptLanguage, QualityItem, q, qitem};
|
||||
/// use actix_web::http::header::{AcceptLanguage, QualityItem, q};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// AcceptLanguage(vec![
|
||||
/// qitem("da".parse().unwrap()),
|
||||
/// QualityItem::new("en-GB".parse().unwrap(), q(800)),
|
||||
/// QualityItem::new("en".parse().unwrap(), q(700)),
|
||||
/// QualityItem::max("da".parse().unwrap()),
|
||||
/// QualityItem::new("en-GB".parse().unwrap(), q(0.8)),
|
||||
/// QualityItem::new("en".parse().unwrap(), q(0.7)),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
@ -72,9 +72,9 @@ common_header! {
|
||||
not_ordered_by_weight,
|
||||
vec![b"en-US, en; q=0.5, fr"],
|
||||
Some(AcceptLanguage(vec![
|
||||
qitem("en-US".parse().unwrap()),
|
||||
QualityItem::new("en".parse().unwrap(), q(500)),
|
||||
qitem("fr".parse().unwrap()),
|
||||
QualityItem::max("en-US".parse().unwrap()),
|
||||
QualityItem::new("en".parse().unwrap(), q(0.5)),
|
||||
QualityItem::max("fr".parse().unwrap()),
|
||||
]))
|
||||
);
|
||||
|
||||
@ -82,11 +82,11 @@ common_header! {
|
||||
has_wildcard,
|
||||
vec![b"fr-CH, fr; q=0.9, en; q=0.8, de; q=0.7, *; q=0.5"],
|
||||
Some(AcceptLanguage(vec![
|
||||
qitem("fr-CH".parse().unwrap()),
|
||||
QualityItem::new("fr".parse().unwrap(), q(900)),
|
||||
QualityItem::new("en".parse().unwrap(), q(800)),
|
||||
QualityItem::new("de".parse().unwrap(), q(700)),
|
||||
QualityItem::new("*".parse().unwrap(), q(500)),
|
||||
QualityItem::max("fr-CH".parse().unwrap()),
|
||||
QualityItem::new("fr".parse().unwrap(), q(0.9)),
|
||||
QualityItem::new("en".parse().unwrap(), q(0.8)),
|
||||
QualityItem::new("de".parse().unwrap(), q(0.7)),
|
||||
QualityItem::new("*".parse().unwrap(), q(0.5)),
|
||||
]))
|
||||
);
|
||||
}
|
||||
@ -122,10 +122,8 @@ impl AcceptLanguage {
|
||||
///
|
||||
/// [q-factor weighting]: https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2
|
||||
pub fn preference(&self) -> Preference<LanguageTag> {
|
||||
use actix_http::header::q;
|
||||
|
||||
let mut max_item = None;
|
||||
let mut max_pref = q(0);
|
||||
let mut max_pref = Quality::MIN;
|
||||
|
||||
// uses manual max lookup loop since we want the first occurrence in the case of same
|
||||
// preference but `Iterator::max_by_key` would give us the last occurrence
|
||||
@ -153,15 +151,15 @@ mod tests {
|
||||
let test = AcceptLanguage(vec![]);
|
||||
assert!(test.ranked().is_empty());
|
||||
|
||||
let test = AcceptLanguage(vec![qitem("fr-CH".parse().unwrap())]);
|
||||
let test = AcceptLanguage(vec![QualityItem::max("fr-CH".parse().unwrap())]);
|
||||
assert_eq!(test.ranked(), vec!("fr-CH".parse().unwrap()));
|
||||
|
||||
let test = AcceptLanguage(vec![
|
||||
QualityItem::new("fr".parse().unwrap(), q(900)),
|
||||
QualityItem::new("fr-CH".parse().unwrap(), q(1000)),
|
||||
QualityItem::new("en".parse().unwrap(), q(800)),
|
||||
QualityItem::new("*".parse().unwrap(), q(500)),
|
||||
QualityItem::new("de".parse().unwrap(), q(700)),
|
||||
QualityItem::new("fr".parse().unwrap(), q(0.900)),
|
||||
QualityItem::new("fr-CH".parse().unwrap(), q(1.0)),
|
||||
QualityItem::new("en".parse().unwrap(), q(0.800)),
|
||||
QualityItem::new("*".parse().unwrap(), q(0.500)),
|
||||
QualityItem::new("de".parse().unwrap(), q(0.700)),
|
||||
]);
|
||||
assert_eq!(
|
||||
test.ranked(),
|
||||
@ -175,11 +173,11 @@ mod tests {
|
||||
);
|
||||
|
||||
let test = AcceptLanguage(vec![
|
||||
qitem("fr".parse().unwrap()),
|
||||
qitem("fr-CH".parse().unwrap()),
|
||||
qitem("en".parse().unwrap()),
|
||||
qitem("*".parse().unwrap()),
|
||||
qitem("de".parse().unwrap()),
|
||||
QualityItem::max("fr".parse().unwrap()),
|
||||
QualityItem::max("fr-CH".parse().unwrap()),
|
||||
QualityItem::max("en".parse().unwrap()),
|
||||
QualityItem::max("*".parse().unwrap()),
|
||||
QualityItem::max("de".parse().unwrap()),
|
||||
]);
|
||||
assert_eq!(
|
||||
test.ranked(),
|
||||
@ -196,11 +194,11 @@ mod tests {
|
||||
#[test]
|
||||
fn preference_selection() {
|
||||
let test = AcceptLanguage(vec![
|
||||
QualityItem::new("fr".parse().unwrap(), q(900)),
|
||||
QualityItem::new("fr-CH".parse().unwrap(), q(1000)),
|
||||
QualityItem::new("en".parse().unwrap(), q(800)),
|
||||
QualityItem::new("*".parse().unwrap(), q(500)),
|
||||
QualityItem::new("de".parse().unwrap(), q(700)),
|
||||
QualityItem::new("fr".parse().unwrap(), q(0.900)),
|
||||
QualityItem::new("fr-CH".parse().unwrap(), q(1.0)),
|
||||
QualityItem::new("en".parse().unwrap(), q(0.800)),
|
||||
QualityItem::new("*".parse().unwrap(), q(0.500)),
|
||||
QualityItem::new("de".parse().unwrap(), q(0.700)),
|
||||
]);
|
||||
assert_eq!(
|
||||
test.preference(),
|
||||
@ -208,11 +206,11 @@ mod tests {
|
||||
);
|
||||
|
||||
let test = AcceptLanguage(vec![
|
||||
qitem("fr".parse().unwrap()),
|
||||
qitem("fr-CH".parse().unwrap()),
|
||||
qitem("en".parse().unwrap()),
|
||||
qitem("*".parse().unwrap()),
|
||||
qitem("de".parse().unwrap()),
|
||||
QualityItem::max("fr".parse().unwrap()),
|
||||
QualityItem::max("fr-CH".parse().unwrap()),
|
||||
QualityItem::max("en".parse().unwrap()),
|
||||
QualityItem::max("*".parse().unwrap()),
|
||||
QualityItem::max("de".parse().unwrap()),
|
||||
]);
|
||||
assert_eq!(
|
||||
test.preference(),
|
||||
|
@ -23,25 +23,25 @@ common_header! {
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{ContentLanguage, LanguageTag, qitem};
|
||||
/// use actix_web::http::header::{ContentLanguage, LanguageTag, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// ContentLanguage(vec![
|
||||
/// qitem(LanguageTag::parse("en").unwrap()),
|
||||
/// QualityItem::max(LanguageTag::parse("en").unwrap()),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ```
|
||||
/// use actix_web::HttpResponse;
|
||||
/// use actix_web::http::header::{ContentLanguage, LanguageTag, qitem};
|
||||
/// use actix_web::http::header::{ContentLanguage, LanguageTag, QualityItem};
|
||||
///
|
||||
/// let mut builder = HttpResponse::Ok();
|
||||
/// builder.insert_header(
|
||||
/// ContentLanguage(vec![
|
||||
/// qitem(LanguageTag::parse("da").unwrap()),
|
||||
/// qitem(LanguageTag::parse("en-GB").unwrap()),
|
||||
/// QualityItem::max(LanguageTag::parse("da").unwrap()),
|
||||
/// QualityItem::max(LanguageTag::parse("en-GB").unwrap()),
|
||||
/// ])
|
||||
/// );
|
||||
/// ```
|
||||
|
Reference in New Issue
Block a user