relay-knowledge 1.1.17

Graph-database-based knowledge graph project.
Documentation
use rusqlite::Row;

use crate::{
    domain::{CodeExtractionMetadata, CodeRange, DomainError, SourceScope},
    storage::StorageError,
};

pub(super) struct RawRange {
    start_byte: u32,
    end_byte: u32,
    start_line: u32,
    end_line: u32,
}

impl RawRange {
    pub(super) fn from_row(row: &Row<'_>, start_index: usize) -> rusqlite::Result<Self> {
        Ok(Self {
            start_byte: row.get(start_index)?,
            end_byte: row.get(start_index + 1)?,
            start_line: row.get(start_index + 2)?,
            end_line: row.get(start_index + 3)?,
        })
    }

    pub(super) fn into_range(self) -> Result<CodeRange, StorageError> {
        CodeRange::new(
            self.start_byte,
            self.end_byte,
            self.start_line,
            self.end_line,
        )
        .map_err(domain_error)
    }
}

pub(super) fn extraction(
    grammar_version: String,
    query_name: String,
    query_version: String,
    node_kind: String,
    capture_kind: String,
) -> CodeExtractionMetadata {
    CodeExtractionMetadata {
        grammar_version,
        query_name,
        query_version,
        node_kind,
        capture_kind,
    }
}

pub(super) fn optional_extraction(
    grammar_version: Option<String>,
    query_name: Option<String>,
    query_version: Option<String>,
    node_kind: Option<String>,
    capture_kind: Option<String>,
) -> Option<CodeExtractionMetadata> {
    Some(CodeExtractionMetadata {
        grammar_version: grammar_version?,
        query_name: query_name?,
        query_version: query_version?,
        node_kind: node_kind?,
        capture_kind: capture_kind?,
    })
}

pub(super) fn normalize_filter(
    field: &'static str,
    value: Option<String>,
) -> Result<Option<String>, StorageError> {
    value
        .map(|value| {
            let trimmed = value.trim();
            if trimmed.is_empty() {
                return Err(StorageError::InvalidInput(format!(
                    "{field} filter must not be empty"
                )));
            }
            if trimmed.contains('\0') {
                return Err(StorageError::InvalidInput(format!(
                    "{field} filter must not contain NUL bytes"
                )));
            }

            Ok(trimmed.to_owned())
        })
        .transpose()
}

pub(super) fn validate_limit(label: &'static str, limit: usize) -> Result<(), StorageError> {
    if limit == 0 {
        return Err(StorageError::InvalidInput(format!(
            "{label} must be greater than zero"
        )));
    }

    Ok(())
}

pub(super) fn parse_scope(value: String) -> Result<SourceScope, StorageError> {
    SourceScope::parse(value).map_err(domain_error)
}

pub(super) fn invalid_code_metadata(message: String) -> StorageError {
    StorageError::InvalidInput(format!("{message} in code graph metadata"))
}

fn domain_error(error: DomainError) -> StorageError {
    StorageError::InvalidInput(error.to_string())
}

#[cfg(test)]
#[path = "common_tests.rs"]
mod common_tests;