criware_utf_core/lib.rs
1//! The core mechanisms offered by `criware-utf`.
2//!
3//! Please do not use this on its own. Use the full `criware-utf` crate.
4//!
5
6use thiserror::Error;
7
8mod packet;
9mod reader;
10mod schema;
11mod table;
12mod value;
13mod writer;
14
15pub use crate::packet::Packet;
16pub use crate::reader::Reader;
17pub use crate::schema::{ColumnStorageFormat, Schema, SchemaColumn};
18pub use crate::table::Table;
19pub use crate::value::{Primitive, Value, ValueKind, utf_size_of};
20pub use crate::writer::{WriteContext, Writer};
21
22/// Error returned when reading or writing a table fails
23///
24#[derive(Debug, Error)]
25pub enum Error {
26 ///
27 /// If a data blob is not the correct size
28 ///
29 /// This is only used in the implementation of [`Value`] for `[u8; N]`
30 ///
31 #[error("wrong size")]
32 BlobWrongSize,
33 ///
34 /// If a string or data blob is unable to be read from a table
35 ///
36 /// This means the table is malformed
37 ///
38 #[error("string/blob not found")]
39 DataNotFound,
40 ///
41 /// If a UTF packet is unable to be decrypted
42 ///
43 /// This means the table's data is malformed
44 ///
45 #[error("unable to decrypt UTF packet")]
46 DecryptionError,
47 ///
48 /// If the entire content of the table is unable to be read from a stream
49 ///
50 #[error("reached end of file early (at {0})")]
51 EOF(String),
52 ///
53 /// If the flag associated with the column's storage method is invalid
54 /// (table is malformed)
55 ///
56 #[error("invalid column storage flag: 0x{0:02}")]
57 InvalidColumnStorage(u8),
58 ///
59 /// If the flag associated with the column's data type is invalid
60 /// (table is malformed)
61 ///
62 #[error("invalid column type flag: 0x{0:02}")]
63 InvalidColumnType(u8),
64 ///
65 /// If an I/O error happens
66 ///
67 /// This does not include end-of-file errors. There's a variant for that
68 /// specifically.
69 ///
70 #[error("i/o error: {0}")]
71 IOError(std::io::Error),
72 ///
73 /// Generic error for any malformed data in the header of a table
74 ///
75 #[error("malformed header")]
76 MalformedHeader,
77 ///
78 /// If a string stored in a table is unable to be decoded
79 ///
80 #[error("error when decoding utf8 string: {0}")]
81 StringMalformed(std::str::Utf8Error),
82 ///
83 /// Occurs when writing
84 ///
85 /// For a rowed optional value, the value in each row must ALL either be
86 /// `Some` or `None`. If this condition is violated, this error is
87 /// returned.
88 ///
89 #[error("optional column conflict: \"{0}\" (values must be all Some or all None)")]
90 OptionalColumnConflict(&'static str),
91 ///
92 /// If a conversion from a primitive to another value (or vice versa) fails
93 ///
94 #[error("failed to convert {0} to {1}: {2}")]
95 ValueConversion(&'static str, &'static str, Box<dyn std::error::Error>),
96 ///
97 /// If the name of a column is not what was expected
98 ///
99 /// This indicates the table doesn't follow the expected schema. The table
100 /// may still be perfectly valid.
101 ///
102 #[error("wrong column name: \"{0}\" (expected \"{1}\"")]
103 WrongColumnName(String, &'static str),
104 ///
105 /// If the type of data stored in a column is not what was expected.
106 ///
107 /// This indicates the table doesn't follow the expected schema. The table
108 /// may still be perfectly valid.
109 ///
110 #[error("wrong column type flag: 0x{0:02} (expected 0x{1:02})")]
111 WrongColumnType(u8, u8),
112 ///
113 /// If the method a column stores data is not what was expected
114 ///
115 /// This indicates the table doesn't follow the expected schema. The table
116 /// may still be perfectly valid.
117 ///
118 #[error("wrong column storage flag: 0x{0:02} (expected {1})")]
119 WrongColumnStorage(u8, &'static str),
120 ///
121 /// Generic error for a table not following a schema. The table may still
122 /// be valid.
123 ///
124 #[error("wrong table schema")]
125 WrongTableSchema,
126}
127
128/// A typedef of the result returned by much of the crate.
129///
130pub type Result<T> = std::result::Result<T, Error>;
131
132pub(crate) trait IOErrorHelper<T> {
133 fn io(self, message: &str) -> Result<T>;
134}
135impl IOErrorHelper<()> for std::io::Result<()> {
136 fn io(self, message: &str) -> Result<()> {
137 match self {
138 Ok(value) => Ok(value),
139 Err(error) => match error.kind() {
140 std::io::ErrorKind::UnexpectedEof => {
141 return Err(Error::EOF(message.to_owned()));
142 }
143 _ => return Err(Error::IOError(error)),
144 },
145 }
146 }
147}