titanite 0.3.0

Client/Server Library for Gemini protocol with Titan support
Documentation
pub mod default;
pub mod sensitive;

pub use default::Default;
pub use sensitive::Sensitive;

use anyhow::{bail, Result};

/// [Input expected](https://geminiprotocol.net/docs/protocol-specification.gmi#input-expected)
pub enum Input {
    Default(Default),
    Sensitive(Sensitive),
}

impl Input {
    pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
        if buffer.first().is_none_or(|b| *b != b'1') {
            bail!("Unexpected first byte")
        }
        match buffer.get(1) {
            Some(byte) => Ok(match byte {
                b'0' => Self::Default(Default::from_bytes(buffer)?),
                b'1' => Self::Sensitive(Sensitive::from_bytes(buffer)?),
                b => bail!("Unexpected second byte: {b}"),
            }),
            None => bail!("Invalid request"),
        }
    }
    pub fn into_bytes(self) -> Vec<u8> {
        match self {
            Self::Default(this) => this.into_bytes(),
            Self::Sensitive(this) => this.into_bytes(),
        }
    }
}

#[test]
fn test() {
    // 10
    let request = format!("10 message\r\n");
    let source = Input::from_bytes(request.as_bytes()).unwrap();

    match source {
        Input::Default(ref this) => assert_eq!(this.message, Some("message".to_string())),
        _ => panic!(),
    }
    assert_eq!(source.into_bytes(), request.as_bytes());

    // 11
    let request = format!("11 message\r\n");
    let source = Input::from_bytes(request.as_bytes()).unwrap();

    match source {
        Input::Sensitive(ref this) => {
            assert_eq!(this.message, Some("message".to_string()))
        }
        _ => panic!(),
    }
    assert_eq!(source.into_bytes(), request.as_bytes());
}