typesensei 0.2.0

Typesense client library
Documentation
use crate::schema::OwnedField;
use serde::{de::Visitor, Deserialize, Serialize};
use serde_with::skip_serializing_none;

pub mod alias;
pub mod collection;
pub mod documents;
pub mod keys;

#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CollectionResponse {
    pub name: String,
    pub num_documents: usize,
    pub fields: Vec<OwnedField>,
    pub default_sorting_field: String,
}

#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CollectionUpdate {
    pub fields: Vec<OwnedField>,
}

#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ImportResponse {
    pub success: bool,
    pub error: Option<String>,
    pub document: Option<String>,
}

#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MultiSearchResponse<T> {
    pub results: Vec<SearchResponse<T>>,
}

#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResponse<T> {
    pub facet_counts: Vec<usize>,
    pub found: usize,
    pub hits: Vec<SearchHit<T>>,
    pub out_of: usize,
    pub page: usize,
    pub request_params: SearchParams,
    pub search_cutoff: bool,
    pub search_time_ms: usize,
}

#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchHit<T> {
    pub document: T,
    pub highlights: Vec<SearchHighlight>,
    pub text_match: usize,
}

#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchHighlight {
    pub field: String,
    pub indices: Option<Vec<usize>>,
    pub matched_tokens: Vec<MatchedToken>,
    pub snippet: Option<String>,
    pub snippets: Option<Vec<String>>,
}

#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchParams {
    pub collection_name: String,
    pub per_page: usize,
    pub q: String,
}

#[derive(Debug, Clone)]
pub enum MatchedToken {
    Token(String),
    Tokens(Vec<String>),
}

impl MatchedToken {
    pub fn is_token(&self) -> bool {
        matches!(self, MatchedToken::Token(_))
    }

    pub fn is_tokens(&self) -> bool {
        matches!(self, MatchedToken::Tokens(_))
    }

    pub fn get_token(&self) -> Option<&String> {
        if let Self::Token(t) = self {
            Some(t)
        } else {
            None
        }
    }

    pub fn get_tokens(&self) -> Option<&Vec<String>> {
        if let Self::Tokens(t) = self {
            Some(t)
        } else {
            None
        }
    }

    pub fn take_token(self) -> Option<String> {
        if let Self::Token(t) = self {
            Some(t)
        } else {
            None
        }
    }

    pub fn take_tokens(self) -> Option<Vec<String>> {
        if let Self::Tokens(t) = self {
            Some(t)
        } else {
            None
        }
    }
}

impl Serialize for MatchedToken {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        match self {
            Self::Token(t) => t.serialize(serializer),
            Self::Tokens(t) => t.serialize(serializer),
        }
    }
}

impl<'de> Deserialize<'de> for MatchedToken {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        deserializer.deserialize_any(MatchedTokensVisitor)
    }
}

struct MatchedTokensVisitor;

impl<'de> Visitor<'de> for MatchedTokensVisitor {
    type Value = MatchedToken;

    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        formatter.write_str("string or sequence of strings")
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: serde::de::Error,
    {
        Ok(Self::Value::Token(v.to_owned()))
    }

    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
    where
        E: serde::de::Error,
    {
        Ok(Self::Value::Token(v))
    }

    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
    where
        A: serde::de::SeqAccess<'de>,
    {
        let mut ret = seq
            .size_hint()
            .map(|n| if n == 0 { 1 } else { n })
            .map(|n| Vec::with_capacity(n))
            .unwrap_or_default();

        while let Some(item) = seq.next_element()? {
            ret.push(item);
        }

        Ok(Self::Value::Tokens(ret))
    }
}