1use std::fmt;
2use std::time::Duration;
3
4use crate::{Kind, SurrealValue, ToSql, Value};
5
6#[allow(missing_docs)]
12mod code {
13 pub const PARSE_ERROR: i64 = -32700;
14 pub const INVALID_REQUEST: i64 = -32600;
15 pub const METHOD_NOT_FOUND: i64 = -32601;
16 pub const METHOD_NOT_ALLOWED: i64 = -32602;
17 pub const INVALID_PARAMS: i64 = -32603;
18 pub const LIVE_QUERY_NOT_SUPPORTED: i64 = -32604;
19 pub const BAD_LIVE_QUERY_CONFIG: i64 = -32605;
20 pub const BAD_GRAPHQL_CONFIG: i64 = -32606;
21 pub const INTERNAL_ERROR: i64 = -32000;
22 pub const CLIENT_SIDE_ERROR: i64 = -32001;
23 pub const INVALID_AUTH: i64 = -32002;
24 pub const QUERY_NOT_EXECUTED: i64 = -32003;
25 pub const QUERY_TIMEDOUT: i64 = -32004;
26 pub const QUERY_CANCELLED: i64 = -32005;
27 pub const THROWN: i64 = -32006;
28 pub const SERIALIZATION_ERROR: i64 = -32007;
29 pub const DESERIALIZATION_ERROR: i64 = -32008;
30}
31
32fn default_code() -> i64 {
34 code::INTERNAL_ERROR
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, SurrealValue)]
53#[surreal(crate = "crate")]
54pub struct Error {
55 #[surreal(default = "default_code")]
57 code: i64,
58 message: String,
60 #[surreal(flatten)]
63 details: ErrorDetails,
64 #[surreal(default)]
67 cause: Option<Box<Error>>,
68}
69
70impl Error {
71 pub fn validation(message: String, details: impl Into<Option<ValidationError>>) -> Self {
75 let details = details.into();
76 let code = details
77 .as_ref()
78 .map(|d| match d {
79 ValidationError::Parse => code::PARSE_ERROR,
80 ValidationError::InvalidRequest => code::INVALID_REQUEST,
81 ValidationError::InvalidParams => code::INVALID_PARAMS,
82 ValidationError::NamespaceEmpty
83 | ValidationError::DatabaseEmpty
84 | ValidationError::InvalidParameter {
85 ..
86 }
87 | ValidationError::InvalidContent {
88 ..
89 }
90 | ValidationError::InvalidMerge {
91 ..
92 } => code::INVALID_REQUEST,
93 })
94 .unwrap_or(code::INTERNAL_ERROR);
95 Self {
96 message,
97 code,
98 details: ErrorDetails::Validation(details),
99 cause: None,
100 }
101 }
102
103 pub fn not_allowed(message: String, details: impl Into<Option<NotAllowedError>>) -> Self {
106 let details = details.into();
107 let code = details
108 .as_ref()
109 .map(|d| match d {
110 NotAllowedError::Auth(auth_error) => match auth_error {
111 AuthError::TokenExpired => code::INVALID_AUTH,
112 AuthError::SessionExpired => code::INTERNAL_ERROR,
113 AuthError::InvalidAuth
114 | AuthError::UnexpectedAuth
115 | AuthError::MissingUserOrPass
116 | AuthError::NoSigninTarget
117 | AuthError::InvalidPass
118 | AuthError::TokenMakingFailed
119 | AuthError::InvalidRole {
120 ..
121 }
122 | AuthError::NotAllowed {
123 ..
124 }
125 | AuthError::InvalidSignup => code::INVALID_AUTH,
126 },
127 NotAllowedError::Method {
128 ..
129 }
130 | NotAllowedError::Scripting
131 | NotAllowedError::Function {
132 ..
133 }
134 | NotAllowedError::Target {
135 ..
136 } => code::METHOD_NOT_ALLOWED,
137 })
138 .unwrap_or(code::INTERNAL_ERROR);
139 Self {
140 message,
141 code,
142 details: ErrorDetails::NotAllowed(details),
143 cause: None,
144 }
145 }
146
147 pub fn configuration(message: String, details: impl Into<Option<ConfigurationError>>) -> Self {
150 let details = details.into();
151 let code = details
152 .as_ref()
153 .map(|d| match d {
154 ConfigurationError::LiveQueryNotSupported => code::LIVE_QUERY_NOT_SUPPORTED,
155 ConfigurationError::BadLiveQueryConfig => code::BAD_LIVE_QUERY_CONFIG,
156 ConfigurationError::BadGraphqlConfig => code::BAD_GRAPHQL_CONFIG,
157 })
158 .unwrap_or(code::INTERNAL_ERROR);
159 Self {
160 message,
161 code,
162 details: ErrorDetails::Configuration(details),
163 cause: None,
164 }
165 }
166
167 pub fn thrown(message: String) -> Self {
169 Self {
170 message,
171 code: code::THROWN,
172 details: ErrorDetails::Thrown,
173 cause: None,
174 }
175 }
176
177 pub fn query(message: String, details: impl Into<Option<QueryError>>) -> Self {
180 let details = details.into();
181 let code = details
182 .as_ref()
183 .map(|d| match d {
184 QueryError::NotExecuted => code::QUERY_NOT_EXECUTED,
185 QueryError::TimedOut {
186 ..
187 } => code::QUERY_TIMEDOUT,
188 QueryError::Cancelled => code::QUERY_CANCELLED,
189 })
190 .unwrap_or(code::INTERNAL_ERROR);
191 Self {
192 message,
193 code,
194 details: ErrorDetails::Query(details),
195 cause: None,
196 }
197 }
198
199 pub fn serialization(message: String, details: impl Into<Option<SerializationError>>) -> Self {
202 let details = details.into();
203 let code = details
204 .as_ref()
205 .map(|d| match d {
206 SerializationError::Serialization => code::SERIALIZATION_ERROR,
207 SerializationError::Deserialization => code::DESERIALIZATION_ERROR,
208 })
209 .unwrap_or(code::INTERNAL_ERROR);
210 Self {
211 message,
212 code,
213 details: ErrorDetails::Serialization(details),
214 cause: None,
215 }
216 }
217
218 pub fn not_found(message: String, details: impl Into<Option<NotFoundError>>) -> Self {
222 let details = details.into();
223 let code = details
224 .as_ref()
225 .and_then(|d| match d {
226 NotFoundError::Method {
227 ..
228 } => Some(code::METHOD_NOT_FOUND),
229 _ => None,
230 })
231 .unwrap_or(code::INTERNAL_ERROR);
232 Self {
233 message,
234 code,
235 details: ErrorDetails::NotFound(details),
236 cause: None,
237 }
238 }
239
240 pub fn already_exists(message: String, details: impl Into<Option<AlreadyExistsError>>) -> Self {
242 let details = details.into();
243 Self {
244 message,
245 code: code::INTERNAL_ERROR,
246 details: ErrorDetails::AlreadyExists(details),
247 cause: None,
248 }
249 }
250
251 pub fn connection(message: String, details: impl Into<Option<ConnectionError>>) -> Self {
254 let details = details.into();
255 Self {
256 message,
257 code: code::CLIENT_SIDE_ERROR,
258 details: ErrorDetails::Connection(details),
259 cause: None,
260 }
261 }
262
263 pub fn internal(message: String) -> Self {
265 Self {
266 message,
267 code: code::INTERNAL_ERROR,
268 details: ErrorDetails::Internal,
269 cause: None,
270 }
271 }
272
273 #[doc(hidden)]
277 pub fn from_details(message: String, details: ErrorDetails) -> Self {
278 Self {
279 code: default_code(),
280 message,
281 details,
282 cause: None,
283 }
284 }
285
286 #[doc(hidden)]
289 pub fn from_details_with_cause(
290 message: String,
291 details: ErrorDetails,
292 cause: Option<Box<Error>>,
293 ) -> Self {
294 Self {
295 code: default_code(),
296 message,
297 details,
298 cause,
299 }
300 }
301
302 #[doc(hidden)]
306 pub fn from_parts(message: String, kind: Option<&str>, details: Option<Value>) -> Self {
307 let kind_str = kind.unwrap_or("Internal");
308 let typed_details = match details {
309 Some(v) => ErrorDetails::from_value_with_kind_str(kind_str, v)
310 .unwrap_or_else(|_| ErrorDetails::from_kind_str(kind_str)),
311 None => ErrorDetails::from_kind_str(kind_str),
312 };
313 Self {
314 code: default_code(),
315 message,
316 details: typed_details,
317 cause: None,
318 }
319 }
320
321 pub fn cause(&self) -> Option<&Error> {
323 self.cause.as_deref()
324 }
325
326 pub fn with_cause(mut self, cause: Error) -> Self {
328 self.cause = Some(Box::new(cause));
329 self
330 }
331
332 pub fn kind_str(&self) -> &'static str {
334 self.details.kind_str()
335 }
336
337 pub fn message(&self) -> &str {
339 &self.message
340 }
341
342 pub fn details(&self) -> &ErrorDetails {
344 &self.details
345 }
346
347 pub fn is_validation(&self) -> bool {
349 self.details.is_validation()
350 }
351
352 pub fn is_configuration(&self) -> bool {
354 self.details.is_configuration()
355 }
356
357 pub fn is_query(&self) -> bool {
359 self.details.is_query()
360 }
361
362 pub fn is_serialization(&self) -> bool {
364 self.details.is_serialization()
365 }
366
367 pub fn is_not_allowed(&self) -> bool {
369 self.details.is_not_allowed()
370 }
371
372 pub fn is_not_found(&self) -> bool {
374 self.details.is_not_found()
375 }
376
377 pub fn is_already_exists(&self) -> bool {
379 self.details.is_already_exists()
380 }
381
382 pub fn is_connection(&self) -> bool {
384 self.details.is_connection()
385 }
386
387 pub fn is_thrown(&self) -> bool {
389 self.details.is_thrown()
390 }
391
392 pub fn is_internal(&self) -> bool {
394 self.details.is_internal()
395 }
396
397 pub fn validation_details(&self) -> Option<&ValidationError> {
399 match &self.details {
400 ErrorDetails::Validation(d) => d.as_ref(),
401 _ => None,
402 }
403 }
404
405 pub fn not_allowed_details(&self) -> Option<&NotAllowedError> {
407 match &self.details {
408 ErrorDetails::NotAllowed(d) => d.as_ref(),
409 _ => None,
410 }
411 }
412
413 pub fn configuration_details(&self) -> Option<&ConfigurationError> {
416 match &self.details {
417 ErrorDetails::Configuration(d) => d.as_ref(),
418 _ => None,
419 }
420 }
421
422 pub fn serialization_details(&self) -> Option<&SerializationError> {
425 match &self.details {
426 ErrorDetails::Serialization(d) => d.as_ref(),
427 _ => None,
428 }
429 }
430
431 pub fn not_found_details(&self) -> Option<&NotFoundError> {
433 match &self.details {
434 ErrorDetails::NotFound(d) => d.as_ref(),
435 _ => None,
436 }
437 }
438
439 pub fn query_details(&self) -> Option<&QueryError> {
441 match &self.details {
442 ErrorDetails::Query(d) => d.as_ref(),
443 _ => None,
444 }
445 }
446
447 pub fn already_exists_details(&self) -> Option<&AlreadyExistsError> {
450 match &self.details {
451 ErrorDetails::AlreadyExists(d) => d.as_ref(),
452 _ => None,
453 }
454 }
455
456 pub fn connection_details(&self) -> Option<&ConnectionError> {
458 match &self.details {
459 ErrorDetails::Connection(d) => d.as_ref(),
460 _ => None,
461 }
462 }
463}
464
465#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
483#[non_exhaustive]
484#[surreal(crate = "crate")]
485#[surreal(tag = "kind", content = "details", skip_content_if = "Value::is_empty")]
486pub enum ErrorDetails {
487 Validation(Option<ValidationError>),
489 Configuration(Option<ConfigurationError>),
491 Query(Option<QueryError>),
493 Serialization(Option<SerializationError>),
495 NotAllowed(Option<NotAllowedError>),
497 NotFound(Option<NotFoundError>),
499 AlreadyExists(Option<AlreadyExistsError>),
501 Connection(Option<ConnectionError>),
503 Thrown,
505 #[surreal(other)]
508 Internal,
509}
510
511impl ErrorDetails {
512 pub fn kind_str(&self) -> &'static str {
514 match self {
515 Self::Validation(_) => "Validation",
516 Self::Configuration(_) => "Configuration",
517 Self::Query(_) => "Query",
518 Self::Serialization(_) => "Serialization",
519 Self::NotAllowed(_) => "NotAllowed",
520 Self::NotFound(_) => "NotFound",
521 Self::AlreadyExists(_) => "AlreadyExists",
522 Self::Connection(_) => "Connection",
523 Self::Thrown => "Thrown",
524 Self::Internal => "Internal",
525 }
526 }
527
528 pub fn is_validation(&self) -> bool {
530 matches!(self, Self::Validation(_))
531 }
532 pub fn is_configuration(&self) -> bool {
534 matches!(self, Self::Configuration(_))
535 }
536 pub fn is_query(&self) -> bool {
538 matches!(self, Self::Query(_))
539 }
540 pub fn is_serialization(&self) -> bool {
542 matches!(self, Self::Serialization(_))
543 }
544 pub fn is_not_allowed(&self) -> bool {
546 matches!(self, Self::NotAllowed(_))
547 }
548 pub fn is_not_found(&self) -> bool {
550 matches!(self, Self::NotFound(_))
551 }
552 pub fn is_already_exists(&self) -> bool {
554 matches!(self, Self::AlreadyExists(_))
555 }
556 pub fn is_connection(&self) -> bool {
558 matches!(self, Self::Connection(_))
559 }
560 pub fn is_thrown(&self) -> bool {
562 matches!(self, Self::Thrown)
563 }
564 pub fn is_internal(&self) -> bool {
566 matches!(self, Self::Internal)
567 }
568
569 pub(crate) fn from_kind_str(kind: &str) -> Self {
572 match kind {
573 "Validation" => Self::Validation(None),
574 "Configuration" => Self::Configuration(None),
575 "Query" => Self::Query(None),
576 "Serialization" => Self::Serialization(None),
577 "NotAllowed" => Self::NotAllowed(None),
578 "NotFound" => Self::NotFound(None),
579 "AlreadyExists" => Self::AlreadyExists(None),
580 "Connection" => Self::Connection(None),
581 "Thrown" => Self::Thrown,
582 _ => Self::Internal,
584 }
585 }
586
587 pub(crate) fn from_value_with_kind_str(kind: &str, value: Value) -> Result<Self, Error> {
590 match kind {
591 "Validation" => {
592 ValidationError::from_value(value).map(|v| ErrorDetails::Validation(Some(v)))
593 }
594 "Configuration" => {
595 ConfigurationError::from_value(value).map(|v| ErrorDetails::Configuration(Some(v)))
596 }
597 "Query" => QueryError::from_value(value).map(|v| ErrorDetails::Query(Some(v))),
598 "Serialization" => {
599 SerializationError::from_value(value).map(|v| ErrorDetails::Serialization(Some(v)))
600 }
601 "NotAllowed" => {
602 NotAllowedError::from_value(value).map(|v| ErrorDetails::NotAllowed(Some(v)))
603 }
604 "NotFound" => NotFoundError::from_value(value).map(|v| ErrorDetails::NotFound(Some(v))),
605 "AlreadyExists" => {
606 AlreadyExistsError::from_value(value).map(|v| ErrorDetails::AlreadyExists(Some(v)))
607 }
608 "Connection" => {
609 ConnectionError::from_value(value).map(|v| ErrorDetails::Connection(Some(v)))
610 }
611 "Thrown" => Ok(Self::Thrown),
612 _ => Ok(Self::Internal),
613 }
614 }
615
616 pub fn has_details(&self) -> bool {
618 match self {
619 Self::Validation(d) => d.is_some(),
620 Self::Configuration(d) => d.is_some(),
621 Self::Query(d) => d.is_some(),
622 Self::Serialization(d) => d.is_some(),
623 Self::NotAllowed(d) => d.is_some(),
624 Self::NotFound(d) => d.is_some(),
625 Self::AlreadyExists(d) => d.is_some(),
626 Self::Connection(d) => d.is_some(),
627 Self::Thrown | Self::Internal => false,
628 }
629 }
630}
631
632#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
638#[surreal(crate = "crate")]
639#[surreal(tag = "kind", content = "details")]
640#[non_exhaustive]
641pub enum AuthError {
642 #[surreal(skip_content)]
644 TokenExpired,
645 #[surreal(skip_content)]
647 SessionExpired,
648 #[surreal(skip_content)]
650 InvalidAuth,
651 #[surreal(skip_content)]
653 UnexpectedAuth,
654 #[surreal(skip_content)]
656 MissingUserOrPass,
657 #[surreal(skip_content)]
659 NoSigninTarget,
660 #[surreal(skip_content)]
662 InvalidPass,
663 #[surreal(skip_content)]
665 TokenMakingFailed,
666 #[surreal(skip_content)]
668 InvalidSignup,
669 InvalidRole {
671 name: String,
673 },
674 NotAllowed {
676 actor: String,
678 action: String,
680 resource: String,
682 },
683}
684
685impl From<AuthError> for Option<NotAllowedError> {
686 fn from(auth_error: AuthError) -> Self {
687 Some(NotAllowedError::Auth(auth_error))
688 }
689}
690
691#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
693#[surreal(crate = "crate")]
694#[surreal(tag = "kind", content = "details")]
695#[non_exhaustive]
696pub enum ValidationError {
697 #[surreal(skip_content)]
699 Parse,
700 #[surreal(skip_content)]
702 InvalidRequest,
703 #[surreal(skip_content)]
705 InvalidParams,
706 #[surreal(skip_content)]
708 NamespaceEmpty,
709 #[surreal(skip_content)]
711 DatabaseEmpty,
712 InvalidParameter {
714 name: String,
716 },
717 InvalidContent {
719 value: String,
721 },
722 InvalidMerge {
724 value: String,
726 },
727}
728
729#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
731#[surreal(crate = "crate")]
732#[surreal(tag = "kind", content = "details")]
733#[non_exhaustive]
734pub enum NotAllowedError {
735 #[surreal(skip_content)]
737 Scripting,
738 Auth(AuthError),
740 Method {
742 name: String,
744 },
745 Function {
747 name: String,
749 },
750 Target {
752 name: String,
754 },
755}
756
757#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
759#[surreal(crate = "crate")]
760#[surreal(tag = "kind", skip_content)]
761#[non_exhaustive]
762pub enum ConfigurationError {
763 LiveQueryNotSupported,
765 BadLiveQueryConfig,
767 BadGraphqlConfig,
769}
770
771#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
773#[surreal(crate = "crate")]
774#[surreal(tag = "kind", skip_content)]
775#[non_exhaustive]
776pub enum SerializationError {
777 Serialization,
779 Deserialization,
781}
782
783#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
785#[surreal(crate = "crate")]
786#[surreal(tag = "kind", content = "details")]
787#[non_exhaustive]
788pub enum NotFoundError {
789 Method {
791 name: String,
793 },
794 Session {
796 id: Option<String>,
798 },
799 Table {
801 name: String,
803 },
804 Record {
806 id: String,
808 },
809 Namespace {
811 name: String,
813 },
814 Database {
816 name: String,
818 },
819 #[surreal(skip_content)]
821 Transaction,
822}
823
824#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
826#[surreal(crate = "crate")]
827#[surreal(tag = "kind", content = "details")]
828#[non_exhaustive]
829pub enum QueryError {
830 #[surreal(skip_content)]
832 NotExecuted,
833 TimedOut {
835 duration: Duration,
837 },
838 #[surreal(skip_content)]
840 Cancelled,
841}
842
843#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
845#[surreal(crate = "crate")]
846#[surreal(tag = "kind", content = "details")]
847#[non_exhaustive]
848pub enum AlreadyExistsError {
849 Session {
851 id: String,
853 },
854 Table {
856 name: String,
858 },
859 Record {
861 id: String,
863 },
864 Namespace {
866 name: String,
868 },
869 Database {
871 name: String,
873 },
874}
875
876#[derive(Clone, Debug, PartialEq, Eq, SurrealValue)]
879#[surreal(crate = "crate")]
880#[surreal(tag = "kind", skip_content)]
881#[non_exhaustive]
882pub enum ConnectionError {
883 Uninitialised,
885 AlreadyConnected,
887}
888
889impl fmt::Display for Error {
890 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
891 write!(f, "{}", self.message)
892 }
893}
894
895impl std::error::Error for Error {
896 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
897 self.cause.as_deref().map(|e| e as &(dyn std::error::Error + 'static))
898 }
899}
900
901#[derive(Debug, Clone)]
907#[non_exhaustive]
908pub enum TypeError {
909 Conversion(ConversionError),
911 OutOfRange(OutOfRangeError),
913 LengthMismatch(LengthMismatchError),
915 Invalid(String),
917}
918
919#[derive(Debug, Clone)]
921#[non_exhaustive]
922pub struct ConversionError {
923 pub expected: Kind,
925 pub actual: Kind,
927 pub context: Option<String>,
929}
930
931#[derive(Debug, Clone)]
933#[non_exhaustive]
934pub struct OutOfRangeError {
935 pub value: String,
937 pub target_type: String,
939 pub context: Option<String>,
941}
942
943#[derive(Debug, Clone)]
945#[non_exhaustive]
946pub struct LengthMismatchError {
947 pub expected: usize,
949 pub actual: usize,
951 pub target_type: String,
953}
954
955impl ConversionError {
956 pub fn new(expected: Kind, actual: Kind) -> Self {
958 Self {
959 expected,
960 actual,
961 context: None,
962 }
963 }
964
965 pub fn from_value(expected: Kind, value: &Value) -> Self {
967 Self {
968 expected,
969 actual: value.kind(),
970 context: None,
971 }
972 }
973
974 pub fn with_context(mut self, context: impl Into<String>) -> Self {
976 self.context = Some(context.into());
977 self
978 }
979}
980
981impl OutOfRangeError {
982 pub fn new(value: impl fmt::Display, target_type: impl Into<String>) -> Self {
984 Self {
985 value: value.to_string(),
986 target_type: target_type.into(),
987 context: None,
988 }
989 }
990
991 pub fn with_context(mut self, context: impl Into<String>) -> Self {
993 self.context = Some(context.into());
994 self
995 }
996}
997
998impl LengthMismatchError {
999 pub fn new(expected: usize, actual: usize, target_type: impl Into<String>) -> Self {
1001 Self {
1002 expected,
1003 actual,
1004 target_type: target_type.into(),
1005 }
1006 }
1007}
1008
1009impl fmt::Display for TypeError {
1010 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1011 match self {
1012 TypeError::Conversion(e) => write!(f, "{e}"),
1013 TypeError::OutOfRange(e) => write!(f, "{e}"),
1014 TypeError::LengthMismatch(e) => write!(f, "{e}"),
1015 TypeError::Invalid(e) => write!(f, "Invalid: {e}"),
1016 }
1017 }
1018}
1019
1020impl fmt::Display for ConversionError {
1021 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1022 write!(f, "Expected {}, got {}", self.expected.to_sql(), self.actual.to_sql())?;
1023 if let Some(context) = &self.context {
1024 write!(f, " ({})", context)?;
1025 }
1026 Ok(())
1027 }
1028}
1029
1030impl fmt::Display for OutOfRangeError {
1031 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1032 write!(f, "Value {} is out of range for type {}", self.value, self.target_type)?;
1033 if let Some(context) = &self.context {
1034 write!(f, " ({})", context)?;
1035 }
1036 Ok(())
1037 }
1038}
1039
1040impl fmt::Display for LengthMismatchError {
1041 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1042 write!(
1043 f,
1044 "Length mismatch for {}: expected {}, got {}",
1045 self.target_type, self.expected, self.actual
1046 )
1047 }
1048}
1049
1050impl std::error::Error for TypeError {}
1051impl std::error::Error for ConversionError {}
1052impl std::error::Error for OutOfRangeError {}
1053impl std::error::Error for LengthMismatchError {}
1054
1055impl From<ConversionError> for Error {
1056 fn from(e: ConversionError) -> Self {
1057 Error::internal(e.to_string())
1058 }
1059}
1060
1061impl From<OutOfRangeError> for Error {
1062 fn from(e: OutOfRangeError) -> Self {
1063 Error::internal(e.to_string())
1064 }
1065}
1066
1067impl From<LengthMismatchError> for Error {
1068 fn from(e: LengthMismatchError) -> Self {
1069 Error::internal(e.to_string())
1070 }
1071}
1072
1073impl From<TypeError> for Error {
1074 fn from(e: TypeError) -> Self {
1075 Error::internal(e.to_string())
1076 }
1077}
1078
1079pub fn conversion_error(expected: Kind, value: impl Into<Value>) -> Error {
1081 let value = value.into();
1082 ConversionError::from_value(expected, &value).into()
1083}
1084
1085pub fn out_of_range_error(value: impl fmt::Display, target_type: impl Into<String>) -> Error {
1087 OutOfRangeError::new(value, target_type).into()
1088}
1089
1090pub fn length_mismatch_error(
1092 expected: usize,
1093 actual: usize,
1094 target_type: impl Into<String>,
1095) -> Error {
1096 LengthMismatchError::new(expected, actual, target_type).into()
1097}
1098
1099pub fn union_conversion_error(expected: Kind, value: impl Into<Value>) -> Error {
1102 let value = value.into();
1103 ConversionError::from_value(expected, &value)
1104 .with_context("Value does not match any variant in union type")
1105 .into()
1106}