Skip to main content

Text

Struct Text 

Source
pub struct Text { /* private fields */ }
Expand description

A SQLite text value.

One of the types in a SQLite database is a text type, internally these can have two opaque representations. UTF-8 and UTF-16 (of various endianesses). This library only interacts with the UTF-8 portion of the library.

Rust strings demand that all text is valid and well-formed UTF-8. SQLite despite calling what it returns as UTF-8 it doesn’t validate that the data it stores is well-formed. To put it in other terms, garbage in is garbage out. For a more detailed overview see the Invalid UTF Policy.

Since we want a thing wrapper on top of SQLite, that leaves us with having to treat all text values as potentially malformed UTF-8, which is where this wrapper type comes in. It provides some basic text-like functionality similar to the [bstr crate] which makes your life a little easier. Such as safely printing the value.

A type loaded as Text doesn’t validate that the underlying bytes are valid or well-formed UTF-8, but provide some access to the literal underlying data and convenience method for performing the text validation locally such as Text::to_str.

For cases where you prefer to do this validation up front, we do provide FromColumn implementations for string-like types where you can opt in to eagerly perform the validation.

Reading the UTF policy carefully also leads you to the realization that all SQLite APIs which might mix in user-provided text can produce malformed UTF-8. Like Connection::error_message. Meaning even if we didn’t want to support lossless text values, we would still want to treat these values carefully.

§Examples

use sqll::{Code, Connection, Text};

let mut c = Connection::open_in_memory()?;

