Skip to content

Commit

Permalink
error: improve error variants
Browse files Browse the repository at this point in the history
  • Loading branch information
erikgrinaker committed Jun 2, 2024
1 parent cad5c84 commit 2a285ca
Show file tree
Hide file tree
Showing 206 changed files with 690 additions and 719 deletions.
7 changes: 4 additions & 3 deletions src/bin/toydb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

use serde_derive::Deserialize;
use std::collections::HashMap;
use toydb::error::{Error, Result};
use toydb::errinput;
use toydb::error::Result;
use toydb::raft;
use toydb::sql;
use toydb::storage;
Expand Down Expand Up @@ -43,7 +44,7 @@ fn main() -> Result<()> {
COMPACT_MIN_BYTES,
)?)?,
"memory" => raft::Log::new(storage::Memory::new())?,
name => return Err(Error::Config(format!("Unknown Raft storage engine {}", name))),
name => return errinput!("invalid Raft storage engine {name}"),
};
let raft_state: Box<dyn raft::State> = match cfg.storage_sql.as_str() {
"bitcask" | "" => {
Expand All @@ -58,7 +59,7 @@ fn main() -> Result<()> {
let engine = storage::Memory::new();
Box::new(sql::engine::Raft::new_state(engine)?)
}
name => return Err(Error::Config(format!("Unknown SQL storage engine {}", name))),
name => return errinput!("invalid SQL storage engine {name}"),
};

Server::new(cfg.id, cfg.peers, raft_log, raft_state)?.serve(&cfg.listen_raft, &cfg.listen_sql)
Expand Down
7 changes: 4 additions & 3 deletions src/bin/toydump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
//! human-readable form. It only prints live BitCask data, not garbage entries.
#![warn(clippy::all)]

use toydb::error::{Error, Result};
use toydb::errdata;
use toydb::error::Result;
use toydb::storage::debug;
use toydb::storage::{BitCask, Engine};

Expand All @@ -17,9 +18,9 @@ fn main() -> Result<()> {
let mut scan = engine.scan(..);
while let Some((key, value)) = scan.next().transpose()? {
let (fkey, Some(fvalue)) = debug::format_key_value(&key, &Some(value)) else {
return Err(Error::Internal(format!("Unexpected missing value at key {:?}", key)));
return errdata!("unexpected missing value at key {:?}", key);
};
println!("{} → {}", fkey, fvalue);
println!("{fkey} → {fvalue}");
}
Ok(())
}
17 changes: 8 additions & 9 deletions src/bin/toysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use rustyline::history::DefaultHistory;
use rustyline::validate::{ValidationContext, ValidationResult, Validator};
use rustyline::{error::ReadlineError, Editor, Modifiers};
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};
use toydb::errinput;
use toydb::error::{Error, Result};
use toydb::sql::execution::ResultSet;
use toydb::sql::parser::{Lexer, Token};
Expand Down Expand Up @@ -78,12 +79,12 @@ impl ToySQL {
/// Handles a REPL command (prefixed by !, e.g. !help)
fn execute_command(&mut self, input: &str) -> Result<()> {
let mut input = input.split_ascii_whitespace();
let command = input.next().ok_or_else(|| Error::Parse("Expected command.".to_string()))?;
let command = input.next().ok_or::<Error>(errinput!("expected command"))?;

let getargs = |n| {
let args: Vec<&str> = input.collect();
if args.len() != n {
Err(Error::Parse(format!("{}: expected {} args, got {}", command, n, args.len())))
errinput!("{command}: expected {n} args, got {}", args.len())
} else {
Ok(args)
}
Expand All @@ -99,7 +100,7 @@ impl ToySQL {
self.show_headers = false;
println!("Headers disabled");
}
v => return Err(Error::Parse(format!("Invalid value {}, expected on or off", v))),
v => return errinput!("invalid value {v}, expected on or off"),
},
"!help" => println!(
r#"
Expand Down Expand Up @@ -172,7 +173,7 @@ Storage: {keys} keys, {logical_size} MB logical, {nodes}x {disk_size} MB disk,
println!("{}", table)
}
}
c => return Err(Error::Parse(format!("Unknown command {}", c))),
c => return errinput!("unknown command {c}"),
}
Ok(())
}
Expand Down Expand Up @@ -254,11 +255,9 @@ Storage: {keys} keys, {logical_size} MB logical, {nodes}x {disk_size} MB disk,
println!("Connected to toyDB node \"{}\". Enter !help for instructions.", status.server);

while let Some(input) = self.prompt()? {
match self.execute(&input) {
Ok(()) => {}
error @ Err(Error::Internal(_)) => return error,
Err(error) => println!("Error: {}", error),
}
if let Err(error) = self.execute(&input) {
println!("Error: {error}");
};
}

