#[inline]
pub fn clamp_line_number(n: i64) -> u32 {
n.clamp(1, u32::MAX as i64) as u32
}
#[derive(Clone)]
pub(crate) struct CandidateRow {
pub id: String,
pub name: String,
pub origin: String,
pub language: String,
pub chunk_type: String,
}
impl CandidateRow {
pub(crate) fn from_row(row: &sqlx::sqlite::SqliteRow) -> Self {
use sqlx::Row;
CandidateRow {
id: row.get("id"),
name: row.get("name"),
origin: row.get("origin"),
language: row.get("language"),
chunk_type: row.get("chunk_type"),
}
}
}
#[derive(Clone)]
pub(crate) struct ChunkRow {
pub id: String,
pub origin: String,
pub language: String,
pub chunk_type: String,
pub name: String,
pub signature: String,
pub content: String,
pub doc: Option<String>,
pub line_start: u32,
pub line_end: u32,
pub content_hash: String,
pub window_idx: Option<i32>,
pub parent_id: Option<String>,
pub parent_type_name: Option<String>,
}
impl ChunkRow {
pub(crate) fn from_row(row: &sqlx::sqlite::SqliteRow) -> Self {
use sqlx::Row;
ChunkRow {
id: row.get("id"),
origin: row.get("origin"),
language: row.get("language"),
chunk_type: row.get("chunk_type"),
name: row.get("name"),
signature: row.get("signature"),
content: row.get("content"),
doc: row.get("doc"),
line_start: clamp_line_number(row.get::<i64, _>("line_start")),
line_end: clamp_line_number(row.get::<i64, _>("line_end")),
content_hash: row.try_get("content_hash").unwrap_or_else(|_| {
tracing::warn!("content_hash column missing from row, defaulting to empty");
String::new()
}),
window_idx: row.try_get("window_idx").unwrap_or(None),
parent_id: row.get("parent_id"),
parent_type_name: row.get("parent_type_name"),
}
}
pub(crate) fn from_row_lightweight(row: &sqlx::sqlite::SqliteRow) -> Self {
use sqlx::Row;
ChunkRow {
id: row.get("id"),
origin: row.get("origin"),
language: row.get("language"),
chunk_type: row.get("chunk_type"),
name: row.get("name"),
signature: row.get("signature"),
content: String::new(),
doc: None,
line_start: clamp_line_number(row.get::<i64, _>("line_start")),
line_end: clamp_line_number(row.get::<i64, _>("line_end")),
content_hash: String::new(),
window_idx: None,
parent_id: row.get("parent_id"),
parent_type_name: row.get("parent_type_name"),
}
}
pub(crate) fn from_light_chunk(
light: crate::store::calls::LightChunk,
content: String,
doc: Option<String>,
) -> Self {
ChunkRow {
id: light.id,
origin: light.file.to_string_lossy().into_owned(),
language: light.language.to_string(),
chunk_type: light.chunk_type.to_string(),
name: light.name,
signature: light.signature,
content,
doc,
line_start: light.line_start,
line_end: light.line_end,
content_hash: String::new(),
window_idx: None,
parent_id: None,
parent_type_name: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clamp_line_number_normal() {
assert_eq!(clamp_line_number(1), 1);
assert_eq!(clamp_line_number(100), 100);
}
#[test]
fn test_clamp_line_number_negative() {
assert_eq!(clamp_line_number(-1), 1);
assert_eq!(clamp_line_number(-1000), 1);
assert_eq!(clamp_line_number(0), 1);
}
#[test]
fn test_clamp_line_number_overflow() {
assert_eq!(clamp_line_number(i64::MAX), u32::MAX);
assert_eq!(clamp_line_number(u32::MAX as i64 + 1), u32::MAX);
}
}