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}