titanite/src/response/certificate.rs
2025-02-24 03:05:13 +02:00

75 lines
2.2 KiB
Rust

pub mod expected;
pub mod not_authorized;
pub mod not_valid;
pub use expected::Expected;
pub use not_authorized::NotAuthorized;
pub use not_valid::NotValid;
use anyhow::{bail, Result};
/// [Client certificates](https://geminiprotocol.net/docs/protocol-specification.gmi#client-certificates)
pub enum Certificate {
Expected(Expected),
NotAuthorized(NotAuthorized),
NotValid(NotValid),
}
impl Certificate {
pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
if buffer.first().is_none_or(|b| *b != b'6') {
bail!("Unexpected first byte")
}
match buffer.get(1) {
Some(byte) => Ok(match byte {
b'0' => Self::Expected(Expected::from_bytes(buffer)?),
b'1' => Self::NotAuthorized(NotAuthorized::from_bytes(buffer)?),
b'2' => Self::NotValid(NotValid::from_bytes(buffer)?),
b => bail!("Unexpected second byte: {b}"),
}),
None => bail!("Invalid request"),
}
}
pub fn into_bytes(self) -> Vec<u8> {
match self {
Self::Expected(this) => this.into_bytes(),
Self::NotAuthorized(this) => this.into_bytes(),
Self::NotValid(this) => this.into_bytes(),
}
}
}
#[test]
fn test() {
// 60
let request = "60 message\r\n";
let source = Certificate::from_bytes(request.as_bytes()).unwrap();
match source {
Certificate::Expected(ref this) => assert_eq!(this.message, Some("message".to_string())),
_ => panic!(),
}
assert_eq!(source.into_bytes(), request.as_bytes());
// 61
let request = "61 message\r\n";
let source = Certificate::from_bytes(request.as_bytes()).unwrap();
match source {
Certificate::NotAuthorized(ref this) => {
assert_eq!(this.message, Some("message".to_string()))
}
_ => panic!(),
}
assert_eq!(source.into_bytes(), request.as_bytes());
// 62
let request = "62 message\r\n";
let source = Certificate::from_bytes(request.as_bytes()).unwrap();
match source {
Certificate::NotValid(ref this) => assert_eq!(this.message, Some("message".to_string())),
_ => panic!(),
}
assert_eq!(source.into_bytes(), request.as_bytes());
}