braid-core 0.1.4

Unified Braid Protocol implementation in Rust, including Braid-HTTP, Antimatter CRDT, and BraidFS.
Documentation
//! Parse incoming update requests for Braid protocol.

use crate::core::error::Result;
use crate::core::protocol_mod as protocol;
use crate::core::{Patch, Version};
use axum::extract::Request;
use bytes::Bytes;

/// Parsed update from request body.
#[derive(Clone, Debug)]
pub struct ParsedUpdate {
    /// Version ID(s) from Version header
    pub version: Vec<Version>,
    /// Parent version ID(s) from Parents header
    pub parents: Vec<Version>,
    /// Patches extracted from request body
    pub patches: Vec<Patch>,
    /// Full body if not patches (snapshot)
    pub body: Option<Bytes>,
}

impl ParsedUpdate {
    /// Create from HTTP request headers.
    pub fn from_request_headers(req: &Request) -> Result<Self> {
        let version_header = req
            .headers()
            .get("version")
            .and_then(|v| v.to_str().ok())
            .unwrap_or("");

        let parents_header = req
            .headers()
            .get("parents")
            .and_then(|v| v.to_str().ok())
            .unwrap_or("");

        let version = protocol::parse_version_header(version_header)?;
        let parents = protocol::parse_version_header(parents_header)?;

        Ok(ParsedUpdate {
            version,
            parents,
            patches: Vec::new(),
            body: None,
        })
    }
}

/// Extension trait for Axum request to parse Braid updates.
pub trait ParseUpdateExt {
    fn get_version(&self) -> Result<Vec<Version>>;
    fn get_parents(&self) -> Result<Vec<Version>>;
}

impl ParseUpdateExt for Request {
    fn get_version(&self) -> Result<Vec<Version>> {
        let val = self
            .headers()
            .get("version")
            .and_then(|v| v.to_str().ok())
            .unwrap_or("");
        Ok(protocol::parse_version_header(val)?)
    }

    fn get_parents(&self) -> Result<Vec<Version>> {
        let val = self
            .headers()
            .get("parents")
            .and_then(|v| v.to_str().ok())
            .unwrap_or("");
        Ok(protocol::parse_version_header(val)?)
    }
}