if let Some(path) = &self.history_path {
Expand Down
13 changes: 6 additions & 7 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::io::Write as _;

use crate::encoding::Value as _;
use crate::errdata;
use crate::error::{Error, Result};
use crate::server::{Request, Response, Status};
use crate::sql::execution::ResultSet;
Expand Down Expand Up @@ -35,7 +36,7 @@ impl Client {
pub fn execute(&mut self, query: &str) -> Result<ResultSet> {
let mut resultset = match self.call(Request::Execute(query.into()))? {
Response::Execute(rs) => rs,
resp => return Err(Error::Internal(format!("Unexpected response {:?}", resp))),
response => return errdata!("unexpected response {response:?}"),
};
if let ResultSet::Query { columns, .. } = resultset {
// FIXME We buffer rows for now to avoid lifetime hassles
Expand All @@ -44,9 +45,7 @@ impl Client {
match Result::<Response>::decode_from(&mut self.reader)?? {
Response::Row(Some(row)) => rows.push(row),
Response::Row(None) => break,
response => {
return Err(Error::Internal(format!("Unexpected response {:?}", response)))
}
response => return errdata!("unexpected response {response:?}"),
}
}
resultset = ResultSet::Query { columns, rows: Box::new(rows.into_iter().map(Ok)) }
Expand All @@ -64,23 +63,23 @@ impl Client {
pub fn get_table(&mut self, table: &str) -> Result<Table> {
match self.call(Request::GetTable(table.into()))? {
Response::GetTable(t) => Ok(t),
resp => Err(Error::Value(format!("Unexpected response: {:?}", resp))),
resp => errdata!("unexpected response: {resp:?}"),
}
}

/// Lists database tables
pub fn list_tables(&mut self) -> Result<Vec<String>> {
match self.call(Request::ListTables)? {
Response::ListTables(t) => Ok(t),
resp => Err(Error::Value(format!("Unexpected response: {:?}", resp))),
resp => errdata!("unexpected response: {resp:?}"),
}
}

/// Checks server status
pub fn status(&mut self) -> Result<Status> {
match self.call(Request::Status)? {
Response::Status(s) => Ok(s),
resp => Err(Error::Value(format!("Unexpected response: {:?}", resp))),
resp => errdata!("unexpected response: {resp:?}"),
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/encoding/bincode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use crate::error::{Error, Result};

use bincode::Options;
use bincode::Options as _;

/// Returns the default Bincode options, initialized on first use.
fn bincode() -> &'static bincode::DefaultOptions {
Expand Down
22 changes: 10 additions & 12 deletions src/encoding/keycode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ use de::IntoDeserializer;
use serde::{de, ser};

use crate::error::{Error, Result};
use crate::{errassert, errdata};

// Serializes a key to a binary KeyCode representation.
pub fn serialize<T: serde::Serialize>(key: &T) -> Result<Vec<u8>> {
Expand All @@ -61,10 +62,10 @@ pub fn deserialize<'a, T: serde::Deserialize<'a>>(input: &'a [u8]) -> Result<T>
let mut deserializer = Deserializer::from_bytes(input);
let t = T::deserialize(&mut deserializer)?;
if !deserializer.input.is_empty() {
return Err(Error::Internal(format!(
"Unexpected trailing bytes {:x?} at end of key {:x?}",
deserializer.input, input
)));
return errdata!(
"unexpected trailing bytes {:x?} at end of key {input:x?}",
deserializer.input,
);
}
Ok(t)
}
Expand Down Expand Up @@ -329,10 +330,7 @@ impl<'de> Deserializer<'de> {
// there aren't enough bytes left.
fn take_bytes(&mut self, len: usize) -> Result<&[u8]> {
if self.input.len() < len {
return Err(Error::Internal(format!(
"Insufficient bytes, expected {} bytes for {:x?}",
len, self.input
)));
return errdata!("insufficient bytes, expected {len} bytes for {:x?}", self.input);
}
let bytes = &self.input[..len];
self.input = &self.input[len..];
Expand All @@ -351,10 +349,10 @@ impl<'de> Deserializer<'de> {
Some((_, 0x00)) => match iter.next() {
Some((i, 0x00)) => break i + 1, // terminator
Some((_, 0xff)) => decoded.push(0x00), // escaped 0x00
_ => return Err(Error::Value("Invalid escape sequence".to_string())),
_ => return errdata!("invalid escape sequence"),
},
Some((_, b)) => decoded.push(*b),
None => return Err(Error::Value("Unexpected end of input".to_string())),
None => return errdata!("unexpected end of input"),
}
};
self.input = &self.input[taken..];
Expand All @@ -367,14 +365,14 @@ impl<'de, 'a> serde::Deserializer<'de> for &'a mut Deserializer<'de> {
type Error = Error;

fn deserialize_any<V: de::Visitor<'de>>(self, _: V) -> Result<V::Value> {
Err(Error::Internal("Must provide type, KeyCode is not self-describing".to_string()))
errassert!("must provide type, KeyCode is not self-describing")
}

fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
visitor.visit_bool(match self.take_bytes(1)?[0] {
0x00 => false,
0x01 => true,
b => return Err(Error::Internal(format!("Invalid boolean value {:?}", b))),
b => return errdata!("Invalid boolean value {b:?}"),
})
}

Expand Down
Loading

0 comments on commit 2a285ca

Please sign in to comment.