leyline-http 0.1.1

HTTP client that mimics browsers on the wire
Documentation
use std::collections::{HashMap, HashSet};

use super::{Button, Form};

#[derive(Clone)]
pub(super) enum Owner {
    Open(usize),
    Id(String),
}

pub(super) enum Item {
    Field {
        name: String,
        value: String,
        radio: bool,
    },
    Button(Button),
}

pub(super) struct Entry {
    pub(super) owner: Owner,
    pub(super) item: Item,
}

pub(super) fn assign(
    forms: &mut [Form],
    entries: Vec<Entry>,
    ids: &HashMap<String, Option<usize>>,
) {
    let mut fields: Vec<Vec<(String, String, bool)>> = vec![Vec::new(); forms.len()];
    for entry in entries {
        let index = match &entry.owner {
            Owner::Open(index) => Some(*index),
            Owner::Id(id) => ids.get(id).copied().flatten(),
        };
        let Some(index) = index.filter(|index| *index < forms.len()) else {
            continue;
        };
        match entry.item {
            Item::Field { name, value, radio } => fields[index].push((name, value, radio)),
            Item::Button(button) => forms[index].buttons.push(button),
        }
    }
    for (form, fields) in forms.iter_mut().zip(fields) {
        form.fields = last_radio(fields);
    }
}

fn last_radio(fields: Vec<(String, String, bool)>) -> Vec<(String, String)> {
    let mut seen = HashSet::new();
    let mut kept: Vec<(String, String)> = fields
        .into_iter()
        .rev()
        .filter(|(name, _, radio)| !radio || seen.insert(name.clone()))
        .map(|(name, value, _)| (name, value))
        .collect();
    kept.reverse();
    kept
}