enigma-packet 0.1.0

Canonical message packet format + serialization for Enigma secure messaging
Documentation
use crate::types::{
    AttachmentAckMeta, AttachmentChunkMeta, AttachmentKind, AttachmentMeta, Message, MessageMeta,
    MessageType,
};
use uuid::Uuid;

const BASE_ID: &str = "11111111-1111-1111-1111-111111111111";
const ATTACHMENT_ID: &str = "22222222-2222-2222-2222-222222222222";

fn base_envelope(msg_type: MessageType, payload: Vec<u8>, meta: MessageMeta) -> Message {
    Message {
        id: Uuid::parse_str(BASE_ID).unwrap(),
        sender: "alice".into(),
        receiver: "bob".into(),
        timestamp_ms: 1,
        msg_type,
        payload,
        meta,
    }
}

pub fn text_message() -> Message {
    base_envelope(
        MessageType::Text,
        b"hello enigma".to_vec(),
        MessageMeta::Basic {
            content_type: Some("text/plain".into()),
        },
    )
}

pub fn inline_file_message() -> Message {
    base_envelope(
        MessageType::File,
        vec![1, 2, 3, 4],
        MessageMeta::Basic {
            content_type: Some("application/octet-stream".into()),
        },
    )
}

pub fn voice_message() -> Message {
    base_envelope(
        MessageType::Voice,
        b"voice bytes".to_vec(),
        MessageMeta::Basic {
            content_type: Some("audio/ogg".into()),
        },
    )
}

pub fn attachment_init_message() -> Message {
    base_envelope(
        MessageType::AttachmentInit,
        Vec::new(),
        MessageMeta::AttachmentInit(AttachmentMeta {
            attachment_id: Uuid::parse_str(ATTACHMENT_ID).unwrap(),
            kind: AttachmentKind::File,
            filename: Some("archive.bin".into()),
            content_type: Some("application/octet-stream".into()),
            total_size: 8,
            chunk_size: 4,
            chunk_count: 2,
            sha256: None,
            created_at_ms: Some(1),
        }),
    )
}

pub fn attachment_chunk_message(index: u32) -> Message {
    let payload = match index {
        0 => vec![10, 11, 12, 13],
        _ => vec![14, 15, 16, 17],
    };
    base_envelope(
        MessageType::AttachmentChunk,
        payload,
        MessageMeta::AttachmentChunk(AttachmentChunkMeta {
            attachment_id: Uuid::parse_str(ATTACHMENT_ID).unwrap(),
            index,
            offset: index as u64 * 4,
            chunk_size: 4,
            total_size: Some(8),
        }),
    )
}

pub fn attachment_end_message() -> Message {
    base_envelope(
        MessageType::AttachmentEnd,
        Vec::new(),
        MessageMeta::AttachmentEnd {
            attachment_id: Uuid::parse_str(ATTACHMENT_ID).unwrap(),
            sha256: None,
            total_size: 8,
            chunk_count: 2,
        },
    )
}

pub fn attachment_abort_message() -> Message {
    base_envelope(
        MessageType::AttachmentAbort,
        Vec::new(),
        MessageMeta::AttachmentAbort {
            attachment_id: Uuid::parse_str(ATTACHMENT_ID).unwrap(),
            reason: Some("cancelled".into()),
        },
    )
}

pub fn attachment_ack_message() -> Message {
    base_envelope(
        MessageType::AttachmentAck,
        Vec::new(),
        MessageMeta::AttachmentAck(AttachmentAckMeta {
            attachment_id: Uuid::parse_str(ATTACHMENT_ID).unwrap(),
            received_up_to_index: Some(1),
        }),
    )
}

pub mod codec_tests;
pub mod framing_tests;
pub mod negative_tests;
pub mod validation_tests;