2021-10-28 11:18:32 +02:00
use std ::collections ::BTreeSet ;
2021-06-14 16:58:38 +02:00
use std ::convert ::Infallible ;
2021-06-10 17:31:08 +02:00
use std ::error ::Error as StdError ;
2021-06-14 16:58:38 +02:00
use std ::{ fmt , io , str } ;
2021-06-09 17:05:46 +02:00
2021-06-16 18:33:33 +02:00
use heed ::{ Error as HeedError , MdbError } ;
2021-06-14 16:58:38 +02:00
use rayon ::ThreadPoolBuildError ;
2021-06-10 17:31:08 +02:00
use serde_json ::{ Map , Value } ;
2021-09-27 19:07:22 +02:00
use crate ::{ CriterionError , DocumentId , FieldId , SortError } ;
2021-06-10 15:55:22 +02:00
2021-06-10 17:31:08 +02:00
pub type Object = Map < String , Value > ;
2021-06-09 17:05:46 +02:00
2021-09-02 15:57:40 +02:00
pub fn is_reserved_keyword ( keyword : & str ) -> bool {
2021-09-20 17:21:02 +02:00
[ " _geo " , " _geoDistance " , " _geoPoint " , " _geoRadius " ] . contains ( & keyword )
2021-09-02 15:57:40 +02:00
}
2021-06-10 17:31:08 +02:00
#[ derive(Debug) ]
2021-06-09 17:05:46 +02:00
pub enum Error {
InternalError ( InternalError ) ,
IoError ( io ::Error ) ,
UserError ( UserError ) ,
}
2021-06-10 17:31:08 +02:00
#[ derive(Debug) ]
2021-06-09 17:05:46 +02:00
pub enum InternalError {
2021-06-14 16:58:38 +02:00
DatabaseClosing ,
2021-06-10 17:31:08 +02:00
DatabaseMissingEntry { db_name : & 'static str , key : Option < & 'static str > } ,
2021-06-09 17:05:46 +02:00
FieldIdMapMissingEntry ( FieldIdMapMissingEntry ) ,
2021-06-14 16:58:38 +02:00
Fst ( fst ::Error ) ,
GrenadInvalidCompressionType ,
2022-02-16 15:28:48 +01:00
GrenadInvalidFormatVersion ,
2021-06-10 17:31:08 +02:00
IndexingMergingKeys { process : & 'static str } ,
2021-06-10 15:55:22 +02:00
InvalidDatabaseTyping ,
2021-06-14 16:58:38 +02:00
RayonThreadPool ( ThreadPoolBuildError ) ,
SerdeJson ( serde_json ::Error ) ,
Serialization ( SerializationError ) ,
Store ( MdbError ) ,
Utf8 ( str ::Utf8Error ) ,
2021-06-10 15:55:22 +02:00
}
2021-06-10 17:31:08 +02:00
#[ derive(Debug) ]
2021-06-10 15:55:22 +02:00
pub enum SerializationError {
Decoding { db_name : Option < & 'static str > } ,
Encoding { db_name : Option < & 'static str > } ,
InvalidNumberSerialization ,
2021-06-09 17:05:46 +02:00
}
2021-06-10 17:31:08 +02:00
#[ derive(Debug) ]
2021-06-09 17:05:46 +02:00
pub enum FieldIdMapMissingEntry {
2021-06-15 11:10:50 +02:00
FieldId { field_id : FieldId , process : & 'static str } ,
FieldName { field_name : String , process : & 'static str } ,
2021-06-09 17:05:46 +02:00
}
2021-06-10 17:31:08 +02:00
#[ derive(Debug) ]
2021-06-09 17:05:46 +02:00
pub enum UserError {
2021-06-10 15:55:22 +02:00
AttributeLimitReached ,
2021-09-22 16:02:07 +02:00
CriterionError ( CriterionError ) ,
2021-06-10 15:55:22 +02:00
DocumentLimitReached ,
2021-06-10 17:31:08 +02:00
InvalidDocumentId { document_id : Value } ,
2021-10-28 11:18:32 +02:00
InvalidFacetsDistribution { invalid_facets_name : BTreeSet < String > } ,
2021-09-02 15:57:40 +02:00
InvalidGeoField { document_id : Value , object : Value } ,
2021-11-04 17:24:55 +01:00
InvalidFilter ( String ) ,
2021-10-28 11:18:32 +02:00
InvalidSortableAttribute { field : String , valid_fields : BTreeSet < String > } ,
2021-09-07 10:37:57 +02:00
SortRankingRuleMissing ,
2021-06-14 16:58:38 +02:00
InvalidStoreFile ,
2021-06-23 13:56:13 +02:00
MaxDatabaseSizeReached ,
2021-10-26 17:49:35 +02:00
MissingDocumentId { primary_key : String , document : Object } ,
2021-06-10 15:55:22 +02:00
MissingPrimaryKey ,
NoSpaceLeftOnDevice ,
2021-10-26 17:49:35 +02:00
PrimaryKeyCannotBeChanged ( String ) ,
2021-06-14 16:58:38 +02:00
SerdeJson ( serde_json ::Error ) ,
2021-09-27 19:07:22 +02:00
SortError ( SortError ) ,
2021-06-14 16:58:38 +02:00
UnknownInternalDocumentId { document_id : DocumentId } ,
2021-06-10 15:55:22 +02:00
}
impl From < io ::Error > for Error {
fn from ( error : io ::Error ) -> Error {
// TODO must be improved and more precise
Error ::IoError ( error )
}
}
2021-06-14 16:58:38 +02:00
impl From < fst ::Error > for Error {
fn from ( error : fst ::Error ) -> Error {
Error ::InternalError ( InternalError ::Fst ( error ) )
}
}
2021-06-16 18:33:33 +02:00
impl < E > From < grenad ::Error < E > > for Error
where
Error : From < E > ,
{
2021-06-14 16:58:38 +02:00
fn from ( error : grenad ::Error < E > ) -> Error {
match error {
grenad ::Error ::Io ( error ) = > Error ::IoError ( error ) ,
grenad ::Error ::Merge ( error ) = > Error ::from ( error ) ,
grenad ::Error ::InvalidCompressionType = > {
Error ::InternalError ( InternalError ::GrenadInvalidCompressionType )
2021-06-16 18:33:33 +02:00
}
2022-02-16 15:28:48 +01:00
grenad ::Error ::InvalidFormatVersion = > {
Error ::InternalError ( InternalError ::GrenadInvalidFormatVersion )
}
2021-06-14 16:58:38 +02:00
}
}
}
impl From < str ::Utf8Error > for Error {
fn from ( error : str ::Utf8Error ) -> Error {
Error ::InternalError ( InternalError ::Utf8 ( error ) )
}
}
impl From < Infallible > for Error {
fn from ( _error : Infallible ) -> Error {
unreachable! ( )
}
}
2021-06-10 15:55:22 +02:00
impl From < HeedError > for Error {
fn from ( error : HeedError ) -> Error {
use self ::Error ::* ;
use self ::InternalError ::* ;
use self ::SerializationError ::* ;
use self ::UserError ::* ;
2021-06-09 17:05:46 +02:00
2021-06-10 15:55:22 +02:00
match error {
HeedError ::Io ( error ) = > Error ::from ( error ) ,
2021-06-15 17:20:33 +02:00
HeedError ::Mdb ( MdbError ::MapFull ) = > UserError ( MaxDatabaseSizeReached ) ,
2021-06-10 15:55:22 +02:00
HeedError ::Mdb ( MdbError ::Invalid ) = > UserError ( InvalidStoreFile ) ,
2021-06-14 16:58:38 +02:00
HeedError ::Mdb ( error ) = > InternalError ( Store ( error ) ) ,
HeedError ::Encoding = > InternalError ( Serialization ( Encoding { db_name : None } ) ) ,
HeedError ::Decoding = > InternalError ( Serialization ( Decoding { db_name : None } ) ) ,
2021-06-10 15:55:22 +02:00
HeedError ::InvalidDatabaseTyping = > InternalError ( InvalidDatabaseTyping ) ,
HeedError ::DatabaseClosing = > InternalError ( DatabaseClosing ) ,
}
}
2021-06-09 17:05:46 +02:00
}
2021-06-10 17:31:08 +02:00
2021-06-14 16:58:38 +02:00
impl From < ThreadPoolBuildError > for Error {
fn from ( error : ThreadPoolBuildError ) -> Error {
Error ::InternalError ( InternalError ::RayonThreadPool ( error ) )
}
}
impl From < FieldIdMapMissingEntry > for Error {
fn from ( error : FieldIdMapMissingEntry ) -> Error {
Error ::InternalError ( InternalError ::FieldIdMapMissingEntry ( error ) )
}
}
impl From < InternalError > for Error {
fn from ( error : InternalError ) -> Error {
Error ::InternalError ( error )
}
}
impl From < UserError > for Error {
fn from ( error : UserError ) -> Error {
Error ::UserError ( error )
}
}
impl From < SerializationError > for Error {
fn from ( error : SerializationError ) -> Error {
Error ::InternalError ( InternalError ::Serialization ( error ) )
}
}
2021-06-10 17:31:08 +02:00
impl fmt ::Display for Error {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
match self {
2021-10-26 17:49:35 +02:00
Self ::InternalError ( error ) = > write! ( f , " internal: {}. " , error ) ,
2021-06-10 17:31:08 +02:00
Self ::IoError ( error ) = > error . fmt ( f ) ,
Self ::UserError ( error ) = > error . fmt ( f ) ,
}
}
}
impl StdError for Error { }
impl fmt ::Display for InternalError {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
match self {
Self ::DatabaseMissingEntry { db_name , key } = > {
2021-10-26 17:49:35 +02:00
write! ( f , " Missing {} in the {} database. " , key . unwrap_or ( " key " ) , db_name )
2021-06-16 18:33:33 +02:00
}
2021-06-10 17:31:08 +02:00
Self ::FieldIdMapMissingEntry ( error ) = > error . fmt ( f ) ,
2021-06-14 16:58:38 +02:00
Self ::Fst ( error ) = > error . fmt ( f ) ,
Self ::GrenadInvalidCompressionType = > {
2021-10-26 17:49:35 +02:00
f . write_str ( " Invalid compression type have been specified to grenad. " )
2021-06-16 18:33:33 +02:00
}
2022-02-16 15:28:48 +01:00
Self ::GrenadInvalidFormatVersion = > {
f . write_str ( " Invalid grenad file with an invalid version format. " )
}
2021-06-10 17:31:08 +02:00
Self ::IndexingMergingKeys { process } = > {
2021-10-26 17:49:35 +02:00
write! ( f , " Invalid merge while processing {}. " , process )
2021-06-16 18:33:33 +02:00
}
2021-06-14 16:58:38 +02:00
Self ::Serialization ( error ) = > error . fmt ( f ) ,
2021-06-10 17:31:08 +02:00
Self ::InvalidDatabaseTyping = > HeedError ::InvalidDatabaseTyping . fmt ( f ) ,
2021-06-14 16:58:38 +02:00
Self ::RayonThreadPool ( error ) = > error . fmt ( f ) ,
Self ::SerdeJson ( error ) = > error . fmt ( f ) ,
2021-06-10 17:31:08 +02:00
Self ::DatabaseClosing = > HeedError ::DatabaseClosing . fmt ( f ) ,
2021-06-14 16:58:38 +02:00
Self ::Store ( error ) = > error . fmt ( f ) ,
Self ::Utf8 ( error ) = > error . fmt ( f ) ,
2021-06-10 17:31:08 +02:00
}
}
}
impl StdError for InternalError { }
impl fmt ::Display for UserError {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
match self {
2021-11-06 16:34:30 +01:00
Self ::InvalidFilter ( error ) = > f . write_str ( error ) ,
2021-11-04 13:19:32 +01:00
Self ::AttributeLimitReached = > f . write_str ( " A document cannot contain more than 65,535 fields. " ) ,
2021-09-22 16:59:23 +02:00
Self ::CriterionError ( error ) = > write! ( f , " {} " , error ) ,
2021-10-26 17:49:35 +02:00
Self ::DocumentLimitReached = > f . write_str ( " Maximum number of documents reached. " ) ,
2021-06-23 13:56:13 +02:00
Self ::InvalidFacetsDistribution { invalid_facets_name } = > {
let name_list =
invalid_facets_name . iter ( ) . map ( AsRef ::as_ref ) . collect ::< Vec < _ > > ( ) . join ( " , " ) ;
write! (
f ,
2021-10-26 17:49:35 +02:00
" Invalid facet distribution, the fields `{}` are not set as filterable. " ,
2021-06-23 13:56:13 +02:00
name_list
)
}
2021-11-03 11:24:06 +01:00
Self ::InvalidGeoField { document_id , object } = > {
let document_id = match document_id {
Value ::String ( id ) = > id . clone ( ) ,
_ = > document_id . to_string ( ) ,
} ;
let object = match object {
Value ::String ( id ) = > id . clone ( ) ,
_ = > object . to_string ( ) ,
} ;
write! (
f ,
" The document with the id: `{}` contains an invalid _geo field: `{}`. " ,
document_id , object
)
} ,
2021-06-10 17:31:08 +02:00
Self ::InvalidDocumentId { document_id } = > {
2021-10-26 17:49:35 +02:00
let document_id = match document_id {
Value ::String ( id ) = > id . clone ( ) ,
_ = > document_id . to_string ( ) ,
} ;
2021-06-22 11:31:58 +02:00
write! (
f ,
2021-10-26 17:49:35 +02:00
" Document identifier `{}` is invalid. \
A document identifier can be of type integer or string , \
only composed of alphanumeric characters ( a - z A - Z 0 - 9 ) , hyphens ( - ) and underscores ( _ ) . " ,
document_id
2021-06-22 11:31:58 +02:00
)
2021-06-16 18:33:33 +02:00
}
2021-08-23 11:37:18 +02:00
Self ::InvalidSortableAttribute { field , valid_fields } = > {
let valid_names =
valid_fields . iter ( ) . map ( AsRef ::as_ref ) . collect ::< Vec < _ > > ( ) . join ( " , " ) ;
write! (
f ,
2021-10-26 17:49:35 +02:00
" Attribute `{}` is not sortable. Available sortable attributes are: `{}`. " ,
2021-08-23 11:37:18 +02:00
field , valid_names
)
}
2021-09-07 10:37:57 +02:00
Self ::SortRankingRuleMissing = > f . write_str (
2021-10-26 17:49:35 +02:00
" The sort ranking rule must be specified in the \
ranking rules settings to use the sort parameter at search time . " ,
2021-09-07 10:37:57 +02:00
) ,
2021-10-26 17:49:35 +02:00
Self ::MissingDocumentId { primary_key , document } = > {
2021-06-10 17:31:08 +02:00
let json = serde_json ::to_string ( document ) . unwrap ( ) ;
2021-10-26 17:49:35 +02:00
write! ( f , " Document doesn't have a `{}` attribute: `{}`. " , primary_key , json )
2021-06-16 18:33:33 +02:00
}
2021-11-04 13:19:32 +01:00
Self ::MissingPrimaryKey = > f . write_str ( " The primary key inference process failed because the engine did not find any fields containing `id` substring in their name. If your document identifier does not contain any `id` substring, you can set the primary key of the index. " ) ,
2021-11-03 11:24:06 +01:00
Self ::MaxDatabaseSizeReached = > f . write_str ( " Maximum database size has been reached. " ) ,
Self ::NoSpaceLeftOnDevice = > f . write_str ( " There is no more space left on the device. Consider increasing the size of the disk/partition. " ) ,
Self ::InvalidStoreFile = > f . write_str ( " The database file is in an invalid state. " ) ,
2021-10-26 17:49:35 +02:00
Self ::PrimaryKeyCannotBeChanged ( primary_key ) = > {
write! ( f , " Index already has a primary key: `{}`. " , primary_key )
2021-06-16 18:33:33 +02:00
}
2021-06-14 16:58:38 +02:00
Self ::SerdeJson ( error ) = > error . fmt ( f ) ,
2021-09-27 19:07:22 +02:00
Self ::SortError ( error ) = > write! ( f , " {} " , error ) ,
2021-06-14 16:58:38 +02:00
Self ::UnknownInternalDocumentId { document_id } = > {
2021-10-26 17:49:35 +02:00
write! ( f , " An unknown internal document id have been used: `{}`. " , document_id )
2021-06-16 18:33:33 +02:00
}
2021-06-10 17:31:08 +02:00
}
}
}
impl StdError for UserError { }
impl fmt ::Display for FieldIdMapMissingEntry {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
match self {
2021-06-15 11:10:50 +02:00
Self ::FieldId { field_id , process } = > {
write! ( f , " unknown field id {} coming from the {} process " , field_id , process )
2021-06-16 18:33:33 +02:00
}
2021-06-15 11:10:50 +02:00
Self ::FieldName { field_name , process } = > {
write! ( f , " unknown field name {} coming from the {} process " , field_name , process )
2021-06-16 18:33:33 +02:00
}
2021-06-10 17:31:08 +02:00
}
}
}
impl StdError for FieldIdMapMissingEntry { }
impl fmt ::Display for SerializationError {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
match self {
Self ::Decoding { db_name : Some ( name ) } = > {
write! ( f , " decoding from the {} database failed " , name )
2021-06-16 18:33:33 +02:00
}
2021-06-10 17:31:08 +02:00
Self ::Decoding { db_name : None } = > f . write_str ( " decoding failed " ) ,
Self ::Encoding { db_name : Some ( name ) } = > {
write! ( f , " encoding into the {} database failed " , name )
2021-06-16 18:33:33 +02:00
}
2021-06-10 17:31:08 +02:00
Self ::Encoding { db_name : None } = > f . write_str ( " encoding failed " ) ,
Self ::InvalidNumberSerialization = > f . write_str ( " number is not a valid finite number " ) ,
}
}
}
impl StdError for SerializationError { }