titanite 0.3.0

Client/Server Library for Gemini protocol with Titan support
Documentation
pub mod permanent;
pub mod temporary;

pub use permanent::Permanent;
pub use temporary::Temporary;

use anyhow::{bail, Result};

pub enum Failure {
    /// [Permanent failure](https://geminiprotocol.net/docs/protocol-specification.gmi#permanent-failure)
    Permanent(Permanent),
    /// [Temporary failure](https://geminiprotocol.net/docs/protocol-specification.gmi#temporary-failure)
    Temporary(Temporary),
}

impl Failure {
    pub fn from_bytes(buffer: &[u8]) -> Result<Self> {
        match buffer.first() {
            Some(byte) => Ok(match byte {
                b'4' => Self::Temporary(Temporary::from_bytes(buffer)?),
                b'5' => Self::Permanent(Permanent::from_bytes(buffer)?),
                b => bail!("Unexpected first byte: {b}"),
            }),
            None => bail!("Invalid request"),
        }
    }
    pub fn into_bytes(self) -> Vec<u8> {
        match self {
            Self::Temporary(this) => this.into_bytes(),
            Self::Permanent(this) => this.into_bytes(),
        }
    }
}

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

            match source {
                Failure::Temporary(ref this) => match this {
                    Temporary::General(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
        // 41
        {
            let request = format!("41 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

            match source {
                Failure::Temporary(ref this) => match this {
                    Temporary::ServerUnavailable(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
        // 42
        {
            let request = format!("42 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

            match source {
                Failure::Temporary(ref this) => match this {
                    Temporary::CgiError(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
        // 43
        {
            let request = format!("43 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

            match source {
                Failure::Temporary(ref this) => match this {
                    Temporary::ProxyError(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
        // 44
        {
            let request = format!("44 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

            match source {
                Failure::Temporary(ref this) => match this {
                    Temporary::SlowDown(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
    }
    // 5*
    {
        // 50
        {
            let request = format!("50 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

            match source {
                Failure::Permanent(ref this) => match this {
                    Permanent::General(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
        // 51
        {
            let request = format!("51 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

            match source {
                Failure::Permanent(ref this) => match this {
                    Permanent::NotFound(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
        // 52
        {
            let request = format!("52 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

            match source {
                Failure::Permanent(ref this) => match this {
                    Permanent::Gone(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
        // 53
        {
            let request = format!("53 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

            match source {
                Failure::Permanent(ref this) => match this {
                    Permanent::ProxyRequestRefused(this) => {
                        assert_eq!(this.message, Some("message".to_string()))
                    }
                    _ => panic!(),
                },
                _ => panic!(),
            }
            assert_eq!(source.into_bytes(), request.as_bytes());
        }
        // 59
        {
            let request = format!("59 message\r\n");
            let source = Failure::from_bytes(request.as_bytes()).unwrap();

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