c.execute(r#"
    CREATE TABLE example (data TEXT);
"#)?;

let mut insert = c.prepare("INSERT INTO example (data) VALUES (?)")?;
insert.execute(Text::new(b"invalid: \xF0\x90\x80\xF0\x90\x80"))?;
insert.execute(Text::new(b"valid: \xe2\x9d\xa4\xef\xb8\x8f"))?;

let mut stmt = c.prepare("SELECT data FROM example")?;
let e = stmt.next::<&str>().unwrap_err();
assert_eq!(e.code(), Code::MISMATCH);

stmt.reset()?;

let text = stmt.next::<&Text>()?.expect("expected value");
assert_eq!(text.as_bytes(), b"invalid: \xF0\x90\x80\xF0\x90\x80");
assert_eq!(text.to_string(), "invalid: ��");

let text = stmt.next::<&Text>()?.expect("expected value");
assert_eq!(text.as_bytes(), b"valid: \xe2\x9d\xa4\xef\xb8\x8f");
assert_eq!(text.to_str()?, "valid: ❤️");

Implementations§

Source§

impl Text

Source

pub fn new<T>(bytes: &T) -> &Self
where T: ?Sized + AsRef<[u8]>,

Create a new Text from the given type coerced into a byte slice.

§Examples
use sqll::Text;

let a = Text::new(b"hello");
assert_eq!(a, "hello");
Source

pub const fn from_bytes(bytes: &[u8]) -> &Self

Create a new Text from the given byte slice.

§Examples
use sqll::Text;

let t = Text::from_bytes(b"example");
assert_eq!(t, "example");
Source

pub fn as_bytes(&self) -> &[u8]

Get the underlying byte slice for this Text.

§Examples
use sqll::Text;

let t = Text::new(b"example");
assert_eq!(t.as_bytes(), b"example");
Source

pub fn to_str(&self) -> Result<&str, Utf8Error>

Attempt to convert this Text into a UTF-8 string slice.

Returns an error if the underlying bytes are not valid UTF-8.

§Examples
use sqll::Text;

let t = Text::new(b"example");
assert_eq!(t.to_str()?, "example");

let invalid = Text::new(b"\xF0\x90\x80");
assert!(invalid.to_str().is_err());

Trait Implementations§

Source§

impl AsRef<[u8]> for Text

Allow getting a reference to the underlying byte slice.

§Examples

use sqll::Text;

let t = Text::new(b"example");
let b: &[u8] = t.as_ref();
assert_eq!(b, b"example");
Source§

fn as_ref(&self) -> &[u8]

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<const N: usize> AsRef<Text> for FixedText<N>

Coerce into Text.

§Examples

use sqll::{FixedText, Text};

let text = FixedText::from(*b"example");
let text: &Text = text.as_ref();
assert_eq!(text, "example");
Source§

fn as_ref(&self) -> &Text

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl AsRef<Text> for Text

Allow getting a reference to self.

§Examples

use sqll::Text;

let t = Text::new(b"example");
let t_ref: &Text = t.as_ref();
assert_eq!(t_ref, t);
Source§

fn as_ref(&self) -> &Text

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl AsRef<Text> for str

Allow getting a a string as a Text reference.

§Examples

use sqll::Text;

let t = "example";
let t_ref: &Text = t.as_ref();
assert_eq!(t_ref, t);
Source§

fn as_ref(&self) -> &Text

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl Bind for Text

Bind implementation for Text slices.

§Examples

use sqll::{Connection, Text};

let c = Connection::open_in_memory()?;

c.execute(r#"
    CREATE TABLE users (name TEXT, age INTEGER);

    INSERT INTO users (name, age) VALUES ('Alice', 42), ('Bob', 30), ('', 25);
"#)?;

let mut stmt = c.prepare("SELECT age FROM users WHERE name = ?")?;

stmt.bind(Text::new(b"Alice"))?;
assert_eq!(stmt.iter::<i64>().collect::<Vec<_>>(), [Ok(42)]);

stmt.bind(Text::new(b""))?;
assert_eq!(stmt.iter::<i64>().collect::<Vec<_>>(), [Ok(25)]);

stmt.bind(b"")?;
assert_eq!(stmt.iter::<i64>().collect::<Vec<_>>(), []);
Source§

fn bind(&self, stmt: &mut Statement) -> Result<()>

Bind this value into the given Statement.
Source§

impl BindValue for Text

BindValue implementation for Text slices.

§Examples

use sqll::{Connection, Text, BIND_INDEX};

let c = Connection::open_in_memory()?;

c.execute(r#"
    CREATE TABLE users (name TEXT, age INTEGER);

    INSERT INTO users (name, age) VALUES ('Alice', 42), ('Bob', 30), ('', 25);
"#)?;

let mut stmt = c.prepare("SELECT age FROM users WHERE name = ?")?;

stmt.reset()?;
stmt.bind_value(BIND_INDEX, Text::new(b"Alice"))?;
assert_eq!(stmt.iter::<i64>().collect::<Vec<_>>(), [Ok(42)]);

stmt.reset()?;
stmt.bind_value(BIND_INDEX, Text::new(b""))?;
assert_eq!(stmt.iter::<i64>().collect::<Vec<_>>(), [Ok(25)]);

stmt.reset()?;
stmt.bind_value(BIND_INDEX, b"")?;
assert_eq!(stmt.iter::<i64>().collect::<Vec<_>>(), []);
Source§

fn bind_value(&self, stmt: &mut Statement, index: c_int) -> Result<()>

Bind a value to the specified parameter index. Read more
Source§

impl Borrow<[u8]> for Text

Allow borrowing the underlying byte slice.

§Examples

use sqll::Text;
use core::borrow::Borrow;

let t = Text::new(b"example");
let b: &[u8] = t.borrow();
assert_eq!(b, b"example");
Source§

fn borrow(&self) -> &[u8]

Immutably borrows from an owned value. Read more
Source§

impl Debug for Text

The debug implementation for Text will output a string literal style representation of the text, escaping invalid UTF-8 bytes as \xNN escapes.

§Examples

use sqll::Text;

assert_eq! {
    format!("{:?}", Text::new(b"Hello, \xF0\x90\x80World!")),
    "\"Hello, \\xF0\\x90\\x80World!\"",
};
Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Text

The display implementation for Text will convert it into a UTF-8 string lossily, replacing invalid sequences with the replacement character .

§Examples

use sqll::Text;

let text = Text::new(b"before\xF0\x90\x80after");
assert_eq!(text.to_string(), "before�after");

let text = Text::new(b"before\xF0\x90\x80\xF0\x90\x80");
assert_eq!(text.to_string(), "before��");
Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'stmt> FromColumn<'stmt> for &'stmt Text

FromColumn implementation which returns a borrowed Text.

§Examples

use sqll::{Connection, Text};

let c = Connection::open_in_memory()?;

c.execute(r#"
    CREATE TABLE users (name TEXT);

    INSERT INTO users (name) VALUES ('Alice'), ('Bob');
"#)?;

let mut stmt = c.prepare("SELECT name FROM users")?;

assert_eq!(stmt.next::<&Text>()?, Some(Text::new(b"Alice")));
assert_eq!(stmt.next::<&Text>()?, Some(Text::new(b"Bob")));
assert_eq!(stmt.next::<&Text>()?, None);

Automatic conversion being denied:

use sqll::{Connection, Code, Text};

let c = Connection::open_in_memory()?;

c.execute(r#"
    CREATE TABLE users (id INTEGER);

    INSERT INTO users (id) VALUES (1), (2);
"#)?;

let mut stmt = c.prepare("SELECT id FROM users")?;

let e = stmt.next::<&Text>().unwrap_err();
assert_eq!(e.code(), Code::MISMATCH);
Source§

type Type = Text

The type of a column. Read more
Source§

fn from_column(stmt: &'stmt Statement, index: Text) -> Result<Self>

Read a value from the specified column. Read more
Source§

impl FromUnsizedColumn for Text

FromUnsizedColumn implementation for Text.

This corresponds exactly with the internal SQLite TEXT or Text types.

§Examples

use sqll::{Connection, Text};

let c = Connection::open_in_memory()?;

c.execute(r#"
    CREATE TABLE users (name TEXT);

    INSERT INTO users (name) VALUES ('Alice'), ('Bob');
"#)?;

let mut stmt = c.prepare("SELECT name FROM users")?;

assert!(stmt.step()?.is_row());
let name = stmt.unsized_column::<Text>(0)?;
assert_eq!(name, "Alice");

assert!(stmt.step()?.is_row());
let name = stmt.unsized_column::<Text>(0)?;
assert_eq!(name, "Bob");

Automatic conversion being denied:

use sqll::{Connection, Code};

let c = Connection::open_in_memory()?;

c.execute(r#"
    CREATE TABLE users (id INTEGER);

    INSERT INTO users (id) VALUES (1), (2);
"#)?;

let mut stmt = c.prepare("SELECT id FROM users")?;
let mut name = String::new();

while stmt.step()?.is_row() {
    let e = stmt.unsized_column::<str>(0).unwrap_err();
    assert_eq!(e.code(), Code::MISMATCH);
}
Source§

type Type = Text

The type of a column. Read more
Source§

fn from_unsized_column(stmt: &Statement, index: Text) -> Result<&Self>

Read an unsized value from the specified column. Read more
Source§

impl Hash for Text

Hash the text based on its byte sequence.

§Examples

use sqll::Text;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

let t1 = Text::new(b"example");
let t2 = Text::new(b"example");

let mut hasher1 = DefaultHasher::new();
let mut hasher2 = DefaultHasher::new();

t1.hash(&mut hasher1);
t2.hash(&mut hasher2);

assert_eq!(hasher1.finish(), hasher2.finish());

Inserting into a has set:

use sqll::Text;
use std::collections::HashSet;

let a = Text::new("Apple");
let b = Text::new("Banana");

let mut set = HashSet::from([a, b]);

let c = Text::new("Banana");
assert!(set.contains(&c));
assert!(!set.insert(c));
Source§

fn hash<H>(&self, state: &mut H)
where H: Hasher,

Feeds this value into the given Hasher. Read more
Source§

impl Ord for Text

Compare for ordering.

§Examples

use sqll::Text;
use std::collections::BTreeSet;

let a = Text::new("Apple");
let b = Text::new("Banana");

let mut set = BTreeSet::from([a, b]);

let c = Text::new("Banana");
assert!(set.contains(&c));
assert!(!set.insert(c));
Source§

fn cmp(&self, other: &Text) -> Ordering

This method returns an Ordering between self and other. Read more
Source§

impl<const N: usize> PartialEq<Text> for FixedText<N>

Compare the text for equality with a Text. This performs a byte-wise comparison.

§Examples

use sqll::{FixedText, Text};

let t1 = FixedText::from(*b"example");
let t2 = Text::new("example");
let t3 = Text::new("different");

assert_eq!(t1, *t2);
assert_ne!(t1, *t3);
Source§

fn eq(&self, other: &Text) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialEq<str> for Text

Compare the text for equality with a str.

This performs a byte-wise comparison.

§Examples

use sqll::Text;
let t = Text::new(b"example");

assert_eq!(t, "example");
assert_ne!(t, "different");
Source§

fn eq(&self, other: &str) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialEq for Text

Compare the text for equality with another Text. This performs a byte-wise comparison.

§Examples

use sqll::Text;

let t1 = Text::new(b"example");
let t2 = Text::new(b"example");
let t3 = Text::new(b"different");

assert_eq!(t1, t2);
assert_ne!(t1, t3);
Source§

fn eq(&self, other: &Text) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialOrd for Text

Texts are ordered by their byte sequences.

§Examples

use sqll::Text;

let t1 = Text::new(b"apple");
let t2 = Text::new(b"banana");

assert!(t1 < t2);
Source§

fn partial_cmp(&self, other: &Text) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl Eq for Text

Texts are equal if their bytes are equal.

§Examples

use sqll::Text;

let t1 = Text::new(b"example");
let t2 = Text::new(b"example");

assert!(t1 == t2);

Auto Trait Implementations§

§

impl Freeze for Text

§

impl RefUnwindSafe for Text

§

impl Send for Text

§

impl !Sized for Text

§

impl Sync for Text

§

impl Unpin for Text

§

impl UnsafeUnpin for Text

§

impl UnwindSafe for Text

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more