atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
1a144ee92b627d87d2ff575eded19a9b8baa3fe1
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git

Blame: src/game/outcome.rs

4f54028cba69atagen2026-10-14 11:45 UTC1
use axum::http::{HeaderName, StatusCode, header};
4f54028cba69atagen2026-10-14 11:45 UTC2
use serde_json::{Value, json};
4f54028cba69atagen2026-10-14 11:45 UTC3
4f54028cba69atagen2026-10-14 11:45 UTC4
use crate::link::{self, Link};
782069860236atagen2026-10-10 12:44 UTC5
782069860236atagen2026-10-10 12:44 UTC6
pub enum Payload {
782069860236atagen2026-10-10 12:44 UTC7
    Empty,
782069860236atagen2026-10-10 12:44 UTC8
    Json(Value),
782069860236atagen2026-10-10 12:44 UTC9
    Raw(&'static str, Vec<u8>),
782069860236atagen2026-10-10 12:44 UTC10
}
782069860236atagen2026-10-10 12:44 UTC11
4f54028cba69atagen2026-10-14 11:45 UTC12
/// One way out of a 300, offered in the body and in `Link` alike.
4f54028cba69atagen2026-10-14 11:45 UTC13
pub struct Choice {
4f54028cba69atagen2026-10-14 11:45 UTC14
    pub(crate) href: String,
4f54028cba69atagen2026-10-14 11:45 UTC15
    pub(crate) method: &'static str,
4f54028cba69atagen2026-10-14 11:45 UTC16
    pub(crate) title: &'static str,
4f54028cba69atagen2026-10-14 11:45 UTC17
}
4f54028cba69atagen2026-10-14 11:45 UTC18
782069860236atagen2026-10-10 12:44 UTC19
/// A successful result of a game action, before it becomes an HTTP response.
782069860236atagen2026-10-10 12:44 UTC20
pub struct Outcome {
8b8e83329a1datagen2026-10-12 12:01 UTC21
    status: StatusCode,
8b8e83329a1datagen2026-10-12 12:01 UTC22
    payload: Payload,
8b8e83329a1datagen2026-10-12 12:01 UTC23
    headers: Vec<(HeaderName, String)>,
782069860236atagen2026-10-10 12:44 UTC24
}
782069860236atagen2026-10-10 12:44 UTC25
782069860236atagen2026-10-10 12:44 UTC26
impl Outcome {
782069860236atagen2026-10-10 12:44 UTC27
    pub fn empty(status: StatusCode) -> Self {
782069860236atagen2026-10-10 12:44 UTC28
        Self {
782069860236atagen2026-10-10 12:44 UTC29
            status,
782069860236atagen2026-10-10 12:44 UTC30
            payload: Payload::Empty,
782069860236atagen2026-10-10 12:44 UTC31
            headers: Vec::new(),
782069860236atagen2026-10-10 12:44 UTC32
        }
782069860236atagen2026-10-10 12:44 UTC33
    }
782069860236atagen2026-10-10 12:44 UTC34
782069860236atagen2026-10-10 12:44 UTC35
    pub fn json(status: StatusCode, body: Value) -> Self {
782069860236atagen2026-10-10 12:44 UTC36
        Self {
782069860236atagen2026-10-10 12:44 UTC37
            payload: Payload::Json(body),
782069860236atagen2026-10-10 12:44 UTC38
            ..Self::empty(status)
782069860236atagen2026-10-10 12:44 UTC39
        }
782069860236atagen2026-10-10 12:44 UTC40
    }
782069860236atagen2026-10-10 12:44 UTC41
782069860236atagen2026-10-10 12:44 UTC42
    pub fn raw(status: StatusCode, content_type: &'static str, body: impl Into<Vec<u8>>) -> Self {
782069860236atagen2026-10-10 12:44 UTC43
        Self {
782069860236atagen2026-10-10 12:44 UTC44
            payload: Payload::Raw(content_type, body.into()),
782069860236atagen2026-10-10 12:44 UTC45
            ..Self::empty(status)
782069860236atagen2026-10-10 12:44 UTC46
        }
782069860236atagen2026-10-10 12:44 UTC47
    }
782069860236atagen2026-10-10 12:44 UTC48
4f54028cba69atagen2026-10-14 11:45 UTC49
    pub fn choices(detail: &str, choices: &[Choice]) -> Self {
4f54028cba69atagen2026-10-14 11:45 UTC50
        let listed: Vec<Value> = choices
4f54028cba69atagen2026-10-14 11:45 UTC51
            .iter()
4f54028cba69atagen2026-10-14 11:45 UTC52
            .map(|c| json!({ "href": c.href, "method": c.method, "title": c.title }))
4f54028cba69atagen2026-10-14 11:45 UTC53
            .collect();
4f54028cba69atagen2026-10-14 11:45 UTC54
        let links = link::join(choices.iter().map(|c| {
4f54028cba69atagen2026-10-14 11:45 UTC55
            Link::registered(&c.href, "alternate")
4f54028cba69atagen2026-10-14 11:45 UTC56
                .title(c.title)
4f54028cba69atagen2026-10-14 11:45 UTC57
                .allow(c.method)
4f54028cba69atagen2026-10-14 11:45 UTC58
        }));
4f54028cba69atagen2026-10-14 11:45 UTC59
        Self::json(
4f54028cba69atagen2026-10-14 11:45 UTC60
            StatusCode::MULTIPLE_CHOICES,
4f54028cba69atagen2026-10-14 11:45 UTC61
            json!({ "detail": detail, "choices": listed }),
4f54028cba69atagen2026-10-14 11:45 UTC62
        )
4f54028cba69atagen2026-10-14 11:45 UTC63
        .header(header::LINK, links)
4f54028cba69atagen2026-10-14 11:45 UTC64
    }
4f54028cba69atagen2026-10-14 11:45 UTC65
782069860236atagen2026-10-10 12:44 UTC66
    pub fn header(mut self, name: HeaderName, value: impl Into<String>) -> Self {
782069860236atagen2026-10-10 12:44 UTC67
        self.headers.push((name, value.into()));
782069860236atagen2026-10-10 12:44 UTC68
        self
782069860236atagen2026-10-10 12:44 UTC69
    }
8b8e83329a1datagen2026-10-12 12:01 UTC70
8b8e83329a1datagen2026-10-12 12:01 UTC71
    pub fn status(&self) -> StatusCode {
8b8e83329a1datagen2026-10-12 12:01 UTC72
        self.status
8b8e83329a1datagen2026-10-12 12:01 UTC73
    }
8b8e83329a1datagen2026-10-12 12:01 UTC74
98432b6057aaatagen2026-10-14 09:03 UTC75
    pub fn body(&self) -> Option<&Value> {
98432b6057aaatagen2026-10-14 09:03 UTC76
        match &self.payload {
98432b6057aaatagen2026-10-14 09:03 UTC77
            Payload::Json(body) => Some(body),
98432b6057aaatagen2026-10-14 09:03 UTC78
            _ => None,
98432b6057aaatagen2026-10-14 09:03 UTC79
        }
98432b6057aaatagen2026-10-14 09:03 UTC80
    }
98432b6057aaatagen2026-10-14 09:03 UTC81
98432b6057aaatagen2026-10-14 09:03 UTC82
    pub fn header_value(&self, name: &HeaderName) -> Option<&str> {
98432b6057aaatagen2026-10-14 09:03 UTC83
        self.headers
98432b6057aaatagen2026-10-14 09:03 UTC84
            .iter()
98432b6057aaatagen2026-10-14 09:03 UTC85
            .find(|(n, _)| n == name)
98432b6057aaatagen2026-10-14 09:03 UTC86
            .map(|(_, v)| v.as_str())
98432b6057aaatagen2026-10-14 09:03 UTC87
    }
98432b6057aaatagen2026-10-14 09:03 UTC88
8b8e83329a1datagen2026-10-12 12:01 UTC89
    pub(super) fn retold(mut self, status: StatusCode, detail: &str) -> Self {
8b8e83329a1datagen2026-10-12 12:01 UTC90
        self.status = status;
8b8e83329a1datagen2026-10-12 12:01 UTC91
        if let Payload::Json(body) = &mut self.payload {
8b8e83329a1datagen2026-10-12 12:01 UTC92
            body["detail"] = Value::from(detail);
8b8e83329a1datagen2026-10-12 12:01 UTC93
        }
8b8e83329a1datagen2026-10-12 12:01 UTC94
        self
8b8e83329a1datagen2026-10-12 12:01 UTC95
    }
8b8e83329a1datagen2026-10-12 12:01 UTC96
8b8e83329a1datagen2026-10-12 12:01 UTC97
    pub fn into_parts(self) -> (StatusCode, Payload, Vec<(HeaderName, String)>) {
8b8e83329a1datagen2026-10-12 12:01 UTC98
        (self.status, self.payload, self.headers)
8b8e83329a1datagen2026-10-12 12:01 UTC99
    }
782069860236atagen2026-10-10 12:44 UTC100
}