Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QualityItem Design #7

Open
seanmonstar opened this issue Oct 3, 2018 · 3 comments
Open

QualityItem Design #7

seanmonstar opened this issue Oct 3, 2018 · 3 comments
Labels
rfc Request for comments. More discussion would help move this along.

Comments

@seanmonstar
Copy link
Member

Several headers that a client can send include a list of "quality items", thereby ranking which sorts of representations are more preferable. For example, Accept: image/svg+xml, image/*;q=0.8. These are often used as part of "Content Negotiation". The API design in this library for these headers should be reconsidered here.

@seanmonstar seanmonstar added the rfc Request for comments. More discussion would help move this along. label Dec 10, 2018
@eggyal
Copy link

eggyal commented Apr 29, 2020

Given that there is already some degree of implementation for this in src/disabled (and taking note of #67 (comment) together with related commit a514a37), what is the thinking for moving this (also #53) forward from here?

@eggyal
Copy link

eggyal commented Apr 30, 2020

In terms of external API, perhaps expose a trait:

pub trait QualityItem<T> {
    fn quality(&self) -> u16;
    fn item(&self) -> &T;
}

Which might have a generic implementation along the following lines:

use QualityItem;

pub(crate) struct SimpleQualityItem<T> {
    quality: u16,
    item: T,
}

impl <T> QualityItem<T> for SimpleQualityItem<T> {
    fn quality(&self) -> u16 { self.quality }
    fn item(&self) -> &T { &self.item }
}

Which would enable the relevant header types to be defined like this, without exposing the internal implementation:

use SimpleQualityItem;

struct Encoding { /* ... */ }
pub struct AcceptEncoding(Vec<SimpleQualityItem<Encoding>>);

impl AcceptEncoding {
    pub fn iter(&self) -> impl Iterator<Item = &impl QualityItem<Encoding>> {
        self.0.iter()
    }
}

For headers whose items might carry additional data, such as Accept (which can include "extension parameters" after the quality-value), one could expose and implement additional traits:

use std::collections::HashMap;
use mime::Mime;
use {QualityItem, SimpleQualityItem};

struct AcceptItem {
    content_type_and_quality: SimpleQualityItem<Mime>,
    extension_params: HashMap<String, Option<String>>,
}

impl QualityItem<Mime> for AcceptItem {
    fn quality(&self) -> u16 { self.content_type_and_quality.quality() }
    fn item(&self) -> &Mime { self.content_type_and_quality.item() }
}

pub trait ExtensionParams {
    fn get_extension_param(&self, name: &str) -> Option<Option<&String>>;
}

impl ExtensionParams for AcceptItem {
    fn get_extension_param(&self, name: &str) -> Option<Option<&String>> {
        self.extension_params.get(name).map(Option::as_ref)
    }
}

pub struct Accept(Vec<AcceptItem>);

impl Accept {
    pub fn iter(&self) -> impl Iterator<Item = &(impl QualityItem<Mime> + ExtensionParams)> {
        self.0.iter()
    }
}

Do you think this would be broadly okay, @seanmonstar? If so, I'm happy to work it up and submit a PR.

@ParkMyCar
Copy link

#70 adds a QualityValue type, it could totally be reworked if necessary, and open to comments on it 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rfc Request for comments. More discussion would help move this along.
Projects
None yet
Development

No branches or pull requests

3 participants