musq 0.0.4

Musq is an asynchronous SQLite toolkit for Rust.
Documentation
use std::{result::Result as StdResult, sync::Arc};

use crate::{
    SqliteDataType, Value,
    decode::Decode,
    encode::Encode,
    error::{DecodeError, EncodeError},
};

impl Encode for &str {
    fn encode(&self) -> Result<Value, EncodeError> {
        Ok(Value::Text {
            value: self.to_string().into(),
            type_info: None,
        })
    }
}

impl<'r> Decode<'r> for &'r str {
    fn decode(value: &'r Value) -> StdResult<Self, DecodeError> {
        compatible!(value, SqliteDataType::Text);
        value.text()
    }
}

impl Encode for &String {
    fn encode(&self) -> Result<Value, EncodeError> {
        Ok(Value::Text {
            value: (*self).clone().into(),
            type_info: None,
        })
    }
}

impl Encode for String {
    fn encode(&self) -> Result<Value, EncodeError> {
        Ok(Value::Text {
            value: self.clone().into(),
            type_info: None,
        })
    }
}

impl<'r> Decode<'r> for String {
    fn decode(value: &'r Value) -> StdResult<Self, DecodeError> {
        compatible!(value, SqliteDataType::Text);
        value.text().map(ToOwned::to_owned)
    }
}

impl Encode for Arc<String> {
    fn encode(&self) -> Result<Value, EncodeError> {
        Ok(Value::Text {
            value: self.as_ref().clone().into(),
            type_info: None,
        })
    }
}

impl<'r> Decode<'r> for Arc<String> {
    fn decode(value: &'r Value) -> StdResult<Self, DecodeError> {
        compatible!(value, SqliteDataType::Text);
        value.text().map(|x| Self::new(x.to_owned()))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_string_reference_encode() {
        let value = String::from("hello");
        let result = value.encode().unwrap();
        if let Value::Text { value: encoded, .. } = result {
            assert_eq!(encoded.as_ref(), b"hello");
        } else {
            panic!("Expected Text value");
        }
    }

    #[test]
    fn test_ref_pattern_like_user_code() {
        // Simulate the pattern: RemoveFilter::Tag(ref tag) => sql!("DELETE FROM tags WHERE tag = {tag}")
        let tag = String::from("test_tag");
        let ref_tag = &tag; // This is what "ref tag" creates

        // This should now work without the Copy error
        let result = ref_tag.encode().unwrap();
        if let Value::Text { value: encoded, .. } = result {
            assert_eq!(encoded.as_ref(), b"test_tag");
        } else {
            panic!("Expected Text value");
        }
    }
}