mirror of
https://github.com/mikedilger/chorus.git
synced 2026-05-03 06:51:42 +00:00
MAJOR error rewrite to track file/line
This commit is contained in:
parent
612ddb0ab3
commit
fef0d7a542
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -152,7 +152,6 @@ dependencies = [
|
|||||||
"secp256k1",
|
"secp256k1",
|
||||||
"serde",
|
"serde",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -20,7 +20,6 @@ ron = "0.8"
|
|||||||
rustls-pemfile = "1.0"
|
rustls-pemfile = "1.0"
|
||||||
secp256k1 = { version = "0.28", features = [ "hashes", "global-context", "rand-std" ] }
|
secp256k1 = { version = "0.28", features = [ "hashes", "global-context", "rand-std" ] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
thiserror = "1.0"
|
|
||||||
tokio = { version = "1", features = [ "full" ] }
|
tokio = { version = "1", features = [ "full" ] }
|
||||||
tokio-rustls = "0.24"
|
tokio-rustls = "0.24"
|
||||||
|
|
||||||
|
|||||||
286
src/error.rs
286
src/error.rs
@ -1,112 +1,308 @@
|
|||||||
use thiserror::Error;
|
use std::error::Error as StdError;
|
||||||
|
use std::panic::Location;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Error {
|
||||||
|
pub inner: ChorusError,
|
||||||
|
location: &'static Location<'static>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StdError for Error {
|
||||||
|
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||||
|
Some(&self.inner)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}, {}", self.inner, self.location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Errors that can occur in the chorus crate
|
/// Errors that can occur in the chorus crate
|
||||||
#[derive(Error, Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum ChorusError {
|
||||||
// Bad event id
|
// Bad event id
|
||||||
#[error("Bad event id, does not match hash")]
|
|
||||||
BadEventId,
|
BadEventId,
|
||||||
|
|
||||||
// Bad hex input
|
// Bad hex input
|
||||||
#[error("Bad hex input")]
|
|
||||||
BadHexInput,
|
BadHexInput,
|
||||||
|
|
||||||
// Output buffer too small
|
// Output buffer too small
|
||||||
#[error("Output buffer too small")]
|
|
||||||
BufferTooSmall,
|
BufferTooSmall,
|
||||||
|
|
||||||
// Channel Recv
|
// Channel Recv
|
||||||
#[error("Channel receive: {0}")]
|
ChannelRecv(tokio::sync::broadcast::error::RecvError),
|
||||||
ChannelRecv(#[from] tokio::sync::broadcast::error::RecvError),
|
|
||||||
|
|
||||||
// Channel Send
|
// Channel Send
|
||||||
#[error("Channel send: {0}")]
|
ChannelSend(tokio::sync::broadcast::error::SendError<usize>),
|
||||||
ChannelSend(#[from] tokio::sync::broadcast::error::SendError<usize>),
|
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
#[error("Config: {0}")]
|
Config(ron::error::SpannedError),
|
||||||
Config(#[from] ron::error::SpannedError),
|
|
||||||
|
|
||||||
// Crypto
|
// Crypto
|
||||||
#[error("Crypto: {0}")]
|
Crypto(secp256k1::Error),
|
||||||
Crypto(#[from] secp256k1::Error),
|
|
||||||
|
|
||||||
// Duplicate event
|
// Duplicate event
|
||||||
#[error("Duplicate")]
|
|
||||||
Duplicate,
|
Duplicate,
|
||||||
|
|
||||||
// End of Input
|
// End of Input
|
||||||
#[error("End of input")]
|
|
||||||
EndOfInput,
|
EndOfInput,
|
||||||
|
|
||||||
// Http
|
// Http
|
||||||
#[error("HTTP: {0}")]
|
Http(hyper::http::Error),
|
||||||
Http(#[from] hyper::http::Error),
|
|
||||||
|
|
||||||
// Hyper
|
// Hyper
|
||||||
#[error("Hyper: {0}")]
|
Hyper(hyper::Error),
|
||||||
Hyper(#[from] hyper::Error),
|
|
||||||
|
|
||||||
// I/O Error
|
// I/O
|
||||||
#[error("I/O: {0}")]
|
Io(std::io::Error),
|
||||||
Io(#[from] std::io::Error),
|
|
||||||
|
|
||||||
// JSON Bad (general)
|
// JSON Bad (general)
|
||||||
#[error("JSON bad: {0} at position {1}")]
|
|
||||||
JsonBad(&'static str, usize),
|
JsonBad(&'static str, usize),
|
||||||
|
|
||||||
// JSON Bad Character
|
// JSON Bad Character
|
||||||
#[error("JSON bad character: {0} at position {1}, {2} was expected")]
|
|
||||||
JsonBadCharacter(char, usize, char),
|
JsonBadCharacter(char, usize, char),
|
||||||
|
|
||||||
// JSON Bad Event
|
// JSON Bad Event
|
||||||
#[error("JSON bad event: {0} at position {1}")]
|
|
||||||
JsonBadEvent(&'static str, usize),
|
JsonBadEvent(&'static str, usize),
|
||||||
|
|
||||||
// JSON Bad Filter
|
// JSON Bad Filter
|
||||||
#[error("JSON bad filter: {0} at position {1}")]
|
|
||||||
JsonBadFilter(&'static str, usize),
|
JsonBadFilter(&'static str, usize),
|
||||||
|
|
||||||
// JSON Bad String Character
|
// JSON Bad String Character
|
||||||
#[error("JSON string bad character: codepoint {0}")]
|
|
||||||
JsonBadStringChar(u32),
|
JsonBadStringChar(u32),
|
||||||
|
|
||||||
// JSON Escape
|
// JSON Escape
|
||||||
#[error("JSON string escape error")]
|
|
||||||
JsonEscape,
|
JsonEscape,
|
||||||
|
|
||||||
// JSON Escape Surrogate
|
// JSON Escape Surrogate
|
||||||
#[error("JSON string escape surrogate (ancient style) is not supported")]
|
|
||||||
JsonEscapeSurrogate,
|
JsonEscapeSurrogate,
|
||||||
|
|
||||||
// LMDB
|
// LMDB
|
||||||
#[error("LMDB: {0}")]
|
Lmdb(heed::Error),
|
||||||
Lmdb(#[from] heed::Error),
|
|
||||||
|
|
||||||
#[error("Private Key Not Found")]
|
// No private key
|
||||||
NoPrivateKey,
|
NoPrivateKey,
|
||||||
|
|
||||||
// Rustls
|
// Rustls
|
||||||
#[error("TLS: {0}")]
|
Rustls(tokio_rustls::rustls::Error),
|
||||||
Rustls(#[from] tokio_rustls::rustls::Error),
|
|
||||||
|
|
||||||
// Tunstenite
|
// Tungstenite
|
||||||
#[error("Websocket: {0}")]
|
Tungstenite(hyper_tungstenite::tungstenite::error::Error),
|
||||||
Tungstenite(#[from] hyper_tungstenite::tungstenite::error::Error),
|
|
||||||
|
|
||||||
// Filter is underspecified
|
// Filter is underspecified
|
||||||
#[error("Filter is underspecified. Scrapers are not allowed")]
|
|
||||||
Scraper,
|
Scraper,
|
||||||
|
|
||||||
// UTF-8
|
// UTF-8
|
||||||
#[error("UTF-8: {0}")]
|
Utf8(std::str::Utf8Error),
|
||||||
Utf8(#[from] std::str::Utf8Error),
|
|
||||||
|
|
||||||
// UTF-8
|
// UTF-8
|
||||||
#[error("UTF-8 error")]
|
|
||||||
Utf8Error,
|
Utf8Error,
|
||||||
|
|
||||||
// Tunstenite Protocol
|
// Tungstenite Protocol
|
||||||
#[error("Websocket Protocol: {0}")]
|
WebsocketProtocol(hyper_tungstenite::tungstenite::error::ProtocolError),
|
||||||
WebsocketProtocol(#[from] hyper_tungstenite::tungstenite::error::ProtocolError),
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for ChorusError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
ChorusError::BadEventId => write!(f, "Bad event id, does not match hash"),
|
||||||
|
ChorusError::BadHexInput => write!(f, "Bad hex input"),
|
||||||
|
ChorusError::BufferTooSmall => write!(f, "Output buffer too small"),
|
||||||
|
ChorusError::ChannelRecv(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::ChannelSend(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::Config(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::Crypto(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::Duplicate => write!(f, "Duplicate"),
|
||||||
|
ChorusError::EndOfInput => write!(f, "End of input"),
|
||||||
|
ChorusError::Http(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::Hyper(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::Io(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::JsonBad(err, pos) => write!(f, "JSON bad: {err} at position {pos}"),
|
||||||
|
ChorusError::JsonBadCharacter(c, pos, ec) => write!(
|
||||||
|
f,
|
||||||
|
"JSON bad character: {c} at position {pos}, {ec} was expected"
|
||||||
|
),
|
||||||
|
ChorusError::JsonBadEvent(err, pos) => {
|
||||||
|
write!(f, "JSON bad event: {err} at position {pos}")
|
||||||
|
}
|
||||||
|
ChorusError::JsonBadFilter(err, pos) => {
|
||||||
|
write!(f, "JSON bad filter: {err} at position {pos}")
|
||||||
|
}
|
||||||
|
ChorusError::JsonBadStringChar(ch) => {
|
||||||
|
write!(f, "JSON string bad character: codepoint {ch}")
|
||||||
|
}
|
||||||
|
ChorusError::JsonEscape => write!(f, "JSON string escape error"),
|
||||||
|
ChorusError::JsonEscapeSurrogate => write!(
|
||||||
|
f,
|
||||||
|
"JSON string escape surrogate (ancient style) is not supported"
|
||||||
|
),
|
||||||
|
ChorusError::Lmdb(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::NoPrivateKey => write!(f, "Private Key Not Found"),
|
||||||
|
ChorusError::Rustls(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::Tungstenite(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::Scraper => write!(f, "Filter is underspecified. Scrapers are not allowed"),
|
||||||
|
ChorusError::Utf8(e) => write!(f, "{e}"),
|
||||||
|
ChorusError::Utf8Error => write!(f, "UTF-8 error"),
|
||||||
|
ChorusError::WebsocketProtocol(e) => write!(f, "{e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StdError for ChorusError {
|
||||||
|
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||||
|
match self {
|
||||||
|
ChorusError::ChannelRecv(e) => Some(e),
|
||||||
|
ChorusError::ChannelSend(e) => Some(e),
|
||||||
|
ChorusError::Config(e) => Some(e),
|
||||||
|
ChorusError::Crypto(e) => Some(e),
|
||||||
|
ChorusError::Http(e) => Some(e),
|
||||||
|
ChorusError::Hyper(e) => Some(e),
|
||||||
|
ChorusError::Io(e) => Some(e),
|
||||||
|
ChorusError::Lmdb(e) => Some(e),
|
||||||
|
ChorusError::Rustls(e) => Some(e),
|
||||||
|
ChorusError::Tungstenite(e) => Some(e),
|
||||||
|
ChorusError::Utf8(e) => Some(e),
|
||||||
|
ChorusError::WebsocketProtocol(e) => Some(e),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: we impl Into because our typical pattern is ChorusError::Variant.into()
|
||||||
|
// when we tried implementing From, the location was deep in rust code's
|
||||||
|
// blanket into implementation, which wasn't the line number we wanted.
|
||||||
|
//
|
||||||
|
// As for converting other error types (below) the try! macro uses From so it
|
||||||
|
// is correct.
|
||||||
|
#[allow(clippy::from_over_into)]
|
||||||
|
impl Into<Error> for ChorusError {
|
||||||
|
#[track_caller]
|
||||||
|
fn into(self) -> Error {
|
||||||
|
Error {
|
||||||
|
inner: self,
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<tokio::sync::broadcast::error::RecvError> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: tokio::sync::broadcast::error::RecvError) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::ChannelRecv(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<tokio::sync::broadcast::error::SendError<usize>> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: tokio::sync::broadcast::error::SendError<usize>) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::ChannelSend(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ron::error::SpannedError> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: ron::error::SpannedError) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Config(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<secp256k1::Error> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: secp256k1::Error) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Crypto(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<hyper::http::Error> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: hyper::http::Error) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Http(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<hyper::Error> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: hyper::Error) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Hyper(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::io::Error> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: std::io::Error) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Io(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<heed::Error> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: heed::Error) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Lmdb(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<tokio_rustls::rustls::Error> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: tokio_rustls::rustls::Error) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Rustls(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<hyper_tungstenite::tungstenite::error::Error> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: hyper_tungstenite::tungstenite::error::Error) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Tungstenite(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<std::str::Utf8Error> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: std::str::Utf8Error) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::Utf8(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<hyper_tungstenite::tungstenite::error::ProtocolError> for Error {
|
||||||
|
#[track_caller]
|
||||||
|
fn from(err: hyper_tungstenite::tungstenite::error::ProtocolError) -> Self {
|
||||||
|
Error {
|
||||||
|
inner: ChorusError::WebsocketProtocol(err),
|
||||||
|
location: std::panic::Location::caller(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ macro_rules! write_hex {
|
|||||||
($input:expr, $output:expr, $bytelen:expr) => {{
|
($input:expr, $output:expr, $bytelen:expr) => {{
|
||||||
assert_eq!($input.len(), $bytelen);
|
assert_eq!($input.len(), $bytelen);
|
||||||
if $output.len() != $bytelen * 2 {
|
if $output.len() != $bytelen * 2 {
|
||||||
Err(Error::BufferTooSmall)
|
Err(crate::error::ChorusError::BufferTooSmall.into())
|
||||||
} else {
|
} else {
|
||||||
for (i, byte) in $input.iter().enumerate() {
|
for (i, byte) in $input.iter().enumerate() {
|
||||||
$output[i * 2] = crate::HEX_CHARS[((byte & 0xF0) >> 4) as usize];
|
$output[i * 2] = crate::HEX_CHARS[((byte & 0xF0) >> 4) as usize];
|
||||||
@ -34,17 +34,17 @@ macro_rules! read_hex {
|
|||||||
($input:expr, $output:expr, $bytelen:expr) => {{
|
($input:expr, $output:expr, $bytelen:expr) => {{
|
||||||
assert_eq!($output.len(), $bytelen);
|
assert_eq!($output.len(), $bytelen);
|
||||||
if $input.len() != $bytelen * 2 {
|
if $input.len() != $bytelen * 2 {
|
||||||
Err(Error::EndOfInput)
|
Err(Into::<crate::error::Error>::into(crate::error::ChorusError::EndOfInput))
|
||||||
} else {
|
} else {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
let high = crate::HEX_INVERSE[$input[i * 2] as usize];
|
let high = crate::HEX_INVERSE[$input[i * 2] as usize];
|
||||||
if high == 255 {
|
if high == 255 {
|
||||||
break Err(Error::BadHexInput);
|
break Err(crate::error::ChorusError::BadHexInput.into());
|
||||||
}
|
}
|
||||||
let low = crate::HEX_INVERSE[$input[i * 2 + 1] as usize];
|
let low = crate::HEX_INVERSE[$input[i * 2 + 1] as usize];
|
||||||
if low == 255 {
|
if low == 255 {
|
||||||
break Err(Error::BadHexInput);
|
break Err(crate::error::ChorusError::BadHexInput.into());
|
||||||
}
|
}
|
||||||
$output[i] = high * 16 + low;
|
$output[i] = high * 16 + low;
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|||||||
18
src/main.rs
18
src/main.rs
@ -11,7 +11,7 @@ pub mod types;
|
|||||||
pub mod web;
|
pub mod web;
|
||||||
|
|
||||||
use crate::config::{Config, FriendlyConfig};
|
use crate::config::{Config, FriendlyConfig};
|
||||||
use crate::error::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
use crate::globals::GLOBALS;
|
use crate::globals::GLOBALS;
|
||||||
use crate::reply::NostrReply;
|
use crate::reply::NostrReply;
|
||||||
use crate::store::Store;
|
use crate::store::Store;
|
||||||
@ -172,13 +172,15 @@ async fn handle_http_request(
|
|||||||
|
|
||||||
// Handle the websocket
|
// Handle the websocket
|
||||||
if let Err(e) = ws_service.handle_websocket_stream().await {
|
if let Err(e) = ws_service.handle_websocket_stream().await {
|
||||||
match e {
|
if matches!(
|
||||||
Error::Tungstenite(tungstenite::error::Error::Protocol(
|
e.inner,
|
||||||
tungstenite::error::ProtocolError::ResetWithoutClosingHandshake,
|
ChorusError::Tungstenite(tungstenite::error::Error::Protocol(
|
||||||
)) => {
|
tungstenite::error::ProtocolError::ResetWithoutClosingHandshake
|
||||||
// swallow
|
))
|
||||||
}
|
) {
|
||||||
e => log::error!("{}: {}", peer, e),
|
// Swallow the boring error
|
||||||
|
} else {
|
||||||
|
log::error!("{}: {}", peer, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
src/nostr.rs
11
src/nostr.rs
@ -1,4 +1,4 @@
|
|||||||
use crate::error::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
use crate::globals::GLOBALS;
|
use crate::globals::GLOBALS;
|
||||||
use crate::reply::NostrReply;
|
use crate::reply::NostrReply;
|
||||||
use crate::types::parse::json_escape::json_unescape;
|
use crate::types::parse::json_escape::json_unescape;
|
||||||
@ -140,8 +140,13 @@ impl WebSocketService {
|
|||||||
GLOBALS.new_events.send(offset)?; // advertise the new event
|
GLOBALS.new_events.send(offset)?; // advertise the new event
|
||||||
NostrReply::Ok(event.id(), true, "".to_owned())
|
NostrReply::Ok(event.id(), true, "".to_owned())
|
||||||
}
|
}
|
||||||
Err(Error::Duplicate) => NostrReply::Ok(event.id(), true, "duplicate:".to_owned()),
|
Err(e) => {
|
||||||
Err(e) => NostrReply::Ok(event.id(), false, format!("{e}")),
|
if matches!(e.inner, ChorusError::Duplicate) {
|
||||||
|
NostrReply::Ok(event.id(), true, "duplicate:".to_owned())
|
||||||
|
} else {
|
||||||
|
NostrReply::Ok(event.id(), false, format!("{e}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.websocket.send(Message::text(reply.as_json())).await?;
|
self.websocket.send(Message::text(reply.as_json())).await?;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
pub mod event_store;
|
pub mod event_store;
|
||||||
pub use event_store::EventStore;
|
pub use event_store::EventStore;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
use crate::types::{Event, Filter, Id, Kind, Pubkey, Time};
|
use crate::types::{Event, Filter, Id, Kind, Pubkey, Time};
|
||||||
use heed::types::{OwnedType, UnalignedSlice};
|
use heed::types::{OwnedType, UnalignedSlice};
|
||||||
use heed::{Database, Env, EnvFlags, EnvOpenOptions};
|
use heed::{Database, Env, EnvFlags, EnvOpenOptions};
|
||||||
@ -133,7 +133,7 @@ impl Store {
|
|||||||
|
|
||||||
txn.commit()?;
|
txn.commit()?;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Duplicate);
|
return Err(ChorusError::Duplicate.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(offset)
|
Ok(offset)
|
||||||
@ -294,7 +294,7 @@ impl Store {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Scraper);
|
return Err(ChorusError::Scraper.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(output)
|
Ok(output)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::error::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
use rustls::{Certificate, PrivateKey};
|
use rustls::{Certificate, PrivateKey};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
@ -25,7 +25,7 @@ pub fn tls_acceptor(config: &Config) -> Result<TlsAcceptor, Error> {
|
|||||||
|
|
||||||
let key = match keys.pop() {
|
let key = match keys.pop() {
|
||||||
Some(k) => k,
|
Some(k) => k,
|
||||||
None => return Err(Error::NoPrivateKey),
|
None => return Err(ChorusError::NoPrivateKey.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let tls_config = rustls::ServerConfig::builder()
|
let tls_config = rustls::ServerConfig::builder()
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
use crate::error::{ChorusError, Error};
|
||||||
use crate::types::parse::json_parse::*;
|
use crate::types::parse::json_parse::*;
|
||||||
use crate::Error;
|
|
||||||
|
|
||||||
/// Parses a JSON event from the `input` buffer. Places the parsed event into the `output` buffer.
|
/// Parses a JSON event from the `input` buffer. Places the parsed event into the `output` buffer.
|
||||||
/// Returns the count of consumed bytes and output bytes
|
/// Returns the count of consumed bytes and output bytes
|
||||||
@ -7,7 +7,7 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
// Minimum-sized JSON event is 204 characters long
|
// Minimum-sized JSON event is 204 characters long
|
||||||
// NOTE: 152 is the minimum binary event
|
// NOTE: 152 is the minimum binary event
|
||||||
if input.len() < 204 {
|
if input.len() < 204 {
|
||||||
return Err(Error::JsonBadEvent("Too Short", 0));
|
return Err(ChorusError::JsonBadEvent("Too Short", 0).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This tracks where we are currently looking in the input as we scan forward.
|
// This tracks where we are currently looking in the input as we scan forward.
|
||||||
@ -49,12 +49,12 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
// field and value: kind":1
|
// field and value: kind":1
|
||||||
// This allows us to skip length tests below that are shorter than inpos+7
|
// This allows us to skip length tests below that are shorter than inpos+7
|
||||||
if inpos + 7 > input.len() {
|
if inpos + 7 > input.len() {
|
||||||
return Err(Error::JsonBadEvent("Too Short or Missing Fields", inpos));
|
return Err(ChorusError::JsonBadEvent("Too Short or Missing Fields", inpos).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if &input[inpos..inpos + 3] == b"id\"" {
|
if &input[inpos..inpos + 3] == b"id\"" {
|
||||||
if complete & HAVE_ID == HAVE_ID {
|
if complete & HAVE_ID == HAVE_ID {
|
||||||
return Err(Error::JsonBadEvent("Duplicate id field", inpos));
|
return Err(ChorusError::JsonBadEvent("Duplicate id field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 3;
|
inpos += 3;
|
||||||
eat_colon_with_whitespace(input, &mut inpos)?;
|
eat_colon_with_whitespace(input, &mut inpos)?;
|
||||||
@ -62,7 +62,7 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
complete |= HAVE_ID;
|
complete |= HAVE_ID;
|
||||||
} else if &input[inpos..inpos + 4] == b"sig\"" {
|
} else if &input[inpos..inpos + 4] == b"sig\"" {
|
||||||
if complete & HAVE_SIG == HAVE_SIG {
|
if complete & HAVE_SIG == HAVE_SIG {
|
||||||
return Err(Error::JsonBadEvent("Duplicate sig field", inpos));
|
return Err(ChorusError::JsonBadEvent("Duplicate sig field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 4;
|
inpos += 4;
|
||||||
eat_colon_with_whitespace(input, &mut inpos)?;
|
eat_colon_with_whitespace(input, &mut inpos)?;
|
||||||
@ -70,7 +70,7 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
complete |= HAVE_SIG;
|
complete |= HAVE_SIG;
|
||||||
} else if &input[inpos..inpos + 5] == b"kind\"" {
|
} else if &input[inpos..inpos + 5] == b"kind\"" {
|
||||||
if complete & HAVE_KIND == HAVE_KIND {
|
if complete & HAVE_KIND == HAVE_KIND {
|
||||||
return Err(Error::JsonBadEvent("Duplicate kind field", inpos));
|
return Err(ChorusError::JsonBadEvent("Duplicate kind field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 5;
|
inpos += 5;
|
||||||
eat_colon_with_whitespace(input, &mut inpos)?;
|
eat_colon_with_whitespace(input, &mut inpos)?;
|
||||||
@ -79,7 +79,7 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
complete |= HAVE_KIND;
|
complete |= HAVE_KIND;
|
||||||
} else if &input[inpos..inpos + 5] == b"tags\"" {
|
} else if &input[inpos..inpos + 5] == b"tags\"" {
|
||||||
if complete & HAVE_TAGS == HAVE_TAGS {
|
if complete & HAVE_TAGS == HAVE_TAGS {
|
||||||
return Err(Error::JsonBadEvent("Duplicate tags field", inpos));
|
return Err(ChorusError::JsonBadEvent("Duplicate tags field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 5;
|
inpos += 5;
|
||||||
eat_colon_with_whitespace(input, &mut inpos)?;
|
eat_colon_with_whitespace(input, &mut inpos)?;
|
||||||
@ -93,7 +93,7 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
}
|
}
|
||||||
} else if &input[inpos..inpos + 7] == b"pubkey\"" {
|
} else if &input[inpos..inpos + 7] == b"pubkey\"" {
|
||||||
if complete & HAVE_PUBKEY == HAVE_PUBKEY {
|
if complete & HAVE_PUBKEY == HAVE_PUBKEY {
|
||||||
return Err(Error::JsonBadEvent("Duplicate pubkey field", inpos));
|
return Err(ChorusError::JsonBadEvent("Duplicate pubkey field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 7;
|
inpos += 7;
|
||||||
eat_colon_with_whitespace(input, &mut inpos)?;
|
eat_colon_with_whitespace(input, &mut inpos)?;
|
||||||
@ -101,7 +101,7 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
complete |= HAVE_PUBKEY;
|
complete |= HAVE_PUBKEY;
|
||||||
} else if inpos + 8 <= input.len() && &input[inpos..inpos + 8] == b"content\"" {
|
} else if inpos + 8 <= input.len() && &input[inpos..inpos + 8] == b"content\"" {
|
||||||
if complete & HAVE_CONTENT == HAVE_CONTENT {
|
if complete & HAVE_CONTENT == HAVE_CONTENT {
|
||||||
return Err(Error::JsonBadEvent("Duplicate pubkey field", inpos));
|
return Err(ChorusError::JsonBadEvent("Duplicate pubkey field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 8;
|
inpos += 8;
|
||||||
eat_colon_with_whitespace(input, &mut inpos)?;
|
eat_colon_with_whitespace(input, &mut inpos)?;
|
||||||
@ -119,7 +119,7 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
}
|
}
|
||||||
} else if inpos + 11 <= input.len() && &input[inpos..inpos + 11] == b"created_at\"" {
|
} else if inpos + 11 <= input.len() && &input[inpos..inpos + 11] == b"created_at\"" {
|
||||||
if complete & HAVE_CREATED_AT == HAVE_CREATED_AT {
|
if complete & HAVE_CREATED_AT == HAVE_CREATED_AT {
|
||||||
return Err(Error::JsonBadEvent("Duplicate created_at field", inpos));
|
return Err(ChorusError::JsonBadEvent("Duplicate created_at field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 11;
|
inpos += 11;
|
||||||
eat_colon_with_whitespace(input, &mut inpos)?;
|
eat_colon_with_whitespace(input, &mut inpos)?;
|
||||||
@ -142,7 +142,7 @@ pub fn parse_json_event(input: &[u8], output: &mut [u8]) -> Result<(usize, usize
|
|||||||
u32::from_ne_bytes(output[0..4].try_into().unwrap()) as usize,
|
u32::from_ne_bytes(output[0..4].try_into().unwrap()) as usize,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Err(Error::JsonBadEvent("Missing Fields", inpos))
|
Err(ChorusError::JsonBadEvent("Missing Fields", inpos).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use super::{Id, Kind, Pubkey, Sig, Tags, Time};
|
use super::{Id, Kind, Pubkey, Sig, Tags, Time};
|
||||||
use crate::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
mod json_event;
|
mod json_event;
|
||||||
@ -35,11 +35,11 @@ impl<'a> Event<'a> {
|
|||||||
// this marks off the slice of bytes that represent an event from a potentially longer input
|
// this marks off the slice of bytes that represent an event from a potentially longer input
|
||||||
pub fn delineate(input: &'a [u8]) -> Result<Event<'a>, Error> {
|
pub fn delineate(input: &'a [u8]) -> Result<Event<'a>, Error> {
|
||||||
if input.len() < 144 + 4 + 4 {
|
if input.len() < 144 + 4 + 4 {
|
||||||
return Err(Error::EndOfInput);
|
return Err(ChorusError::EndOfInput.into());
|
||||||
}
|
}
|
||||||
let len = parse_u32!(input, 0) as usize;
|
let len = parse_u32!(input, 0) as usize;
|
||||||
if input.len() < len {
|
if input.len() < len {
|
||||||
return Err(Error::EndOfInput);
|
return Err(ChorusError::EndOfInput.into());
|
||||||
}
|
}
|
||||||
Ok(Event(&input[0..len]))
|
Ok(Event(&input[0..len]))
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ impl<'a> Event<'a> {
|
|||||||
// This copies
|
// This copies
|
||||||
pub fn copy(&self, output: &mut [u8]) -> Result<(), Error> {
|
pub fn copy(&self, output: &mut [u8]) -> Result<(), Error> {
|
||||||
if output.len() < self.0.len() {
|
if output.len() < self.0.len() {
|
||||||
return Err(Error::BufferTooSmall);
|
return Err(ChorusError::BufferTooSmall.into());
|
||||||
}
|
}
|
||||||
output[..self.0.len()].copy_from_slice(self.0);
|
output[..self.0.len()].copy_from_slice(self.0);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -56,7 +56,7 @@ impl<'a> Event<'a> {
|
|||||||
// This copies, using the event_store mmap-append api
|
// This copies, using the event_store mmap-append api
|
||||||
pub fn macopy(&self, output: &mut [u8]) -> Result<usize, std::io::Error> {
|
pub fn macopy(&self, output: &mut [u8]) -> Result<usize, std::io::Error> {
|
||||||
if output.len() < self.0.len() {
|
if output.len() < self.0.len() {
|
||||||
return Err(std::io::Error::other(Error::BufferTooSmall));
|
return Err(std::io::Error::other(ChorusError::BufferTooSmall));
|
||||||
}
|
}
|
||||||
output[..self.0.len()].copy_from_slice(self.0);
|
output[..self.0.len()].copy_from_slice(self.0);
|
||||||
Ok(self.0.len())
|
Ok(self.0.len())
|
||||||
@ -144,7 +144,7 @@ impl<'a> Event<'a> {
|
|||||||
|
|
||||||
let hashref = <sha256::Hash as AsRef<[u8]>>::as_ref(&hash);
|
let hashref = <sha256::Hash as AsRef<[u8]>>::as_ref(&hash);
|
||||||
if hashref != self.id().as_slice() {
|
if hashref != self.id().as_slice() {
|
||||||
return Err(Error::BadEventId);
|
return Err(ChorusError::BadEventId.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let pubkey = XOnlyPublicKey::from_slice(self.pubkey().as_slice())?;
|
let pubkey = XOnlyPublicKey::from_slice(self.pubkey().as_slice())?;
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
|
use crate::error::{ChorusError, Error};
|
||||||
use crate::types::parse::json_escape::json_unescape;
|
use crate::types::parse::json_escape::json_unescape;
|
||||||
use crate::types::parse::json_parse::*;
|
use crate::types::parse::json_parse::*;
|
||||||
use crate::Error;
|
|
||||||
|
|
||||||
/// Parses a JSON filter from the `input` buffer. Places the parsed filter into the `output` buffer.
|
/// Parses a JSON filter from the `input` buffer. Places the parsed filter into the `output` buffer.
|
||||||
/// Returns the count of consumed bytes and output bytes
|
/// Returns the count of consumed bytes and output bytes
|
||||||
pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usize), Error> {
|
pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usize), Error> {
|
||||||
if input.len() < 2 {
|
if input.len() < 2 {
|
||||||
return Err(Error::JsonBadFilter("Too short", 0));
|
return Err(ChorusError::JsonBadFilter("Too short", 0).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This tracks where we are currently looking in the input as we scan forward.
|
// This tracks where we are currently looking in the input as we scan forward.
|
||||||
@ -76,7 +76,7 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
if inpos + 4 <= input.len() && &input[inpos..inpos + 4] == b"ids\"" {
|
if inpos + 4 <= input.len() && &input[inpos..inpos + 4] == b"ids\"" {
|
||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
if found & HAVE_IDS == HAVE_IDS {
|
if found & HAVE_IDS == HAVE_IDS {
|
||||||
return Err(Error::JsonBadFilter("Duplicate id field", inpos));
|
return Err(ChorusError::JsonBadFilter("Duplicate id field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 4;
|
inpos += 4;
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
} else if inpos + 8 <= input.len() && &input[inpos..inpos + 8] == b"authors\"" {
|
} else if inpos + 8 <= input.len() && &input[inpos..inpos + 8] == b"authors\"" {
|
||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
if found & HAVE_AUTHORS == HAVE_AUTHORS {
|
if found & HAVE_AUTHORS == HAVE_AUTHORS {
|
||||||
return Err(Error::JsonBadFilter("Duplicate authors field", inpos));
|
return Err(ChorusError::JsonBadFilter("Duplicate authors field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 8;
|
inpos += 8;
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
} else if inpos + 6 <= input.len() && &input[inpos..inpos + 6] == b"kinds\"" {
|
} else if inpos + 6 <= input.len() && &input[inpos..inpos + 6] == b"kinds\"" {
|
||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
if found & HAVE_KINDS == HAVE_KINDS {
|
if found & HAVE_KINDS == HAVE_KINDS {
|
||||||
return Err(Error::JsonBadFilter("Duplicate kinds field", inpos));
|
return Err(ChorusError::JsonBadFilter("Duplicate kinds field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 6;
|
inpos += 6;
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
} else if inpos + 6 <= input.len() && &input[inpos..inpos + 6] == b"since\"" {
|
} else if inpos + 6 <= input.len() && &input[inpos..inpos + 6] == b"since\"" {
|
||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
if found & HAVE_SINCE == HAVE_SINCE {
|
if found & HAVE_SINCE == HAVE_SINCE {
|
||||||
return Err(Error::JsonBadFilter("Duplicate since field", inpos));
|
return Err(ChorusError::JsonBadFilter("Duplicate since field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 6;
|
inpos += 6;
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
} else if inpos + 6 <= input.len() && &input[inpos..inpos + 6] == b"until\"" {
|
} else if inpos + 6 <= input.len() && &input[inpos..inpos + 6] == b"until\"" {
|
||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
if found & HAVE_UNTIL == HAVE_UNTIL {
|
if found & HAVE_UNTIL == HAVE_UNTIL {
|
||||||
return Err(Error::JsonBadFilter("Duplicate until field", inpos));
|
return Err(ChorusError::JsonBadFilter("Duplicate until field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 6;
|
inpos += 6;
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
} else if inpos + 6 <= input.len() && &input[inpos..inpos + 6] == b"limit\"" {
|
} else if inpos + 6 <= input.len() && &input[inpos..inpos + 6] == b"limit\"" {
|
||||||
// Check for duplicate
|
// Check for duplicate
|
||||||
if found & HAVE_LIMIT == HAVE_LIMIT {
|
if found & HAVE_LIMIT == HAVE_LIMIT {
|
||||||
return Err(Error::JsonBadFilter("Duplicate limit field", inpos));
|
return Err(ChorusError::JsonBadFilter("Duplicate limit field", inpos).into());
|
||||||
}
|
}
|
||||||
inpos += 6;
|
inpos += 6;
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
// Remember we found this tag in the `found_tags` bitfield
|
// Remember we found this tag in the `found_tags` bitfield
|
||||||
if let Some(bit) = letter_to_tag_bit(letter) {
|
if let Some(bit) = letter_to_tag_bit(letter) {
|
||||||
if found_tags & bit == bit {
|
if found_tags & bit == bit {
|
||||||
return Err(Error::JsonBadFilter("Duplicate tag", inpos));
|
return Err(ChorusError::JsonBadFilter("Duplicate tag", inpos).into());
|
||||||
}
|
}
|
||||||
found_tags |= bit;
|
found_tags |= bit;
|
||||||
}
|
}
|
||||||
@ -250,10 +250,9 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
}
|
}
|
||||||
let u = read_u64(input, &mut inpos)?;
|
let u = read_u64(input, &mut inpos)?;
|
||||||
if u > 65535 {
|
if u > 65535 {
|
||||||
return Err(Error::JsonBadFilter(
|
return Err(
|
||||||
"Filter has kind number too large",
|
ChorusError::JsonBadFilter("Filter has kind number too large", inpos).into(),
|
||||||
inpos,
|
);
|
||||||
));
|
|
||||||
}
|
}
|
||||||
output[end..end + 2].copy_from_slice((u as u16).to_ne_bytes().as_slice());
|
output[end..end + 2].copy_from_slice((u as u16).to_ne_bytes().as_slice());
|
||||||
num_kinds += 1;
|
num_kinds += 1;
|
||||||
@ -321,7 +320,7 @@ pub fn parse_json_filter(input: &[u8], output: &mut [u8]) -> Result<(usize, usiz
|
|||||||
}
|
}
|
||||||
|
|
||||||
if end > 65535 {
|
if end > 65535 {
|
||||||
return Err(Error::JsonBadFilter("Filter is too long", end));
|
return Err(ChorusError::JsonBadFilter("Filter is too long", end).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write length of filter
|
// Write length of filter
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use super::{Event, Id, Kind, Pubkey, Tags, Time};
|
use super::{Event, Id, Kind, Pubkey, Tags, Time};
|
||||||
use crate::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
mod json_filter;
|
mod json_filter;
|
||||||
@ -47,18 +47,18 @@ impl<'a> Filter<'a> {
|
|||||||
|
|
||||||
pub fn delineate(input: &'a [u8]) -> Result<Filter<'a>, Error> {
|
pub fn delineate(input: &'a [u8]) -> Result<Filter<'a>, Error> {
|
||||||
if input.len() < ARRAYS_OFFSET {
|
if input.len() < ARRAYS_OFFSET {
|
||||||
return Err(Error::EndOfInput);
|
return Err(ChorusError::EndOfInput.into());
|
||||||
}
|
}
|
||||||
let len = parse_u16!(input, 0) as usize;
|
let len = parse_u16!(input, 0) as usize;
|
||||||
if input.len() < len {
|
if input.len() < len {
|
||||||
return Err(Error::EndOfInput);
|
return Err(ChorusError::EndOfInput.into());
|
||||||
}
|
}
|
||||||
Ok(Filter(&input[0..len]))
|
Ok(Filter(&input[0..len]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy(&self, output: &mut [u8]) -> Result<(), Error> {
|
pub fn copy(&self, output: &mut [u8]) -> Result<(), Error> {
|
||||||
if output.len() < self.0.len() {
|
if output.len() < self.0.len() {
|
||||||
return Err(Error::EndOfInput);
|
return Err(ChorusError::EndOfInput.into());
|
||||||
}
|
}
|
||||||
output[..self.0.len()].copy_from_slice(self.0);
|
output[..self.0.len()].copy_from_slice(self.0);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::Error;
|
use crate::error::Error;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use super::utf8::{encode_utf8, next_code_point};
|
use super::utf8::{encode_utf8, next_code_point};
|
||||||
use crate::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
|
|
||||||
// LITERAL UNESCAPED: 0x20-0x21, 0x23-0x5B, 0x5D-10FFFF
|
// LITERAL UNESCAPED: 0x20-0x21, 0x23-0x5B, 0x5D-10FFFF
|
||||||
// ESCAPES: \" \\ \/ /b /f /n /r /t
|
// ESCAPES: \" \\ \/ /b /f /n /r /t
|
||||||
@ -13,7 +13,7 @@ pub fn json_escape(input: &[u8], out: &mut [u8]) -> Result<usize, Error> {
|
|||||||
// closure to output bytes
|
// closure to output bytes
|
||||||
let mut output = |s: &[u8]| -> Result<(), Error> {
|
let mut output = |s: &[u8]| -> Result<(), Error> {
|
||||||
if out.len() < write_pos + s.len() {
|
if out.len() < write_pos + s.len() {
|
||||||
Err(Error::BufferTooSmall)
|
Err(ChorusError::BufferTooSmall.into())
|
||||||
} else {
|
} else {
|
||||||
out[write_pos..write_pos + s.len()].copy_from_slice(s);
|
out[write_pos..write_pos + s.len()].copy_from_slice(s);
|
||||||
write_pos += s.len();
|
write_pos += s.len();
|
||||||
@ -51,7 +51,9 @@ pub fn json_escape(input: &[u8], out: &mut [u8]) -> Result<usize, Error> {
|
|||||||
macro_rules! output_slice {
|
macro_rules! output_slice {
|
||||||
($slice:expr, $out:expr, $pos:expr) => {
|
($slice:expr, $out:expr, $pos:expr) => {
|
||||||
if $out.len() < *$pos + $slice.len() {
|
if $out.len() < *$pos + $slice.len() {
|
||||||
Err(Error::BufferTooSmall)
|
Err(Into::<crate::error::Error>::into(
|
||||||
|
crate::error::ChorusError::BufferTooSmall,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
$out[*$pos..*$pos + $slice.len()].copy_from_slice($slice);
|
$out[*$pos..*$pos + $slice.len()].copy_from_slice($slice);
|
||||||
*$pos += $slice.len();
|
*$pos += $slice.len();
|
||||||
@ -63,7 +65,9 @@ macro_rules! output_slice {
|
|||||||
macro_rules! output_byte {
|
macro_rules! output_byte {
|
||||||
($byte:expr, $out:expr, $pos:expr) => {
|
($byte:expr, $out:expr, $pos:expr) => {
|
||||||
if $out.len() < *$pos + 1 {
|
if $out.len() < *$pos + 1 {
|
||||||
Err(Error::BufferTooSmall)
|
Err(Into::<crate::error::Error>::into(
|
||||||
|
crate::error::ChorusError::BufferTooSmall,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
unsafe { *$out.get_unchecked_mut(*$pos) = $byte };
|
unsafe { *$out.get_unchecked_mut(*$pos) = $byte };
|
||||||
*$pos += 1;
|
*$pos += 1;
|
||||||
@ -99,7 +103,7 @@ pub fn json_unescape(input: &[u8], out: &mut [u8]) -> Result<(usize, usize), Err
|
|||||||
if inescape {
|
if inescape {
|
||||||
inescape = false;
|
inescape = false;
|
||||||
if codepoint > 255 {
|
if codepoint > 255 {
|
||||||
return Err(Error::JsonEscape);
|
return Err(ChorusError::JsonEscape.into());
|
||||||
}
|
}
|
||||||
match codepoint as u8 {
|
match codepoint as u8 {
|
||||||
QUOTE | BACKSLASH | SLASH => {
|
QUOTE | BACKSLASH | SLASH => {
|
||||||
@ -111,17 +115,17 @@ pub fn json_unescape(input: &[u8], out: &mut [u8]) -> Result<(usize, usize), Err
|
|||||||
b'r' => output_byte!(CR, out, &mut write_pos)?,
|
b'r' => output_byte!(CR, out, &mut write_pos)?,
|
||||||
b't' => output_byte!(TAB, out, &mut write_pos)?,
|
b't' => output_byte!(TAB, out, &mut write_pos)?,
|
||||||
b'u' => uescape = Some((0, 0)),
|
b'u' => uescape = Some((0, 0)),
|
||||||
_ => return Err(Error::JsonEscape), // nothing else is a legal escape
|
_ => return Err(ChorusError::JsonEscape.into()), // nothing else is a legal escape
|
||||||
}
|
}
|
||||||
} else if let Some((digit, total)) = uescape {
|
} else if let Some((digit, total)) = uescape {
|
||||||
// must be a digit
|
// must be a digit
|
||||||
if !(48..=57).contains(&codepoint) {
|
if !(48..=57).contains(&codepoint) {
|
||||||
return Err(Error::JsonEscape);
|
return Err(ChorusError::JsonEscape.into());
|
||||||
}
|
}
|
||||||
let total = total + ((codepoint - 48) << (4 * (3 - digit)));
|
let total = total + ((codepoint - 48) << (4 * (3 - digit)));
|
||||||
if digit >= 3 {
|
if digit >= 3 {
|
||||||
if (0xD800..=0xDFFF).contains(&total) {
|
if (0xD800..=0xDFFF).contains(&total) {
|
||||||
return Err(Error::JsonEscapeSurrogate);
|
return Err(ChorusError::JsonEscapeSurrogate.into());
|
||||||
}
|
}
|
||||||
let s = encode_utf8(total, &mut out[write_pos..])?;
|
let s = encode_utf8(total, &mut out[write_pos..])?;
|
||||||
write_pos += s;
|
write_pos += s;
|
||||||
@ -138,7 +142,7 @@ pub fn json_unescape(input: &[u8], out: &mut [u8]) -> Result<(usize, usize), Err
|
|||||||
// ending double quote
|
// ending double quote
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::JsonBadStringChar(codepoint));
|
return Err(ChorusError::JsonBadStringChar(codepoint).into());
|
||||||
}
|
}
|
||||||
p += size;
|
p += size;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use super::json_escape::json_unescape;
|
use super::json_escape::json_unescape;
|
||||||
use crate::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn eat_whitespace(input: &[u8], inposp: &mut usize) {
|
pub fn eat_whitespace(input: &[u8], inposp: &mut usize) {
|
||||||
@ -18,16 +18,12 @@ pub fn eat_whitespace_and_commas(input: &[u8], inposp: &mut usize) {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn verify_char(input: &[u8], ch: u8, inposp: &mut usize) -> Result<(), Error> {
|
pub fn verify_char(input: &[u8], ch: u8, inposp: &mut usize) -> Result<(), Error> {
|
||||||
if *inposp >= input.len() {
|
if *inposp >= input.len() {
|
||||||
Err(Error::JsonBad("Too Short or Missing Fields", *inposp))
|
Err(ChorusError::JsonBad("Too Short or Missing Fields", *inposp).into())
|
||||||
} else if input[*inposp] == ch {
|
} else if input[*inposp] == ch {
|
||||||
*inposp += 1;
|
*inposp += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::JsonBadCharacter(
|
Err(ChorusError::JsonBadCharacter(input[*inposp] as char, *inposp, ch as char).into())
|
||||||
input[*inposp] as char,
|
|
||||||
*inposp,
|
|
||||||
ch as char,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +38,7 @@ pub fn next_object_field(input: &[u8], inposp: &mut usize) -> Result<bool, Error
|
|||||||
eat_whitespace(input, inposp);
|
eat_whitespace(input, inposp);
|
||||||
// next comes either comma or end brace
|
// next comes either comma or end brace
|
||||||
if *inposp >= input.len() {
|
if *inposp >= input.len() {
|
||||||
return Err(Error::JsonBad("Too short", *inposp));
|
return Err(ChorusError::JsonBad("Too short", *inposp).into());
|
||||||
}
|
}
|
||||||
if input[*inposp] == b'}' {
|
if input[*inposp] == b'}' {
|
||||||
*inposp += 1;
|
*inposp += 1;
|
||||||
@ -51,14 +47,14 @@ pub fn next_object_field(input: &[u8], inposp: &mut usize) -> Result<bool, Error
|
|||||||
*inposp += 1;
|
*inposp += 1;
|
||||||
Ok(false)
|
Ok(false)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::JsonBad("Unexpected char", *inposp))
|
Err(ChorusError::JsonBad("Unexpected char", *inposp).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_id(input: &[u8], inposp: &mut usize, output: &mut [u8]) -> Result<(), Error> {
|
pub fn read_id(input: &[u8], inposp: &mut usize, output: &mut [u8]) -> Result<(), Error> {
|
||||||
verify_char(input, b'"', inposp)?;
|
verify_char(input, b'"', inposp)?;
|
||||||
if *inposp + 64 >= input.len() {
|
if *inposp + 64 >= input.len() {
|
||||||
return Err(Error::JsonBad("Too short reading id", *inposp));
|
return Err(ChorusError::JsonBad("Too short reading id", *inposp).into());
|
||||||
}
|
}
|
||||||
// Read the hex ID and write the binary ID into the output event structure
|
// Read the hex ID and write the binary ID into the output event structure
|
||||||
read_hex!(&input[*inposp..*inposp + 64], &mut output[..32], 32)?;
|
read_hex!(&input[*inposp..*inposp + 64], &mut output[..32], 32)?;
|
||||||
@ -70,7 +66,7 @@ pub fn read_id(input: &[u8], inposp: &mut usize, output: &mut [u8]) -> Result<()
|
|||||||
pub fn read_pubkey(input: &[u8], inposp: &mut usize, output: &mut [u8]) -> Result<(), Error> {
|
pub fn read_pubkey(input: &[u8], inposp: &mut usize, output: &mut [u8]) -> Result<(), Error> {
|
||||||
verify_char(input, b'"', inposp)?;
|
verify_char(input, b'"', inposp)?;
|
||||||
if *inposp + 64 >= input.len() {
|
if *inposp + 64 >= input.len() {
|
||||||
return Err(Error::JsonBad("Too short reading pubkey", *inposp));
|
return Err(ChorusError::JsonBad("Too short reading pubkey", *inposp).into());
|
||||||
}
|
}
|
||||||
// Read the hex pubkey and write the binary pubkey into the output event structure
|
// Read the hex pubkey and write the binary pubkey into the output event structure
|
||||||
read_hex!(&input[*inposp..*inposp + 64], &mut output[..32], 32)?;
|
read_hex!(&input[*inposp..*inposp + 64], &mut output[..32], 32)?;
|
||||||
@ -88,10 +84,11 @@ pub fn read_u64(input: &[u8], inposp: &mut usize) -> Result<u64, Error> {
|
|||||||
*inposp += 1;
|
*inposp += 1;
|
||||||
}
|
}
|
||||||
if !any {
|
if !any {
|
||||||
return Err(Error::JsonBad(
|
return Err(ChorusError::JsonBad(
|
||||||
"Created at must be a positive or zero valued number",
|
"Created at must be a positive or zero valued number",
|
||||||
*inposp,
|
*inposp,
|
||||||
));
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
@ -105,13 +102,14 @@ pub fn read_kind(input: &[u8], inposp: &mut usize) -> Result<u16, Error> {
|
|||||||
*inposp += 1;
|
*inposp += 1;
|
||||||
}
|
}
|
||||||
if !any {
|
if !any {
|
||||||
return Err(Error::JsonBad(
|
return Err(ChorusError::JsonBad(
|
||||||
"Kind at must be a positive or zero valued number",
|
"Kind at must be a positive or zero valued number",
|
||||||
*inposp,
|
*inposp,
|
||||||
));
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
if value > 65535 {
|
if value > 65535 {
|
||||||
Err(Error::JsonBad("Kind larger than 65535", *inposp))
|
Err(ChorusError::JsonBad("Kind larger than 65535", *inposp).into())
|
||||||
} else {
|
} else {
|
||||||
Ok(value as u16)
|
Ok(value as u16)
|
||||||
}
|
}
|
||||||
@ -173,7 +171,7 @@ pub fn read_tags_array(
|
|||||||
}
|
}
|
||||||
eat_whitespace(input, inposp);
|
eat_whitespace(input, inposp);
|
||||||
}
|
}
|
||||||
_ => return Err(Error::JsonBad("Tag array bad character", *inposp)),
|
_ => return Err(ChorusError::JsonBad("Tag array bad character", *inposp).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +189,7 @@ pub fn count_tags(input: &[u8], mut inpos: usize) -> Result<usize, Error> {
|
|||||||
match input[inpos] {
|
match input[inpos] {
|
||||||
b']' => return Ok(0), // no tags
|
b']' => return Ok(0), // no tags
|
||||||
b'[' => (), // expected
|
b'[' => (), // expected
|
||||||
_ => return Err(Error::JsonBad("Tag array bad initial character", inpos)),
|
_ => return Err(ChorusError::JsonBad("Tag array bad initial character", inpos).into()),
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut count = 1;
|
let mut count = 1;
|
||||||
@ -210,7 +208,7 @@ pub fn count_tags(input: &[u8], mut inpos: usize) -> Result<usize, Error> {
|
|||||||
burn_tag(input, &mut inpos)?;
|
burn_tag(input, &mut inpos)?;
|
||||||
eat_whitespace(input, &mut inpos);
|
eat_whitespace(input, &mut inpos);
|
||||||
}
|
}
|
||||||
_ => return Err(Error::JsonBad("Tag array bad character", inpos)),
|
_ => return Err(ChorusError::JsonBad("Tag array bad character", inpos).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,7 +247,7 @@ pub fn read_tag(
|
|||||||
*inposp += 1;
|
*inposp += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
_ => return Err(Error::JsonBad("Tag array bad character", *inposp)),
|
_ => return Err(ChorusError::JsonBad("Tag array bad character", *inposp).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,7 +282,7 @@ pub fn read_content(
|
|||||||
pub fn read_sig(input: &[u8], inposp: &mut usize, output: &mut [u8]) -> Result<(), Error> {
|
pub fn read_sig(input: &[u8], inposp: &mut usize, output: &mut [u8]) -> Result<(), Error> {
|
||||||
verify_char(input, b'"', inposp)?;
|
verify_char(input, b'"', inposp)?;
|
||||||
if *inposp + 128 >= input.len() {
|
if *inposp + 128 >= input.len() {
|
||||||
return Err(Error::JsonBad("Too short reading sig", *inposp));
|
return Err(ChorusError::JsonBad("Too short reading sig", *inposp).into());
|
||||||
}
|
}
|
||||||
// Read the hex sig and write the binary sig into the output event structure
|
// Read the hex sig and write the binary sig into the output event structure
|
||||||
read_hex!(&input[*inposp..*inposp + 128], &mut output[80..144], 64)?;
|
read_hex!(&input[*inposp..*inposp + 128], &mut output[80..144], 64)?;
|
||||||
@ -307,7 +305,7 @@ pub fn burn_string(input: &[u8], inposp: &mut usize) -> Result<(), Error> {
|
|||||||
*inposp += 1;
|
*inposp += 1;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::JsonBad("Unterminated string", *inposp))
|
Err(ChorusError::JsonBad("Unterminated string", *inposp).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,10 +370,7 @@ pub fn burn_array(input: &[u8], inposp: &mut usize) -> Result<(), Error> {
|
|||||||
|
|
||||||
pub fn burn_value(input: &[u8], inposp: &mut usize) -> Result<(), Error> {
|
pub fn burn_value(input: &[u8], inposp: &mut usize) -> Result<(), Error> {
|
||||||
if *inposp >= input.len() {
|
if *inposp >= input.len() {
|
||||||
return Err(Error::JsonBad(
|
return Err(ChorusError::JsonBad("Too short burning an unused JSON value", *inposp).into());
|
||||||
"Too short burning an unused JSON value",
|
|
||||||
*inposp,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
match input[*inposp] {
|
match input[*inposp] {
|
||||||
b'"' => {
|
b'"' => {
|
||||||
@ -398,10 +393,11 @@ pub fn burn_value(input: &[u8], inposp: &mut usize) -> Result<(), Error> {
|
|||||||
if b"123456789".contains(&input[*inposp]) {
|
if b"123456789".contains(&input[*inposp]) {
|
||||||
burn_number(input, inposp)?
|
burn_number(input, inposp)?
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::JsonBad(
|
return Err(ChorusError::JsonBad(
|
||||||
"Too short burning an unused JSON value",
|
"Too short burning an unused JSON value",
|
||||||
*inposp,
|
*inposp,
|
||||||
));
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,7 +410,7 @@ pub fn burn_null(input: &[u8], inposp: &mut usize) -> Result<(), Error> {
|
|||||||
*inposp += 4;
|
*inposp += 4;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::JsonBad("Expected null", *inposp))
|
Err(ChorusError::JsonBad("Expected null", *inposp).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,7 +419,7 @@ pub fn burn_true(input: &[u8], inposp: &mut usize) -> Result<(), Error> {
|
|||||||
*inposp += 4;
|
*inposp += 4;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::JsonBad("Expected true", *inposp))
|
Err(ChorusError::JsonBad("Expected true", *inposp).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,7 +428,7 @@ pub fn burn_false(input: &[u8], inposp: &mut usize) -> Result<(), Error> {
|
|||||||
*inposp += 5;
|
*inposp += 5;
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(Error::JsonBad("Expected false", *inposp))
|
Err(ChorusError::JsonBad("Expected false", *inposp).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
|
|
||||||
// Reads the next code point if UTF-8, and returns it along with the number of characters
|
// Reads the next code point if UTF-8, and returns it along with the number of characters
|
||||||
// that make it up.
|
// that make it up.
|
||||||
@ -18,7 +18,7 @@ pub fn next_code_point(input: &[u8]) -> Result<Option<(u32, usize)>, Error> {
|
|||||||
// Decode from a byte combination out of: [[[x y] z] w]
|
// Decode from a byte combination out of: [[[x y] z] w]
|
||||||
let init = utf8_first_byte(x, 2);
|
let init = utf8_first_byte(x, 2);
|
||||||
if len < 2 {
|
if len < 2 {
|
||||||
return Err(Error::Utf8Error);
|
return Err(ChorusError::Utf8Error.into());
|
||||||
}
|
}
|
||||||
let y = input[1];
|
let y = input[1];
|
||||||
let mut ch = utf8_acc_cont_byte(init, y);
|
let mut ch = utf8_acc_cont_byte(init, y);
|
||||||
@ -26,7 +26,7 @@ pub fn next_code_point(input: &[u8]) -> Result<Option<(u32, usize)>, Error> {
|
|||||||
// [[x y z] w] case
|
// [[x y z] w] case
|
||||||
// 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid
|
// 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid
|
||||||
if len < 3 {
|
if len < 3 {
|
||||||
return Err(Error::Utf8Error);
|
return Err(ChorusError::Utf8Error.into());
|
||||||
}
|
}
|
||||||
let z = input[2];
|
let z = input[2];
|
||||||
let y_z = utf8_acc_cont_byte((y & CONT_MASK) as u32, z);
|
let y_z = utf8_acc_cont_byte((y & CONT_MASK) as u32, z);
|
||||||
@ -35,7 +35,7 @@ pub fn next_code_point(input: &[u8]) -> Result<Option<(u32, usize)>, Error> {
|
|||||||
// [x y z w] case
|
// [x y z w] case
|
||||||
// use only the lower 3 bits of `init`
|
// use only the lower 3 bits of `init`
|
||||||
if len < 4 {
|
if len < 4 {
|
||||||
return Err(Error::Utf8Error);
|
return Err(ChorusError::Utf8Error.into());
|
||||||
}
|
}
|
||||||
let w = input[3];
|
let w = input[3];
|
||||||
ch = (init & 7) << 18 | utf8_acc_cont_byte(y_z, w);
|
ch = (init & 7) << 18 | utf8_acc_cont_byte(y_z, w);
|
||||||
@ -78,7 +78,7 @@ pub fn encode_utf8(code: u32, dst: &mut [u8]) -> Result<usize, Error> {
|
|||||||
*dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
|
*dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT;
|
||||||
4
|
4
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BufferTooSmall);
|
return Err(ChorusError::BufferTooSmall.into());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(len)
|
Ok(len)
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::Error;
|
use crate::error::{ChorusError, Error};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -23,11 +23,11 @@ impl<'a> Tags<'a> {
|
|||||||
// this marks off the slice of bytes that represent the tags from a potentially longer input
|
// this marks off the slice of bytes that represent the tags from a potentially longer input
|
||||||
pub fn delineate(input: &'a [u8]) -> Result<Tags<'a>, Error> {
|
pub fn delineate(input: &'a [u8]) -> Result<Tags<'a>, Error> {
|
||||||
if input.len() < 2 {
|
if input.len() < 2 {
|
||||||
return Err(Error::EndOfInput);
|
return Err(ChorusError::EndOfInput.into());
|
||||||
}
|
}
|
||||||
let len = parse_u16!(input, 0) as usize;
|
let len = parse_u16!(input, 0) as usize;
|
||||||
if input.len() < len {
|
if input.len() < len {
|
||||||
return Err(Error::EndOfInput);
|
return Err(ChorusError::EndOfInput.into());
|
||||||
}
|
}
|
||||||
Ok(Tags(&input[0..len]))
|
Ok(Tags(&input[0..len]))
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ impl<'a> Tags<'a> {
|
|||||||
// This copies
|
// This copies
|
||||||
pub fn copy(&self, output: &mut [u8]) -> Result<(), Error> {
|
pub fn copy(&self, output: &mut [u8]) -> Result<(), Error> {
|
||||||
if output.len() < self.0.len() {
|
if output.len() < self.0.len() {
|
||||||
return Err(Error::BufferTooSmall);
|
return Err(ChorusError::BufferTooSmall.into());
|
||||||
}
|
}
|
||||||
output[..self.0.len()].copy_from_slice(self.0);
|
output[..self.0.len()].copy_from_slice(self.0);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user