libsql_orm/
compat.rs

1//! Compatibility layer for handling different database backends
2//!
3//! This module provides type aliases and compatibility functions
4//! for working with both libsql and WASM-only environments.
5
6#[cfg(all(feature = "libsql", target_arch = "wasm32"))]
7pub use libsql::wasm::Rows as LibsqlRows;
8#[cfg(all(feature = "libsql", target_arch = "wasm32"))]
9pub use libsql::{Error as LibsqlError, Row as LibsqlRow, Value as LibsqlValue};
10
11#[cfg(all(feature = "libsql", not(target_arch = "wasm32")))]
12pub use libsql::{
13    Error as LibsqlError, Row as LibsqlRow, Rows as LibsqlRows, Value as LibsqlValue,
14};
15
16#[cfg(not(feature = "libsql"))]
17#[derive(Debug, Clone, PartialEq)]
18pub enum LibsqlValue {
19    Null,
20    Integer(i64),
21    Real(f64),
22    Text(String),
23    Blob(Vec<u8>),
24}
25
26#[cfg(not(feature = "libsql"))]
27pub struct LibsqlRow {
28    data: std::collections::HashMap<String, LibsqlValue>,
29}
30
31#[cfg(not(feature = "libsql"))]
32impl LibsqlRow {
33    pub fn new() -> Self {
34        Self {
35            data: std::collections::HashMap::new(),
36        }
37    }
38
39    pub fn get(&self, index: usize) -> Result<&LibsqlValue, crate::error::Error> {
40        // For WASM implementation, we'll use a simple index-based access
41        // This is a stub - in a real implementation you'd map indices to column names
42        Err(crate::error::Error::Generic(
43            "Column access by index not supported in WASM mode".to_string(),
44        ))
45    }
46
47    pub fn get_value(&self, index: usize) -> Option<LibsqlValue> {
48        // Stub implementation
49        Some(LibsqlValue::Null)
50    }
51
52    pub fn column_count(&self) -> usize {
53        // Stub implementation
54        0
55    }
56
57    pub fn column_name(&self, _index: usize) -> Option<&str> {
58        // Stub implementation
59        None
60    }
61}
62
63#[cfg(not(feature = "libsql"))]
64pub struct LibsqlRows {
65    rows: Vec<LibsqlRow>,
66    index: std::cell::Cell<usize>,
67}
68
69#[cfg(not(feature = "libsql"))]
70impl LibsqlRows {
71    pub fn new(rows: Vec<LibsqlRow>) -> Self {
72        Self {
73            rows,
74            index: std::cell::Cell::new(0),
75        }
76    }
77
78    pub async fn next(&self) -> Result<Option<&LibsqlRow>, crate::error::Error> {
79        let current_index = self.index.get();
80        if current_index < self.rows.len() {
81            self.index.set(current_index + 1);
82            Ok(self.rows.get(current_index))
83        } else {
84            Ok(None)
85        }
86    }
87}
88
89#[cfg(not(feature = "libsql"))]
90pub type LibsqlError = crate::error::Error;
91
92/// Create a null value compatible with both backends
93pub fn null_value() -> LibsqlValue {
94    #[cfg(feature = "libsql")]
95    return libsql::Value::Null;
96
97    #[cfg(not(feature = "libsql"))]
98    return LibsqlValue::Null;
99}
100
101/// Create a text value compatible with both backends
102pub fn text_value(s: String) -> LibsqlValue {
103    #[cfg(feature = "libsql")]
104    return libsql::Value::Text(s);
105
106    #[cfg(not(feature = "libsql"))]
107    return LibsqlValue::Text(s);
108}
109
110/// Create an integer value compatible with both backends
111pub fn integer_value(i: i64) -> LibsqlValue {
112    #[cfg(feature = "libsql")]
113    return libsql::Value::Integer(i);
114
115    #[cfg(not(feature = "libsql"))]
116    return LibsqlValue::Integer(i);
117}
118
119/// Create a real/float value compatible with both backends
120pub fn real_value(f: f64) -> LibsqlValue {
121    #[cfg(feature = "libsql")]
122    return libsql::Value::Real(f);
123
124    #[cfg(not(feature = "libsql"))]
125    return LibsqlValue::Real(f);
126}
127
128/// Create a blob value compatible with both backends
129pub fn blob_value(b: Vec<u8>) -> LibsqlValue {
130    #[cfg(feature = "libsql")]
131    return libsql::Value::Blob(b);
132
133    #[cfg(not(feature = "libsql"))]
134    return LibsqlValue::Blob(b);
135}