Skip to content

Instantly share code, notes, and snippets.

@ColinTimBarndt
Created September 8, 2021 10:48
Show Gist options
  • Save ColinTimBarndt/28857d3f955dfd1fadea01b6fe0fe450 to your computer and use it in GitHub Desktop.
Save ColinTimBarndt/28857d3f955dfd1fadea01b6fe0fe450 to your computer and use it in GitHub Desktop.
Diesel wrapper for Smallstring
mod smallstring {
use std::{
fmt,
ops::{Deref, DerefMut},
};
use diesel::{backend::Backend, types::FromSql};
use serde::{Deserialize, Serialize};
use smallstr::SmallString as ExtSmallString;
pub struct SmallString<A>(ExtSmallString<A>)
where
A: smallvec::Array<Item = u8>;
impl<A> SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
pub fn new() -> Self {
Self(ExtSmallString::new())
}
pub fn allocate(n: usize) -> Self {
Self(ExtSmallString::with_capacity(n))
}
}
impl<A, ST, DB> FromSql<ST, DB> for SmallString<A>
where
A: smallvec::Array<Item = u8>,
DB: Backend,
*const str: FromSql<ST, DB>,
{
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
let str_ptr = <*const str as FromSql<ST, DB>>::from_sql(bytes)?;
// We know that the pointer impl will never return null
let string = unsafe { &*str_ptr };
if string.len() <= A::size() {
Ok(SmallString(ExtSmallString::from_str(string)))
} else {
Err("String size exceeds bounds".into())
}
}
}
impl<A> Deref for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
type Target = ExtSmallString<A>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<A> DerefMut for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<A> AsRef<ExtSmallString<A>> for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
fn as_ref(&self) -> &ExtSmallString<A> {
&self.0
}
}
impl<A> AsMut<ExtSmallString<A>> for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
fn as_mut(&mut self) -> &mut ExtSmallString<A> {
&mut self.0
}
}
impl<A> From<ExtSmallString<A>> for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
fn from(ext: ExtSmallString<A>) -> Self {
Self(ext)
}
}
impl<A> fmt::Debug for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<A> fmt::Display for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<A> Serialize for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de, A> Deserialize<'de> for SmallString<A>
where
A: smallvec::Array<Item = u8>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Self(ExtSmallString::deserialize(deserializer)?))
}
fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
where
D: serde::Deserializer<'de>,
{
ExtSmallString::deserialize_in_place(deserializer, &mut place.0)?;
Ok(())
}
}
mod foreign_impls {
#[allow(dead_code)]
use super::*;
#[derive(FromSqlRow)]
#[diesel(foreign_derive)]
//#[sql_type = "Text"]
struct SmallStringProxy<A>(SmallString<A>)
where
A: smallvec::Array<Item = u8>;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment